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);
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
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,
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,
3065 /*ObjectType=*/QualType(),
3066 /*AllowBuiltinCreation=*/true);
3067
3068 if (Lookup.isAmbiguous())
3069 return ExprError();
3070
3071 VarDecl *VD;
3072 if (!Lookup.isSingleResult()) {
3073 VarDeclFilterCCC CCC(SemaRef);
3074 if (TypoCorrection Corrected =
3075 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3078 Corrected,
3079 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3080 : diag::err_omp_expected_var_arg_suggest)
3081 << Id.getName());
3082 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3083 } else {
3084 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3085 : diag::err_omp_expected_var_arg)
3086 << Id.getName();
3087 return ExprError();
3088 }
3089 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3090 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3091 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3092 return ExprError();
3093 }
3094 Lookup.suppressDiagnostics();
3095
3096 // OpenMP [2.9.2, Syntax, C/C++]
3097 // Variables must be file-scope, namespace-scope, or static block-scope.
3098 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3099 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3100 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3101 bool IsDecl =
3103 Diag(VD->getLocation(),
3104 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3105 << VD;
3106 return ExprError();
3107 }
3108
3109 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3110 NamedDecl *ND = CanonicalVD;
3111 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3112 // A threadprivate directive for file-scope variables must appear outside
3113 // any definition or declaration.
3114 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3116 Diag(Id.getLoc(), diag::err_omp_var_scope)
3117 << getOpenMPDirectiveName(Kind) << VD;
3118 bool IsDecl =
3120 Diag(VD->getLocation(),
3121 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3122 << VD;
3123 return ExprError();
3124 }
3125 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3126 // A threadprivate directive for static class member variables must appear
3127 // in the class definition, in the same scope in which the member
3128 // variables are declared.
3129 if (CanonicalVD->isStaticDataMember() &&
3130 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3131 Diag(Id.getLoc(), diag::err_omp_var_scope)
3132 << getOpenMPDirectiveName(Kind) << VD;
3133 bool IsDecl =
3135 Diag(VD->getLocation(),
3136 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3137 << VD;
3138 return ExprError();
3139 }
3140 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3141 // A threadprivate directive for namespace-scope variables must appear
3142 // outside any definition or declaration other than the namespace
3143 // definition itself.
3144 if (CanonicalVD->getDeclContext()->isNamespace() &&
3147 CanonicalVD->getDeclContext()))) {
3148 Diag(Id.getLoc(), diag::err_omp_var_scope)
3149 << getOpenMPDirectiveName(Kind) << VD;
3150 bool IsDecl =
3152 Diag(VD->getLocation(),
3153 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3154 << VD;
3155 return ExprError();
3156 }
3157 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3158 // A threadprivate directive for static block-scope variables must appear
3159 // in the scope of the variable and not in a nested scope.
3160 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3162 Diag(Id.getLoc(), diag::err_omp_var_scope)
3163 << getOpenMPDirectiveName(Kind) << VD;
3164 bool IsDecl =
3166 Diag(VD->getLocation(),
3167 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3168 << VD;
3169 return ExprError();
3170 }
3171
3172 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3173 // A threadprivate directive must lexically precede all references to any
3174 // of the variables in its list.
3175 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3176 !DSAStack->isThreadPrivate(VD)) {
3177 Diag(Id.getLoc(), diag::err_omp_var_used)
3178 << getOpenMPDirectiveName(Kind) << VD;
3179 return ExprError();
3180 }
3181
3182 QualType ExprType = VD->getType().getNonReferenceType();
3184 SourceLocation(), VD,
3185 /*RefersToEnclosingVariableOrCapture=*/false,
3186 Id.getLoc(), ExprType, VK_LValue);
3187}
3188
3191 ArrayRef<Expr *> VarList) {
3195 }
3196 return nullptr;
3197}
3198
3199namespace {
3200class LocalVarRefChecker final
3201 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3202 Sema &SemaRef;
3203
3204public:
3205 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3206 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3207 if (VD->hasLocalStorage()) {
3208 SemaRef.Diag(E->getBeginLoc(),
3209 diag::err_omp_local_var_in_threadprivate_init)
3210 << E->getSourceRange();
3211 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3212 << VD << VD->getSourceRange();
3213 return true;
3214 }
3215 }
3216 return false;
3217 }
3218 bool VisitStmt(const Stmt *S) {
3219 for (const Stmt *Child : S->children()) {
3220 if (Child && Visit(Child))
3221 return true;
3222 }
3223 return false;
3224 }
3225 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3226};
3227} // namespace
3228
3231 ArrayRef<Expr *> VarList) {
3232 ASTContext &Context = getASTContext();
3234 for (Expr *RefExpr : VarList) {
3235 auto *DE = cast<DeclRefExpr>(RefExpr);
3236 auto *VD = cast<VarDecl>(DE->getDecl());
3237 SourceLocation ILoc = DE->getExprLoc();
3238
3239 // Mark variable as used.
3240 VD->setReferenced();
3241 VD->markUsed(Context);
3242
3243 QualType QType = VD->getType();
3244 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3245 // It will be analyzed later.
3246 Vars.push_back(DE);
3247 continue;
3248 }
3249
3250 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3251 // A threadprivate variable must not have an incomplete type.
3253 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3254 continue;
3255 }
3256
3257 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3258 // A threadprivate variable must not have a reference type.
3259 if (VD->getType()->isReferenceType()) {
3260 Diag(ILoc, diag::err_omp_ref_type_arg)
3261 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3262 bool IsDecl =
3264 Diag(VD->getLocation(),
3265 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3266 << VD;
3267 continue;
3268 }
3269
3270 // Check if this is a TLS variable. If TLS is not being supported, produce
3271 // the corresponding diagnostic.
3272 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3273 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3274 getLangOpts().OpenMPUseTLS &&
3275 getASTContext().getTargetInfo().isTLSSupported())) ||
3276 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3277 !VD->isLocalVarDecl())) {
3278 Diag(ILoc, diag::err_omp_var_thread_local)
3279 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3280 bool IsDecl =
3282 Diag(VD->getLocation(),
3283 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3284 << VD;
3285 continue;
3286 }
3287
3288 // Check if initial value of threadprivate variable reference variable with
3289 // local storage (it is not supported by runtime).
3290 if (const Expr *Init = VD->getAnyInitializer()) {
3291 LocalVarRefChecker Checker(SemaRef);
3292 if (Checker.Visit(Init))
3293 continue;
3294 }
3295
3296 Vars.push_back(RefExpr);
3297 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3298 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3299 Context, SourceRange(Loc, Loc)));
3300 if (ASTMutationListener *ML = Context.getASTMutationListener())
3301 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3302 }
3303 OMPThreadPrivateDecl *D = nullptr;
3304 if (!Vars.empty()) {
3306 Loc, Vars);
3307 D->setAccess(AS_public);
3308 }
3309 return D;
3310}
3311
3312static OMPAllocateDeclAttr::AllocatorTypeTy
3313getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3314 if (!Allocator)
3315 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3316 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3317 Allocator->isInstantiationDependent() ||
3318 Allocator->containsUnexpandedParameterPack())
3319 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3320 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3321 llvm::FoldingSetNodeID AEId;
3322 const Expr *AE = Allocator->IgnoreParenImpCasts();
3323 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3324 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3325 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3326 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3327 llvm::FoldingSetNodeID DAEId;
3328 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3329 /*Canonical=*/true);
3330 if (AEId == DAEId) {
3331 AllocatorKindRes = AllocatorKind;
3332 break;
3333 }
3334 }
3335 return AllocatorKindRes;
3336}
3337
3339 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3340 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3341 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3342 return false;
3343 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3344 Expr *PrevAllocator = A->getAllocator();
3345 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3346 getAllocatorKind(S, Stack, PrevAllocator);
3347 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3348 if (AllocatorsMatch &&
3349 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3350 Allocator && PrevAllocator) {
3351 const Expr *AE = Allocator->IgnoreParenImpCasts();
3352 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3353 llvm::FoldingSetNodeID AEId, PAEId;
3354 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3355 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3356 AllocatorsMatch = AEId == PAEId;
3357 }
3358 if (!AllocatorsMatch) {
3359 SmallString<256> AllocatorBuffer;
3360 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3361 if (Allocator)
3362 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3363 SmallString<256> PrevAllocatorBuffer;
3364 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3365 if (PrevAllocator)
3366 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3367 S.getPrintingPolicy());
3368
3369 SourceLocation AllocatorLoc =
3370 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3371 SourceRange AllocatorRange =
3372 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3373 SourceLocation PrevAllocatorLoc =
3374 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3375 SourceRange PrevAllocatorRange =
3376 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3377 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3378 << (Allocator ? 1 : 0) << AllocatorStream.str()
3379 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3380 << AllocatorRange;
3381 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3382 << PrevAllocatorRange;
3383 return true;
3384 }
3385 return false;
3386}
3387
3388static void
3390 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3391 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3392 if (VD->hasAttr<OMPAllocateDeclAttr>())
3393 return;
3394 if (Alignment &&
3395 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3396 Alignment->isInstantiationDependent() ||
3397 Alignment->containsUnexpandedParameterPack()))
3398 // Apply later when we have a usable value.
3399 return;
3400 if (Allocator &&
3401 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3402 Allocator->isInstantiationDependent() ||
3403 Allocator->containsUnexpandedParameterPack()))
3404 return;
3405 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3406 Allocator, Alignment, SR);
3407 VD->addAttr(A);
3409 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3410}
3411
3414 DeclContext *Owner) {
3415 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3416 Expr *Alignment = nullptr;
3417 Expr *Allocator = nullptr;
3418 if (Clauses.empty()) {
3419 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3420 // allocate directives that appear in a target region must specify an
3421 // allocator clause unless a requires directive with the dynamic_allocators
3422 // clause is present in the same compilation unit.
3423 if (getLangOpts().OpenMPIsTargetDevice &&
3424 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3425 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3426 } else {
3427 for (const OMPClause *C : Clauses)
3428 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3429 Allocator = AC->getAllocator();
3430 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3431 Alignment = AC->getAlignment();
3432 else
3433 llvm_unreachable("Unexpected clause on allocate directive");
3434 }
3435 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3436 getAllocatorKind(SemaRef, DSAStack, Allocator);
3438 for (Expr *RefExpr : VarList) {
3439 auto *DE = cast<DeclRefExpr>(RefExpr);
3440 auto *VD = cast<VarDecl>(DE->getDecl());
3441
3442 // Check if this is a TLS variable or global register.
3443 if (VD->getTLSKind() != VarDecl::TLS_None ||
3444 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3445 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3446 !VD->isLocalVarDecl()))
3447 continue;
3448
3449 // If the used several times in the allocate directive, the same allocator
3450 // must be used.
3452 AllocatorKind, Allocator))
3453 continue;
3454
3455 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3456 // If a list item has a static storage type, the allocator expression in the
3457 // allocator clause must be a constant expression that evaluates to one of
3458 // the predefined memory allocator values.
3459 if (Allocator && VD->hasGlobalStorage()) {
3460 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3461 Diag(Allocator->getExprLoc(),
3462 diag::err_omp_expected_predefined_allocator)
3463 << Allocator->getSourceRange();
3464 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3466 Diag(VD->getLocation(),
3467 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3468 << VD;
3469 continue;
3470 }
3471 }
3472
3473 Vars.push_back(RefExpr);
3474 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3475 DE->getSourceRange());
3476 }
3477 if (Vars.empty())
3478 return nullptr;
3479 if (!Owner)
3480 Owner = SemaRef.getCurLexicalContext();
3481 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3482 D->setAccess(AS_public);
3483 Owner->addDecl(D);
3485}
3486
3489 ArrayRef<OMPClause *> ClauseList) {
3490 OMPRequiresDecl *D = nullptr;
3492 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3493 } else {
3494 D = CheckOMPRequiresDecl(Loc, ClauseList);
3495 if (D) {
3497 DSAStack->addRequiresDecl(D);
3498 }
3499 }
3501}
3502
3504 OpenMPDirectiveKind DKind,
3505 ArrayRef<std::string> Assumptions,
3506 bool SkippedClauses) {
3507 if (!SkippedClauses && Assumptions.empty())
3508 Diag(Loc, diag::err_omp_no_clause_for_directive)
3509 << llvm::omp::getAllAssumeClauseOptions()
3510 << llvm::omp::getOpenMPDirectiveName(DKind);
3511
3512 auto *AA =
3513 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3514 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3515 OMPAssumeScoped.push_back(AA);
3516 return;
3517 }
3518
3519 // Global assumes without assumption clauses are ignored.
3520 if (Assumptions.empty())
3521 return;
3522
3523 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3524 "Unexpected omp assumption directive!");
3525 OMPAssumeGlobal.push_back(AA);
3526
3527 // The OMPAssumeGlobal scope above will take care of new declarations but
3528 // we also want to apply the assumption to existing ones, e.g., to
3529 // declarations in included headers. To this end, we traverse all existing
3530 // declaration contexts and annotate function declarations here.
3531 SmallVector<DeclContext *, 8> DeclContexts;
3532 auto *Ctx = SemaRef.CurContext;
3533 while (Ctx->getLexicalParent())
3534 Ctx = Ctx->getLexicalParent();
3535 DeclContexts.push_back(Ctx);
3536 while (!DeclContexts.empty()) {
3537 DeclContext *DC = DeclContexts.pop_back_val();
3538 for (auto *SubDC : DC->decls()) {
3539 if (SubDC->isInvalidDecl())
3540 continue;
3541 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3542 DeclContexts.push_back(CTD->getTemplatedDecl());
3543 llvm::append_range(DeclContexts, CTD->specializations());
3544 continue;
3545 }
3546 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3547 DeclContexts.push_back(DC);
3548 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3549 F->addAttr(AA);
3550 continue;
3551 }
3552 }
3553 }
3554}
3555
3557 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3558 OMPAssumeScoped.pop_back();
3559}
3560
3563 ArrayRef<OMPClause *> ClauseList) {
3564 /// For target specific clauses, the requires directive cannot be
3565 /// specified after the handling of any of the target regions in the
3566 /// current compilation unit.
3567 ArrayRef<SourceLocation> TargetLocations =
3568 DSAStack->getEncounteredTargetLocs();
3569 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3570 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3571 for (const OMPClause *CNew : ClauseList) {
3572 // Check if any of the requires clauses affect target regions.
3573 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3574 isa<OMPUnifiedAddressClause>(CNew) ||
3575 isa<OMPReverseOffloadClause>(CNew) ||
3576 isa<OMPDynamicAllocatorsClause>(CNew)) {
3577 Diag(Loc, diag::err_omp_directive_before_requires)
3578 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3579 for (SourceLocation TargetLoc : TargetLocations) {
3580 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3581 << "target";
3582 }
3583 } else if (!AtomicLoc.isInvalid() &&
3584 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3585 Diag(Loc, diag::err_omp_directive_before_requires)
3586 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3587 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3588 << "atomic";
3589 }
3590 }
3591 }
3592
3593 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3595 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3596 return nullptr;
3597}
3598
3599static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3600 const ValueDecl *D,
3601 const DSAStackTy::DSAVarData &DVar,
3602 bool IsLoopIterVar) {
3603 if (DVar.RefExpr) {
3604 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3605 << getOpenMPClauseName(DVar.CKind);
3606 return;
3607 }
3608 enum {
3609 PDSA_StaticMemberShared,
3610 PDSA_StaticLocalVarShared,
3611 PDSA_LoopIterVarPrivate,
3612 PDSA_LoopIterVarLinear,
3613 PDSA_LoopIterVarLastprivate,
3614 PDSA_ConstVarShared,
3615 PDSA_GlobalVarShared,
3616 PDSA_TaskVarFirstprivate,
3617 PDSA_LocalVarPrivate,
3618 PDSA_Implicit
3619 } Reason = PDSA_Implicit;
3620 bool ReportHint = false;
3621 auto ReportLoc = D->getLocation();
3622 auto *VD = dyn_cast<VarDecl>(D);
3623 if (IsLoopIterVar) {
3624 if (DVar.CKind == OMPC_private)
3625 Reason = PDSA_LoopIterVarPrivate;
3626 else if (DVar.CKind == OMPC_lastprivate)
3627 Reason = PDSA_LoopIterVarLastprivate;
3628 else
3629 Reason = PDSA_LoopIterVarLinear;
3630 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3631 DVar.CKind == OMPC_firstprivate) {
3632 Reason = PDSA_TaskVarFirstprivate;
3633 ReportLoc = DVar.ImplicitDSALoc;
3634 } else if (VD && VD->isStaticLocal())
3635 Reason = PDSA_StaticLocalVarShared;
3636 else if (VD && VD->isStaticDataMember())
3637 Reason = PDSA_StaticMemberShared;
3638 else if (VD && VD->isFileVarDecl())
3639 Reason = PDSA_GlobalVarShared;
3640 else if (D->getType().isConstant(SemaRef.getASTContext()))
3641 Reason = PDSA_ConstVarShared;
3642 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3643 ReportHint = true;
3644 Reason = PDSA_LocalVarPrivate;
3645 }
3646 if (Reason != PDSA_Implicit) {
3647 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3648 << Reason << ReportHint
3649 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3650 } else if (DVar.ImplicitDSALoc.isValid()) {
3651 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3652 << getOpenMPClauseName(DVar.CKind);
3653 }
3654}
3655
3658 bool IsAggregateOrDeclareTarget) {
3660 switch (M) {
3661 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3662 Kind = OMPC_MAP_alloc;
3663 break;
3664 case OMPC_DEFAULTMAP_MODIFIER_to:
3665 Kind = OMPC_MAP_to;
3666 break;
3667 case OMPC_DEFAULTMAP_MODIFIER_from:
3668 Kind = OMPC_MAP_from;
3669 break;
3670 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3671 Kind = OMPC_MAP_tofrom;
3672 break;
3673 case OMPC_DEFAULTMAP_MODIFIER_present:
3674 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3675 // If implicit-behavior is present, each variable referenced in the
3676 // construct in the category specified by variable-category is treated as if
3677 // it had been listed in a map clause with the map-type of alloc and
3678 // map-type-modifier of present.
3679 Kind = OMPC_MAP_alloc;
3680 break;
3681 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3683 llvm_unreachable("Unexpected defaultmap implicit behavior");
3684 case OMPC_DEFAULTMAP_MODIFIER_none:
3685 case OMPC_DEFAULTMAP_MODIFIER_default:
3687 // IsAggregateOrDeclareTarget could be true if:
3688 // 1. the implicit behavior for aggregate is tofrom
3689 // 2. it's a declare target link
3690 if (IsAggregateOrDeclareTarget) {
3691 Kind = OMPC_MAP_tofrom;
3692 break;
3693 }
3694 llvm_unreachable("Unexpected defaultmap implicit behavior");
3695 }
3696 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3697 return Kind;
3698}
3699
3700namespace {
3701class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3702 DSAStackTy *Stack;
3703 Sema &SemaRef;
3704 bool ErrorFound = false;
3705 bool TryCaptureCXXThisMembers = false;
3706 CapturedStmt *CS = nullptr;
3707 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3708 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3709 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3710 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3712 ImplicitMapModifier[DefaultmapKindNum];
3713 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3714 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3715
3716 void VisitSubCaptures(OMPExecutableDirective *S) {
3717 // Check implicitly captured variables.
3718 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3719 return;
3720 if (S->getDirectiveKind() == OMPD_atomic ||
3721 S->getDirectiveKind() == OMPD_critical ||
3722 S->getDirectiveKind() == OMPD_section ||
3723 S->getDirectiveKind() == OMPD_master ||
3724 S->getDirectiveKind() == OMPD_masked ||
3725 S->getDirectiveKind() == OMPD_scope ||
3726 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3727 Visit(S->getAssociatedStmt());
3728 return;
3729 }
3730 visitSubCaptures(S->getInnermostCapturedStmt());
3731 // Try to capture inner this->member references to generate correct mappings
3732 // and diagnostics.
3733 if (TryCaptureCXXThisMembers ||
3734 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3735 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3736 [](const CapturedStmt::Capture &C) {
3737 return C.capturesThis();
3738 }))) {
3739 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3740 TryCaptureCXXThisMembers = true;
3741 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3742 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3743 }
3744 // In tasks firstprivates are not captured anymore, need to analyze them
3745 // explicitly.
3746 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3747 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3748 for (OMPClause *C : S->clauses())
3749 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3750 for (Expr *Ref : FC->varlists())
3751 Visit(Ref);
3752 }
3753 }
3754 }
3755
3756public:
3757 void VisitDeclRefExpr(DeclRefExpr *E) {
3758 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3762 return;
3763 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3764 // Check the datasharing rules for the expressions in the clauses.
3765 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3766 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3767 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3768 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3769 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3770 Visit(CED->getInit());
3771 return;
3772 }
3773 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3774 // Do not analyze internal variables and do not enclose them into
3775 // implicit clauses.
3776 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3777 return;
3778 VD = VD->getCanonicalDecl();
3779 // Skip internally declared variables.
3780 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3781 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3782 !Stack->isImplicitTaskFirstprivate(VD))
3783 return;
3784 // Skip allocators in uses_allocators clauses.
3785 if (Stack->isUsesAllocatorsDecl(VD))
3786 return;
3787
3788 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3789 // Check if the variable has explicit DSA set and stop analysis if it so.
3790 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3791 return;
3792
3793 // Skip internally declared static variables.
3794 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3795 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3796 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3797 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3798 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3799 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3800 !Stack->isImplicitTaskFirstprivate(VD))
3801 return;
3802
3803 SourceLocation ELoc = E->getExprLoc();
3804 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3805 // The default(none) clause requires that each variable that is referenced
3806 // in the construct, and does not have a predetermined data-sharing
3807 // attribute, must have its data-sharing attribute explicitly determined
3808 // by being listed in a data-sharing attribute clause.
3809 if (DVar.CKind == OMPC_unknown &&
3810 (Stack->getDefaultDSA() == DSA_none ||
3811 Stack->getDefaultDSA() == DSA_private ||
3812 Stack->getDefaultDSA() == DSA_firstprivate) &&
3813 isImplicitOrExplicitTaskingRegion(DKind) &&
3814 VarsWithInheritedDSA.count(VD) == 0) {
3815 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3816 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3817 Stack->getDefaultDSA() == DSA_private)) {
3818 DSAStackTy::DSAVarData DVar =
3819 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3820 InheritedDSA = DVar.CKind == OMPC_unknown;
3821 }
3822 if (InheritedDSA)
3823 VarsWithInheritedDSA[VD] = E;
3824 if (Stack->getDefaultDSA() == DSA_none)
3825 return;
3826 }
3827
3828 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3829 // If implicit-behavior is none, each variable referenced in the
3830 // construct that does not have a predetermined data-sharing attribute
3831 // and does not appear in a to or link clause on a declare target
3832 // directive must be listed in a data-mapping attribute clause, a
3833 // data-sharing attribute clause (including a data-sharing attribute
3834 // clause on a combined construct where target. is one of the
3835 // constituent constructs), or an is_device_ptr clause.
3836 OpenMPDefaultmapClauseKind ClauseKind =
3838 if (SemaRef.getLangOpts().OpenMP >= 50) {
3839 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3840 OMPC_DEFAULTMAP_MODIFIER_none;
3841 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3842 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3843 // Only check for data-mapping attribute and is_device_ptr here
3844 // since we have already make sure that the declaration does not
3845 // have a data-sharing attribute above
3846 if (!Stack->checkMappableExprComponentListsForDecl(
3847 VD, /*CurrentRegionOnly=*/true,
3849 MapExprComponents,
3851 auto MI = MapExprComponents.rbegin();
3852 auto ME = MapExprComponents.rend();
3853 return MI != ME && MI->getAssociatedDeclaration() == VD;
3854 })) {
3855 VarsWithInheritedDSA[VD] = E;
3856 return;
3857 }
3858 }
3859 }
3860 if (SemaRef.getLangOpts().OpenMP > 50) {
3861 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3862 OMPC_DEFAULTMAP_MODIFIER_present;
3863 if (IsModifierPresent) {
3864 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3865 OMPC_MAP_MODIFIER_present)) {
3866 ImplicitMapModifier[ClauseKind].push_back(
3867 OMPC_MAP_MODIFIER_present);
3868 }
3869 }
3870 }
3871
3873 !Stack->isLoopControlVariable(VD).first) {
3874 if (!Stack->checkMappableExprComponentListsForDecl(
3875 VD, /*CurrentRegionOnly=*/true,
3877 StackComponents,
3879 if (SemaRef.LangOpts.OpenMP >= 50)
3880 return !StackComponents.empty();
3881 // Variable is used if it has been marked as an array, array
3882 // section, array shaping or the variable iself.
3883 return StackComponents.size() == 1 ||
3884 llvm::all_of(
3885 llvm::drop_begin(llvm::reverse(StackComponents)),
3886 [](const OMPClauseMappableExprCommon::
3887 MappableComponent &MC) {
3888 return MC.getAssociatedDeclaration() ==
3889 nullptr &&
3890 (isa<ArraySectionExpr>(
3891 MC.getAssociatedExpression()) ||
3892 isa<OMPArrayShapingExpr>(
3893 MC.getAssociatedExpression()) ||
3894 isa<ArraySubscriptExpr>(
3895 MC.getAssociatedExpression()));
3896 });
3897 })) {
3898 bool IsFirstprivate = false;
3899 // By default lambdas are captured as firstprivates.
3900 if (const auto *RD =
3902 IsFirstprivate = RD->isLambda();
3903 IsFirstprivate =
3904 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3905 if (IsFirstprivate) {
3906 ImplicitFirstprivate.emplace_back(E);
3907 } else {
3909 Stack->getDefaultmapModifier(ClauseKind);
3911 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3912 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3913 }
3914 return;
3915 }
3916 }
3917
3918 // OpenMP [2.9.3.6, Restrictions, p.2]
3919 // A list item that appears in a reduction clause of the innermost
3920 // enclosing worksharing or parallel construct may not be accessed in an
3921 // explicit task.
3922 DVar = Stack->hasInnermostDSA(
3923 VD,
3924 [](OpenMPClauseKind C, bool AppliedToPointee) {
3925 return C == OMPC_reduction && !AppliedToPointee;
3926 },
3927 [](OpenMPDirectiveKind K) {
3928 return isOpenMPParallelDirective(K) ||
3930 },
3931 /*FromParent=*/true);
3932 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3933 ErrorFound = true;
3934 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3935 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3936 return;
3937 }
3938
3939 // Define implicit data-sharing attributes for task.
3940 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3941 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3942 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3943 DVar.CKind == OMPC_firstprivate) ||
3944 (Stack->getDefaultDSA() == DSA_private &&
3945 DVar.CKind == OMPC_private)) &&
3946 !DVar.RefExpr)) &&
3947 !Stack->isLoopControlVariable(VD).first) {
3948 if (Stack->getDefaultDSA() == DSA_private)
3949 ImplicitPrivate.push_back(E);
3950 else
3951 ImplicitFirstprivate.push_back(E);
3952 return;
3953 }
3954
3955 // Store implicitly used globals with declare target link for parent
3956 // target.
3957 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3958 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3959 Stack->addToParentTargetRegionLinkGlobals(E);
3960 return;
3961 }
3962 }
3963 }
3964 void VisitMemberExpr(MemberExpr *E) {
3965 if (E->isTypeDependent() || E->isValueDependent() ||
3967 return;
3968 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3969 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3970 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3971 if (!FD)
3972 return;
3973 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3974 // Check if the variable has explicit DSA set and stop analysis if it
3975 // so.
3976 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3977 return;
3978
3980 !Stack->isLoopControlVariable(FD).first &&
3981 !Stack->checkMappableExprComponentListsForDecl(
3982 FD, /*CurrentRegionOnly=*/true,
3984 StackComponents,
3986 return isa<CXXThisExpr>(
3987 cast<MemberExpr>(
3988 StackComponents.back().getAssociatedExpression())
3989 ->getBase()
3990 ->IgnoreParens());
3991 })) {
3992 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3993 // A bit-field cannot appear in a map clause.
3994 //
3995 if (FD->isBitField())
3996 return;
3997
3998 // Check to see if the member expression is referencing a class that
3999 // has already been explicitly mapped
4000 if (Stack->isClassPreviouslyMapped(TE->getType()))
4001 return;
4002
4004 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4005 OpenMPDefaultmapClauseKind ClauseKind =
4008 Modifier, /*IsAggregateOrDeclareTarget*/ true);
4009 ImplicitMap[ClauseKind][Kind].emplace_back(E);
4010 return;
4011 }
4012
4013 SourceLocation ELoc = E->getExprLoc();
4014 // OpenMP [2.9.3.6, Restrictions, p.2]
4015 // A list item that appears in a reduction clause of the innermost
4016 // enclosing worksharing or parallel construct may not be accessed in
4017 // an explicit task.
4018 DVar = Stack->hasInnermostDSA(
4019 FD,
4020 [](OpenMPClauseKind C, bool AppliedToPointee) {
4021 return C == OMPC_reduction && !AppliedToPointee;
4022 },
4023 [](OpenMPDirectiveKind K) {
4024 return isOpenMPParallelDirective(K) ||
4026 },
4027 /*FromParent=*/true);
4028 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4029 ErrorFound = true;
4030 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4031 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4032 return;
4033 }
4034
4035 // Define implicit data-sharing attributes for task.
4036 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4037 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4038 !Stack->isLoopControlVariable(FD).first) {
4039 // Check if there is a captured expression for the current field in the
4040 // region. Do not mark it as firstprivate unless there is no captured
4041 // expression.
4042 // TODO: try to make it firstprivate.
4043 if (DVar.CKind != OMPC_unknown)
4044 ImplicitFirstprivate.push_back(E);
4045 }
4046 return;
4047 }
4050 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4051 Stack->getCurrentDirective(),
4052 /*NoDiagnose=*/true))
4053 return;
4054 const auto *VD = cast<ValueDecl>(
4055 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4056 if (!Stack->checkMappableExprComponentListsForDecl(
4057 VD, /*CurrentRegionOnly=*/true,
4058 [&CurComponents](
4060 StackComponents,
4062 auto CCI = CurComponents.rbegin();
4063 auto CCE = CurComponents.rend();
4064 for (const auto &SC : llvm::reverse(StackComponents)) {
4065 // Do both expressions have the same kind?
4066 if (CCI->getAssociatedExpression()->getStmtClass() !=
4067 SC.getAssociatedExpression()->getStmtClass())
4068 if (!((isa<ArraySectionExpr>(
4069 SC.getAssociatedExpression()) ||
4070 isa<OMPArrayShapingExpr>(
4071 SC.getAssociatedExpression())) &&
4072 isa<ArraySubscriptExpr>(
4073 CCI->getAssociatedExpression())))
4074 return false;
4075
4076 const Decl *CCD = CCI->getAssociatedDeclaration();
4077 const Decl *SCD = SC.getAssociatedDeclaration();
4078 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4079 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4080 if (SCD != CCD)
4081 return false;
4082 std::advance(CCI, 1);
4083 if (CCI == CCE)
4084 break;
4085 }
4086 return true;
4087 })) {
4088 Visit(E->getBase());
4089 }
4090 } else if (!TryCaptureCXXThisMembers) {
4091 Visit(E->getBase());
4092 }
4093 }
4094 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4095 for (OMPClause *C : S->clauses()) {
4096 // Skip analysis of arguments of private clauses for task|target
4097 // directives.
4098 if (isa_and_nonnull<OMPPrivateClause>(C))
4099 continue;
4100 // Skip analysis of arguments of implicitly defined firstprivate clause
4101 // for task|target directives.
4102 // Skip analysis of arguments of implicitly defined map clause for target
4103 // directives.
4104 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4105 C->isImplicit() &&
4106 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4107 for (Stmt *CC : C->children()) {
4108 if (CC)
4109 Visit(CC);
4110 }
4111 }
4112 }
4113 // Check implicitly captured variables.
4114 VisitSubCaptures(S);
4115 }
4116
4117 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4118 // Loop transformation directives do not introduce data sharing
4119 VisitStmt(S);
4120 }
4121
4122 void VisitCallExpr(CallExpr *S) {
4123 for (Stmt *C : S->arguments()) {
4124 if (C) {
4125 // Check implicitly captured variables in the task-based directives to
4126 // check if they must be firstprivatized.
4127 Visit(C);
4128 }
4129 }
4130 if (Expr *Callee = S->getCallee()) {
4131 auto *CI = Callee->IgnoreParenImpCasts();
4132 if (auto *CE = dyn_cast<MemberExpr>(CI))
4133 Visit(CE->getBase());
4134 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4135 Visit(CE);
4136 }
4137 }
4138 void VisitStmt(Stmt *S) {
4139 for (Stmt *C : S->children()) {
4140 if (C) {
4141 // Check implicitly captured variables in the task-based directives to
4142 // check if they must be firstprivatized.
4143 Visit(C);
4144 }
4145 }
4146 }
4147
4148 void visitSubCaptures(CapturedStmt *S) {
4149 for (const CapturedStmt::Capture &Cap : S->captures()) {
4150 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4151 continue;
4152 VarDecl *VD = Cap.getCapturedVar();
4153 // Do not try to map the variable if it or its sub-component was mapped
4154 // already.
4155 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4156 Stack->checkMappableExprComponentListsForDecl(
4157 VD, /*CurrentRegionOnly=*/true,
4159 OpenMPClauseKind) { return true; }))
4160 continue;
4162 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4163 Cap.getLocation(), /*RefersToCapture=*/true);
4164 Visit(DRE);
4165 }
4166 }
4167 bool isErrorFound() const { return ErrorFound; }
4168 ArrayRef<Expr *> getImplicitFirstprivate() const {
4169 return ImplicitFirstprivate;
4170 }
4171 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4173 OpenMPMapClauseKind MK) const {
4174 return ImplicitMap[DK][MK];
4175 }
4177 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4178 return ImplicitMapModifier[Kind];
4179 }
4180 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4181 return VarsWithInheritedDSA;
4182 }
4183
4184 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4185 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4186 // Process declare target link variables for the target directives.
4187 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4188 for (DeclRefExpr *E : Stack->getLinkGlobals())
4189 Visit(E);
4190 }
4191 }
4192};
4193} // namespace
4194
4195static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4196 OpenMPDirectiveKind DKind,
4197 bool ScopeEntry) {
4200 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4201 if (isOpenMPTeamsDirective(DKind))
4202 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4203 if (isOpenMPParallelDirective(DKind))
4204 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4206 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4207 if (isOpenMPSimdDirective(DKind))
4208 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4209 Stack->handleConstructTrait(Traits, ScopeEntry);
4210}
4211
4213 Scope *CurScope) {
4214 ASTContext &Context = getASTContext();
4215 switch (DKind) {
4216 case OMPD_parallel:
4217 case OMPD_parallel_for:
4218 case OMPD_parallel_for_simd:
4219 case OMPD_parallel_sections:
4220 case OMPD_parallel_master:
4221 case OMPD_parallel_masked:
4222 case OMPD_parallel_loop:
4223 case OMPD_teams:
4224 case OMPD_teams_distribute:
4225 case OMPD_teams_distribute_simd: {
4226 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4227 QualType KmpInt32PtrTy =
4228 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4230 std::make_pair(".global_tid.", KmpInt32PtrTy),
4231 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4232 std::make_pair(StringRef(), QualType()) // __context with shared vars
4233 };
4234 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4235 CR_OpenMP, Params);
4236 break;
4237 }
4238 case OMPD_target_teams:
4239 case OMPD_target_parallel:
4240 case OMPD_target_parallel_for:
4241 case OMPD_target_parallel_for_simd:
4242 case OMPD_target_parallel_loop:
4243 case OMPD_target_teams_distribute:
4244 case OMPD_target_teams_distribute_simd: {
4245 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4246 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4247 QualType KmpInt32PtrTy =
4248 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4249 QualType Args[] = {VoidPtrTy};
4251 EPI.Variadic = true;
4252 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4254 std::make_pair(".global_tid.", KmpInt32Ty),
4255 std::make_pair(".part_id.", KmpInt32PtrTy),
4256 std::make_pair(".privates.", VoidPtrTy),
4257 std::make_pair(
4258 ".copy_fn.",
4259 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4260 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4261 std::make_pair(StringRef(), QualType()) // __context with shared vars
4262 };
4263 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4264 CR_OpenMP, Params,
4265 /*OpenMPCaptureLevel=*/0);
4266 // Mark this captured region as inlined, because we don't use outlined
4267 // function directly.
4269 AlwaysInlineAttr::CreateImplicit(
4270 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4272 if (getLangOpts().OpenMPIsTargetDevice)
4273 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4274 ParamsTarget.push_back(
4275 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4276 // Start a captured region for 'target' with no implicit parameters.
4277 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4278 CR_OpenMP, ParamsTarget,
4279 /*OpenMPCaptureLevel=*/1);
4280 SemaOpenMP::CapturedParamNameType ParamsTeamsOrParallel[] = {
4281 std::make_pair(".global_tid.", KmpInt32PtrTy),
4282 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4283 std::make_pair(StringRef(), QualType()) // __context with shared vars
4284 };
4285 // Start a captured region for 'teams' or 'parallel'. Both regions have
4286 // the same implicit parameters.
4287 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4288 CR_OpenMP, ParamsTeamsOrParallel,
4289 /*OpenMPCaptureLevel=*/2);
4290 break;
4291 }
4292 case OMPD_target:
4293 case OMPD_target_simd: {
4294 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4295 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4296 QualType KmpInt32PtrTy =
4297 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4298 QualType Args[] = {VoidPtrTy};
4300 EPI.Variadic = true;
4301 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4303 std::make_pair(".global_tid.", KmpInt32Ty),
4304 std::make_pair(".part_id.", KmpInt32PtrTy),
4305 std::make_pair(".privates.", VoidPtrTy),
4306 std::make_pair(
4307 ".copy_fn.",
4308 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4309 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4310 std::make_pair(StringRef(), QualType()) // __context with shared vars
4311 };
4312 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4313 CR_OpenMP, Params,
4314 /*OpenMPCaptureLevel=*/0);
4315 // Mark this captured region as inlined, because we don't use outlined
4316 // function directly.
4318 AlwaysInlineAttr::CreateImplicit(
4319 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4321 if (getLangOpts().OpenMPIsTargetDevice)
4322 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4323 ParamsTarget.push_back(
4324 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4325 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4326 CR_OpenMP, ParamsTarget,
4327 /*OpenMPCaptureLevel=*/1);
4328 break;
4329 }
4330 case OMPD_atomic:
4331 case OMPD_critical:
4332 case OMPD_section:
4333 case OMPD_master:
4334 case OMPD_masked:
4335 case OMPD_tile:
4336 case OMPD_unroll:
4337 break;
4338 case OMPD_loop:
4339 // TODO: 'loop' may require additional parameters depending on the binding.
4340 // Treat similar to OMPD_simd/OMPD_for for now.
4341 case OMPD_simd:
4342 case OMPD_for:
4343 case OMPD_for_simd:
4344 case OMPD_sections:
4345 case OMPD_single:
4346 case OMPD_taskgroup:
4347 case OMPD_distribute:
4348 case OMPD_distribute_simd:
4349 case OMPD_ordered:
4350 case OMPD_scope:
4351 case OMPD_target_data:
4352 case OMPD_dispatch: {
4354 std::make_pair(StringRef(), QualType()) // __context with shared vars
4355 };
4356 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4357 CR_OpenMP, Params);
4358 break;
4359 }
4360 case OMPD_task: {
4361 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4362 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4363 QualType KmpInt32PtrTy =
4364 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4365 QualType Args[] = {VoidPtrTy};
4367 EPI.Variadic = true;
4368 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4370 std::make_pair(".global_tid.", KmpInt32Ty),
4371 std::make_pair(".part_id.", KmpInt32PtrTy),
4372 std::make_pair(".privates.", VoidPtrTy),
4373 std::make_pair(
4374 ".copy_fn.",
4375 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4376 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4377 std::make_pair(StringRef(), QualType()) // __context with shared vars
4378 };
4379 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4380 CR_OpenMP, Params);
4381 // Mark this captured region as inlined, because we don't use outlined
4382 // function directly.
4384 AlwaysInlineAttr::CreateImplicit(
4385 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4386 break;
4387 }
4388 case OMPD_taskloop:
4389 case OMPD_taskloop_simd:
4390 case OMPD_master_taskloop:
4391 case OMPD_masked_taskloop:
4392 case OMPD_masked_taskloop_simd:
4393 case OMPD_master_taskloop_simd: {
4394 QualType KmpInt32Ty =
4395 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4396 .withConst();
4397 QualType KmpUInt64Ty =
4398 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4399 .withConst();
4400 QualType KmpInt64Ty =
4401 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4402 .withConst();
4403 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4404 QualType KmpInt32PtrTy =
4405 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4406 QualType Args[] = {VoidPtrTy};
4408 EPI.Variadic = true;
4409 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4411 std::make_pair(".global_tid.", KmpInt32Ty),
4412 std::make_pair(".part_id.", KmpInt32PtrTy),
4413 std::make_pair(".privates.", VoidPtrTy),
4414 std::make_pair(
4415 ".copy_fn.",
4416 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4417 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4418 std::make_pair(".lb.", KmpUInt64Ty),
4419 std::make_pair(".ub.", KmpUInt64Ty),
4420 std::make_pair(".st.", KmpInt64Ty),
4421 std::make_pair(".liter.", KmpInt32Ty),
4422 std::make_pair(".reductions.", VoidPtrTy),
4423 std::make_pair(StringRef(), QualType()) // __context with shared vars
4424 };
4425 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4426 CR_OpenMP, Params);
4427 // Mark this captured region as inlined, because we don't use outlined
4428 // function directly.
4430 AlwaysInlineAttr::CreateImplicit(
4431 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4432 break;
4433 }
4434 case OMPD_parallel_masked_taskloop:
4435 case OMPD_parallel_masked_taskloop_simd:
4436 case OMPD_parallel_master_taskloop:
4437 case OMPD_parallel_master_taskloop_simd: {
4438 QualType KmpInt32Ty =
4439 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1)
4440 .withConst();
4441 QualType KmpUInt64Ty =
4442 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0)
4443 .withConst();
4444 QualType KmpInt64Ty =
4445 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1)
4446 .withConst();
4447 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4448 QualType KmpInt32PtrTy =
4449 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4450 SemaOpenMP::CapturedParamNameType ParamsParallel[] = {
4451 std::make_pair(".global_tid.", KmpInt32PtrTy),
4452 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4453 std::make_pair(StringRef(), QualType()) // __context with shared vars
4454 };
4455 // Start a captured region for 'parallel'.
4456 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4457 CR_OpenMP, ParamsParallel,
4458 /*OpenMPCaptureLevel=*/0);
4459 QualType Args[] = {VoidPtrTy};
4461 EPI.Variadic = true;
4462 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4464 std::make_pair(".global_tid.", KmpInt32Ty),
4465 std::make_pair(".part_id.", KmpInt32PtrTy),
4466 std::make_pair(".privates.", VoidPtrTy),
4467 std::make_pair(
4468 ".copy_fn.",
4469 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4470 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4471 std::make_pair(".lb.", KmpUInt64Ty),
4472 std::make_pair(".ub.", KmpUInt64Ty),
4473 std::make_pair(".st.", KmpInt64Ty),
4474 std::make_pair(".liter.", KmpInt32Ty),
4475 std::make_pair(".reductions.", VoidPtrTy),
4476 std::make_pair(StringRef(), QualType()) // __context with shared vars
4477 };
4478 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4479 CR_OpenMP, Params,
4480 /*OpenMPCaptureLevel=*/1);
4481 // Mark this captured region as inlined, because we don't use outlined
4482 // function directly.
4484 AlwaysInlineAttr::CreateImplicit(
4485 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4486 break;
4487 }
4488 case OMPD_distribute_parallel_for_simd:
4489 case OMPD_distribute_parallel_for: {
4490 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4491 QualType KmpInt32PtrTy =
4492 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4494 std::make_pair(".global_tid.", KmpInt32PtrTy),
4495 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4496 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4497 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4498 std::make_pair(StringRef(), QualType()) // __context with shared vars
4499 };
4500 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4501 CR_OpenMP, Params);
4502 break;
4503 }
4504 // For 'target teams loop', collect all captured regions so codegen can
4505 // later decide the best IR to emit given the associated loop-nest.
4506 case OMPD_target_teams_loop:
4507 case OMPD_target_teams_distribute_parallel_for:
4508 case OMPD_target_teams_distribute_parallel_for_simd: {
4509 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4510 QualType KmpInt32PtrTy =
4511 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4512 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4513
4514 QualType Args[] = {VoidPtrTy};
4516 EPI.Variadic = true;
4517 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4519 std::make_pair(".global_tid.", KmpInt32Ty),
4520 std::make_pair(".part_id.", KmpInt32PtrTy),
4521 std::make_pair(".privates.", VoidPtrTy),
4522 std::make_pair(
4523 ".copy_fn.",
4524 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4525 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4526 std::make_pair(StringRef(), QualType()) // __context with shared vars
4527 };
4528 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4529 CR_OpenMP, Params,
4530 /*OpenMPCaptureLevel=*/0);
4531 // Mark this captured region as inlined, because we don't use outlined
4532 // function directly.
4534 AlwaysInlineAttr::CreateImplicit(
4535 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4537 if (getLangOpts().OpenMPIsTargetDevice)
4538 ParamsTarget.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4539 ParamsTarget.push_back(
4540 std::make_pair(StringRef(), QualType())); // __context with shared vars;
4541 // Start a captured region for 'target' with no implicit parameters.
4542 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4543 CR_OpenMP, ParamsTarget,
4544 /*OpenMPCaptureLevel=*/1);
4545
4546 SemaOpenMP::CapturedParamNameType ParamsTeams[] = {
4547 std::make_pair(".global_tid.", KmpInt32PtrTy),
4548 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4549 std::make_pair(StringRef(), QualType()) // __context with shared vars
4550 };
4551 // Start a captured region for 'target' with no implicit parameters.
4552 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4553 CR_OpenMP, ParamsTeams,
4554 /*OpenMPCaptureLevel=*/2);
4555
4556 SemaOpenMP::CapturedParamNameType ParamsParallel[] = {
4557 std::make_pair(".global_tid.", KmpInt32PtrTy),
4558 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4559 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4560 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4561 std::make_pair(StringRef(), QualType()) // __context with shared vars
4562 };
4563 // Start a captured region for 'teams' or 'parallel'. Both regions have
4564 // the same implicit parameters.
4565 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4566 CR_OpenMP, ParamsParallel,
4567 /*OpenMPCaptureLevel=*/3);
4568 break;
4569 }
4570
4571 case OMPD_teams_loop:
4572 case OMPD_teams_distribute_parallel_for:
4573 case OMPD_teams_distribute_parallel_for_simd: {
4574 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4575 QualType KmpInt32PtrTy =
4576 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4577
4578 SemaOpenMP::CapturedParamNameType ParamsTeams[] = {
4579 std::make_pair(".global_tid.", KmpInt32PtrTy),
4580 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4581 std::make_pair(StringRef(), QualType()) // __context with shared vars
4582 };
4583 // Start a captured region for 'target' with no implicit parameters.
4584 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4585 CR_OpenMP, ParamsTeams,
4586 /*OpenMPCaptureLevel=*/0);
4587
4588 SemaOpenMP::CapturedParamNameType ParamsParallel[] = {
4589 std::make_pair(".global_tid.", KmpInt32PtrTy),
4590 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4591 std::make_pair(".previous.lb.", Context.getSizeType().withConst()),
4592 std::make_pair(".previous.ub.", Context.getSizeType().withConst()),
4593 std::make_pair(StringRef(), QualType()) // __context with shared vars
4594 };
4595 // Start a captured region for 'teams' or 'parallel'. Both regions have
4596 // the same implicit parameters.
4597 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4598 CR_OpenMP, ParamsParallel,
4599 /*OpenMPCaptureLevel=*/1);
4600 break;
4601 }
4602 case OMPD_target_update:
4603 case OMPD_target_enter_data:
4604 case OMPD_target_exit_data: {
4605 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4606 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4607 QualType KmpInt32PtrTy =
4608 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4609 QualType Args[] = {VoidPtrTy};
4611 EPI.Variadic = true;
4612 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4614 std::make_pair(".global_tid.", KmpInt32Ty),
4615 std::make_pair(".part_id.", KmpInt32PtrTy),
4616 std::make_pair(".privates.", VoidPtrTy),
4617 std::make_pair(
4618 ".copy_fn.",
4619 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4620 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4621 std::make_pair(StringRef(), QualType()) // __context with shared vars
4622 };
4623 SemaRef.ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope,
4624 CR_OpenMP, Params);
4625 // Mark this captured region as inlined, because we don't use outlined
4626 // function directly.
4628 AlwaysInlineAttr::CreateImplicit(
4629 Context, {}, AlwaysInlineAttr::Keyword_forceinline));
4630 break;
4631 }
4632 case OMPD_threadprivate:
4633 case OMPD_allocate:
4634 case OMPD_taskyield:
4635 case OMPD_error:
4636 case OMPD_barrier:
4637 case OMPD_taskwait:
4638 case OMPD_cancellation_point:
4639 case OMPD_cancel:
4640 case OMPD_flush:
4641 case OMPD_depobj:
4642 case OMPD_scan:
4643 case OMPD_declare_reduction:
4644 case OMPD_declare_mapper:
4645 case OMPD_declare_simd:
4646 case OMPD_declare_target:
4647 case OMPD_end_declare_target:
4648 case OMPD_requires:
4649 case OMPD_declare_variant:
4650 case OMPD_begin_declare_variant:
4651 case OMPD_end_declare_variant:
4652 case OMPD_metadirective:
4653 llvm_unreachable("OpenMP Directive is not allowed");
4654 case OMPD_unknown:
4655 default:
4656 llvm_unreachable("Unknown OpenMP directive");
4657 }
4658 DSAStack->setContext(SemaRef.CurContext);
4659 handleDeclareVariantConstructTrait(DSAStack, DKind, /* ScopeEntry */ true);
4660}
4661
4662int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4663 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4664}
4665
4668 getOpenMPCaptureRegions(CaptureRegions, DKind);
4669 return CaptureRegions.size();
4670}
4671
4673 Expr *CaptureExpr, bool WithInit,
4674 DeclContext *CurContext,
4675 bool AsExpression) {
4676 assert(CaptureExpr);
4677 ASTContext &C = S.getASTContext();
4678 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4679 QualType Ty = Init->getType();
4680 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4681 if (S.getLangOpts().CPlusPlus) {
4682 Ty = C.getLValueReferenceType(Ty);
4683 } else {
4684 Ty = C.getPointerType(Ty);
4685 ExprResult Res =
4686 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4687 if (!Res.isUsable())
4688 return nullptr;
4689 Init = Res.get();
4690 }
4691 WithInit = true;
4692 }
4693 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4694 CaptureExpr->getBeginLoc());
4695 if (!WithInit)
4696 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4697 CurContext->addHiddenDecl(CED);
4699 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4700 return CED;
4701}
4702
4703static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4704 bool WithInit) {
4706 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4707 CD = cast<OMPCapturedExprDecl>(VD);
4708 else
4709 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4710 S.CurContext,
4711 /*AsExpression=*/false);
4712 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4713 CaptureExpr->getExprLoc());
4714}
4715
4716static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4717 StringRef Name) {
4718 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4719 if (!Ref) {
4721 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4722 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4723 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4724 CaptureExpr->getExprLoc());
4725 }
4726 ExprResult Res = Ref;
4727 if (!S.getLangOpts().CPlusPlus &&
4728 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4729 Ref->getType()->isPointerType()) {
4730 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4731 if (!Res.isUsable())
4732 return ExprError();
4733 }
4734 return S.DefaultLvalueConversion(Res.get());
4735}
4736
4737namespace {
4738// OpenMP directives parsed in this section are represented as a
4739// CapturedStatement with an associated statement. If a syntax error
4740// is detected during the parsing of the associated statement, the
4741// compiler must abort processing and close the CapturedStatement.
4742//
4743// Combined directives such as 'target parallel' have more than one
4744// nested CapturedStatements. This RAII ensures that we unwind out
4745// of all the nested CapturedStatements when an error is found.
4746class CaptureRegionUnwinderRAII {
4747private:
4748 Sema &S;
4749 bool &ErrorFound;
4750 OpenMPDirectiveKind DKind = OMPD_unknown;
4751
4752public:
4753 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4754 OpenMPDirectiveKind DKind)
4755 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4756 ~CaptureRegionUnwinderRAII() {
4757 if (ErrorFound) {
4758 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4759 while (--ThisCaptureLevel >= 0)
4761 }
4762 }
4763};
4764} // namespace
4765
4767 // Capture variables captured by reference in lambdas for target-based
4768 // directives.
4770 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4772 DSAStack->getCurrentDirective()))) {
4773 QualType Type = V->getType();
4774 if (const auto *RD = Type.getCanonicalType()
4775 .getNonReferenceType()
4776 ->getAsCXXRecordDecl()) {
4777 bool SavedForceCaptureByReferenceInTargetExecutable =
4778 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4779 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4780 /*V=*/true);
4781 if (RD->isLambda()) {
4782 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4783 FieldDecl *ThisCapture;
4784 RD->getCaptureFields(Captures, ThisCapture);
4785 for (const LambdaCapture &LC : RD->captures()) {
4786 if (LC.getCaptureKind() == LCK_ByRef) {
4787 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4788 DeclContext *VDC = VD->getDeclContext();
4789 if (!VDC->Encloses(SemaRef.CurContext))
4790 continue;
4791 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4792 } else if (LC.getCaptureKind() == LCK_This) {
4794 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4795 ThisTy, ThisCapture->getType()))
4796 SemaRef.CheckCXXThisCapture(LC.getLocation());
4797 }
4798 }
4799 }
4800 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4801 SavedForceCaptureByReferenceInTargetExecutable);
4802 }
4803 }
4804}
4805
4807 const ArrayRef<OMPClause *> Clauses) {
4808 const OMPOrderedClause *Ordered = nullptr;
4809 const OMPOrderClause *Order = nullptr;
4810
4811 for (const OMPClause *Clause : Clauses) {
4812 if (Clause->getClauseKind() == OMPC_ordered)
4813 Ordered = cast<OMPOrderedClause>(Clause);
4814 else if (Clause->getClauseKind() == OMPC_order) {
4815 Order = cast<OMPOrderClause>(Clause);
4816 if (Order->getKind() != OMPC_ORDER_concurrent)
4817 Order = nullptr;
4818 }
4819 if (Ordered && Order)
4820 break;
4821 }
4822
4823 if (Ordered && Order) {
4824 S.Diag(Order->getKindKwLoc(),
4825 diag::err_omp_simple_clause_incompatible_with_ordered)
4826 << getOpenMPClauseName(OMPC_order)
4827 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4828 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4829 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4830 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4831 return true;
4832 }
4833 return false;
4834}
4835
4837 ArrayRef<OMPClause *> Clauses) {
4839 /* ScopeEntry */ false);
4840 if (DSAStack->getCurrentDirective() == OMPD_atomic ||
4841 DSAStack->getCurrentDirective() == OMPD_critical ||
4842 DSAStack->getCurrentDirective() == OMPD_section ||
4843 DSAStack->getCurrentDirective() == OMPD_master ||
4844 DSAStack->getCurrentDirective() == OMPD_masked)
4845 return S;
4846
4847 bool ErrorFound = false;
4848 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4849 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4850 if (!S.isUsable()) {
4851 ErrorFound = true;
4852 return StmtError();
4853 }
4854
4856 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4857 OMPOrderedClause *OC = nullptr;
4858 OMPScheduleClause *SC = nullptr;
4861 // This is required for proper codegen.
4862 for (OMPClause *Clause : Clauses) {
4863 if (!getLangOpts().OpenMPSimd &&
4864 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4865 DSAStack->getCurrentDirective() == OMPD_target) &&
4866 Clause->getClauseKind() == OMPC_in_reduction) {
4867 // Capture taskgroup task_reduction descriptors inside the tasking regions
4868 // with the corresponding in_reduction items.
4869 auto *IRC = cast<OMPInReductionClause>(Clause);
4870 for (Expr *E : IRC->taskgroup_descriptors())
4871 if (E)
4873 }
4874 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4875 Clause->getClauseKind() == OMPC_copyprivate ||
4876 (getLangOpts().OpenMPUseTLS &&
4877 getASTContext().getTargetInfo().isTLSSupported() &&
4878 Clause->getClauseKind() == OMPC_copyin)) {
4879 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4880 // Mark all variables in private list clauses as used in inner region.
4881 for (Stmt *VarRef : Clause->children()) {
4882 if (auto *E = cast_or_null<Expr>(VarRef)) {
4884 }
4885 }
4886 DSAStack->setForceVarCapturing(/*V=*/false);
4888 DSAStack->getCurrentDirective())) {
4889 assert(CaptureRegions.empty() &&
4890 "No captured regions in loop transformation directives.");
4891 } else if (CaptureRegions.size() > 1 ||
4892 CaptureRegions.back() != OMPD_unknown) {
4893 if (auto *C = OMPClauseWithPreInit::get(Clause))
4894 PICs.push_back(C);
4895 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4896 if (Expr *E = C->getPostUpdateExpr())
4898 }
4899 }
4900 if (Clause->getClauseKind() == OMPC_schedule)
4901 SC = cast<OMPScheduleClause>(Clause);
4902 else if (Clause->getClauseKind() == OMPC_ordered)
4903 OC = cast<OMPOrderedClause>(Clause);
4904 else if (Clause->getClauseKind() == OMPC_linear)
4905 LCs.push_back(cast<OMPLinearClause>(Clause));
4906 }
4907 // Capture allocator expressions if used.
4908 for (Expr *E : DSAStack->getInnerAllocators())
4910 // OpenMP, 2.7.1 Loop Construct, Restrictions
4911 // The nonmonotonic modifier cannot be specified if an ordered clause is
4912 // specified.
4913 if (SC &&
4914 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4916 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4917 OC) {
4918 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4921 diag::err_omp_simple_clause_incompatible_with_ordered)
4922 << getOpenMPClauseName(OMPC_schedule)
4923 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4924 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4925 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4926 ErrorFound = true;
4927 }
4928 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4929 // If an order(concurrent) clause is present, an ordered clause may not appear
4930 // on the same directive.
4931 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4932 ErrorFound = true;
4933 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4934 for (const OMPLinearClause *C : LCs) {
4935 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4936 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4937 }
4938 ErrorFound = true;
4939 }
4940 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4941 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4942 OC->getNumForLoops()) {
4943 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4944 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4945 ErrorFound = true;
4946 }
4947 if (ErrorFound) {
4948 return StmtError();
4949 }
4950 StmtResult SR = S;
4951 unsigned CompletedRegions = 0;
4952 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4953 // Mark all variables in private list clauses as used in inner region.
4954 // Required for proper codegen of combined directives.
4955 // TODO: add processing for other clauses.
4956 if (ThisCaptureRegion != OMPD_unknown) {
4957 for (const clang::OMPClauseWithPreInit *C : PICs) {
4958 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4959 // Find the particular capture region for the clause if the
4960 // directive is a combined one with multiple capture regions.
4961 // If the directive is not a combined one, the capture region
4962 // associated with the clause is OMPD_unknown and is generated
4963 // only once.
4964 if (CaptureRegion == ThisCaptureRegion ||
4965 CaptureRegion == OMPD_unknown) {
4966 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4967 for (Decl *D : DS->decls())
4969 cast<VarDecl>(D));
4970 }
4971 }
4972 }
4973 }
4974 if (ThisCaptureRegion == OMPD_target) {
4975 // Capture allocator traits in the target region. They are used implicitly
4976 // and, thus, are not captured by default.
4977 for (OMPClause *C : Clauses) {
4978 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4979 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4980 ++I) {
4981 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4982 if (Expr *E = D.AllocatorTraits)
4984 }
4985 continue;
4986 }
4987 }
4988 }
4989 if (ThisCaptureRegion == OMPD_parallel) {
4990 // Capture temp arrays for inscan reductions and locals in aligned
4991 // clauses.
4992 for (OMPClause *C : Clauses) {
4993 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4994 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4995 continue;
4996 for (Expr *E : RC->copy_array_temps())
4997 if (E)
4999 }
5000 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
5001 for (Expr *E : AC->varlists())
5003 }
5004 }
5005 }
5006 if (++CompletedRegions == CaptureRegions.size())
5007 DSAStack->setBodyComplete();
5009 }
5010 return SR;
5011}
5012
5013static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
5014 OpenMPDirectiveKind CancelRegion,
5015 SourceLocation StartLoc) {
5016 // CancelRegion is only needed for cancel and cancellation_point.
5017 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
5018 return false;
5019
5020 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
5021 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
5022 return false;
5023
5024 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
5025 << getOpenMPDirectiveName(CancelRegion);
5026 return true;
5027}
5028
5029static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
5030 OpenMPDirectiveKind CurrentRegion,
5031 const DeclarationNameInfo &CurrentName,
5032 OpenMPDirectiveKind CancelRegion,
5033 OpenMPBindClauseKind BindKind,
5034 SourceLocation StartLoc) {
5035 if (Stack->getCurScope()) {
5036 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5037 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5038 bool NestingProhibited = false;
5039 bool CloseNesting = true;
5040 bool OrphanSeen = false;
5041 enum {
5042 NoRecommend,
5043 ShouldBeInParallelRegion,
5044 ShouldBeInOrderedRegion,
5045 ShouldBeInTargetRegion,
5046 ShouldBeInTeamsRegion,
5047 ShouldBeInLoopSimdRegion,
5048 } Recommend = NoRecommend;
5049 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
5050 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
5051 CurrentRegion != OMPD_parallel &&
5052 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
5053 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5054 << getOpenMPDirectiveName(CurrentRegion);
5055 return true;
5056 }
5057 if (isOpenMPSimdDirective(ParentRegion) &&
5058 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
5059 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
5060 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5061 CurrentRegion != OMPD_scan))) {
5062 // OpenMP [2.16, Nesting of Regions]
5063 // OpenMP constructs may not be nested inside a simd region.
5064 // OpenMP [2.8.1,simd Construct, Restrictions]
5065 // An ordered construct with the simd clause is the only OpenMP
5066 // construct that can appear in the simd region.
5067 // Allowing a SIMD construct nested in another SIMD construct is an
5068 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5069 // message.
5070 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5071 // The only OpenMP constructs that can be encountered during execution of
5072 // a simd region are the atomic construct, the loop construct, the simd
5073 // construct and the ordered construct with the simd clause.
5074 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5075 ? diag::err_omp_prohibited_region_simd
5076 : diag::warn_omp_nesting_simd)
5077 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
5078 return CurrentRegion != OMPD_simd;
5079 }
5080 if (ParentRegion == OMPD_atomic) {
5081 // OpenMP [2.16, Nesting of Regions]
5082 // OpenMP constructs may not be nested inside an atomic region.
5083 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5084 return true;
5085 }
5086 if (CurrentRegion == OMPD_section) {
5087 // OpenMP [2.7.2, sections Construct, Restrictions]
5088 // Orphaned section directives are prohibited. That is, the section
5089 // directives must appear within the sections construct and must not be
5090 // encountered elsewhere in the sections region.
5091 if (ParentRegion != OMPD_sections &&
5092 ParentRegion != OMPD_parallel_sections) {
5093 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5094 << (ParentRegion != OMPD_unknown)
5095 << getOpenMPDirectiveName(ParentRegion);
5096 return true;
5097 }
5098 return false;
5099 }
5100 // Allow some constructs (except teams and cancellation constructs) to be
5101 // orphaned (they could be used in functions, called from OpenMP regions
5102 // with the required preconditions).
5103 if (ParentRegion == OMPD_unknown &&
5104 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5105 CurrentRegion != OMPD_cancellation_point &&
5106 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5107 return false;
5108 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5109 // for a detailed explanation
5110 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
5111 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5112 (isOpenMPWorksharingDirective(ParentRegion) ||
5113 ParentRegion == OMPD_loop)) {
5114 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5115 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5116 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
5117 << getOpenMPDirectiveName(CurrentRegion);
5118 return true;
5119 }
5120 if (CurrentRegion == OMPD_cancellation_point ||
5121 CurrentRegion == OMPD_cancel) {
5122 // OpenMP [2.16, Nesting of Regions]
5123 // A cancellation point construct for which construct-type-clause is
5124 // taskgroup must be nested inside a task construct. A cancellation
5125 // point construct for which construct-type-clause is not taskgroup must
5126 // be closely nested inside an OpenMP construct that matches the type
5127 // specified in construct-type-clause.
5128 // A cancel construct for which construct-type-clause is taskgroup must be
5129 // nested inside a task construct. A cancel construct for which
5130 // construct-type-clause is not taskgroup must be closely nested inside an
5131 // OpenMP construct that matches the type specified in
5132 // construct-type-clause.
5133 NestingProhibited =
5134 !((CancelRegion == OMPD_parallel &&
5135 (ParentRegion == OMPD_parallel ||
5136 ParentRegion == OMPD_target_parallel)) ||
5137 (CancelRegion == OMPD_for &&
5138 (ParentRegion == OMPD_for || ParentRegion == OMPD_parallel_for ||
5139 ParentRegion == OMPD_target_parallel_for ||
5140 ParentRegion == OMPD_distribute_parallel_for ||
5141 ParentRegion == OMPD_teams_distribute_parallel_for ||
5142 ParentRegion == OMPD_target_teams_distribute_parallel_for)) ||
5143 (CancelRegion == OMPD_taskgroup &&
5144 (ParentRegion == OMPD_task ||
5145 (SemaRef.getLangOpts().OpenMP >= 50 &&
5146 (ParentRegion == OMPD_taskloop ||
5147 ParentRegion == OMPD_master_taskloop ||
5148 ParentRegion == OMPD_masked_taskloop ||
5149 ParentRegion == OMPD_parallel_masked_taskloop ||
5150 ParentRegion == OMPD_parallel_master_taskloop)))) ||
5151 (CancelRegion == OMPD_sections &&
5152 (ParentRegion == OMPD_section || ParentRegion == OMPD_sections ||
5153 ParentRegion == OMPD_parallel_sections)));
5154 OrphanSeen = ParentRegion == OMPD_unknown;
5155 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5156 // OpenMP 5.1 [2.22, Nesting of Regions]
5157 // A masked region may not be closely nested inside a worksharing, loop,
5158 // atomic, task, or taskloop region.
5159 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5160 isOpenMPGenericLoopDirective(ParentRegion) ||
5161 isOpenMPTaskingDirective(ParentRegion);
5162 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5163 // OpenMP [2.16, Nesting of Regions]
5164 // A critical region may not be nested (closely or otherwise) inside a
5165 // critical region with the same name. Note that this restriction is not
5166 // sufficient to prevent deadlock.
5167 SourceLocation PreviousCriticalLoc;
5168 bool DeadLock = Stack->hasDirective(
5169 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5170 const DeclarationNameInfo &DNI,
5172 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5173 PreviousCriticalLoc = Loc;
5174 return true;
5175 }
5176 return false;
5177 },
5178 false /* skip top directive */);
5179 if (DeadLock) {
5180 SemaRef.Diag(StartLoc,
5181 diag::err_omp_prohibited_region_critical_same_name)
5182 << CurrentName.getName();
5183 if (PreviousCriticalLoc.isValid())
5184 SemaRef.Diag(PreviousCriticalLoc,
5185 diag::note_omp_previous_critical_region);
5186 return true;
5187 }
5188 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5189 // OpenMP 5.1 [2.22, Nesting of Regions]
5190 // A scope region may not be closely nested inside a worksharing, loop,
5191 // task, taskloop, critical, ordered, atomic, or masked region.
5192 // OpenMP 5.1 [2.22, Nesting of Regions]
5193 // A barrier region may not be closely nested inside a worksharing, loop,
5194 // task, taskloop, critical, ordered, atomic, or masked region.
5195 NestingProhibited =
5196 isOpenMPWorksharingDirective(ParentRegion) ||
5197 isOpenMPGenericLoopDirective(ParentRegion) ||
5198 isOpenMPTaskingDirective(ParentRegion) ||
5199 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5200 ParentRegion == OMPD_parallel_master ||
5201 ParentRegion == OMPD_parallel_masked ||
5202 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5203 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5204 !isOpenMPParallelDirective(CurrentRegion) &&
5205 !isOpenMPTeamsDirective(CurrentRegion)) {
5206 // OpenMP 5.1 [2.22, Nesting of Regions]
5207 // A loop region that binds to a parallel region or a worksharing region
5208 // may not be closely nested inside a worksharing, loop, task, taskloop,
5209 // critical, ordered, atomic, or masked region.
5210 NestingProhibited =
5211 isOpenMPWorksharingDirective(ParentRegion) ||
5212 isOpenMPGenericLoopDirective(ParentRegion) ||
5213 isOpenMPTaskingDirective(ParentRegion) ||
5214 ParentRegion == OMPD_master || ParentRegion == OMPD_masked ||
5215 ParentRegion == OMPD_parallel_master ||
5216 ParentRegion == OMPD_parallel_masked ||
5217 ParentRegion == OMPD_critical || ParentRegion == OMPD_ordered;
5218 Recommend = ShouldBeInParallelRegion;
5219 } else if (CurrentRegion == OMPD_ordered) {
5220 // OpenMP [2.16, Nesting of Regions]
5221 // An ordered region may not be closely nested inside a critical,
5222 // atomic, or explicit task region.
5223 // An ordered region must be closely nested inside a loop region (or
5224 // parallel loop region) with an ordered clause.
5225 // OpenMP [2.8.1,simd Construct, Restrictions]
5226 // An ordered construct with the simd clause is the only OpenMP construct
5227 // that can appear in the simd region.
5228 NestingProhibited = ParentRegion == OMPD_critical ||
5229 isOpenMPTaskingDirective(ParentRegion) ||
5230 !(isOpenMPSimdDirective(ParentRegion) ||
5231 Stack->isParentOrderedRegion());
5232 Recommend = ShouldBeInOrderedRegion;
5233 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5234 // OpenMP [2.16, Nesting of Regions]
5235 // If specified, a teams construct must be contained within a target
5236 // construct.
5237 NestingProhibited =
5238 (SemaRef.LangOpts.OpenMP <= 45 && ParentRegion != OMPD_target) ||
5239 (SemaRef.LangOpts.OpenMP >= 50 && ParentRegion != OMPD_unknown &&
5240 ParentRegion != OMPD_target);
5241 OrphanSeen = ParentRegion == OMPD_unknown;
5242 Recommend = ShouldBeInTargetRegion;
5243 } else if (CurrentRegion == OMPD_scan) {
5244 // OpenMP [2.16, Nesting of Regions]
5245 // If specified, a teams construct must be contained within a target
5246 // construct.
5247 NestingProhibited =
5248 SemaRef.LangOpts.OpenMP < 50 ||
5249 (ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
5250 ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
5251 ParentRegion != OMPD_parallel_for_simd);
5252 OrphanSeen = ParentRegion == OMPD_unknown;
5253 Recommend = ShouldBeInLoopSimdRegion;
5254 }
5255 if (!NestingProhibited &&
5256 !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5257 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5258 (ParentRegion == OMPD_teams || ParentRegion == OMPD_target_teams)) {
5259 // OpenMP [5.1, 2.22, Nesting of Regions]
5260 // distribute, distribute simd, distribute parallel worksharing-loop,
5261 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5262 // including any parallel regions arising from combined constructs,
5263 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5264 // only OpenMP regions that may be strictly nested inside the teams
5265 // region.
5266 //
5267 // As an extension, we permit atomic within teams as well.
5268 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5269 !isOpenMPDistributeDirective(CurrentRegion) &&
5270 CurrentRegion != OMPD_loop &&
5271 !(SemaRef.getLangOpts().OpenMPExtensions &&
5272 CurrentRegion == OMPD_atomic);
5273 Recommend = ShouldBeInParallelRegion;
5274 }
5275 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5276 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5277 // If the bind clause is present on the loop construct and binding is
5278 // teams then the corresponding loop region must be strictly nested inside
5279 // a teams region.
5280 NestingProhibited = BindKind == OMPC_BIND_teams &&
5281 ParentRegion != OMPD_teams &&
5282 ParentRegion != OMPD_target_teams;
5283 Recommend = ShouldBeInTeamsRegion;
5284 }
5285 if (!NestingProhibited &&
5286 isOpenMPNestingDistributeDirective(CurrentRegion)) {
5287 // OpenMP 4.5 [2.17 Nesting of Regions]
5288 // The region associated with the distribute construct must be strictly
5289 // nested inside a teams region
5290 NestingProhibited =
5291 (ParentRegion != OMPD_teams && ParentRegion != OMPD_target_teams);
5292 Recommend = ShouldBeInTeamsRegion;
5293 }
5294 if (!NestingProhibited &&
5295 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5296 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5297 // OpenMP 4.5 [2.17 Nesting of Regions]
5298 // If a target, target update, target data, target enter data, or
5299 // target exit data construct is encountered during execution of a
5300 // target region, the behavior is unspecified.
5301 NestingProhibited = Stack->hasDirective(
5302 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5305 OffendingRegion = K;
5306 return true;
5307 }
5308 return false;
5309 },
5310 false /* don't skip top directive */);
5311 CloseNesting = false;
5312 }
5313 if (NestingProhibited) {
5314 if (OrphanSeen) {
5315 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5316 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5317 } else {
5318 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5319 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5320 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5321 }
5322 return true;
5323 }
5324 }
5325 return false;
5326}
5327
5330 unsigned operator()(argument_type DK) { return unsigned(DK); }
5331};
5333 ArrayRef<OMPClause *> Clauses,
5334 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5335 bool ErrorFound = false;
5336 unsigned NamedModifiersNumber = 0;
5337 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5338 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5339 SmallVector<SourceLocation, 4> NameModifierLoc;
5340 for (const OMPClause *C : Clauses) {
5341 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5342 // At most one if clause without a directive-name-modifier can appear on
5343 // the directive.
5344 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5345 if (FoundNameModifiers[CurNM]) {
5346 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5347 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5348 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5349 ErrorFound = true;
5350 } else if (CurNM != OMPD_unknown) {
5351 NameModifierLoc.push_back(IC->getNameModifierLoc());
5352 ++NamedModifiersNumber;
5353 }
5354 FoundNameModifiers[CurNM] = IC;
5355 if (CurNM == OMPD_unknown)
5356 continue;
5357 // Check if the specified name modifier is allowed for the current
5358 // directive.
5359 // At most one if clause with the particular directive-name-modifier can
5360 // appear on the directive.
5361 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5362 S.Diag(IC->getNameModifierLoc(),
5363 diag::err_omp_wrong_if_directive_name_modifier)
5364 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5365 ErrorFound = true;
5366 }
5367 }
5368 }
5369 // If any if clause on the directive includes a directive-name-modifier then
5370 // all if clauses on the directive must include a directive-name-modifier.
5371 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5372 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5373 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5374 diag::err_omp_no_more_if_clause);
5375 } else {
5376 std::string Values;
5377 std::string Sep(", ");
5378 unsigned AllowedCnt = 0;
5379 unsigned TotalAllowedNum =
5380 AllowedNameModifiers.size() - NamedModifiersNumber;
5381 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5382 ++Cnt) {
5383 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5384 if (!FoundNameModifiers[NM]) {
5385 Values += "'";
5386 Values += getOpenMPDirectiveName(NM);
5387 Values += "'";
5388 if (AllowedCnt + 2 == TotalAllowedNum)
5389 Values += " or ";
5390 else if (AllowedCnt + 1 != TotalAllowedNum)
5391 Values += Sep;
5392 ++AllowedCnt;
5393 }
5394 }
5395 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5396 diag::err_omp_unnamed_if_clause)
5397 << (TotalAllowedNum > 1) << Values;
5398 }
5399 for (SourceLocation Loc : NameModifierLoc) {
5400 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5401 }
5402 ErrorFound = true;
5403 }
5404 return ErrorFound;
5405}
5406
5407static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5408 SourceLocation &ELoc,
5409 SourceRange &ERange,
5410 bool AllowArraySection,
5411 StringRef DiagType) {
5412 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5414 return std::make_pair(nullptr, true);
5415
5416 // OpenMP [3.1, C/C++]
5417 // A list item is a variable name.
5418 // OpenMP [2.9.3.3, Restrictions, p.1]
5419 // A variable that is part of another variable (as an array or
5420 // structure element) cannot appear in a private clause.
5421 RefExpr = RefExpr->IgnoreParens();
5422 enum {
5423 NoArrayExpr = -1,
5424 ArraySubscript = 0,
5425 OMPArraySection = 1
5426 } IsArrayExpr = NoArrayExpr;
5427 if (AllowArraySection) {
5428 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5429 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5430 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5431 Base = TempASE->getBase()->IgnoreParenImpCasts();
5432 RefExpr = Base;
5433 IsArrayExpr = ArraySubscript;
5434 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5435 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5436 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5437 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5438 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5439 Base = TempASE->getBase()->IgnoreParenImpCasts();
5440 RefExpr = Base;
5441 IsArrayExpr = OMPArraySection;
5442 }
5443 }
5444 ELoc = RefExpr->getExprLoc();
5445 ERange = RefExpr->getSourceRange();
5446 RefExpr = RefExpr->IgnoreParenImpCasts();
5447 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5448 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5449 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5450 (S.getCurrentThisType().isNull() || !ME ||
5451 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5452 !isa<FieldDecl>(ME->getMemberDecl()))) {
5453 if (IsArrayExpr != NoArrayExpr) {
5454 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5455 << IsArrayExpr << ERange;
5456 } else if (!DiagType.empty()) {
5457 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5458 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5459 : 0;
5460 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5461 << DiagSelect << DiagType << ERange;
5462 } else {
5463 S.Diag(ELoc,
5464 AllowArraySection
5465 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5466 : diag::err_omp_expected_var_name_member_expr)
5467 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5468 }
5469 return std::make_pair(nullptr, false);
5470 }
5471 return std::make_pair(
5472 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5473}
5474
5475namespace {
5476/// Checks if the allocator is used in uses_allocators clause to be allowed in
5477/// target regions.
5478class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5479 DSAStackTy *S = nullptr;
5480
5481public:
5482 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5483 return S->isUsesAllocatorsDecl(E->getDecl())
5484 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5485 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5486 }
5487 bool VisitStmt(const Stmt *S) {
5488 for (const Stmt *Child : S->children()) {
5489 if (Child && Visit(Child))
5490 return true;
5491 }
5492 return false;
5493 }
5494 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5495};
5496} // namespace
5497
5498static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5499 ArrayRef<OMPClause *> Clauses) {
5500 assert(!S.CurContext->isDependentContext() &&
5501 "Expected non-dependent context.");
5502 auto AllocateRange =
5503 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5504 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5505 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5506 return isOpenMPPrivate(C->getClauseKind());
5507 });
5508 for (OMPClause *Cl : PrivateRange) {
5510 if (Cl->getClauseKind() == OMPC_private) {
5511 auto *PC = cast<OMPPrivateClause>(Cl);
5512 I = PC->private_copies().begin();
5513 It = PC->varlist_begin();
5514 Et = PC->varlist_end();
5515 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5516 auto *PC = cast<OMPFirstprivateClause>(Cl);
5517 I = PC->private_copies().begin();
5518 It = PC->varlist_begin();
5519 Et = PC->varlist_end();
5520 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5521 auto *PC = cast<OMPLastprivateClause>(Cl);
5522 I = PC->private_copies().begin();
5523 It = PC->varlist_begin();
5524 Et = PC->varlist_end();
5525 } else if (Cl->getClauseKind() == OMPC_linear) {
5526 auto *PC = cast<OMPLinearClause>(Cl);
5527 I = PC->privates().begin();
5528 It = PC->varlist_begin();
5529 Et = PC->varlist_end();
5530 } else if (Cl->getClauseKind() == OMPC_reduction) {
5531 auto *PC = cast<OMPReductionClause>(Cl);
5532 I = PC->privates().begin();
5533 It = PC->varlist_begin();
5534 Et = PC->varlist_end();
5535 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5536 auto *PC = cast<OMPTaskReductionClause>(Cl);
5537 I = PC->privates().begin();
5538 It = PC->varlist_begin();
5539 Et = PC->varlist_end();
5540 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5541 auto *PC = cast<OMPInReductionClause>(Cl);
5542 I = PC->privates().begin();
5543 It = PC->varlist_begin();
5544 Et = PC->varlist_end();
5545 } else {
5546 llvm_unreachable("Expected private clause.");
5547 }
5548 for (Expr *E : llvm::make_range(It, Et)) {
5549 if (!*I) {
5550 ++I;
5551 continue;
5552 }
5553 SourceLocation ELoc;
5554 SourceRange ERange;
5555 Expr *SimpleRefExpr = E;
5556 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5557 /*AllowArraySection=*/true);
5558 DeclToCopy.try_emplace(Res.first,
5559 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5560 ++I;
5561 }
5562 }
5563 for (OMPClause *C : AllocateRange) {
5564 auto *AC = cast<OMPAllocateClause>(C);
5565 if (S.getLangOpts().OpenMP >= 50 &&
5566 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5567 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5568 AC->getAllocator()) {
5569 Expr *Allocator = AC->getAllocator();
5570 // OpenMP, 2.12.5 target Construct
5571 // Memory allocators that do not appear in a uses_allocators clause cannot
5572 // appear as an allocator in an allocate clause or be used in the target
5573 // region unless a requires directive with the dynamic_allocators clause
5574 // is present in the same compilation unit.
5575 AllocatorChecker Checker(Stack);
5576 if (Checker.Visit(Allocator))
5577 S.Diag(Allocator->getExprLoc(),
5578 diag::err_omp_allocator_not_in_uses_allocators)
5579 << Allocator->getSourceRange();
5580 }
5581 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5582 getAllocatorKind(S, Stack, AC->getAllocator());
5583 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5584 // For task, taskloop or target directives, allocation requests to memory
5585 // allocators with the trait access set to thread result in unspecified
5586 // behavior.
5587 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5588 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5589 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5590 S.Diag(AC->getAllocator()->getExprLoc(),
5591 diag::warn_omp_allocate_thread_on_task_target_directive)
5592 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5593 }
5594 for (Expr *E : AC->varlists()) {
5595 SourceLocation ELoc;
5596 SourceRange ERange;
5597 Expr *SimpleRefExpr = E;
5598 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5599 ValueDecl *VD = Res.first;
5600 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5601 if (!isOpenMPPrivate(Data.CKind)) {
5602 S.Diag(E->getExprLoc(),
5603 diag::err_omp_expected_private_copy_for_allocate);
5604 continue;
5605 }
5606 VarDecl *PrivateVD = DeclToCopy[VD];
5607 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5608 AllocatorKind, AC->getAllocator()))
5609 continue;
5610 // Placeholder until allocate clause supports align modifier.
5611 Expr *Alignment = nullptr;
5612 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5613 Alignment, E->getSourceRange());
5614 }
5615 }
5616}
5617
5618namespace {
5619/// Rewrite statements and expressions for Sema \p Actions CurContext.
5620///
5621/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5622/// context. DeclRefExpr used inside the new context are changed to refer to the
5623/// captured variable instead.
5624class CaptureVars : public TreeTransform<CaptureVars> {
5625 using BaseTransform = TreeTransform<CaptureVars>;
5626
5627public:
5628 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5629
5630 bool AlwaysRebuild() { return true; }
5631};
5632} // namespace
5633
5634static VarDecl *precomputeExpr(Sema &Actions,
5635 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5636 StringRef Name) {
5637 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5638 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5639 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5640 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5641 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5642 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5643 BodyStmts.push_back(NewDeclStmt);
5644 return NewVar;
5645}
5646
5647/// Create a closure that computes the number of iterations of a loop.
5648///
5649/// \param Actions The Sema object.
5650/// \param LogicalTy Type for the logical iteration number.
5651/// \param Rel Comparison operator of the loop condition.
5652/// \param StartExpr Value of the loop counter at the first iteration.
5653/// \param StopExpr Expression the loop counter is compared against in the loop
5654/// condition. \param StepExpr Amount of increment after each iteration.
5655///
5656/// \return Closure (CapturedStmt) of the distance calculation.
5657static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5659 Expr *StartExpr, Expr *StopExpr,
5660 Expr *StepExpr) {
5661 ASTContext &Ctx = Actions.getASTContext();
5662 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5663
5664 // Captured regions currently don't support return values, we use an
5665 // out-parameter instead. All inputs are implicit captures.
5666 // TODO: Instead of capturing each DeclRefExpr occurring in
5667 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5668 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5669 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5670 {StringRef(), QualType()}};
5671 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5672
5673 Stmt *Body;
5674 {
5675 Sema::CompoundScopeRAII CompoundScope(Actions);
5676 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5677
5678 // Get the LValue expression for the result.
5679 ImplicitParamDecl *DistParam = CS->getParam(0);
5680 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5681 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5682
5683 SmallVector<Stmt *, 4> BodyStmts;
5684
5685 // Capture all referenced variable references.
5686 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5687 // CapturedStmt, we could compute them before and capture the result, to be
5688 // used jointly with the LoopVar function.
5689 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5690 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5691 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5692 auto BuildVarRef = [&](VarDecl *VD) {
5693 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5694 };
5695
5697 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5699 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5700 Expr *Dist;
5701 if (Rel == BO_NE) {
5702 // When using a != comparison, the increment can be +1 or -1. This can be
5703 // dynamic at runtime, so we need to check for the direction.
5704 Expr *IsNegStep = AssertSuccess(
5705 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5706
5707 // Positive increment.
5708 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5709 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5710 ForwardRange = AssertSuccess(
5711 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5712 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5713 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5714
5715 // Negative increment.
5716 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5717 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5718 BackwardRange = AssertSuccess(
5719 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5720 Expr *NegIncAmount = AssertSuccess(
5721 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5722 Expr *BackwardDist = AssertSuccess(
5723 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5724
5725 // Use the appropriate case.
5726 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5727 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5728 } else {
5729 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5730 "Expected one of these relational operators");
5731
5732 // We can derive the direction from any other comparison operator. It is
5733 // non well-formed OpenMP if Step increments/decrements in the other
5734 // directions. Whether at least the first iteration passes the loop
5735 // condition.
5736 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5737 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5738
5739 // Compute the range between first and last counter value.
5740 Expr *Range;
5741 if (Rel == BO_GE || Rel == BO_GT)
5742 Range = AssertSuccess(Actions.BuildBinOp(
5743 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5744 else
5745 Range = AssertSuccess(Actions.BuildBinOp(
5746 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5747
5748 // Ensure unsigned range space.
5749 Range =
5750 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5751
5752 if (Rel == BO_LE || Rel == BO_GE) {
5753 // Add one to the range if the relational operator is inclusive.
5754 Range =
5755 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5756 }
5757
5758 // Divide by the absolute step amount. If the range is not a multiple of
5759 // the step size, rounding-up the effective upper bound ensures that the
5760 // last iteration is included.
5761 // Note that the rounding-up may cause an overflow in a temporry that
5762 // could be avoided, but would have occurred in a C-style for-loop as
5763 // well.
5764 Expr *Divisor = BuildVarRef(NewStep);
5765 if (Rel == BO_GE || Rel == BO_GT)
5766 Divisor =
5767 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5768 Expr *DivisorMinusOne =
5769 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5770 Expr *RangeRoundUp = AssertSuccess(
5771 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5772 Dist = AssertSuccess(
5773 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5774
5775 // If there is not at least one iteration, the range contains garbage. Fix
5776 // to zero in this case.
5777 Dist = AssertSuccess(
5778 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5779 }
5780
5781 // Assign the result to the out-parameter.
5782 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5783 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5784 BodyStmts.push_back(ResultAssign);
5785
5786 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5787 }
5788
5789 return cast<CapturedStmt>(
5790 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5791}
5792
5793/// Create a closure that computes the loop variable from the logical iteration
5794/// number.
5795///
5796/// \param Actions The Sema object.
5797/// \param LoopVarTy Type for the loop variable used for result value.
5798/// \param LogicalTy Type for the logical iteration number.
5799/// \param StartExpr Value of the loop counter at the first iteration.
5800/// \param Step Amount of increment after each iteration.
5801/// \param Deref Whether the loop variable is a dereference of the loop
5802/// counter variable.
5803///
5804/// \return Closure (CapturedStmt) of the loop value calculation.
5805static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5806 QualType LogicalTy,
5807 DeclRefExpr *StartExpr, Expr *Step,
5808 bool Deref) {
5809 ASTContext &Ctx = Actions.getASTContext();
5810
5811 // Pass the result as an out-parameter. Passing as return value would require
5812 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5813 // invoke a copy constructor.
5814 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5815 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5816 {"Logical", LogicalTy},
5817 {StringRef(), QualType()}};
5818 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5819
5820 // Capture the initial iterator which represents the LoopVar value at the
5821 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5822 // it in every iteration, capture it by value before it is modified.
5823 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5824 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5826 (void)Invalid;
5827 assert(!Invalid && "Expecting capture-by-value to work.");
5828
5829 Expr *Body;
5830 {
5831 Sema::CompoundScopeRAII CompoundScope(Actions);
5832 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5833
5834 ImplicitParamDecl *TargetParam = CS->getParam(0);
5835 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5836 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5837 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5838 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5839 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5840
5841 // Capture the Start expression.
5842 CaptureVars Recap(Actions);
5843 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5844 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5845
5846 Expr *Skip = AssertSuccess(
5847 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5848 // TODO: Explicitly cast to the iterator's difference_type instead of
5849 // relying on implicit conversion.
5850 Expr *Advanced =
5851 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5852
5853 if (Deref) {
5854 // For range-based for-loops convert the loop counter value to a concrete
5855 // loop variable value by dereferencing the iterator.
5856 Advanced =
5857 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5858 }
5859
5860 // Assign the result to the output parameter.
5861 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5862 BO_Assign, TargetRef, Advanced));
5863 }
5864 return cast<CapturedStmt>(
5865 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5866}
5867
5869 ASTContext &Ctx = getASTContext();
5870
5871 // Extract the common elements of ForStmt and CXXForRangeStmt:
5872 // Loop variable, repeat condition, increment
5873 Expr *Cond, *Inc;
5874 VarDecl *LIVDecl, *LUVDecl;
5875 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5876 Stmt *Init = For->getInit();
5877 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5878 // For statement declares loop variable.
5879 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5880 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5881 // For statement reuses variable.
5882 assert(LCAssign->getOpcode() == BO_Assign &&
5883 "init part must be a loop variable assignment");
5884 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5885 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5886 } else
5887 llvm_unreachable("Cannot determine loop variable");
5888 LUVDecl = LIVDecl;
5889
5890 Cond = For->getCond();
5891 Inc = For->getInc();
5892 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5893 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5894 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5895 LUVDecl = RangeFor->getLoopVariable();
5896
5897 Cond = RangeFor->getCond();
5898 Inc = RangeFor->getInc();
5899 } else
5900 llvm_unreachable("unhandled kind of loop");
5901
5902 QualType CounterTy = LIVDecl->getType();
5903 QualType LVTy = LUVDecl->getType();
5904
5905 // Analyze the loop condition.
5906 Expr *LHS, *RHS;
5907 BinaryOperator::Opcode CondRel;
5908 Cond = Cond->IgnoreImplicit();
5909 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5910 LHS = CondBinExpr->getLHS();
5911 RHS = CondBinExpr->getRHS();
5912 CondRel = CondBinExpr->getOpcode();
5913 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5914 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5915 LHS = CondCXXOp->getArg(0);
5916 RHS = CondCXXOp->getArg(1);
5917 switch (CondCXXOp->getOperator()) {
5918 case OO_ExclaimEqual:
5919 CondRel = BO_NE;
5920 break;
5921 case OO_Less:
5922 CondRel = BO_LT;
5923 break;
5924 case OO_LessEqual:
5925 CondRel = BO_LE;
5926 break;
5927 case OO_Greater:
5928 CondRel = BO_GT;
5929 break;
5930 case OO_GreaterEqual:
5931 CondRel = BO_GE;
5932 break;
5933 default:
5934 llvm_unreachable("unexpected iterator operator");
5935 }
5936 } else
5937 llvm_unreachable("unexpected loop condition");
5938
5939 // Normalize such that the loop counter is on the LHS.
5940 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5941 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5942 std::swap(LHS, RHS);
5943 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5944 }
5945 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5946
5947 // Decide the bit width for the logical iteration counter. By default use the
5948 // unsigned ptrdiff_t integer size (for iterators and pointers).
5949 // TODO: For iterators, use iterator::difference_type,
5950 // std::iterator_traits<>::difference_type or decltype(it - end).
5951 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5952 if (CounterTy->isIntegerType()) {
5953 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5954 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5955 }
5956
5957 // Analyze the loop increment.
5958 Expr *Step;
5959 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5960 int Direction;
5961 switch (IncUn->getOpcode()) {
5962 case UO_PreInc:
5963 case UO_PostInc:
5964 Direction = 1;
5965 break;
5966 case UO_PreDec:
5967 case UO_PostDec:
5968 Direction = -1;
5969 break;
5970 default:
5971 llvm_unreachable("unhandled unary increment operator");
5972 }
5974 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5975 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5976 if (IncBin->getOpcode() == BO_AddAssign) {
5977 Step = IncBin->getRHS();
5978 } else if (IncBin->getOpcode() == BO_SubAssign) {
5979 Step = AssertSuccess(
5980 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5981 } else
5982 llvm_unreachable("unhandled binary increment operator");
5983 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5984 switch (CondCXXOp->getOperator()) {
5985 case OO_PlusPlus:
5987 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5988 break;
5989 case OO_MinusMinus:
5991 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5992 break;
5993 case OO_PlusEqual:
5994 Step = CondCXXOp->getArg(1);
5995 break;
5996 case OO_MinusEqual:
5997 Step = AssertSuccess(
5998 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5999 break;
6000 default:
6001 llvm_unreachable("unhandled overloaded increment operator");
6002 }
6003 } else
6004 llvm_unreachable("unknown increment expression");
6005
6006 CapturedStmt *DistanceFunc =
6007 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
6008 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
6009 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
6010 DeclRefExpr *LVRef =
6011 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
6012 nullptr, nullptr, {}, nullptr);
6013 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
6014 LoopVarFunc, LVRef);
6015}
6016
6018 // Handle a literal loop.
6019 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
6020 return ActOnOpenMPCanonicalLoop(AStmt);
6021
6022 // If not a literal loop, it must be the result of a loop transformation.
6023 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
6024 assert(
6026 "Loop transformation directive expected");
6027 return LoopTransform;
6028}
6029
6031 CXXScopeSpec &MapperIdScopeSpec,
6032 const DeclarationNameInfo &MapperId,
6033 QualType Type,
6034 Expr *UnresolvedMapper);
6035
6036/// Perform DFS through the structure/class data members trying to find
6037/// member(s) with user-defined 'default' mapper and generate implicit map
6038/// clauses for such members with the found 'default' mapper.
6039static void
6042 // Check for the deault mapper for data members.
6043 if (S.getLangOpts().OpenMP < 50)
6044 return;
6045 SmallVector<OMPClause *, 4> ImplicitMaps;
6046 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6047 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6048 if (!C)
6049 continue;
6050 SmallVector<Expr *, 4> SubExprs;
6051 auto *MI = C->mapperlist_begin();
6052 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6053 ++I, ++MI) {
6054 // Expression is mapped using mapper - skip it.
6055 if (*MI)
6056 continue;
6057 Expr *E = *I;
6058 // Expression is dependent - skip it, build the mapper when it gets
6059 // instantiated.
6060 if (E->isTypeDependent() || E->isValueDependent() ||
6062 continue;
6063 // Array section - need to check for the mapping of the array section
6064 // element.
6065 QualType CanonType = E->getType().getCanonicalType();
6066 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
6067 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
6068 QualType BaseType =
6070 QualType ElemType;
6071 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6072 ElemType = ATy->getElementType();
6073 else
6074 ElemType = BaseType->getPointeeType();
6075 CanonType = ElemType;
6076 }
6077
6078 // DFS over data members in structures/classes.
6080 1, {CanonType, nullptr});
6081 llvm::DenseMap<const Type *, Expr *> Visited;
6083 1, {nullptr, 1});
6084 while (!Types.empty()) {
6085 QualType BaseType;
6086 FieldDecl *CurFD;
6087 std::tie(BaseType, CurFD) = Types.pop_back_val();
6088 while (ParentChain.back().second == 0)
6089 ParentChain.pop_back();
6090 --ParentChain.back().second;
6091 if (BaseType.isNull())
6092 continue;
6093 // Only structs/classes are allowed to have mappers.
6094 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6095 if (!RD)
6096 continue;
6097 auto It = Visited.find(BaseType.getTypePtr());
6098 if (It == Visited.end()) {
6099 // Try to find the associated user-defined mapper.
6100 CXXScopeSpec MapperIdScopeSpec;
6101 DeclarationNameInfo DefaultMapperId;
6103 &S.Context.Idents.get("default")));
6104 DefaultMapperId.setLoc(E->getExprLoc());
6106 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6107 BaseType, /*UnresolvedMapper=*/nullptr);
6108 if (ER.isInvalid())
6109 continue;
6110 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6111 }
6112 // Found default mapper.
6113 if (It->second) {
6114 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6116 OE->setIsUnique(/*V=*/true);
6117 Expr *BaseExpr = OE;
6118 for (const auto &P : ParentChain) {
6119 if (P.first) {
6120 BaseExpr = S.BuildMemberExpr(
6121 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6123 DeclAccessPair::make(P.first, P.first->getAccess()),
6124 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6125 P.first->getType(), VK_LValue, OK_Ordinary);
6126 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6127 }
6128 }
6129 if (CurFD)
6130 BaseExpr = S.BuildMemberExpr(
6131 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6133 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6134 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6135 CurFD->getType(), VK_LValue, OK_Ordinary);
6136 SubExprs.push_back(BaseExpr);
6137 continue;
6138 }
6139 // Check for the "default" mapper for data members.
6140 bool FirstIter = true;
6141 for (FieldDecl *FD : RD->fields()) {
6142 if (!FD)
6143 continue;
6144 QualType FieldTy = FD->getType();
6145 if (FieldTy.isNull() ||
6146 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6147 continue;
6148 if (FirstIter) {
6149 FirstIter = false;
6150 ParentChain.emplace_back(CurFD, 1);
6151 } else {
6152 ++ParentChain.back().second;
6153 }
6154 Types.emplace_back(FieldTy, FD);
6155 }
6156 }
6157 }
6158 if (SubExprs.empty())
6159 continue;
6160 CXXScopeSpec MapperIdScopeSpec;
6161 DeclarationNameInfo MapperId;
6162 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6163 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6164 MapperIdScopeSpec, MapperId, C->getMapType(),
6165 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6166 SubExprs, OMPVarListLocTy()))
6167 Clauses.push_back(NewClause);
6168 }
6169}
6170
6171namespace {
6172/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6173/// call in the associated loop-nest cannot be a 'parallel for'.
6174class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6175 Sema &SemaRef;
6176
6177public:
6178 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6179
6180 // Is there a nested OpenMP loop bind(parallel)
6181 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6182 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6183 if (const auto *C = D->getSingleClause<OMPBindClause>())
6184 if (C->getBindKind() == OMPC_BIND_parallel) {
6185 TeamsLoopCanBeParallelFor = false;
6186 // No need to continue visiting any more
6187 return;
6188 }
6189 }
6190 for (const Stmt *Child : D->children())
6191 if (Child)
6192 Visit(Child);
6193 }
6194
6195 void VisitCallExpr(const CallExpr *C) {
6196 // Function calls inhibit parallel loop translation of 'target teams loop'
6197 // unless the assume-no-nested-parallelism flag has been specified.
6198 // OpenMP API runtime library calls do not inhibit parallel loop
6199 // translation, regardless of the assume-no-nested-parallelism.
6200 if (C) {
6201 bool IsOpenMPAPI = false;
6202 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6203 if (FD) {
6204 std::string Name = FD->getNameInfo().getAsString();
6205 IsOpenMPAPI = Name.find("omp_") == 0;
6206 }
6207 TeamsLoopCanBeParallelFor =
6208 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6209 if (!TeamsLoopCanBeParallelFor)
6210 return;
6211 }
6212 for (const Stmt *Child : C->children())
6213 if (Child)
6214 Visit(Child);
6215 }
6216
6217 void VisitCapturedStmt(const CapturedStmt *S) {
6218 if (!S)
6219 return;
6220 Visit(S->getCapturedDecl()->getBody());
6221 }
6222
6223 void VisitStmt(const Stmt *S) {
6224 if (!S)
6225 return;
6226 for (const Stmt *Child : S->children())
6227 if (Child)
6228 Visit(Child);
6229 }
6230 explicit TeamsLoopChecker(Sema &SemaRef)
6231 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6232
6233private:
6234 bool TeamsLoopCanBeParallelFor;
6235};
6236} // namespace
6237
6238static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6239 TeamsLoopChecker Checker(SemaRef);
6240 Checker.Visit(AStmt);
6241 return Checker.teamsLoopCanBeParallelFor();
6242}
6243
6244bool SemaOpenMP::mapLoopConstruct(
6245 llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
6247 OpenMPDirectiveKind &Kind, OpenMPDirectiveKind &PrevMappedDirective,
6248 SourceLocation StartLoc, SourceLocation EndLoc,
6249 const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion) {
6250
6251 bool UseClausesWithoutBind = false;
6252
6253 // Restricting to "#pragma omp loop bind"
6254 if (getLangOpts().OpenMP >= 50 && Kind == OMPD_loop) {
6255
6256 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6257
6258 if (BindKind == OMPC_BIND_unknown) {
6259 // Setting the enclosing teams or parallel construct for the loop
6260 // directive without bind clause.
6261 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6262
6263 if (ParentDirective == OMPD_unknown) {
6264 Diag(DSAStack->getDefaultDSALocation(),
6265 diag::err_omp_bind_required_on_loop);
6266 } else if (ParentDirective == OMPD_parallel ||
6267 ParentDirective == OMPD_target_parallel) {
6268 BindKind = OMPC_BIND_parallel;
6269 } else if (ParentDirective == OMPD_teams ||
6270 ParentDirective == OMPD_target_teams) {
6271 BindKind = OMPC_BIND_teams;
6272 }
6273 } else {
6274 // bind clause is present in loop directive. When the loop directive is
6275 // changed to a new directive the bind clause is not used. So, we should
6276 // set flag indicating to only use the clauses that aren't the
6277 // bind clause.
6278 UseClausesWithoutBind = true;
6279 }
6280
6281 for (OMPClause *C : Clauses) {
6282 // Spec restriction : bind(teams) and reduction not permitted.
6283 if (BindKind == OMPC_BIND_teams &&
6284 C->getClauseKind() == llvm::omp::Clause::OMPC_reduction)
6285 Diag(DSAStack->getDefaultDSALocation(),
6286 diag::err_omp_loop_reduction_clause);
6287
6288 // A new Vector ClausesWithoutBind, which does not contain the bind
6289 // clause, for passing to new directive.
6290 if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind)
6291 ClausesWithoutBind.push_back(C);
6292 }
6293
6294 switch (BindKind) {
6295 case OMPC_BIND_parallel:
6296 Kind = OMPD_for;
6297 DSAStack->setCurrentDirective(OMPD_for);
6298 DSAStack->setMappedDirective(OMPD_loop);
6299 PrevMappedDirective = OMPD_loop;
6300 break;
6301 case OMPC_BIND_teams:
6302 Kind = OMPD_distribute;
6303 DSAStack->setCurrentDirective(OMPD_distribute);
6304 DSAStack->setMappedDirective(OMPD_loop);
6305 PrevMappedDirective = OMPD_loop;
6306 break;
6307 case OMPC_BIND_thread:
6308 Kind = OMPD_simd;
6309 DSAStack->setCurrentDirective(OMPD_simd);
6310 DSAStack->setMappedDirective(OMPD_loop);
6311 PrevMappedDirective = OMPD_loop;
6312 break;
6313 case OMPC_BIND_unknown:
6314 break;
6315 }
6316 } else if (PrevMappedDirective == OMPD_loop) {
6317 /// An initial pass after recognizing all the statements is done in the
6318 /// Parser when the directive OMPD_loop is mapped to OMPD_for,
6319 /// OMPD_distribute or OMPD_simd. A second transform pass with call from
6320 /// clang::TreeTransform::TransformOMPExecutableDirective() is done
6321 /// with the Directive as one of the above mapped directive without
6322 /// the bind clause. Then "PrevMappedDirective" stored in the
6323 /// OMPExecutableDirective is accessed and hence this else statement.
6324
6325 DSAStack->setMappedDirective(OMPD_loop);
6326 }
6327
6328 return UseClausesWithoutBind;
6329}
6330
6332 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6333 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6334 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc,
6335 OpenMPDirectiveKind PrevMappedDirective) {
6336 StmtResult Res = StmtError();
6338 llvm::SmallVector<OMPClause *> ClausesWithoutBind;
6339 bool UseClausesWithoutBind = false;
6340
6341 if (const OMPBindClause *BC =
6342 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6343 BindKind = BC->getBindKind();
6344
6345 // Variable used to note down the DirectiveKind because mapLoopConstruct may
6346 // change "Kind" variable, due to mapping of "omp loop" to other directives.
6347 OpenMPDirectiveKind DK = Kind;
6348 if (Kind == OMPD_loop || PrevMappedDirective == OMPD_loop) {
6349 UseClausesWithoutBind = mapLoopConstruct(
6350 ClausesWithoutBind, Clauses, BindKind, Kind, PrevMappedDirective,
6351 StartLoc, EndLoc, DirName, CancelRegion);
6352 DK = OMPD_loop;
6353 }
6354
6355 // First check CancelRegion which is then used in checkNestingOfRegions.
6356 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6357 checkNestingOfRegions(SemaRef, DSAStack, DK, DirName, CancelRegion,
6358 BindKind, StartLoc)) {
6359 return StmtError();
6360 }
6361
6362 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6365 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6366
6367 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6368 VarsWithInheritedDSAType VarsWithInheritedDSA;
6369 bool ErrorFound = false;
6370 if (getLangOpts().OpenMP >= 50 && UseClausesWithoutBind) {
6371 ClausesWithImplicit.append(ClausesWithoutBind.begin(),
6372 ClausesWithoutBind.end());
6373 } else {
6374 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6375 }
6376 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6377 Kind != OMPD_atomic && Kind != OMPD_critical && Kind != OMPD_section &&
6378 Kind != OMPD_master && Kind != OMPD_masked &&
6380 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6381
6382 // Check default data sharing attributes for referenced variables.
6383 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6384 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6385 Stmt *S = AStmt;
6386 while (--ThisCaptureLevel >= 0)
6387 S = cast<CapturedStmt>(S)->getCapturedStmt();
6388 DSAChecker.Visit(S);
6390 !isOpenMPTaskingDirective(Kind)) {
6391 // Visit subcaptures to generate implicit clauses for captured vars.
6392 auto *CS = cast<CapturedStmt>(AStmt);
6394 getOpenMPCaptureRegions(CaptureRegions, Kind);
6395 // Ignore outer tasking regions for target directives.
6396 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6397 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6398 DSAChecker.visitSubCaptures(CS);
6399 }
6400 if (DSAChecker.isErrorFound())
6401 return StmtError();
6402 // Generate list of implicitly defined firstprivate variables.
6403 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6404
6405 SmallVector<Expr *, 4> ImplicitFirstprivates(
6406 DSAChecker.getImplicitFirstprivate().begin(),
6407 DSAChecker.getImplicitFirstprivate().end());
6408 SmallVector<Expr *, 4> ImplicitPrivates(
6409 DSAChecker.getImplicitPrivate().begin(),
6410 DSAChecker.getImplicitPrivate().end());
6411 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6412 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6414 ImplicitMapModifiers[DefaultmapKindNum];
6416 ImplicitMapModifiersLoc[DefaultmapKindNum];
6417 // Get the original location of present modifier from Defaultmap clause.
6418 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6419 for (OMPClause *C : Clauses) {
6420 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6421 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6422 PresentModifierLocs[DMC->getDefaultmapKind()] =
6423 DMC->getDefaultmapModifierLoc();
6424 }
6425 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6426 auto Kind = static_cast<OpenMPDefaultmapClauseKind>(VC);
6427 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6428 ArrayRef<Expr *> ImplicitMap = DSAChecker.getImplicitMap(
6429 Kind, static_cast<OpenMPMapClauseKind>(I));
6430 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6431 }
6432 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6433 DSAChecker.getImplicitMapModifier(Kind);
6434 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6435 ImplicitModifier.end());
6436 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6437 ImplicitModifier.size(), PresentModifierLocs[VC]);
6438 }
6439 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6440 for (OMPClause *C : Clauses) {
6441 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6442 for (Expr *E : IRC->taskgroup_descriptors())
6443 if (E)
6444 ImplicitFirstprivates.emplace_back(E);
6445 }
6446 // OpenMP 5.0, 2.10.1 task Construct
6447 // [detach clause]... The event-handle will be considered as if it was
6448 // specified on a firstprivate clause.
6449 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6450 ImplicitFirstprivates.push_back(DC->getEventHandler());
6451 }
6452 if (!ImplicitFirstprivates.empty()) {
6454 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6455 SourceLocation())) {
6456 ClausesWithImplicit.push_back(Implicit);
6457 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6458 ImplicitFirstprivates.size();
6459 } else {
6460 ErrorFound = true;
6461 }
6462 }
6463 if (!ImplicitPrivates.empty()) {
6464 if (OMPClause *Implicit =
6465 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6467 ClausesWithImplicit.push_back(Implicit);
6468 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6469 ImplicitPrivates.size();
6470 } else {
6471 ErrorFound = true;
6472 }
6473 }
6474 // OpenMP 5.0 [2.19.7]
6475 // If a list item appears in a reduction, lastprivate or linear
6476 // clause on a combined target construct then it is treated as
6477 // if it also appears in a map clause with a map-type of tofrom
6478 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6480 SmallVector<Expr *, 4> ImplicitExprs;
6481 for (OMPClause *C : Clauses) {
6482 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6483 for (Expr *E : RC->varlists())
6484 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6485 ImplicitExprs.emplace_back(E);
6486 }
6487 if (!ImplicitExprs.empty()) {
6488 ArrayRef<Expr *> Exprs = ImplicitExprs;
6489 CXXScopeSpec MapperIdScopeSpec;
6490 DeclarationNameInfo MapperId;
6493 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6494 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6495 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6496 ClausesWithImplicit.emplace_back(Implicit);
6497 }
6498 }
6499 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6500 int ClauseKindCnt = -1;
6501 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6502 ++ClauseKindCnt;
6503 if (ImplicitMap.empty())
6504 continue;
6505 CXXScopeSpec MapperIdScopeSpec;
6506 DeclarationNameInfo MapperId;
6507 auto Kind = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6509 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6510 MapperIdScopeSpec, MapperId, Kind, /*IsMapTypeImplicit=*/true,
6511 SourceLocation(), SourceLocation(), ImplicitMap,
6512 OMPVarListLocTy())) {
6513 ClausesWithImplicit.emplace_back(Implicit);
6514 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6515 ImplicitMap.size();
6516 } else {
6517 ErrorFound = true;
6518 }
6519 }
6520 }
6521 // Build expressions for implicit maps of data members with 'default'
6522 // mappers.
6523 if (getLangOpts().OpenMP >= 50)
6525 ClausesWithImplicit);
6526 }
6527
6528 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6529 switch (Kind) {
6530 case OMPD_parallel:
6531 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6532 EndLoc);
6533 AllowedNameModifiers.push_back(OMPD_parallel);
6534 break;
6535 case OMPD_simd:
6536 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6537 VarsWithInheritedDSA);
6538 if (getLangOpts().OpenMP >= 50)
6539 AllowedNameModifiers.push_back(OMPD_simd);
6540 break;
6541 case OMPD_tile:
6542 Res =
6543 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6544 break;
6545 case OMPD_unroll:
6546 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6547 EndLoc);
6548 break;
6549 case OMPD_for:
6550 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6551 VarsWithInheritedDSA);
6552 break;
6553 case OMPD_for_simd:
6554 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6555 EndLoc, VarsWithInheritedDSA);
6556 if (getLangOpts().OpenMP >= 50)
6557 AllowedNameModifiers.push_back(OMPD_simd);
6558 break;
6559 case OMPD_sections:
6560 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6561 EndLoc);
6562 break;
6563 case OMPD_section:
6564 assert(ClausesWithImplicit.empty() &&
6565 "No clauses are allowed for 'omp section' directive");
6566 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6567 break;
6568 case OMPD_single:
6569 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6570 EndLoc);
6571 break;
6572 case OMPD_master:
6573 assert(ClausesWithImplicit.empty() &&
6574 "No clauses are allowed for 'omp master' directive");
6575 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6576 break;
6577 case OMPD_masked:
6578 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6579 EndLoc);
6580 break;
6581 case OMPD_critical:
6582 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6583 StartLoc, EndLoc);
6584 break;
6585 case OMPD_parallel_for:
6586 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6587 EndLoc, VarsWithInheritedDSA);
6588 AllowedNameModifiers.push_back(OMPD_parallel);
6589 break;
6590 case OMPD_parallel_for_simd:
6592 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6593 AllowedNameModifiers.push_back(OMPD_parallel);
6594 if (getLangOpts().OpenMP >= 50)
6595 AllowedNameModifiers.push_back(OMPD_simd);
6596 break;
6597 case OMPD_scope:
6598 Res =
6599 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6600 break;
6601 case OMPD_parallel_master:
6602 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6603 StartLoc, EndLoc);
6604 AllowedNameModifiers.push_back(OMPD_parallel);
6605 break;
6606 case OMPD_parallel_masked:
6607 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6608 StartLoc, EndLoc);
6609 AllowedNameModifiers.push_back(OMPD_parallel);
6610 break;
6611 case OMPD_parallel_sections:
6612 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6613 StartLoc, EndLoc);
6614 AllowedNameModifiers.push_back(OMPD_parallel);
6615 break;
6616 case OMPD_task:
6617 Res =
6618 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6619 AllowedNameModifiers.push_back(OMPD_task);
6620 break;
6621 case OMPD_taskyield:
6622 assert(ClausesWithImplicit.empty() &&
6623 "No clauses are allowed for 'omp taskyield' directive");
6624 assert(AStmt == nullptr &&
6625 "No associated statement allowed for 'omp taskyield' directive");
6626 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6627 break;
6628 case OMPD_error:
6629 assert(AStmt == nullptr &&
6630 "No associated statement allowed for 'omp error' directive");
6631 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6632 break;
6633 case OMPD_barrier:
6634 assert(ClausesWithImplicit.empty() &&
6635 "No clauses are allowed for 'omp barrier' directive");
6636 assert(AStmt == nullptr &&
6637 "No associated statement allowed for 'omp barrier' directive");
6638 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6639 break;
6640 case OMPD_taskwait:
6641 assert(AStmt == nullptr &&
6642 "No associated statement allowed for 'omp taskwait' directive");
6643 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6644 break;
6645 case OMPD_taskgroup:
6646 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6647 EndLoc);
6648 break;
6649 case OMPD_flush:
6650 assert(AStmt == nullptr &&
6651 "No associated statement allowed for 'omp flush' directive");
6652 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6653 break;
6654 case OMPD_depobj:
6655 assert(AStmt == nullptr &&
6656 "No associated statement allowed for 'omp depobj' directive");
6657 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6658 break;
6659 case OMPD_scan:
6660 assert(AStmt == nullptr &&
6661 "No associated statement allowed for 'omp scan' directive");
6662 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6663 break;
6664 case OMPD_ordered:
6665 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6666 EndLoc);
6667 break;
6668 case OMPD_atomic:
6669 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6670 EndLoc);
6671 break;
6672 case OMPD_teams:
6673 Res =
6674 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6675 break;
6676 case OMPD_target:
6677 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6678 EndLoc);
6679 AllowedNameModifiers.push_back(OMPD_target);
6680 break;
6681 case OMPD_target_parallel:
6682 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6683 StartLoc, EndLoc);
6684 AllowedNameModifiers.push_back(OMPD_target);
6685 AllowedNameModifiers.push_back(OMPD_parallel);
6686 break;
6687 case OMPD_target_parallel_for:
6689 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6690 AllowedNameModifiers.push_back(OMPD_target);
6691 AllowedNameModifiers.push_back(OMPD_parallel);
6692 break;
6693 case OMPD_cancellation_point:
6694 assert(ClausesWithImplicit.empty() &&
6695 "No clauses are allowed for 'omp cancellation point' directive");
6696 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6697 "cancellation point' directive");
6698 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6699 break;
6700 case OMPD_cancel:
6701 assert(AStmt == nullptr &&
6702 "No associated statement allowed for 'omp cancel' directive");
6703 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6704 CancelRegion);
6705 AllowedNameModifiers.push_back(OMPD_cancel);
6706 break;
6707 case OMPD_target_data:
6708 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6709 EndLoc);
6710 AllowedNameModifiers.push_back(OMPD_target_data);
6711 break;
6712 case OMPD_target_enter_data:
6713 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6714 EndLoc, AStmt);
6715 AllowedNameModifiers.push_back(OMPD_target_enter_data);
6716 break;
6717 case OMPD_target_exit_data:
6718 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6719 EndLoc, AStmt);
6720 AllowedNameModifiers.push_back(OMPD_target_exit_data);
6721 break;
6722 case OMPD_taskloop:
6723 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6724 EndLoc, VarsWithInheritedDSA);
6725 AllowedNameModifiers.push_back(OMPD_taskloop);
6726 break;
6727 case OMPD_taskloop_simd:
6728 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6729 EndLoc, VarsWithInheritedDSA);
6730 AllowedNameModifiers.push_back(OMPD_taskloop);
6731 if (getLangOpts().OpenMP >= 50)
6732 AllowedNameModifiers.push_back(OMPD_simd);
6733 break;
6734 case OMPD_master_taskloop:
6736 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6737 AllowedNameModifiers.push_back(OMPD_taskloop);
6738 break;
6739 case OMPD_masked_taskloop:
6741 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6742 AllowedNameModifiers.push_back(OMPD_taskloop);
6743 break;
6744 case OMPD_master_taskloop_simd:
6746 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6747 AllowedNameModifiers.push_back(OMPD_taskloop);
6748 if (getLangOpts().OpenMP >= 50)
6749 AllowedNameModifiers.push_back(OMPD_simd);
6750 break;
6751 case OMPD_masked_taskloop_simd:
6753 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6754 if (getLangOpts().OpenMP >= 51) {
6755 AllowedNameModifiers.push_back(OMPD_taskloop);
6756 AllowedNameModifiers.push_back(OMPD_simd);
6757 }
6758 break;
6759 case OMPD_parallel_master_taskloop:
6761 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6762 AllowedNameModifiers.push_back(OMPD_taskloop);
6763 AllowedNameModifiers.push_back(OMPD_parallel);
6764 break;
6765 case OMPD_parallel_masked_taskloop:
6767 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6768 if (getLangOpts().OpenMP >= 51) {
6769 AllowedNameModifiers.push_back(OMPD_taskloop);
6770 AllowedNameModifiers.push_back(OMPD_parallel);
6771 }
6772 break;
6773 case OMPD_parallel_master_taskloop_simd:
6775 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6776 AllowedNameModifiers.push_back(OMPD_taskloop);
6777 AllowedNameModifiers.push_back(OMPD_parallel);
6778 if (getLangOpts().OpenMP >= 50)
6779 AllowedNameModifiers.push_back(OMPD_simd);
6780 break;
6781 case OMPD_parallel_masked_taskloop_simd:
6783 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6784 if (getLangOpts().OpenMP >= 51) {
6785 AllowedNameModifiers.push_back(OMPD_taskloop);
6786 AllowedNameModifiers.push_back(OMPD_parallel);
6787 AllowedNameModifiers.push_back(OMPD_simd);
6788 }
6789 break;
6790 case OMPD_distribute:
6791 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6792 EndLoc, VarsWithInheritedDSA);
6793 break;
6794 case OMPD_target_update:
6795 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6796 EndLoc, AStmt);
6797 AllowedNameModifiers.push_back(OMPD_target_update);
6798 break;
6799 case OMPD_distribute_parallel_for:
6801 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6802 AllowedNameModifiers.push_back(OMPD_parallel);
6803 break;
6804 case OMPD_distribute_parallel_for_simd:
6806 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6807 AllowedNameModifiers.push_back(OMPD_parallel);
6808 if (getLangOpts().OpenMP >= 50)
6809 AllowedNameModifiers.push_back(OMPD_simd);
6810 break;
6811 case OMPD_distribute_simd:
6813 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6814 if (getLangOpts().OpenMP >= 50)
6815 AllowedNameModifiers.push_back(OMPD_simd);
6816 break;
6817 case OMPD_target_parallel_for_simd:
6819 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6820 AllowedNameModifiers.push_back(OMPD_target);
6821 AllowedNameModifiers.push_back(OMPD_parallel);
6822 if (getLangOpts().OpenMP >= 50)
6823 AllowedNameModifiers.push_back(OMPD_simd);
6824 break;
6825 case OMPD_target_simd:
6826 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6827 EndLoc, VarsWithInheritedDSA);
6828 AllowedNameModifiers.push_back(OMPD_target);
6829 if (getLangOpts().OpenMP >= 50)
6830 AllowedNameModifiers.push_back(OMPD_simd);
6831 break;
6832 case OMPD_teams_distribute:
6834 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6835 break;
6836 case OMPD_teams_distribute_simd:
6838 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6839 if (getLangOpts().OpenMP >= 50)
6840 AllowedNameModifiers.push_back(OMPD_simd);
6841 break;
6842 case OMPD_teams_distribute_parallel_for_simd:
6844 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6845 AllowedNameModifiers.push_back(OMPD_parallel);
6846 if (getLangOpts().OpenMP >= 50)
6847 AllowedNameModifiers.push_back(OMPD_simd);
6848 break;
6849 case OMPD_teams_distribute_parallel_for:
6851 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6852 AllowedNameModifiers.push_back(OMPD_parallel);
6853 break;
6854 case OMPD_target_teams:
6855 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6856 EndLoc);
6857 AllowedNameModifiers.push_back(OMPD_target);
6858 break;
6859 case OMPD_target_teams_distribute:
6861 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6862 AllowedNameModifiers.push_back(OMPD_target);
6863 break;
6864 case OMPD_target_teams_distribute_parallel_for:
6866 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6867 AllowedNameModifiers.push_back(OMPD_target);
6868 AllowedNameModifiers.push_back(OMPD_parallel);
6869 break;
6870 case OMPD_target_teams_distribute_parallel_for_simd:
6872 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6873 AllowedNameModifiers.push_back(OMPD_target);
6874 AllowedNameModifiers.push_back(OMPD_parallel);
6875 if (getLangOpts().OpenMP >= 50)
6876 AllowedNameModifiers.push_back(OMPD_simd);
6877 break;
6878 case OMPD_target_teams_distribute_simd:
6880 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6881 AllowedNameModifiers.push_back(OMPD_target);
6882 if (getLangOpts().OpenMP >= 50)
6883 AllowedNameModifiers.push_back(OMPD_simd);
6884 break;
6885 case OMPD_interop:
6886 assert(AStmt == nullptr &&
6887 "No associated statement allowed for 'omp interop' directive");
6888 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6889 break;
6890 case OMPD_dispatch:
6891 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6892 EndLoc);
6893 break;
6894 case OMPD_loop:
6895 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6896 EndLoc, VarsWithInheritedDSA);
6897 break;
6898 case OMPD_teams_loop:
6900 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6901 break;
6902 case OMPD_target_teams_loop:
6904 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6905 AllowedNameModifiers.push_back(OMPD_target);
6906 break;
6907 case OMPD_parallel_loop:
6909 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6910 break;
6911 case OMPD_target_parallel_loop:
6913 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6914 break;
6915 case OMPD_declare_target:
6916 case OMPD_end_declare_target:
6917 case OMPD_threadprivate:
6918 case OMPD_allocate:
6919 case OMPD_declare_reduction:
6920 case OMPD_declare_mapper:
6921 case OMPD_declare_simd:
6922 case OMPD_requires:
6923 case OMPD_declare_variant:
6924 case OMPD_begin_declare_variant:
6925 case OMPD_end_declare_variant:
6926 llvm_unreachable("OpenMP Directive is not allowed");
6927 case OMPD_unknown:
6928 default:
6929 llvm_unreachable("Unknown OpenMP directive");
6930 }
6931
6932 ErrorFound = Res.isInvalid() || ErrorFound;
6933
6934 // Check variables in the clauses if default(none) or
6935 // default(firstprivate) was specified.
6936 if (DSAStack->getDefaultDSA() == DSA_none ||
6937 DSAStack->getDefaultDSA() == DSA_private ||
6938 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6939 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6940 for (OMPClause *C : Clauses) {
6941 switch (C->getClauseKind()) {
6942 case OMPC_num_threads:
6943 case OMPC_dist_schedule:
6944 // Do not analyse if no parent teams directive.
6945 if (isOpenMPTeamsDirective(Kind))
6946 break;
6947 continue;
6948 case OMPC_if:
6949 if (isOpenMPTeamsDirective(Kind) &&
6950 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6951 break;
6952 if (isOpenMPParallelDirective(Kind) &&
6954 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6955 break;
6956 continue;
6957 case OMPC_schedule:
6958 case OMPC_detach:
6959 break;
6960 case OMPC_grainsize:
6961 case OMPC_num_tasks:
6962 case OMPC_final:
6963 case OMPC_priority:
6964 case OMPC_novariants:
6965 case OMPC_nocontext:
6966 // Do not analyze if no parent parallel directive.
6967 if (isOpenMPParallelDirective(Kind))
6968 break;
6969 continue;
6970 case OMPC_ordered:
6971 case OMPC_device:
6972 case OMPC_num_teams:
6973 case OMPC_thread_limit:
6974 case OMPC_hint:
6975 case OMPC_collapse:
6976 case OMPC_safelen:
6977 case OMPC_simdlen:
6978 case OMPC_sizes:
6979 case OMPC_default:
6980 case OMPC_proc_bind:
6981 case OMPC_private:
6982 case OMPC_firstprivate:
6983 case OMPC_lastprivate:
6984 case OMPC_shared:
6985 case OMPC_reduction:
6986 case OMPC_task_reduction:
6987 case OMPC_in_reduction:
6988 case OMPC_linear:
6989 case OMPC_aligned:
6990 case OMPC_copyin:
6991 case OMPC_copyprivate:
6992 case OMPC_nowait:
6993 case OMPC_untied:
6994 case OMPC_mergeable:
6995 case OMPC_allocate:
6996 case OMPC_read:
6997 case OMPC_write:
6998 case OMPC_update:
6999 case OMPC_capture:
7000 case OMPC_compare:
7001 case OMPC_seq_cst:
7002 case OMPC_acq_rel:
7003 case OMPC_acquire:
7004 case OMPC_release:
7005 case OMPC_relaxed:
7006 case OMPC_depend:
7007 case OMPC_threads:
7008 case OMPC_simd:
7009 case OMPC_map:
7010 case OMPC_nogroup:
7011 case OMPC_defaultmap:
7012 case OMPC_to:
7013 case OMPC_from:
7014 case OMPC_use_device_ptr:
7015 case OMPC_use_device_addr:
7016 case OMPC_is_device_ptr:
7017 case OMPC_has_device_addr:
7018 case OMPC_nontemporal:
7019 case OMPC_order:
7020 case OMPC_destroy:
7021 case OMPC_inclusive:
7022 case OMPC_exclusive:
7023 case OMPC_uses_allocators:
7024 case OMPC_affinity:
7025 case OMPC_bind:
7026 case OMPC_filter:
7027 continue;
7028 case OMPC_allocator:
7029 case OMPC_flush:
7030 case OMPC_depobj:
7031 case OMPC_threadprivate:
7032 case OMPC_uniform:
7033 case OMPC_unknown:
7034 case OMPC_unified_address:
7035 case OMPC_unified_shared_memory:
7036 case OMPC_reverse_offload:
7037 case OMPC_dynamic_allocators:
7038 case OMPC_atomic_default_mem_order:
7039 case OMPC_device_type:
7040 case OMPC_match:
7041 case OMPC_when:
7042 case OMPC_at:
7043 case OMPC_severity:
7044 case OMPC_message:
7045 default:
7046 llvm_unreachable("Unexpected clause");
7047 }
7048 for (Stmt *CC : C->children()) {
7049 if (CC)
7050 DSAChecker.Visit(CC);
7051 }
7052 }
7053 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
7054 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
7055 }
7056 for (const auto &P : VarsWithInheritedDSA) {
7057 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
7058 continue;
7059 ErrorFound = true;
7060 if (DSAStack->getDefaultDSA() == DSA_none ||
7061 DSAStack->getDefaultDSA() == DSA_private ||
7062 DSAStack->getDefaultDSA() == DSA_firstprivate) {
7063 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
7064 << P.first << P.second->getSourceRange();
7065 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
7066 } else if (getLangOpts().OpenMP >= 50) {
7067 Diag(P.second->getExprLoc(),
7068 diag::err_omp_defaultmap_no_attr_for_variable)
7069 << P.first << P.second->getSourceRange();
7070 Diag(DSAStack->getDefaultDSALocation(),
7071 diag::note_omp_defaultmap_attr_none);
7072 }
7073 }
7074
7075 if (!AllowedNameModifiers.empty())
7076 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
7077 ErrorFound;
7078
7079 if (ErrorFound)
7080 return StmtError();
7081
7084 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
7085 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
7086 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
7087 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
7088 // Register target to DSA Stack.
7089 DSAStack->addTargetDirLocation(StartLoc);
7090 }
7091
7092 return Res;
7093}
7094
7096 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
7097 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
7098 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
7099 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
7100 assert(Aligneds.size() == Alignments.size());
7101 assert(Linears.size() == LinModifiers.size());
7102 assert(Linears.size() == Steps.size());
7103 if (!DG || DG.get().isNull())
7104 return DeclGroupPtrTy();
7105
7106 const int SimdId = 0;
7107 if (!DG.get().isSingleDecl()) {
7108 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7109 << SimdId;
7110 return DG;
7111 }
7112 Decl *ADecl = DG.get().getSingleDecl();
7113 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7114 ADecl = FTD->getTemplatedDecl();
7115
7116 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7117 if (!FD) {
7118 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
7119 return DeclGroupPtrTy();
7120 }
7121
7122 // OpenMP [2.8.2, declare simd construct, Description]
7123 // The parameter of the simdlen clause must be a constant positive integer
7124 // expression.
7125 ExprResult SL;
7126 if (Simdlen)
7127 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
7128 // OpenMP [2.8.2, declare simd construct, Description]
7129 // The special this pointer can be used as if was one of the arguments to the
7130 // function in any of the linear, aligned, or uniform clauses.
7131 // The uniform clause declares one or more arguments to have an invariant
7132 // value for all concurrent invocations of the function in the execution of a
7133 // single SIMD loop.
7134 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7135 const Expr *UniformedLinearThis = nullptr;
7136 for (const Expr *E : Uniforms) {
7137 E = E->IgnoreParenImpCasts();
7138 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7139 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
7140 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7141 FD->getParamDecl(PVD->getFunctionScopeIndex())
7142 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7143 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7144 continue;
7145 }
7146 if (isa<CXXThisExpr>(E)) {
7147 UniformedLinearThis = E;
7148 continue;
7149 }
7150 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7151 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7152 }
7153 // OpenMP [2.8.2, declare simd construct, Description]
7154 // The aligned clause declares that the object to which each list item points
7155 // is aligned to the number of bytes expressed in the optional parameter of
7156 // the aligned clause.
7157 // The special this pointer can be used as if was one of the arguments to the
7158 // function in any of the linear, aligned, or uniform clauses.
7159 // The type of list items appearing in the aligned clause must be array,
7160 // pointer, reference to array, or reference to pointer.
7161 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7162 const Expr *AlignedThis = nullptr;
7163 for (const Expr *E : Aligneds) {
7164 E = E->IgnoreParenImpCasts();
7165 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7166 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7167 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7168 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7169 FD->getParamDecl(PVD->getFunctionScopeIndex())
7170 ->getCanonicalDecl() == CanonPVD) {
7171 // OpenMP [2.8.1, simd construct, Restrictions]
7172 // A list-item cannot appear in more than one aligned clause.
7173 if (AlignedArgs.count(CanonPVD) > 0) {
7174 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7175 << 1 << getOpenMPClauseName(OMPC_aligned)
7176 << E->getSourceRange();
7177 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
7178 diag::note_omp_explicit_dsa)
7179 << getOpenMPClauseName(OMPC_aligned);
7180 continue;
7181 }
7182 AlignedArgs[CanonPVD] = E;
7183 QualType QTy = PVD->getType()
7184 .getNonReferenceType()
7185 .getUnqualifiedType()
7186 .getCanonicalType();
7187 const Type *Ty = QTy.getTypePtrOrNull();
7188 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7189 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7190 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7191 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7192 }
7193 continue;
7194 }
7195 }
7196 if (isa<CXXThisExpr>(E)) {
7197 if (AlignedThis) {
7198 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7199 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
7200 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7201 << getOpenMPClauseName(OMPC_aligned);
7202 }
7203 AlignedThis = E;
7204 continue;
7205 }
7206 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7207 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7208 }
7209 // The optional parameter of the aligned clause, alignment, must be a constant
7210 // positive integer expression. If no optional parameter is specified,
7211 // implementation-defined default alignments for SIMD instructions on the
7212 // target platforms are assumed.
7214 for (Expr *E : Alignments) {
7215 ExprResult Align;
7216 if (E)
7217 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7218 NewAligns.push_back(Align.get());
7219 }
7220 // OpenMP [2.8.2, declare simd construct, Description]
7221 // The linear clause declares one or more list items to be private to a SIMD
7222 // lane and to have a linear relationship with respect to the iteration space
7223 // of a loop.
7224 // The special this pointer can be used as if was one of the arguments to the
7225 // function in any of the linear, aligned, or uniform clauses.
7226 // When a linear-step expression is specified in a linear clause it must be
7227 // either a constant integer expression or an integer-typed parameter that is
7228 // specified in a uniform clause on the directive.
7229 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7230 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7231 auto MI = LinModifiers.begin();
7232 for (const Expr *E : Linears) {
7233 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7234 ++MI;
7235 E = E->IgnoreParenImpCasts();
7236 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7237 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7238 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7239 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7240 FD->getParamDecl(PVD->getFunctionScopeIndex())
7241 ->getCanonicalDecl() == CanonPVD) {
7242 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7243 // A list-item cannot appear in more than one linear clause.
7244 if (LinearArgs.count(CanonPVD) > 0) {
7245 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7246 << getOpenMPClauseName(OMPC_linear)
7247 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
7248 Diag(LinearArgs[CanonPVD]->getExprLoc(),
7249 diag::note_omp_explicit_dsa)
7250 << getOpenMPClauseName(OMPC_linear);
7251 continue;
7252 }
7253 // Each argument can appear in at most one uniform or linear clause.
7254 if (UniformedArgs.count(CanonPVD) > 0) {
7255 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7256 << getOpenMPClauseName(OMPC_linear)
7257 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
7258 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
7259 diag::note_omp_explicit_dsa)
7260 << getOpenMPClauseName(OMPC_uniform);
7261 continue;
7262 }
7263 LinearArgs[CanonPVD] = E;
7264 if (E->isValueDependent() || E->isTypeDependent() ||
7267 continue;
7268 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7269 PVD->getOriginalType(),
7270 /*IsDeclareSimd=*/true);
7271 continue;
7272 }
7273 }
7274 if (isa<CXXThisExpr>(E)) {
7275 if (UniformedLinearThis) {
7276 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7277 << getOpenMPClauseName(OMPC_linear)
7278 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
7279 << E->getSourceRange();
7280 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7281 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
7282 : OMPC_linear);
7283 continue;
7284 }
7285 UniformedLinearThis = E;
7286 if (E->isValueDependent() || E->isTypeDependent() ||
7288 continue;
7289 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7290 E->getType(), /*IsDeclareSimd=*/true);
7291 continue;
7292 }
7293 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7294 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7295 }
7296 Expr *Step = nullptr;
7297 Expr *NewStep = nullptr;
7298 SmallVector<Expr *, 4> NewSteps;
7299 for (Expr *E : Steps) {
7300 // Skip the same step expression, it was checked already.
7301 if (Step == E || !E) {
7302 NewSteps.push_back(E ? NewStep : nullptr);
7303 continue;
7304 }
7305 Step = E;
7306 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7307 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7308 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7309 if (UniformedArgs.count(CanonPVD) == 0) {
7310 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7311 << Step->getSourceRange();
7312 } else if (E->isValueDependent() || E->isTypeDependent() ||
7315 CanonPVD->getType()->hasIntegerRepresentation()) {
7316 NewSteps.push_back(Step);
7317 } else {
7318 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7319 << Step->getSourceRange();
7320 }
7321 continue;
7322 }
7323 NewStep = Step;
7324 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7325 !Step->isInstantiationDependent() &&
7327 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7328 .get();
7329 if (NewStep)
7330 NewStep = SemaRef
7332 NewStep, /*FIXME*/ Sema::AllowFold)
7333 .get();
7334 }
7335 NewSteps.push_back(NewStep);
7336 }
7337 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7338 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7339 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7340 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7341 const_cast<Expr **>(Linears.data()), Linears.size(),
7342 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7343 NewSteps.data(), NewSteps.size(), SR);
7344 ADecl->addAttr(NewAttr);
7345 return DG;
7346}
7347
7348static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7349 QualType NewType) {
7350 assert(NewType->isFunctionProtoType() &&
7351 "Expected function type with prototype.");
7352 assert(FD->getType()->isFunctionNoProtoType() &&
7353 "Expected function with type with no prototype.");
7354 assert(FDWithProto->getType()->isFunctionProtoType() &&
7355 "Expected function with prototype.");
7356 // Synthesize parameters with the same types.
7357 FD->setType(NewType);
7359 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7360 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7361 SourceLocation(), nullptr, P->getType(),
7362 /*TInfo=*/nullptr, SC_None, nullptr);
7363 Param->setScopeInfo(0, Params.size());
7364 Param->setImplicit();
7365 Params.push_back(Param);
7366 }
7367
7368 FD->setParams(Params);
7369}
7370
7372 if (D->isInvalidDecl())
7373 return;
7374 FunctionDecl *FD = nullptr;
7375 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7376 FD = UTemplDecl->getTemplatedDecl();
7377 else
7378 FD = cast<FunctionDecl>(D);
7379 assert(FD && "Expected a function declaration!");
7380
7381 // If we are instantiating templates we do *not* apply scoped assumptions but
7382 // only global ones. We apply scoped assumption to the template definition
7383 // though.
7385 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7386 FD->addAttr(AA);
7387 }
7388 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7389 FD->addAttr(AA);
7390}
7391
7392SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7393 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7394
7396 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7398 if (!D.getIdentifier())
7399 return;
7400
7401 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7402
7403 // Template specialization is an extension, check if we do it.
7404 bool IsTemplated = !TemplateParamLists.empty();
7405 if (IsTemplated &
7406 !DVScope.TI->isExtensionActive(
7407 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7408 return;
7409
7410 const IdentifierInfo *BaseII = D.getIdentifier();
7414 /*ObjectType=*/QualType());
7415
7417 QualType FType = TInfo->getType();
7418
7419 bool IsConstexpr =
7421 bool IsConsteval =
7423
7424 for (auto *Candidate : Lookup) {
7425 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7426 FunctionDecl *UDecl = nullptr;
7427 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7428 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7429 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7430 UDecl = FTD->getTemplatedDecl();
7431 } else if (!IsTemplated)
7432 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7433 if (!UDecl)
7434 continue;
7435
7436 // Don't specialize constexpr/consteval functions with
7437 // non-constexpr/consteval functions.
7438 if (UDecl->isConstexpr() && !IsConstexpr)
7439 continue;
7440 if (UDecl->isConsteval() && !IsConsteval)
7441 continue;
7442
7443 QualType UDeclTy = UDecl->getType();
7444 if (!UDeclTy->isDependentType()) {
7446 FType, UDeclTy, /* OfBlockPointer */ false,
7447 /* Unqualified */ false, /* AllowCXX */ true);
7448 if (NewType.isNull())
7449 continue;
7450 }
7451
7452 // Found a base!
7453 Bases.push_back(UDecl);
7454 }
7455
7456 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7457 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7458 // If no base was found we create a declaration that we use as base.
7459 if (Bases.empty() && UseImplicitBase) {
7461 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7462 BaseD->setImplicit(true);
7463 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7464 Bases.push_back(BaseTemplD->getTemplatedDecl());
7465 else
7466 Bases.push_back(cast<FunctionDecl>(BaseD));
7467 }
7468
7469 std::string MangledName;
7470 MangledName += D.getIdentifier()->getName();
7471 MangledName += getOpenMPVariantManglingSeparatorStr();
7472 MangledName += DVScope.NameSuffix;
7473 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7474
7475 VariantII.setMangledOpenMPVariantName(true);
7476 D.SetIdentifier(&VariantII, D.getBeginLoc());
7477}
7478
7481 // Do not mark function as is used to prevent its emission if this is the
7482 // only place where it is used.
7485
7486 FunctionDecl *FD = nullptr;
7487 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7488 FD = UTemplDecl->getTemplatedDecl();
7489 else
7490 FD = cast<FunctionDecl>(D);
7491 auto *VariantFuncRef = DeclRefExpr::Create(
7493 /* RefersToEnclosingVariableOrCapture */ false,
7494 /* NameLoc */ FD->getLocation(), FD->getType(),
7496
7497 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7498 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7499 getASTContext(), VariantFuncRef, DVScope.TI,
7500 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7501 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7502 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7503 for (FunctionDecl *BaseFD : Bases)
7504 BaseFD->addAttr(OMPDeclareVariantA);
7505}
7506
7508 SourceLocation LParenLoc,
7509 MultiExprArg ArgExprs,
7510 SourceLocation RParenLoc,
7511 Expr *ExecConfig) {
7512 // The common case is a regular call we do not want to specialize at all. Try
7513 // to make that case fast by bailing early.
7514 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7515 if (!CE)
7516 return Call;
7517
7518 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7519 if (!CalleeFnDecl)
7520 return Call;
7521
7522 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7523 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7524 // checking for any calls inside an Order region
7526 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7527 }
7528
7529 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7530 return Call;
7531
7532 ASTContext &Context = getASTContext();
7533 std::function<void(StringRef)> DiagUnknownTrait = [this,
7534 CE](StringRef ISATrait) {
7535 // TODO Track the selector locations in a way that is accessible here to
7536 // improve the diagnostic location.
7537 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7538 << ISATrait;
7539 };
7540 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7542 DSAStack->getConstructTraits());
7543
7544 QualType CalleeFnType = CalleeFnDecl->getType();
7545
7548 while (CalleeFnDecl) {
7549 for (OMPDeclareVariantAttr *A :
7550 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7551 Expr *VariantRef = A->getVariantFuncRef();
7552
7553 VariantMatchInfo VMI;
7554 OMPTraitInfo &TI = A->getTraitInfo();
7555 TI.getAsVariantMatchInfo(Context, VMI);
7556 if (!isVariantApplicableInContext(VMI, OMPCtx,
7557 /* DeviceSetOnly */ false))
7558 continue;
7559
7560 VMIs.push_back(VMI);
7561 Exprs.push_back(VariantRef);
7562 }
7563
7564 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7565 }
7566
7567 ExprResult NewCall;
7568 do {
7569 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7570 if (BestIdx < 0)
7571 return Call;
7572 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7573 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7574
7575 {
7576 // Try to build a (member) call expression for the current best applicable
7577 // variant expression. We allow this to fail in which case we continue
7578 // with the next best variant expression. The fail case is part of the
7579 // implementation defined behavior in the OpenMP standard when it talks
7580 // about what differences in the function prototypes: "Any differences
7581 // that the specific OpenMP context requires in the prototype of the
7582 // variant from the base function prototype are implementation defined."
7583 // This wording is there to allow the specialized variant to have a
7584 // different type than the base function. This is intended and OK but if
7585 // we cannot create a call the difference is not in the "implementation
7586 // defined range" we allow.
7588
7589 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7590 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7591 BestExpr = MemberExpr::CreateImplicit(
7592 Context, MemberCall->getImplicitObjectArgument(),
7593 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7594 MemberCall->getValueKind(), MemberCall->getObjectKind());
7595 }
7596 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7597 RParenLoc, ExecConfig);
7598 if (NewCall.isUsable()) {
7599 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7600 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7602 CalleeFnType, NewCalleeFnDecl->getType(),
7603 /* OfBlockPointer */ false,
7604 /* Unqualified */ false, /* AllowCXX */ true);
7605 if (!NewType.isNull())
7606 break;
7607 // Don't use the call if the function type was not compatible.
7608 NewCall = nullptr;
7609 }
7610 }
7611 }
7612
7613 VMIs.erase(VMIs.begin() + BestIdx);
7614 Exprs.erase(Exprs.begin() + BestIdx);
7615 } while (!VMIs.empty());
7616
7617 if (!NewCall.isUsable())
7618 return Call;
7619 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7620}
7621
7622std::optional<std::pair<FunctionDecl *, Expr *>>
7624 Expr *VariantRef,
7625 OMPTraitInfo &TI,
7626 unsigned NumAppendArgs,
7627 SourceRange SR) {
7628 ASTContext &Context = getASTContext();
7629 if (!DG || DG.get().isNull())
7630 return std::nullopt;
7631
7632 const int VariantId = 1;
7633 // Must be applied only to single decl.
7634 if (!DG.get().isSingleDecl()) {
7635 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7636 << VariantId << SR;
7637 return std::nullopt;
7638 }
7639 Decl *ADecl = DG.get().getSingleDecl();
7640 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7641 ADecl = FTD->getTemplatedDecl();
7642
7643 // Decl must be a function.
7644 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7645 if (!FD) {
7646 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7647 << VariantId << SR;
7648 return std::nullopt;
7649 }
7650
7651 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7652 // The 'target' attribute needs to be separately checked because it does
7653 // not always signify a multiversion function declaration.
7654 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7655 };
7656 // OpenMP is not compatible with multiversion function attributes.
7657 if (HasMultiVersionAttributes(FD)) {
7658 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7659 << SR;
7660 return std::nullopt;
7661 }
7662
7663 // Allow #pragma omp declare variant only if the function is not used.
7664 if (FD->isUsed(false))
7665 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7666 << FD->getLocation();
7667
7668 // Check if the function was emitted already.
7669 const FunctionDecl *Definition;
7670 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7671 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7672 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7673 << FD->getLocation();
7674
7675 // The VariantRef must point to function.
7676 if (!VariantRef) {
7677 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7678 return std::nullopt;
7679 }
7680
7681 auto ShouldDelayChecks = [](Expr *&E, bool) {
7682 return E && (E->isTypeDependent() || E->isValueDependent() ||
7685 };
7686 // Do not check templates, wait until instantiation.
7687 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7688 TI.anyScoreOrCondition(ShouldDelayChecks))
7689 return std::make_pair(FD, VariantRef);
7690
7691 // Deal with non-constant score and user condition expressions.
7692 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7693 bool IsScore) -> bool {
7694 if (!E || E->isIntegerConstantExpr(getASTContext()))
7695 return false;
7696
7697 if (IsScore) {
7698 // We warn on non-constant scores and pretend they were not present.
7699 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7700 << E;
7701 E = nullptr;
7702 } else {
7703 // We could replace a non-constant user condition with "false" but we
7704 // will soon need to handle these anyway for the dynamic version of
7705 // OpenMP context selectors.
7706 Diag(E->getExprLoc(),
7707 diag::err_omp_declare_variant_user_condition_not_constant)
7708 << E;
7709 }
7710 return true;
7711 };
7712 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7713 return std::nullopt;
7714
7715 QualType AdjustedFnType = FD->getType();
7716 if (NumAppendArgs) {
7717 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7718 if (!PTy) {
7719 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7720 << SR;
7721 return std::nullopt;
7722 }
7723 // Adjust the function type to account for an extra omp_interop_t for each
7724 // specified in the append_args clause.
7725 const TypeDecl *TD = nullptr;
7726 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7729 NamedDecl *ND = Result.getFoundDecl();
7730 TD = dyn_cast_or_null<TypeDecl>(ND);
7731 }
7732 if (!TD) {
7733 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7734 return std::nullopt;
7735 }
7736 QualType InteropType = Context.getTypeDeclType(TD);
7737 if (PTy->isVariadic()) {
7738 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7739 return std::nullopt;
7740 }
7742 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7743 Params.insert(Params.end(), NumAppendArgs, InteropType);
7744 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7745 PTy->getExtProtoInfo());
7746 }
7747
7748 // Convert VariantRef expression to the type of the original function to
7749 // resolve possible conflicts.
7750 ExprResult VariantRefCast = VariantRef;
7751 if (getLangOpts().CPlusPlus) {
7752 QualType FnPtrType;
7753 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7754 if (Method && !Method->isStatic()) {
7755 const Type *ClassType =
7756 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7757 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7758 ExprResult ER;
7759 {
7760 // Build adrr_of unary op to correctly handle type checks for member
7761 // functions.
7763 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7764 VariantRef);
7765 }
7766 if (!ER.isUsable()) {
7767 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7768 << VariantId << VariantRef->getSourceRange();
7769 return std::nullopt;
7770 }
7771 VariantRef = ER.get();
7772 } else {
7773 FnPtrType = Context.getPointerType(AdjustedFnType);
7774 }
7775 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7776 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7778 VariantRef, FnPtrType.getUnqualifiedType(),
7779 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7780 /*InOverloadResolution=*/false,
7781 /*CStyle=*/false,
7782 /*AllowObjCWritebackConversion=*/false);
7783 if (ICS.isFailure()) {
7784 Diag(VariantRef->getExprLoc(),
7785 diag::err_omp_declare_variant_incompat_types)
7786 << VariantRef->getType()
7787 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7788 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7789 return std::nullopt;
7790 }
7791 VariantRefCast = SemaRef.PerformImplicitConversion(
7792 VariantRef, FnPtrType.getUnqualifiedType(), Sema::AA_Converting);
7793 if (!VariantRefCast.isUsable())
7794 return std::nullopt;
7795 }
7796 // Drop previously built artificial addr_of unary op for member functions.
7797 if (Method && !Method->isStatic()) {
7798 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7799 if (auto *UO = dyn_cast<UnaryOperator>(
7800 PossibleAddrOfVariantRef->IgnoreImplicit()))
7801 VariantRefCast = UO->getSubExpr();
7802 }
7803 }
7804
7805 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7806 if (!ER.isUsable() ||
7808 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7809 << VariantId << VariantRef->getSourceRange();
7810 return std::nullopt;
7811 }
7812
7813 // The VariantRef must point to function.
7814 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7815 if (!DRE) {
7816 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7817 << VariantId << VariantRef->getSourceRange();
7818 return std::nullopt;
7819 }
7820 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7821 if (!NewFD) {
7822 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7823 << VariantId << VariantRef->getSourceRange();
7824 return std::nullopt;
7825 }
7826
7827 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7828 Diag(VariantRef->getExprLoc(),
7829 diag::err_omp_declare_variant_same_base_function)
7830 << VariantRef->getSourceRange();
7831 return std::nullopt;
7832 }
7833
7834 // Check if function types are compatible in C.
7835 if (!getLangOpts().CPlusPlus) {
7836 QualType NewType =
7837 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7838 if (NewType.isNull()) {
7839 Diag(VariantRef->getExprLoc(),
7840 diag::err_omp_declare_variant_incompat_types)
7841 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7842 << VariantRef->getSourceRange();
7843 return std::nullopt;
7844 }
7845 if (NewType->isFunctionProtoType()) {
7846 if (FD->getType()->isFunctionNoProtoType())
7847 setPrototype(SemaRef, FD, NewFD, NewType);
7848 else if (NewFD->getType()->isFunctionNoProtoType())
7849 setPrototype(SemaRef, NewFD, FD, NewType);
7850 }
7851 }
7852
7853 // Check if variant function is not marked with declare variant directive.
7854 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7855 Diag(VariantRef->getExprLoc(),
7856 diag::warn_omp_declare_variant_marked_as_declare_variant)
7857 << VariantRef->getSourceRange();
7858 SourceRange SR =
7859 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7860 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7861 return std::nullopt;
7862 }
7863
7864 enum DoesntSupport {
7865 VirtFuncs = 1,
7866 Constructors = 3,
7867 Destructors = 4,
7868 DeletedFuncs = 5,
7869 DefaultedFuncs = 6,
7870 ConstexprFuncs = 7,
7871 ConstevalFuncs = 8,
7872 };
7873 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7874 if (CXXFD->isVirtual()) {
7875 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7876 << VirtFuncs;
7877 return std::nullopt;
7878 }
7879
7880 if (isa<CXXConstructorDecl>(FD)) {
7881 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7882 << Constructors;
7883 return std::nullopt;
7884 }
7885
7886 if (isa<CXXDestructorDecl>(FD)) {
7887 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7888 << Destructors;
7889 return std::nullopt;
7890 }
7891 }
7892
7893 if (FD->isDeleted()) {
7894 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7895 << DeletedFuncs;
7896 return std::nullopt;
7897 }
7898
7899 if (FD->isDefaulted()) {
7900 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7901 << DefaultedFuncs;
7902 return std::nullopt;
7903 }
7904
7905 if (FD->isConstexpr()) {
7906 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7907 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7908 return std::nullopt;
7909 }
7910
7911 // Check general compatibility.
7917 VariantRef->getExprLoc(),
7918 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7919 PartialDiagnosticAt(VariantRef->getExprLoc(),
7920 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7921 << FD->getLocation()),
7922 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7923 /*CLinkageMayDiffer=*/true))
7924 return std::nullopt;
7925 return std::make_pair(FD, cast<Expr>(DRE));
7926}
7927
7929 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7930 ArrayRef<Expr *> AdjustArgsNothing,
7931 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7932 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7933 SourceLocation AppendArgsLoc, SourceRange SR) {
7934
7935 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7936 // An adjust_args clause or append_args clause can only be specified if the
7937 // dispatch selector of the construct selector set appears in the match
7938 // clause.
7939
7940 SmallVector<Expr *, 8> AllAdjustArgs;
7941 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7942 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7943
7944 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7945 VariantMatchInfo VMI;
7947 if (!llvm::is_contained(
7948 VMI.ConstructTraits,
7949 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7950 if (!AllAdjustArgs.empty())
7951 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7952 << getOpenMPClauseName(OMPC_adjust_args);
7953 if (!AppendArgs.empty())
7954 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7955 << getOpenMPClauseName(OMPC_append_args);
7956 return;
7957 }
7958 }
7959
7960 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7961 // Each argument can only appear in a single adjust_args clause for each
7962 // declare variant directive.
7964
7965 for (Expr *E : AllAdjustArgs) {
7966 E = E->IgnoreParenImpCasts();
7967 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7968 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7969 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7970 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7971 FD->getParamDecl(PVD->getFunctionScopeIndex())
7972 ->getCanonicalDecl() == CanonPVD) {
7973 // It's a parameter of the function, check duplicates.
7974 if (!AdjustVars.insert(CanonPVD).second) {
7975 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7976 << PVD;
7977 return;
7978 }
7979 continue;
7980 }
7981 }
7982 }
7983 // Anything that is not a function parameter is an error.
7984 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7985 return;
7986 }
7987
7988 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7989 getASTContext(), VariantRef, &TI,
7990 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7991 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7992 AdjustArgsNeedDevicePtr.size(),
7993 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7994 FD->addAttr(NewAttr);
7995}
7996
7999 Stmt *AStmt, SourceLocation StartLoc,
8000 SourceLocation EndLoc) {
8001 if (!AStmt)
8002 return StmtError();
8003
8004 auto *CS = cast<CapturedStmt>(AStmt);
8005 // 1.2.2 OpenMP Language Terminology
8006 // Structured block - An executable statement with a single entry at the
8007 // top and a single exit at the bottom.
8008 // The point of exit cannot be a branch out of the structured block.
8009 // longjmp() and throw() must not violate the entry/exit criteria.
8010 CS->getCapturedDecl()->setNothrow();
8011
8013
8015 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
8016 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
8017}
8018
8019namespace {
8020/// Iteration space of a single for loop.
8021struct LoopIterationSpace final {
8022 /// True if the condition operator is the strict compare operator (<, > or
8023 /// !=).
8024 bool IsStrictCompare = false;
8025 /// Condition of the loop.
8026 Expr *PreCond = nullptr;
8027 /// This expression calculates the number of iterations in the loop.
8028 /// It is always possible to calculate it before starting the loop.
8029 Expr *NumIterations = nullptr;
8030 /// The loop counter variable.
8031 Expr *CounterVar = nullptr;
8032 /// Private loop counter variable.
8033 Expr *PrivateCounterVar = nullptr;
8034 /// This is initializer for the initial value of #CounterVar.
8035 Expr *CounterInit = nullptr;
8036 /// This is step for the #CounterVar used to generate its update:
8037 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
8038 Expr *CounterStep = nullptr;
8039 /// Should step be subtracted?
8040 bool Subtract = false;
8041 /// Source range of the loop init.
8042 SourceRange InitSrcRange;
8043 /// Source range of the loop condition.
8044 SourceRange CondSrcRange;
8045 /// Source range of the loop increment.
8046 SourceRange IncSrcRange;
8047 /// Minimum value that can have the loop control variable. Used to support
8048 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
8049 /// since only such variables can be used in non-loop invariant expressions.
8050 Expr *MinValue = nullptr;
8051 /// Maximum value that can have the loop control variable. Used to support
8052 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
8053 /// since only such variables can be used in non-loop invariant expressions.
8054 Expr *MaxValue = nullptr;
8055 /// true, if the lower bound depends on the outer loop control var.
8056 bool IsNonRectangularLB = false;
8057 /// true, if the upper bound depends on the outer loop control var.
8058 bool IsNonRectangularUB = false;
8059 /// Index of the loop this loop depends on and forms non-rectangular loop
8060 /// nest.
8061 unsigned LoopDependentIdx = 0;
8062 /// Final condition for the non-rectangular loop nest support. It is used to
8063 /// check that the number of iterations for this particular counter must be
8064 /// finished.
8065 Expr *FinalCondition = nullptr;
8066};
8067
8068/// Helper class for checking canonical form of the OpenMP loops and
8069/// extracting iteration space of each loop in the loop nest, that will be used
8070/// for IR generation.
8071class OpenMPIterationSpaceChecker {
8072 /// Reference to Sema.
8073 Sema &SemaRef;
8074 /// Does the loop associated directive support non-rectangular loops?
8075 bool SupportsNonRectangular;
8076 /// Data-sharing stack.
8077 DSAStackTy &Stack;
8078 /// A location for diagnostics (when there is no some better location).
8079 SourceLocation DefaultLoc;
8080 /// A location for diagnostics (when increment is not compatible).
8081 SourceLocation ConditionLoc;
8082 /// A source location for referring to loop init later.
8083 SourceRange InitSrcRange;
8084 /// A source location for referring to condition later.
8085 SourceRange ConditionSrcRange;
8086 /// A source location for referring to increment later.
8087 SourceRange IncrementSrcRange;
8088 /// Loop variable.
8089 ValueDecl *LCDecl = nullptr;
8090 /// Reference to loop variable.
8091 Expr *LCRef = nullptr;
8092 /// Lower bound (initializer for the var).
8093 Expr *LB = nullptr;
8094 /// Upper bound.
8095 Expr *UB = nullptr;
8096 /// Loop step (increment).
8097 Expr *Step = nullptr;
8098 /// This flag is true when condition is one of:
8099 /// Var < UB
8100 /// Var <= UB
8101 /// UB > Var
8102 /// UB >= Var
8103 /// This will have no value when the condition is !=
8104 std::optional<bool> TestIsLessOp;
8105 /// This flag is true when condition is strict ( < or > ).
8106 bool TestIsStrictOp = false;
8107 /// This flag is true when step is subtracted on each iteration.
8108 bool SubtractStep = false;
8109 /// The outer loop counter this loop depends on (if any).
8110 const ValueDecl *DepDecl = nullptr;
8111 /// Contains number of loop (starts from 1) on which loop counter init
8112 /// expression of this loop depends on.
8113 std::optional<unsigned> InitDependOnLC;
8114 /// Contains number of loop (starts from 1) on which loop counter condition
8115 /// expression of this loop depends on.
8116 std::optional<unsigned> CondDependOnLC;
8117 /// Checks if the provide statement depends on the loop counter.
8118 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8119 bool IsInitializer);
8120 /// Original condition required for checking of the exit condition for
8121 /// non-rectangular loop.
8122 Expr *Condition = nullptr;
8123
8124public:
8125 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
8126 DSAStackTy &Stack, SourceLocation DefaultLoc)
8127 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8128 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
8129 /// Check init-expr for canonical loop form and save loop counter
8130 /// variable - #Var and its initialization value - #LB.
8131 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8132 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8133 /// for less/greater and for strict/non-strict comparison.
8134 bool checkAndSetCond(Expr *S);
8135 /// Check incr-expr for canonical loop form and return true if it
8136 /// does not conform, otherwise save loop step (#Step).
8137 bool checkAndSetInc(Expr *S);
8138 /// Return the loop counter variable.
8139 ValueDecl *getLoopDecl() const { return LCDecl; }
8140 /// Return the reference expression to loop counter variable.
8141 Expr *getLoopDeclRefExpr() const { return LCRef; }
8142 /// Source range of the loop init.
8143 SourceRange getInitSrcRange() const { return InitSrcRange; }
8144 /// Source range of the loop condition.
8145 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8146 /// Source range of the loop increment.
8147 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8148 /// True if the step should be subtracted.
8149 bool shouldSubtractStep() const { return SubtractStep; }
8150 /// True, if the compare operator is strict (<, > or !=).
8151 bool isStrictTestOp() const { return TestIsStrictOp; }
8152 /// Build the expression to calculate the number of iterations.
8153 Expr *buildNumIterations(
8154 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8155 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8156 /// Build the precondition expression for the loops.
8157 Expr *
8158 buildPreCond(Scope *S, Expr *Cond,
8159 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8160 /// Build reference expression to the counter be used for codegen.
8161 DeclRefExpr *
8162 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8163 DSAStackTy &DSA) const;
8164 /// Build reference expression to the private counter be used for
8165 /// codegen.
8166 Expr *buildPrivateCounterVar() const;
8167 /// Build initialization of the counter be used for codegen.
8168 Expr *buildCounterInit() const;
8169 /// Build step of the counter be used for codegen.
8170 Expr *buildCounterStep() const;
8171 /// Build loop data with counter value for depend clauses in ordered
8172 /// directives.
8173 Expr *
8174 buildOrderedLoopData(Scope *S, Expr *Counter,
8175 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8176 SourceLocation Loc, Expr *Inc = nullptr,
8177 OverloadedOperatorKind OOK = OO_Amp);
8178 /// Builds the minimum value for the loop counter.
8179 std::pair<Expr *, Expr *> buildMinMaxValues(
8180 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8181 /// Builds final condition for the non-rectangular loops.
8182 Expr *buildFinalCondition(Scope *S) const;
8183 /// Return true if any expression is dependent.
8184 bool dependent() const;
8185 /// Returns true if the initializer forms non-rectangular loop.
8186 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8187 /// Returns true if the condition forms non-rectangular loop.
8188 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8189 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8190 unsigned getLoopDependentIdx() const {
8191 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8192 }
8193
8194private:
8195 /// Check the right-hand side of an assignment in the increment
8196 /// expression.
8197 bool checkAndSetIncRHS(Expr *RHS);
8198 /// Helper to set loop counter variable and its initializer.
8199 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8200 bool EmitDiags);
8201 /// Helper to set upper bound.
8202 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8204 /// Helper to set loop increment.
8205 bool setStep(Expr *NewStep, bool Subtract);
8206};
8207
8208bool OpenMPIterationSpaceChecker::dependent() const {
8209 if (!LCDecl) {
8210 assert(!LB && !UB && !Step);
8211 return false;
8212 }
8213 return LCDecl->getType()->isDependentType() ||
8214 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8215 (Step && Step->isValueDependent());
8216}
8217
8218bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8219 Expr *NewLCRefExpr,
8220 Expr *NewLB, bool EmitDiags) {
8221 // State consistency checking to ensure correct usage.
8222 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8223 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8224 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8225 return true;
8226 LCDecl = getCanonicalDecl(NewLCDecl);
8227 LCRef = NewLCRefExpr;
8228 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8229 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8230 if ((Ctor->isCopyOrMoveConstructor() ||
8231 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8232 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8233 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8234 LB = NewLB;
8235 if (EmitDiags)
8236 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8237 return false;
8238}
8239
8240bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8241 bool StrictOp, SourceRange SR,
8242 SourceLocation SL) {
8243 // State consistency checking to ensure correct usage.
8244 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8245 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8246 if (!NewUB || NewUB->containsErrors())
8247 return true;
8248 UB = NewUB;
8249 if (LessOp)
8250 TestIsLessOp = LessOp;
8251 TestIsStrictOp = StrictOp;
8252 ConditionSrcRange = SR;
8253 ConditionLoc = SL;
8254 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8255 return false;
8256}
8257
8258bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8259 // State consistency checking to ensure correct usage.
8260 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8261 if (!NewStep || NewStep->containsErrors())
8262 return true;
8263 if (!NewStep->isValueDependent()) {
8264 // Check that the step is integer expression.
8265 SourceLocation StepLoc = NewStep->getBeginLoc();
8267 StepLoc, getExprAsWritten(NewStep));
8268 if (Val.isInvalid())
8269 return true;
8270 NewStep = Val.get();
8271
8272 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8273 // If test-expr is of form var relational-op b and relational-op is < or
8274 // <= then incr-expr must cause var to increase on each iteration of the
8275 // loop. If test-expr is of form var relational-op b and relational-op is
8276 // > or >= then incr-expr must cause var to decrease on each iteration of
8277 // the loop.
8278 // If test-expr is of form b relational-op var and relational-op is < or
8279 // <= then incr-expr must cause var to decrease on each iteration of the
8280 // loop. If test-expr is of form b relational-op var and relational-op is
8281 // > or >= then incr-expr must cause var to increase on each iteration of
8282 // the loop.
8283 std::optional<llvm::APSInt> Result =
8284 NewStep->getIntegerConstantExpr(SemaRef.Context);
8285 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8286 bool IsConstNeg =
8287 Result && Result->isSigned() && (Subtract != Result->isNegative());
8288 bool IsConstPos =
8289 Result && Result->isSigned() && (Subtract == Result->isNegative());
8290 bool IsConstZero = Result && !Result->getBoolValue();
8291
8292 // != with increment is treated as <; != with decrement is treated as >
8293 if (!TestIsLessOp)
8294 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8295 if (UB && (IsConstZero ||
8296 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8297 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8298 SemaRef.Diag(NewStep->getExprLoc(),
8299 diag::err_omp_loop_incr_not_compatible)
8300 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8301 SemaRef.Diag(ConditionLoc,
8302 diag::note_omp_loop_cond_requres_compatible_incr)
8303 << *TestIsLessOp << ConditionSrcRange;
8304 return true;
8305 }
8306 if (*TestIsLessOp == Subtract) {
8307 NewStep =
8308 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8309 .get();
8310 Subtract = !Subtract;
8311 }
8312 }
8313
8314 Step = NewStep;
8315 SubtractStep = Subtract;
8316 return false;
8317}
8318
8319namespace {
8320/// Checker for the non-rectangular loops. Checks if the initializer or
8321/// condition expression references loop counter variable.
8322class LoopCounterRefChecker final
8323 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8324 Sema &SemaRef;
8325 DSAStackTy &Stack;
8326 const ValueDecl *CurLCDecl = nullptr;
8327 const ValueDecl *DepDecl = nullptr;
8328 const ValueDecl *PrevDepDecl = nullptr;
8329 bool IsInitializer = true;
8330 bool SupportsNonRectangular;
8331 unsigned BaseLoopId = 0;
8332 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8333 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8334 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8335 << (IsInitializer ? 0 : 1);
8336 return false;
8337 }
8338 const auto &&Data = Stack.isLoopControlVariable(VD);
8339 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8340 // The type of the loop iterator on which we depend may not have a random
8341 // access iterator type.
8342 if (Data.first && VD->getType()->isRecordType()) {
8343 SmallString<128> Name;
8344 llvm::raw_svector_ostream OS(Name);
8345 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8346 /*Qualified=*/true);
8347 SemaRef.Diag(E->getExprLoc(),
8348 diag::err_omp_wrong_dependency_iterator_type)
8349 << OS.str();
8350 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8351 return false;
8352 }
8353 if (Data.first && !SupportsNonRectangular) {
8354 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8355 return false;
8356 }
8357 if (Data.first &&
8358 (DepDecl || (PrevDepDecl &&
8359 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8360 if (!DepDecl && PrevDepDecl)
8361 DepDecl = PrevDepDecl;
8362 SmallString<128> Name;
8363 llvm::raw_svector_ostream OS(Name);
8364 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8365 /*Qualified=*/true);
8366 SemaRef.Diag(E->getExprLoc(),
8367 diag::err_omp_invariant_or_linear_dependency)
8368 << OS.str();
8369 return false;
8370 }
8371 if (Data.first) {
8372 DepDecl = VD;
8373 BaseLoopId = Data.first;
8374 }
8375 return Data.first;
8376 }
8377
8378public:
8379 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8380 const ValueDecl *VD = E->getDecl();
8381 if (isa<VarDecl>(VD))
8382 return checkDecl(E, VD);
8383 return false;
8384 }
8385 bool VisitMemberExpr(const MemberExpr *E) {
8386 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8387 const ValueDecl *VD = E->getMemberDecl();
8388 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8389 return checkDecl(E, VD);
8390 }
8391 return false;
8392 }
8393 bool VisitStmt(const Stmt *S) {
8394 bool Res = false;
8395 for (const Stmt *Child : S->children())
8396 Res = (Child && Visit(Child)) || Res;
8397 return Res;
8398 }
8399 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8400 const ValueDecl *CurLCDecl, bool IsInitializer,
8401 const ValueDecl *PrevDepDecl = nullptr,
8402 bool SupportsNonRectangular = true)
8403 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8404 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8405 SupportsNonRectangular(SupportsNonRectangular) {}
8406 unsigned getBaseLoopId() const {
8407 assert(CurLCDecl && "Expected loop dependency.");
8408 return BaseLoopId;
8409 }
8410 const ValueDecl *getDepDecl() const {
8411 assert(CurLCDecl && "Expected loop dependency.");
8412 return DepDecl;
8413 }
8414};
8415} // namespace
8416
8417std::optional<unsigned>
8418OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8419 bool IsInitializer) {
8420 // Check for the non-rectangular loops.
8421 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8422 DepDecl, SupportsNonRectangular);
8423 if (LoopStmtChecker.Visit(S)) {
8424 DepDecl = LoopStmtChecker.getDepDecl();
8425 return LoopStmtChecker.getBaseLoopId();
8426 }
8427 return std::nullopt;
8428}
8429
8430bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8431 // Check init-expr for canonical loop form and save loop counter
8432 // variable - #Var and its initialization value - #LB.
8433 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8434 // var = lb
8435 // integer-type var = lb
8436 // random-access-iterator-type var = lb
8437 // pointer-type var = lb
8438 //
8439 if (!S) {
8440 if (EmitDiags) {
8441 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8442 }
8443 return true;
8444 }
8445 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8446 if (!ExprTemp->cleanupsHaveSideEffects())
8447 S = ExprTemp->getSubExpr();
8448
8449 InitSrcRange = S->getSourceRange();
8450 if (Expr *E = dyn_cast<Expr>(S))
8451 S = E->IgnoreParens();
8452 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8453 if (BO->getOpcode() == BO_Assign) {
8454 Expr *LHS = BO->getLHS()->IgnoreParens();
8455 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8456 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8457 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8458 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8459 EmitDiags);
8460 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8461 }
8462 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8463 if (ME->isArrow() &&
8464 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8465 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8466 EmitDiags);
8467 }
8468 }
8469 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8470 if (DS->isSingleDecl()) {
8471 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8472 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8473 // Accept non-canonical init form here but emit ext. warning.
8474 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8475 SemaRef.Diag(S->getBeginLoc(),
8476 diag::ext_omp_loop_not_canonical_init)
8477 << S->getSourceRange();
8478 return setLCDeclAndLB(
8479 Var,
8480 buildDeclRefExpr(SemaRef, Var,
8481 Var->getType().getNonReferenceType(),
8482 DS->getBeginLoc()),
8483 Var->getInit(), EmitDiags);
8484 }
8485 }
8486 }
8487 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8488 if (CE->getOperator() == OO_Equal) {
8489 Expr *LHS = CE->getArg(0);
8490 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8491 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8492 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8493 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8494 EmitDiags);
8495 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8496 }
8497 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8498 if (ME->isArrow() &&
8499 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8500 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8501 EmitDiags);
8502 }
8503 }
8504 }
8505
8506 if (dependent() || SemaRef.CurContext->isDependentContext())
8507 return false;
8508 if (EmitDiags) {
8509 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8510 << S->getSourceRange();
8511 }
8512 return true;
8513}
8514
8515/// Ignore parenthesizes, implicit casts, copy constructor and return the
8516/// variable (which may be the loop variable) if possible.
8517static const ValueDecl *getInitLCDecl(const Expr *E) {
8518 if (!E)
8519 return nullptr;
8520 E = getExprAsWritten(E);
8521 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8522 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8523 if ((Ctor->isCopyOrMoveConstructor() ||
8524 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8525 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8526 E = CE->getArg(0)->IgnoreParenImpCasts();
8527 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8528 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8529 return getCanonicalDecl(VD);
8530 }
8531 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8532 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8533 return getCanonicalDecl(ME->getMemberDecl());
8534 return nullptr;
8535}
8536
8537bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8538 // Check test-expr for canonical form, save upper-bound UB, flags for
8539 // less/greater and for strict/non-strict comparison.
8540 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8541 // var relational-op b
8542 // b relational-op var
8543 //
8544 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8545 if (!S) {
8546 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8547 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8548 return true;
8549 }
8550 Condition = S;
8551 S = getExprAsWritten(S);
8552 SourceLocation CondLoc = S->getBeginLoc();
8553 auto &&CheckAndSetCond =
8554 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8555 const Expr *RHS, SourceRange SR,
8556 SourceLocation OpLoc) -> std::optional<bool> {
8557 if (BinaryOperator::isRelationalOp(Opcode)) {
8558 if (getInitLCDecl(LHS) == LCDecl)
8559 return setUB(const_cast<Expr *>(RHS),
8560 (Opcode == BO_LT || Opcode == BO_LE),
8561 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8562 if (getInitLCDecl(RHS) == LCDecl)
8563 return setUB(const_cast<Expr *>(LHS),
8564 (Opcode == BO_GT || Opcode == BO_GE),
8565 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8566 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8567 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8568 /*LessOp=*/std::nullopt,
8569 /*StrictOp=*/true, SR, OpLoc);
8570 }
8571 return std::nullopt;
8572 };
8573 std::optional<bool> Res;
8574 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8575 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8576 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8577 RBO->getOperatorLoc());
8578 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8579 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8580 BO->getSourceRange(), BO->getOperatorLoc());
8581 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8582 if (CE->getNumArgs() == 2) {
8583 Res = CheckAndSetCond(
8584 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8585 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8586 }
8587 }
8588 if (Res)
8589 return *Res;
8590 if (dependent() || SemaRef.CurContext->isDependentContext())
8591 return false;
8592 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8593 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8594 return true;
8595}
8596
8597bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8598 // RHS of canonical loop form increment can be:
8599 // var + incr
8600 // incr + var
8601 // var - incr
8602 //
8603 RHS = RHS->IgnoreParenImpCasts();
8604 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8605 if (BO->isAdditiveOp()) {
8606 bool IsAdd = BO->getOpcode() == BO_Add;
8607 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8608 return setStep(BO->getRHS(), !IsAdd);
8609 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8610 return setStep(BO->getLHS(), /*Subtract=*/false);
8611 }
8612 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8613 bool IsAdd = CE->getOperator() == OO_Plus;
8614 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8615 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8616 return setStep(CE->getArg(1), !IsAdd);
8617 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8618 return setStep(CE->getArg(0), /*Subtract=*/false);
8619 }
8620 }
8621 if (dependent() || SemaRef.CurContext->isDependentContext())
8622 return false;
8623 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8624 << RHS->getSourceRange() << LCDecl;
8625 return true;
8626}
8627
8628bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8629 // Check incr-expr for canonical loop form and return true if it
8630 // does not conform.
8631 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8632 // ++var
8633 // var++
8634 // --var
8635 // var--
8636 // var += incr
8637 // var -= incr
8638 // var = var + incr
8639 // var = incr + var
8640 // var = var - incr
8641 //
8642 if (!S) {
8643 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8644 return true;
8645 }
8646 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8647 if (!ExprTemp->cleanupsHaveSideEffects())
8648 S = ExprTemp->getSubExpr();
8649
8650 IncrementSrcRange = S->getSourceRange();
8651 S = S->IgnoreParens();
8652 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8653 if (UO->isIncrementDecrementOp() &&
8654 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8655 return setStep(SemaRef
8656 .ActOnIntegerConstant(UO->getBeginLoc(),
8657 (UO->isDecrementOp() ? -1 : 1))
8658 .get(),
8659 /*Subtract=*/false);
8660 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8661 switch (BO->getOpcode()) {
8662 case BO_AddAssign:
8663 case BO_SubAssign:
8664 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8665 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8666 break;
8667 case BO_Assign:
8668 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8669 return checkAndSetIncRHS(BO->getRHS());
8670 break;
8671 default:
8672 break;
8673 }
8674 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8675 switch (CE->getOperator()) {
8676 case OO_PlusPlus:
8677 case OO_MinusMinus:
8678 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8679 return setStep(SemaRef
8680 .ActOnIntegerConstant(
8681 CE->getBeginLoc(),
8682 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8683 .get(),
8684 /*Subtract=*/false);
8685 break;
8686 case OO_PlusEqual:
8687 case OO_MinusEqual:
8688 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8689 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8690 break;
8691 case OO_Equal:
8692 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8693 return checkAndSetIncRHS(CE->getArg(1));
8694 break;
8695 default:
8696 break;
8697 }
8698 }
8699 if (dependent() || SemaRef.CurContext->isDependentContext())
8700 return false;
8701 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8702 << S->getSourceRange() << LCDecl;
8703 return true;
8704}
8705
8706static ExprResult
8707tryBuildCapture(Sema &SemaRef, Expr *Capture,
8708 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8709 StringRef Name = ".capture_expr.") {
8710 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8711 return Capture;
8712 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8713 return SemaRef.PerformImplicitConversion(
8714 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8715 /*AllowExplicit=*/true);
8716 auto I = Captures.find(Capture);
8717 if (I != Captures.end())
8718 return buildCapture(SemaRef, Capture, I->second, Name);
8719 DeclRefExpr *Ref = nullptr;
8720 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8721 Captures[Capture] = Ref;
8722 return Res;
8723}
8724
8725/// Calculate number of iterations, transforming to unsigned, if number of
8726/// iterations may be larger than the original type.
8727static Expr *
8728calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8729 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8730 bool TestIsStrictOp, bool RoundToStep,
8731 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8732 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8733 if (!NewStep.isUsable())
8734 return nullptr;
8735 llvm::APSInt LRes, SRes;
8736 bool IsLowerConst = false, IsStepConst = false;
8737 if (std::optional<llvm::APSInt> Res =
8738 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8739 LRes = *Res;
8740 IsLowerConst = true;
8741 }
8742 if (std::optional<llvm::APSInt> Res =
8743 Step->getIntegerConstantExpr(SemaRef.Context)) {
8744 SRes = *Res;
8745 IsStepConst = true;
8746 }
8747 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8748 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8749 (TestIsStrictOp && LRes.isStrictlyPositive()));
8750 bool NeedToReorganize = false;
8751 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8752 if (!NoNeedToConvert && IsLowerConst &&
8753 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8754 NoNeedToConvert = true;
8755 if (RoundToStep) {
8756 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8757 ? LRes.getBitWidth()
8758 : SRes.getBitWidth();
8759 LRes = LRes.extend(BW + 1);
8760 LRes.setIsSigned(true);
8761 SRes = SRes.extend(BW + 1);
8762 SRes.setIsSigned(true);
8763 LRes -= SRes;
8764 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8765 LRes = LRes.trunc(BW);
8766 }
8767 if (TestIsStrictOp) {
8768 unsigned BW = LRes.getBitWidth();
8769 LRes = LRes.extend(BW + 1);
8770 LRes.setIsSigned(true);
8771 ++LRes;
8772 NoNeedToConvert =
8773 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8774 // truncate to the original bitwidth.
8775 LRes = LRes.trunc(BW);
8776 }
8777 NeedToReorganize = NoNeedToConvert;
8778 }
8779 llvm::APSInt URes;
8780 bool IsUpperConst = false;
8781 if (std::optional<llvm::APSInt> Res =
8782 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8783 URes = *Res;
8784 IsUpperConst = true;
8785 }
8786 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8787 (!RoundToStep || IsStepConst)) {
8788 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8789 : URes.getBitWidth();
8790 LRes = LRes.extend(BW + 1);
8791 LRes.setIsSigned(true);
8792 URes = URes.extend(BW + 1);
8793 URes.setIsSigned(true);
8794 URes -= LRes;
8795 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8796 NeedToReorganize = NoNeedToConvert;
8797 }
8798 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8799 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8800 // unsigned.
8801 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8802 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8803 QualType LowerTy = Lower->getType();
8804 QualType UpperTy = Upper->getType();
8805 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8806 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8807 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8808 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8810 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8811 Upper =
8812 SemaRef
8814 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8816 .get();
8817 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8818 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8819 }
8820 }
8821 if (!Lower || !Upper || NewStep.isInvalid())
8822 return nullptr;
8823
8824 ExprResult Diff;
8825 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8826 // 1]).
8827 if (NeedToReorganize) {
8828 Diff = Lower;
8829
8830 if (RoundToStep) {
8831 // Lower - Step
8832 Diff =
8833 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8834 if (!Diff.isUsable())
8835 return nullptr;
8836 }
8837
8838 // Lower - Step [+ 1]
8839 if (TestIsStrictOp)
8840 Diff = SemaRef.BuildBinOp(
8841 S, DefaultLoc, BO_Add, Diff.get(),
8842 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8843 if (!Diff.isUsable())
8844 return nullptr;
8845
8846 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8847 if (!Diff.isUsable())
8848 return nullptr;
8849
8850 // Upper - (Lower - Step [+ 1]).
8851 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8852 if (!Diff.isUsable())
8853 return nullptr;
8854 } else {
8855 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8856
8857 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8858 // BuildBinOp already emitted error, this one is to point user to upper
8859 // and lower bound, and to tell what is passed to 'operator-'.
8860 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8861 << Upper->getSourceRange() << Lower->getSourceRange();
8862 return nullptr;
8863 }
8864
8865 if (!Diff.isUsable())
8866 return nullptr;
8867
8868 // Upper - Lower [- 1]
8869 if (TestIsStrictOp)
8870 Diff = SemaRef.BuildBinOp(
8871 S, DefaultLoc, BO_Sub, Diff.get(),
8872 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8873 if (!Diff.isUsable())
8874 return nullptr;
8875
8876 if (RoundToStep) {
8877 // Upper - Lower [- 1] + Step
8878 Diff =
8879 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8880 if (!Diff.isUsable())
8881 return nullptr;
8882 }
8883 }
8884
8885 // Parentheses (for dumping/debugging purposes only).
8886 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8887 if (!Diff.isUsable())
8888 return nullptr;
8889
8890 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8891 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8892 if (!Diff.isUsable())
8893 return nullptr;
8894
8895 return Diff.get();
8896}
8897
8898/// Build the expression to calculate the number of iterations.
8899Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8900 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8901 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8902 QualType VarType = LCDecl->getType().getNonReferenceType();
8903 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8904 !SemaRef.getLangOpts().CPlusPlus)
8905 return nullptr;
8906 Expr *LBVal = LB;
8907 Expr *UBVal = UB;
8908 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8909 // max(LB(MinVal), LB(MaxVal)))
8910 if (InitDependOnLC) {
8911 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8912 if (!IS.MinValue || !IS.MaxValue)
8913 return nullptr;
8914 // OuterVar = Min
8915 ExprResult MinValue =
8916 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8917 if (!MinValue.isUsable())
8918 return nullptr;
8919
8920 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8921 IS.CounterVar, MinValue.get());
8922 if (!LBMinVal.isUsable())
8923 return nullptr;
8924 // OuterVar = Min, LBVal
8925 LBMinVal =
8926 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8927 if (!LBMinVal.isUsable())
8928 return nullptr;
8929 // (OuterVar = Min, LBVal)
8930 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8931 if (!LBMinVal.isUsable())
8932 return nullptr;
8933
8934 // OuterVar = Max
8935 ExprResult MaxValue =
8936 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8937 if (!MaxValue.isUsable())
8938 return nullptr;
8939
8940 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8941 IS.CounterVar, MaxValue.get());
8942 if (!LBMaxVal.isUsable())
8943 return nullptr;
8944 // OuterVar = Max, LBVal
8945 LBMaxVal =
8946 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8947 if (!LBMaxVal.isUsable())
8948 return nullptr;
8949 // (OuterVar = Max, LBVal)
8950 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8951 if (!LBMaxVal.isUsable())
8952 return nullptr;
8953
8954 Expr *LBMin =
8955 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8956 Expr *LBMax =
8957 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8958 if (!LBMin || !LBMax)
8959 return nullptr;
8960 // LB(MinVal) < LB(MaxVal)
8961 ExprResult MinLessMaxRes =
8962 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8963 if (!MinLessMaxRes.isUsable())
8964 return nullptr;
8965 Expr *MinLessMax =
8966 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8967 .get();
8968 if (!MinLessMax)
8969 return nullptr;
8970 if (*TestIsLessOp) {
8971 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8972 // LB(MaxVal))
8973 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8974 MinLessMax, LBMin, LBMax);
8975 if (!MinLB.isUsable())
8976 return nullptr;
8977 LBVal = MinLB.get();
8978 } else {
8979 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8980 // LB(MaxVal))
8981 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8982 MinLessMax, LBMax, LBMin);
8983 if (!MaxLB.isUsable())
8984 return nullptr;
8985 LBVal = MaxLB.get();
8986 }
8987 // OuterVar = LB
8988 LBMinVal =
8989 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8990 if (!LBMinVal.isUsable())
8991 return nullptr;
8992 LBVal = LBMinVal.get();
8993 }
8994 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8995 // min(UB(MinVal), UB(MaxVal))
8996 if (CondDependOnLC) {
8997 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8998 if (!IS.MinValue || !IS.MaxValue)
8999 return nullptr;
9000 // OuterVar = Min
9001 ExprResult MinValue =
9002 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
9003 if (!MinValue.isUsable())
9004 return nullptr;
9005
9006 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9007 IS.CounterVar, MinValue.get());
9008 if (!UBMinVal.isUsable())
9009 return nullptr;
9010 // OuterVar = Min, UBVal
9011 UBMinVal =
9012 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
9013 if (!UBMinVal.isUsable())
9014 return nullptr;
9015 // (OuterVar = Min, UBVal)
9016 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
9017 if (!UBMinVal.isUsable())
9018 return nullptr;
9019
9020 // OuterVar = Max
9021 ExprResult MaxValue =
9022 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
9023 if (!MaxValue.isUsable())
9024 return nullptr;
9025
9026 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9027 IS.CounterVar, MaxValue.get());
9028 if (!UBMaxVal.isUsable())
9029 return nullptr;
9030 // OuterVar = Max, UBVal
9031 UBMaxVal =
9032 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
9033 if (!UBMaxVal.isUsable())
9034 return nullptr;
9035 // (OuterVar = Max, UBVal)
9036 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
9037 if (!UBMaxVal.isUsable())
9038 return nullptr;
9039
9040 Expr *UBMin =
9041 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
9042 Expr *UBMax =
9043 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
9044 if (!UBMin || !UBMax)
9045 return nullptr;
9046 // UB(MinVal) > UB(MaxVal)
9047 ExprResult MinGreaterMaxRes =
9048 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9049 if (!MinGreaterMaxRes.isUsable())
9050 return nullptr;
9051 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
9052 Captures, ".min_greater_max")
9053 .get();
9054 if (!MinGreaterMax)
9055 return nullptr;
9056 if (*TestIsLessOp) {
9057 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9058 // UB(MaxVal))
9059 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9060 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9061 if (!MaxUB.isUsable())
9062 return nullptr;
9063 UBVal = MaxUB.get();
9064 } else {
9065 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9066 // UB(MaxVal))
9067 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9068 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9069 if (!MinUB.isUsable())
9070 return nullptr;
9071 UBVal = MinUB.get();
9072 }
9073 }
9074 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9075 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9076 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9077 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9078 if (!Upper || !Lower)
9079 return nullptr;
9080
9081 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9082 Step, VarType, TestIsStrictOp,
9083 /*RoundToStep=*/true, Captures);
9084 if (!Diff.isUsable())
9085 return nullptr;
9086
9087 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9088 QualType Type = Diff.get()->getType();
9089 ASTContext &C = SemaRef.Context;
9090 bool UseVarType = VarType->hasIntegerRepresentation() &&
9091 C.getTypeSize(Type) > C.getTypeSize(VarType);
9092 if (!Type->isIntegerType() || UseVarType) {
9093 unsigned NewSize =
9094 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9095 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9097 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9098 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9099 Diff = SemaRef.PerformImplicitConversion(
9100 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
9101 if (!Diff.isUsable())
9102 return nullptr;
9103 }
9104 }
9105 if (LimitedType) {
9106 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9107 if (NewSize != C.getTypeSize(Type)) {
9108 if (NewSize < C.getTypeSize(Type)) {
9109 assert(NewSize == 64 && "incorrect loop var size");
9110 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9111 << InitSrcRange << ConditionSrcRange;
9112 }
9113 QualType NewType = C.getIntTypeForBitwidth(
9115 C.getTypeSize(Type) < NewSize);
9116 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9117 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9118 Sema::AA_Converting, true);
9119 if (!Diff.isUsable())
9120 return nullptr;
9121 }
9122 }
9123 }
9124
9125 return Diff.get();
9126}
9127
9128std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9129 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9130 // Do not build for iterators, they cannot be used in non-rectangular loop
9131 // nests.
9132 if (LCDecl->getType()->isRecordType())
9133 return std::make_pair(nullptr, nullptr);
9134 // If we subtract, the min is in the condition, otherwise the min is in the
9135 // init value.
9136 Expr *MinExpr = nullptr;
9137 Expr *MaxExpr = nullptr;
9138 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9139 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9140 bool LBNonRect =
9141 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9142 bool UBNonRect =
9143 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9144 Expr *Lower =
9145 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9146 Expr *Upper =
9147 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9148 if (!Upper || !Lower)
9149 return std::make_pair(nullptr, nullptr);
9150
9151 if (*TestIsLessOp)
9152 MinExpr = Lower;
9153 else
9154 MaxExpr = Upper;
9155
9156 // Build minimum/maximum value based on number of iterations.
9157 QualType VarType = LCDecl->getType().getNonReferenceType();
9158
9159 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
9160 Step, VarType, TestIsStrictOp,
9161 /*RoundToStep=*/false, Captures);
9162 if (!Diff.isUsable())
9163 return std::make_pair(nullptr, nullptr);
9164
9165 // ((Upper - Lower [- 1]) / Step) * Step
9166 // Parentheses (for dumping/debugging purposes only).
9167 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9168 if (!Diff.isUsable())
9169 return std::make_pair(nullptr, nullptr);
9170
9171 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9172 if (!NewStep.isUsable())
9173 return std::make_pair(nullptr, nullptr);
9174 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9175 if (!Diff.isUsable())
9176 return std::make_pair(nullptr, nullptr);
9177
9178 // Parentheses (for dumping/debugging purposes only).
9179 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9180 if (!Diff.isUsable())
9181 return std::make_pair(nullptr, nullptr);
9182
9183 // Convert to the ptrdiff_t, if original type is pointer.
9184 if (VarType->isAnyPointerType() &&
9185 !SemaRef.Context.hasSameType(
9186 Diff.get()->getType(),
9188 Diff = SemaRef.PerformImplicitConversion(
9189 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9190 Sema::AA_Converting, /*AllowExplicit=*/true);
9191 }
9192 if (!Diff.isUsable())
9193 return std::make_pair(nullptr, nullptr);
9194
9195 if (*TestIsLessOp) {
9196 // MinExpr = Lower;
9197 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9198 Diff = SemaRef.BuildBinOp(
9199 S, DefaultLoc, BO_Add,
9200 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9201 Diff.get());
9202 if (!Diff.isUsable())
9203 return std::make_pair(nullptr, nullptr);
9204 } else {
9205 // MaxExpr = Upper;
9206 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9207 Diff = SemaRef.BuildBinOp(
9208 S, DefaultLoc, BO_Sub,
9209 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9210 Diff.get());
9211 if (!Diff.isUsable())
9212 return std::make_pair(nullptr, nullptr);
9213 }
9214
9215 // Convert to the original type.
9216 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9217 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9219 /*AllowExplicit=*/true);
9220 if (!Diff.isUsable())
9221 return std::make_pair(nullptr, nullptr);
9222
9223 Sema::TentativeAnalysisScope Trap(SemaRef);
9224 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9225 if (!Diff.isUsable())
9226 return std::make_pair(nullptr, nullptr);
9227
9228 if (*TestIsLessOp)
9229 MaxExpr = Diff.get();
9230 else
9231 MinExpr = Diff.get();
9232
9233 return std::make_pair(MinExpr, MaxExpr);
9234}
9235
9236Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9237 if (InitDependOnLC || CondDependOnLC)
9238 return Condition;
9239 return nullptr;
9240}
9241
9242Expr *OpenMPIterationSpaceChecker::buildPreCond(
9243 Scope *S, Expr *Cond,
9244 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9245 // Do not build a precondition when the condition/initialization is dependent
9246 // to prevent pessimistic early loop exit.
9247 // TODO: this can be improved by calculating min/max values but not sure that
9248 // it will be very effective.
9249 if (CondDependOnLC || InitDependOnLC)
9250 return SemaRef
9252 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9253 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9254 /*AllowExplicit=*/true)
9255 .get();
9256
9257 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9258 Sema::TentativeAnalysisScope Trap(SemaRef);
9259
9260 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9261 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9262 if (!NewLB.isUsable() || !NewUB.isUsable())
9263 return nullptr;
9264
9265 ExprResult CondExpr =
9266 SemaRef.BuildBinOp(S, DefaultLoc,
9267 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9268 : (TestIsStrictOp ? BO_GT : BO_GE),
9269 NewLB.get(), NewUB.get());
9270 if (CondExpr.isUsable()) {
9271 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9272 SemaRef.Context.BoolTy))
9273 CondExpr = SemaRef.PerformImplicitConversion(
9274 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
9275 /*AllowExplicit=*/true);
9276 }
9277
9278 // Otherwise use original loop condition and evaluate it in runtime.
9279 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9280}
9281
9282/// Build reference expression to the counter be used for codegen.
9283DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9284 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9285 DSAStackTy &DSA) const {
9286 auto *VD = dyn_cast<VarDecl>(LCDecl);
9287 if (!VD) {
9288 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9290 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9291 const DSAStackTy::DSAVarData Data =
9292 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9293 // If the loop control decl is explicitly marked as private, do not mark it
9294 // as captured again.
9295 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9296 Captures.insert(std::make_pair(LCRef, Ref));
9297 return Ref;
9298 }
9299 return cast<DeclRefExpr>(LCRef);
9300}
9301
9302Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9303 if (LCDecl && !LCDecl->isInvalidDecl()) {
9305 VarDecl *PrivateVar = buildVarDecl(
9306 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9307 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9308 isa<VarDecl>(LCDecl)
9309 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9310 : nullptr);
9311 if (PrivateVar->isInvalidDecl())
9312 return nullptr;
9313 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9314 }
9315 return nullptr;
9316}
9317
9318/// Build initialization of the counter to be used for codegen.
9319Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9320
9321/// Build step of the counter be used for codegen.
9322Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9323
9324Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9325 Scope *S, Expr *Counter,
9326 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9327 Expr *Inc, OverloadedOperatorKind OOK) {
9328 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9329 if (!Cnt)
9330 return nullptr;
9331 if (Inc) {
9332 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9333 "Expected only + or - operations for depend clauses.");
9334 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9335 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9336 if (!Cnt)
9337 return nullptr;
9338 }
9339 QualType VarType = LCDecl->getType().getNonReferenceType();
9340 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9341 !SemaRef.getLangOpts().CPlusPlus)
9342 return nullptr;
9343 // Upper - Lower
9344 Expr *Upper =
9345 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9346 Expr *Lower =
9347 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9348 if (!Upper || !Lower)
9349 return nullptr;
9350
9351 ExprResult Diff = calculateNumIters(
9352 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9353 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9354 if (!Diff.isUsable())
9355 return nullptr;
9356
9357 return Diff.get();
9358}
9359} // namespace
9360
9362 Stmt *Init) {
9363 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9364 assert(Init && "Expected loop in canonical form.");
9365 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9366 if (AssociatedLoops > 0 &&
9367 isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
9368 DSAStack->loopStart();
9369 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9370 *DSAStack, ForLoc);
9371 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9372 if (ValueDecl *D = ISC.getLoopDecl()) {
9373 auto *VD = dyn_cast<VarDecl>(D);
9374 DeclRefExpr *PrivateRef = nullptr;
9375 if (!VD) {
9377 VD = Private;
9378 } else {
9379 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9380 /*WithInit=*/false);
9381 VD = cast<VarDecl>(PrivateRef->getDecl());
9382 }
9383 }
9384 DSAStack->addLoopControlVariable(D, VD);
9385 const Decl *LD = DSAStack->getPossiblyLoopCunter();
9386 if (LD != D->getCanonicalDecl()) {
9387 DSAStack->resetPossibleLoopCounter();
9388 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9390 SemaRef, const_cast<VarDecl *>(Var),
9391 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9392 /*RefersToCapture=*/true));
9393 }
9394 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9395 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9396 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9397 // associated for-loop of a simd construct with just one associated
9398 // for-loop may be listed in a linear clause with a constant-linear-step
9399 // that is the increment of the associated for-loop. The loop iteration
9400 // variable(s) in the associated for-loop(s) of a for or parallel for
9401 // construct may be listed in a private or lastprivate clause.
9402 DSAStackTy::DSAVarData DVar =
9403 DSAStack->getTopDSA(D, /*FromParent=*/false);
9404 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9405 // is declared in the loop and it is predetermined as a private.
9406 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9407 OpenMPClauseKind PredeterminedCKind =
9409 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9410 : OMPC_private;
9411 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9412 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9413 (getLangOpts().OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate &&
9414 DVar.CKind != OMPC_private))) ||
9415 ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop ||
9416 DKind == OMPD_master_taskloop || DKind == OMPD_masked_taskloop ||
9417 DKind == OMPD_parallel_master_taskloop ||
9418 DKind == OMPD_parallel_masked_taskloop ||
9420 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9421 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9422 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9423 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9424 << getOpenMPClauseName(DVar.CKind)
9425 << getOpenMPDirectiveName(DKind)
9426 << getOpenMPClauseName(PredeterminedCKind);
9427 if (DVar.RefExpr == nullptr)
9428 DVar.CKind = PredeterminedCKind;
9430 /*IsLoopIterVar=*/true);
9431 } else if (LoopDeclRefExpr) {
9432 // Make the loop iteration variable private (for worksharing
9433 // constructs), linear (for simd directives with the only one
9434 // associated loop) or lastprivate (for simd directives with several
9435 // collapsed or ordered loops).
9436 if (DVar.CKind == OMPC_unknown)
9437 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind,
9438 PrivateRef);
9439 }
9440 }
9441 }
9442 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9443 }
9444}
9445
9446namespace {
9447// Utility for openmp doacross clause kind
9448class OMPDoacrossKind {
9449public:
9450 bool isSource(const OMPDoacrossClause *C) {
9451 return C->getDependenceType() == OMPC_DOACROSS_source ||
9452 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9453 }
9454 bool isSink(const OMPDoacrossClause *C) {
9455 return C->getDependenceType() == OMPC_DOACROSS_sink;
9456 }
9457 bool isSinkIter(const OMPDoacrossClause *C) {
9458 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9459 }
9460};
9461} // namespace
9462/// Called on a for stmt to check and extract its iteration space
9463/// for further processing (such as collapsing).
9465 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9466 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9467 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9468 Expr *OrderedLoopCountExpr,
9469 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9471 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9472 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9473 // OpenMP [2.9.1, Canonical Loop Form]
9474 // for (init-expr; test-expr; incr-expr) structured-block
9475 // for (range-decl: range-expr) structured-block
9476 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9477 S = CanonLoop->getLoopStmt();
9478 auto *For = dyn_cast_or_null<ForStmt>(S);
9479 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9480 // Ranged for is supported only in OpenMP 5.0.
9481 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9482 OpenMPDirectiveKind DK = (SemaRef.getLangOpts().OpenMP < 50 ||
9483 DSA.getMappedDirective() == OMPD_unknown)
9484 ? DKind
9485 : DSA.getMappedDirective();
9486 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9487 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9488 << getOpenMPDirectiveName(DK) << TotalNestedLoopCount
9489 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9490 if (TotalNestedLoopCount > 1) {
9491 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9492 SemaRef.Diag(DSA.getConstructLoc(),
9493 diag::note_omp_collapse_ordered_expr)
9494 << 2 << CollapseLoopCountExpr->getSourceRange()
9495 << OrderedLoopCountExpr->getSourceRange();
9496 else if (CollapseLoopCountExpr)
9497 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9498 diag::note_omp_collapse_ordered_expr)
9499 << 0 << CollapseLoopCountExpr->getSourceRange();
9500 else
9501 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9502 diag::note_omp_collapse_ordered_expr)
9503 << 1 << OrderedLoopCountExpr->getSourceRange();
9504 }
9505 return true;
9506 }
9507 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9508 "No loop body.");
9509 // Postpone analysis in dependent contexts for ranged for loops.
9510 if (CXXFor && SemaRef.CurContext->isDependentContext())
9511 return false;
9512
9513 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9514 For ? For->getForLoc() : CXXFor->getForLoc());
9515
9516 // Check init.
9517 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9518 if (ISC.checkAndSetInit(Init))
9519 return true;
9520
9521 bool HasErrors = false;
9522
9523 // Check loop variable's type.
9524 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9525 // OpenMP [2.6, Canonical Loop Form]
9526 // Var is one of the following:
9527 // A variable of signed or unsigned integer type.
9528 // For C++, a variable of a random access iterator type.
9529 // For C, a variable of a pointer type.
9530 QualType VarType = LCDecl->getType().getNonReferenceType();
9531 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9532 !VarType->isPointerType() &&
9533 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9534 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9535 << SemaRef.getLangOpts().CPlusPlus;
9536 HasErrors = true;
9537 }
9538
9539 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9540 // a Construct
9541 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9542 // parallel for construct is (are) private.
9543 // The loop iteration variable in the associated for-loop of a simd
9544 // construct with just one associated for-loop is linear with a
9545 // constant-linear-step that is the increment of the associated for-loop.
9546 // Exclude loop var from the list of variables with implicitly defined data
9547 // sharing attributes.
9548 VarsWithImplicitDSA.erase(LCDecl);
9549
9550 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9551
9552 // Check test-expr.
9553 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9554
9555 // Check incr-expr.
9556 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9557 }
9558
9559 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9560 return HasErrors;
9561
9562 // Build the loop's iteration space representation.
9563 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9564 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9565 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9566 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9572 Captures);
9573 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9574 ISC.buildCounterVar(Captures, DSA);
9575 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9576 ISC.buildPrivateCounterVar();
9577 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9578 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9579 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9580 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9581 ISC.getConditionSrcRange();
9582 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9583 ISC.getIncrementSrcRange();
9584 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9585 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9586 ISC.isStrictTestOp();
9587 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9588 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9589 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9590 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9591 ISC.buildFinalCondition(DSA.getCurScope());
9592 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9593 ISC.doesInitDependOnLC();
9594 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9595 ISC.doesCondDependOnLC();
9596 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9597 ISC.getLoopDependentIdx();
9598
9599 HasErrors |=
9600 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9601 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9602 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9603 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9604 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9605 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9606 if (!HasErrors && DSA.isOrderedRegion()) {
9607 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9608 if (CurrentNestedLoopCount <
9609 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9610 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9611 CurrentNestedLoopCount,
9612 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9613 DSA.getOrderedRegionParam().second->setLoopCounter(
9614 CurrentNestedLoopCount,
9615 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9616 }
9617 }
9618 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9619 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9620 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9621 unsigned NumLoops =
9622 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9623 if (CurrentNestedLoopCount >= NumLoops) {
9624 // Erroneous case - clause has some problems.
9625 continue;
9626 }
9627 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9628 Pair.second.size() <= CurrentNestedLoopCount) {
9629 // Erroneous case - clause has some problems.
9630 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9631 continue;
9632 }
9633 OMPDoacrossKind ODK;
9634 if (DoacrossC && ODK.isSink(DoacrossC) &&
9635 Pair.second.size() <= CurrentNestedLoopCount) {
9636 // Erroneous case - clause has some problems.
9637 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9638 continue;
9639 }
9640 Expr *CntValue;
9641 SourceLocation DepLoc =
9642 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9643 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9644 (DoacrossC && ODK.isSource(DoacrossC)))
9645 CntValue = ISC.buildOrderedLoopData(
9646 DSA.getCurScope(),
9647 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9648 DepLoc);
9649 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9650 Expr *Cnt = SemaRef
9652 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9653 .get();
9654 if (!Cnt)
9655 continue;
9656 // build CounterVar - 1
9657 Expr *Inc =
9658 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9659 .get();
9660 CntValue = ISC.buildOrderedLoopData(
9661 DSA.getCurScope(),
9662 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9663 DepLoc, Inc, clang::OO_Minus);
9664 } else
9665 CntValue = ISC.buildOrderedLoopData(
9666 DSA.getCurScope(),
9667 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9668 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9669 Pair.second[CurrentNestedLoopCount].second);
9670 if (DependC)
9671 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9672 else
9673 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9674 }
9675 }
9676
9677 return HasErrors;
9678}
9679
9680/// Build 'VarRef = Start.
9681static ExprResult
9683 ExprResult Start, bool IsNonRectangularLB,
9684 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9685 // Build 'VarRef = Start.
9686 ExprResult NewStart = IsNonRectangularLB
9687 ? Start.get()
9688 : tryBuildCapture(SemaRef, Start.get(), Captures);
9689 if (!NewStart.isUsable())
9690 return ExprError();
9691 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9692 VarRef.get()->getType())) {
9693 NewStart = SemaRef.PerformImplicitConversion(
9694 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9695 /*AllowExplicit=*/true);
9696 if (!NewStart.isUsable())
9697 return ExprError();
9698 }
9699
9701 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9702 return Init;
9703}
9704
9705/// Build 'VarRef = Start + Iter * Step'.
9707 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9708 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9709 bool IsNonRectangularLB,
9710 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9711 // Add parentheses (for debugging purposes only).
9712 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9713 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9714 !Step.isUsable())
9715 return ExprError();
9716
9717 ExprResult NewStep = Step;
9718 if (Captures)
9719 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9720 if (NewStep.isInvalid())
9721 return ExprError();
9723 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9724 if (!Update.isUsable())
9725 return ExprError();
9726
9727 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9728 // 'VarRef = Start (+|-) Iter * Step'.
9729 if (!Start.isUsable())
9730 return ExprError();
9731 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9732 if (!NewStart.isUsable())
9733 return ExprError();
9734 if (Captures && !IsNonRectangularLB)
9735 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9736 if (NewStart.isInvalid())
9737 return ExprError();
9738
9739 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9740 ExprResult SavedUpdate = Update;
9741 ExprResult UpdateVal;
9742 if (VarRef.get()->getType()->isOverloadableType() ||
9743 NewStart.get()->getType()->isOverloadableType() ||
9744 Update.get()->getType()->isOverloadableType()) {
9745 Sema::TentativeAnalysisScope Trap(SemaRef);
9746
9747 Update =
9748 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9749 if (Update.isUsable()) {
9750 UpdateVal =
9751 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9752 VarRef.get(), SavedUpdate.get());
9753 if (UpdateVal.isUsable()) {
9754 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9755 UpdateVal.get());
9756 }
9757 }
9758 }
9759
9760 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9761 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9762 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9763 NewStart.get(), SavedUpdate.get());
9764 if (!Update.isUsable())
9765 return ExprError();
9766
9767 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9768 VarRef.get()->getType())) {
9770 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9771 if (!Update.isUsable())
9772 return ExprError();
9773 }
9774
9775 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9776 }
9777 return Update;
9778}
9779
9780/// Convert integer expression \a E to make it have at least \a Bits
9781/// bits.
9782static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9783 if (E == nullptr)
9784 return ExprError();
9785 ASTContext &C = SemaRef.Context;
9786 QualType OldType = E->getType();
9787 unsigned HasBits = C.getTypeSize(OldType);
9788 if (HasBits >= Bits)
9789 return ExprResult(E);
9790 // OK to convert to signed, because new type has more bits than old.
9791 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9792 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9793 true);
9794}
9795
9796/// Check if the given expression \a E is a constant integer that fits
9797/// into \a Bits bits.
9798static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9799 if (E == nullptr)
9800 return false;
9801 if (std::optional<llvm::APSInt> Result =
9802 E->getIntegerConstantExpr(SemaRef.Context))
9803 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9804 return false;
9805}
9806
9807/// Build preinits statement for the given declarations.
9809 MutableArrayRef<Decl *> PreInits) {
9810 if (!PreInits.empty()) {
9811 return new (Context) DeclStmt(
9812 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9814 }
9815 return nullptr;
9816}
9817
9818/// Build preinits statement for the given declarations.
9819static Stmt *
9821 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9822 if (!Captures.empty()) {
9823 SmallVector<Decl *, 16> PreInits;
9824 for (const auto &Pair : Captures)
9825 PreInits.push_back(Pair.second->getDecl());
9826 return buildPreInits(Context, PreInits);
9827 }
9828 return nullptr;
9829}
9830
9831/// Build postupdate expression for the given list of postupdates expressions.
9832static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9833 Expr *PostUpdate = nullptr;
9834 if (!PostUpdates.empty()) {
9835 for (Expr *E : PostUpdates) {
9836 Expr *ConvE = S.BuildCStyleCastExpr(
9837 E->getExprLoc(),
9839 E->getExprLoc(), E)
9840 .get();
9841 PostUpdate = PostUpdate
9842 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9843 PostUpdate, ConvE)
9844 .get()
9845 : ConvE;
9846 }
9847 }
9848 return PostUpdate;
9849}
9850
9851/// Called on a for stmt to check itself and nested loops (if any).
9852/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9853/// number of collapsed loops otherwise.
9854static unsigned
9855checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9856 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9857 DSAStackTy &DSA,
9858 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9860 unsigned NestedLoopCount = 1;
9861 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9863
9864 if (CollapseLoopCountExpr) {
9865 // Found 'collapse' clause - calculate collapse number.
9867 if (!CollapseLoopCountExpr->isValueDependent() &&
9868 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9869 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9870 } else {
9871 Built.clear(/*Size=*/1);
9872 return 1;
9873 }
9874 }
9875 unsigned OrderedLoopCount = 1;
9876 if (OrderedLoopCountExpr) {
9877 // Found 'ordered' clause - calculate collapse number.
9878 Expr::EvalResult EVResult;
9879 if (!OrderedLoopCountExpr->isValueDependent() &&
9880 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9881 SemaRef.getASTContext())) {
9882 llvm::APSInt Result = EVResult.Val.getInt();
9883 if (Result.getLimitedValue() < NestedLoopCount) {
9884 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9885 diag::err_omp_wrong_ordered_loop_count)
9886 << OrderedLoopCountExpr->getSourceRange();
9887 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9888 diag::note_collapse_loop_count)
9889 << CollapseLoopCountExpr->getSourceRange();
9890 }
9891 OrderedLoopCount = Result.getLimitedValue();
9892 } else {
9893 Built.clear(/*Size=*/1);
9894 return 1;
9895 }
9896 }
9897 // This is helper routine for loop directives (e.g., 'for', 'simd',
9898 // 'for simd', etc.).
9899 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9900 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9901 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9904 SupportsNonPerfectlyNested, NumLoops,
9905 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9906 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9907 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9909 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9910 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9911 VarsWithImplicitDSA, IterSpaces, Captures))
9912 return true;
9913 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9914 IterSpaces[Cnt].CounterVar) {
9915 // Handle initialization of captured loop iterator variables.
9916 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9917 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9918 Captures[DRE] = DRE;
9919 }
9920 }
9921 return false;
9922 },
9923 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9924 Stmt *DependentPreInits = Transform->getPreInits();
9925 if (!DependentPreInits)
9926 return;
9927 for (Decl *C : cast<DeclStmt>(DependentPreInits)->getDeclGroup()) {
9928 auto *D = cast<VarDecl>(C);
9929 DeclRefExpr *Ref = buildDeclRefExpr(SemaRef, D, D->getType(),
9930 Transform->getBeginLoc());
9931 Captures[Ref] = Ref;
9932 }
9933 }))
9934 return 0;
9935
9936 Built.clear(/* size */ NestedLoopCount);
9937
9938 if (SemaRef.CurContext->isDependentContext())
9939 return NestedLoopCount;
9940
9941 // An example of what is generated for the following code:
9942 //
9943 // #pragma omp simd collapse(2) ordered(2)
9944 // for (i = 0; i < NI; ++i)
9945 // for (k = 0; k < NK; ++k)
9946 // for (j = J0; j < NJ; j+=2) {
9947 // <loop body>
9948 // }
9949 //
9950 // We generate the code below.
9951 // Note: the loop body may be outlined in CodeGen.
9952 // Note: some counters may be C++ classes, operator- is used to find number of
9953 // iterations and operator+= to calculate counter value.
9954 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9955 // or i64 is currently supported).
9956 //
9957 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9958 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9959 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9960 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9961 // // similar updates for vars in clauses (e.g. 'linear')
9962 // <loop body (using local i and j)>
9963 // }
9964 // i = NI; // assign final values of counters
9965 // j = NJ;
9966 //
9967
9968 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9969 // the iteration counts of the collapsed for loops.
9970 // Precondition tests if there is at least one iteration (all conditions are
9971 // true).
9972 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9973 Expr *N0 = IterSpaces[0].NumIterations;
9974 ExprResult LastIteration32 =
9975 widenIterationCount(/*Bits=*/32,
9976 SemaRef
9977 .PerformImplicitConversion(
9978 N0->IgnoreImpCasts(), N0->getType(),
9979 Sema::AA_Converting, /*AllowExplicit=*/true)
9980 .get(),
9981 SemaRef);
9982 ExprResult LastIteration64 = widenIterationCount(
9983 /*Bits=*/64,
9984 SemaRef
9985 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9987 /*AllowExplicit=*/true)
9988 .get(),
9989 SemaRef);
9990
9991 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9992 return NestedLoopCount;
9993
9994 ASTContext &C = SemaRef.Context;
9995 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9996
9997 Scope *CurScope = DSA.getCurScope();
9998 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9999 if (PreCond.isUsable()) {
10000 PreCond =
10001 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10002 PreCond.get(), IterSpaces[Cnt].PreCond);
10003 }
10004 Expr *N = IterSpaces[Cnt].NumIterations;
10006 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10007 if (LastIteration32.isUsable())
10008 LastIteration32 = SemaRef.BuildBinOp(
10009 CurScope, Loc, BO_Mul, LastIteration32.get(),
10010 SemaRef
10013 /*AllowExplicit=*/true)
10014 .get());
10015 if (LastIteration64.isUsable())
10016 LastIteration64 = SemaRef.BuildBinOp(
10017 CurScope, Loc, BO_Mul, LastIteration64.get(),
10018 SemaRef
10021 /*AllowExplicit=*/true)
10022 .get());
10023 }
10024
10025 // Choose either the 32-bit or 64-bit version.
10026 ExprResult LastIteration = LastIteration64;
10027 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10028 (LastIteration32.isUsable() &&
10029 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10030 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10031 fitsInto(
10032 /*Bits=*/32,
10033 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10034 LastIteration64.get(), SemaRef))))
10035 LastIteration = LastIteration32;
10036 QualType VType = LastIteration.get()->getType();
10037 QualType RealVType = VType;
10038 QualType StrideVType = VType;
10039 if (isOpenMPTaskLoopDirective(DKind)) {
10040 VType =
10041 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10042 StrideVType =
10043 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10044 }
10045
10046 if (!LastIteration.isUsable())
10047 return 0;
10048
10049 // Save the number of iterations.
10050 ExprResult NumIterations = LastIteration;
10051 {
10052 LastIteration = SemaRef.BuildBinOp(
10053 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10054 LastIteration.get(),
10055 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10056 if (!LastIteration.isUsable())
10057 return 0;
10058 }
10059
10060 // Calculate the last iteration number beforehand instead of doing this on
10061 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10062 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10063 ExprResult CalcLastIteration;
10064 if (!IsConstant) {
10065 ExprResult SaveRef =
10066 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10067 LastIteration = SaveRef;
10068
10069 // Prepare SaveRef + 1.
10070 NumIterations = SemaRef.BuildBinOp(
10071 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10072 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10073 if (!NumIterations.isUsable())
10074 return 0;
10075 }
10076
10077 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10078
10079 // Build variables passed into runtime, necessary for worksharing directives.
10080 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10085 // Lower bound variable, initialized with zero.
10086 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10087 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10088 SemaRef.AddInitializerToDecl(LBDecl,
10089 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10090 /*DirectInit*/ false);
10091
10092 // Upper bound variable, initialized with last iteration number.
10093 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10094 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10095 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10096 /*DirectInit*/ false);
10097
10098 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10099 // This will be used to implement clause 'lastprivate'.
10100 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10101 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10102 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10103 SemaRef.AddInitializerToDecl(ILDecl,
10104 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10105 /*DirectInit*/ false);
10106
10107 // Stride variable returned by runtime (we initialize it to 1 by default).
10108 VarDecl *STDecl =
10109 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10110 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10111 SemaRef.AddInitializerToDecl(STDecl,
10112 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10113 /*DirectInit*/ false);
10114
10115 // Build expression: UB = min(UB, LastIteration)
10116 // It is necessary for CodeGen of directives with static scheduling.
10117 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10118 UB.get(), LastIteration.get());
10119 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10120 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10121 LastIteration.get(), UB.get());
10122 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10123 CondOp.get());
10124 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
10125
10126 // If we have a combined directive that combines 'distribute', 'for' or
10127 // 'simd' we need to be able to access the bounds of the schedule of the
10128 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10129 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10131 // Lower bound variable, initialized with zero.
10132 VarDecl *CombLBDecl =
10133 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10134 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10135 SemaRef.AddInitializerToDecl(
10136 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10137 /*DirectInit*/ false);
10138
10139 // Upper bound variable, initialized with last iteration number.
10140 VarDecl *CombUBDecl =
10141 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10142 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10143 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10144 /*DirectInit*/ false);
10145
10146 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10147 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10148 ExprResult CombCondOp =
10149 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10150 LastIteration.get(), CombUB.get());
10151 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10152 CombCondOp.get());
10153 CombEUB =
10154 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
10155
10156 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10157 // We expect to have at least 2 more parameters than the 'parallel'
10158 // directive does - the lower and upper bounds of the previous schedule.
10159 assert(CD->getNumParams() >= 4 &&
10160 "Unexpected number of parameters in loop combined directive");
10161
10162 // Set the proper type for the bounds given what we learned from the
10163 // enclosed loops.
10164 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10165 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10166
10167 // Previous lower and upper bounds are obtained from the region
10168 // parameters.
10169 PrevLB =
10170 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10171 PrevUB =
10172 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10173 }
10174 }
10175
10176 // Build the iteration variable and its initialization before loop.
10177 ExprResult IV;
10178 ExprResult Init, CombInit;
10179 {
10180 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10181 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10182 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10187 ? LB.get()
10188 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10189 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10190 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
10191
10193 Expr *CombRHS =
10198 ? CombLB.get()
10199 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10200 CombInit =
10201 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10202 CombInit =
10203 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
10204 }
10205 }
10206
10207 bool UseStrictCompare =
10208 RealVType->hasUnsignedIntegerRepresentation() &&
10209 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10210 return LIS.IsStrictCompare;
10211 });
10212 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10213 // unsigned IV)) for worksharing loops.
10214 SourceLocation CondLoc = AStmt->getBeginLoc();
10215 Expr *BoundUB = UB.get();
10216 if (UseStrictCompare) {
10217 BoundUB =
10218 SemaRef
10219 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10220 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10221 .get();
10222 BoundUB =
10223 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
10224 }
10225 ExprResult Cond =
10230 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10231 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10232 BoundUB)
10233 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10234 NumIterations.get());
10235 ExprResult CombDistCond;
10237 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10238 NumIterations.get());
10239 }
10240
10241 ExprResult CombCond;
10243 Expr *BoundCombUB = CombUB.get();
10244 if (UseStrictCompare) {
10245 BoundCombUB =
10246 SemaRef
10247 .BuildBinOp(
10248 CurScope, CondLoc, BO_Add, BoundCombUB,
10249 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10250 .get();
10251 BoundCombUB =
10252 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
10253 .get();
10254 }
10255 CombCond =
10256 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10257 IV.get(), BoundCombUB);
10258 }
10259 // Loop increment (IV = IV + 1)
10260 SourceLocation IncLoc = AStmt->getBeginLoc();
10261 ExprResult Inc =
10262 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10263 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10264 if (!Inc.isUsable())
10265 return 0;
10266 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10267 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
10268 if (!Inc.isUsable())
10269 return 0;
10270
10271 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10272 // Used for directives with static scheduling.
10273 // In combined construct, add combined version that use CombLB and CombUB
10274 // base variables for the update
10275 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10280 // LB + ST
10281 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10282 if (!NextLB.isUsable())
10283 return 0;
10284 // LB = LB + ST
10285 NextLB =
10286 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10287 NextLB =
10288 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
10289 if (!NextLB.isUsable())
10290 return 0;
10291 // UB + ST
10292 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10293 if (!NextUB.isUsable())
10294 return 0;
10295 // UB = UB + ST
10296 NextUB =
10297 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10298 NextUB =
10299 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
10300 if (!NextUB.isUsable())
10301 return 0;
10303 CombNextLB =
10304 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10305 if (!NextLB.isUsable())
10306 return 0;
10307 // LB = LB + ST
10308 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10309 CombNextLB.get());
10310 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10311 /*DiscardedValue*/ false);
10312 if (!CombNextLB.isUsable())
10313 return 0;
10314 // UB + ST
10315 CombNextUB =
10316 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10317 if (!CombNextUB.isUsable())
10318 return 0;
10319 // UB = UB + ST
10320 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10321 CombNextUB.get());
10322 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10323 /*DiscardedValue*/ false);
10324 if (!CombNextUB.isUsable())
10325 return 0;
10326 }
10327 }
10328
10329 // Create increment expression for distribute loop when combined in a same
10330 // directive with for as IV = IV + ST; ensure upper bound expression based
10331 // on PrevUB instead of NumIterations - used to implement 'for' when found
10332 // in combination with 'distribute', like in 'distribute parallel for'
10333 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10334 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10336 DistCond = SemaRef.BuildBinOp(
10337 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10338 assert(DistCond.isUsable() && "distribute cond expr was not built");
10339
10340 DistInc =
10341 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10342 assert(DistInc.isUsable() && "distribute inc expr was not built");
10343 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10344 DistInc.get());
10345 DistInc =
10346 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10347 assert(DistInc.isUsable() && "distribute inc expr was not built");
10348
10349 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10350 // construct
10351 ExprResult NewPrevUB = PrevUB;
10352 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10353 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10354 PrevUB.get()->getType())) {
10355 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10356 DistEUBLoc,
10358 DistEUBLoc, NewPrevUB.get());
10359 if (!NewPrevUB.isUsable())
10360 return 0;
10361 }
10362 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10363 UB.get(), NewPrevUB.get());
10364 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10365 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10366 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10367 CondOp.get());
10368 PrevEUB =
10369 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10370
10371 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10372 // parallel for is in combination with a distribute directive with
10373 // schedule(static, 1)
10374 Expr *BoundPrevUB = PrevUB.get();
10375 if (UseStrictCompare) {
10376 BoundPrevUB =
10377 SemaRef
10378 .BuildBinOp(
10379 CurScope, CondLoc, BO_Add, BoundPrevUB,
10380 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10381 .get();
10382 BoundPrevUB =
10383 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10384 .get();
10385 }
10386 ParForInDistCond =
10387 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10388 IV.get(), BoundPrevUB);
10389 }
10390
10391 // Build updates and final values of the loop counters.
10392 bool HasErrors = false;
10393 Built.Counters.resize(NestedLoopCount);
10394 Built.Inits.resize(NestedLoopCount);
10395 Built.Updates.resize(NestedLoopCount);
10396 Built.Finals.resize(NestedLoopCount);
10397 Built.DependentCounters.resize(NestedLoopCount);
10398 Built.DependentInits.resize(NestedLoopCount);
10399 Built.FinalsConditions.resize(NestedLoopCount);
10400 {
10401 // We implement the following algorithm for obtaining the
10402 // original loop iteration variable values based on the
10403 // value of the collapsed loop iteration variable IV.
10404 //
10405 // Let n+1 be the number of collapsed loops in the nest.
10406 // Iteration variables (I0, I1, .... In)
10407 // Iteration counts (N0, N1, ... Nn)
10408 //
10409 // Acc = IV;
10410 //
10411 // To compute Ik for loop k, 0 <= k <= n, generate:
10412 // Prod = N(k+1) * N(k+2) * ... * Nn;
10413 // Ik = Acc / Prod;
10414 // Acc -= Ik * Prod;
10415 //
10416 ExprResult Acc = IV;
10417 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10418 LoopIterationSpace &IS = IterSpaces[Cnt];
10419 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10421
10422 // Compute prod
10423 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10424 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10425 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10426 IterSpaces[K].NumIterations);
10427
10428 // Iter = Acc / Prod
10429 // If there is at least one more inner loop to avoid
10430 // multiplication by 1.
10431 if (Cnt + 1 < NestedLoopCount)
10432 Iter =
10433 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10434 else
10435 Iter = Acc;
10436 if (!Iter.isUsable()) {
10437 HasErrors = true;
10438 break;
10439 }
10440
10441 // Update Acc:
10442 // Acc -= Iter * Prod
10443 // Check if there is at least one more inner loop to avoid
10444 // multiplication by 1.
10445 if (Cnt + 1 < NestedLoopCount)
10446 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10447 Prod.get());
10448 else
10449 Prod = Iter;
10450 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10451
10452 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10453 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10454 DeclRefExpr *CounterVar = buildDeclRefExpr(
10455 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10456 /*RefersToCapture=*/true);
10458 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10459 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10460 if (!Init.isUsable()) {
10461 HasErrors = true;
10462 break;
10463 }
10465 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10466 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10467 if (!Update.isUsable()) {
10468 HasErrors = true;
10469 break;
10470 }
10471
10472 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10473 ExprResult Final =
10474 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10475 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10476 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10477 if (!Final.isUsable()) {
10478 HasErrors = true;
10479 break;
10480 }
10481
10482 if (!Update.isUsable() || !Final.isUsable()) {
10483 HasErrors = true;
10484 break;
10485 }
10486 // Save results
10487 Built.Counters[Cnt] = IS.CounterVar;
10488 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10489 Built.Inits[Cnt] = Init.get();
10490 Built.Updates[Cnt] = Update.get();
10491 Built.Finals[Cnt] = Final.get();
10492 Built.DependentCounters[Cnt] = nullptr;
10493 Built.DependentInits[Cnt] = nullptr;
10494 Built.FinalsConditions[Cnt] = nullptr;
10495 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10496 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10497 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10498 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10499 }
10500 }
10501 }
10502
10503 if (HasErrors)
10504 return 0;
10505
10506 // Save results
10507 Built.IterationVarRef = IV.get();
10508 Built.LastIteration = LastIteration.get();
10509 Built.NumIterations = NumIterations.get();
10510 Built.CalcLastIteration = SemaRef
10511 .ActOnFinishFullExpr(CalcLastIteration.get(),
10512 /*DiscardedValue=*/false)
10513 .get();
10514 Built.PreCond = PreCond.get();
10515 Built.PreInits = buildPreInits(C, Captures);
10516 Built.Cond = Cond.get();
10517 Built.Init = Init.get();
10518 Built.Inc = Inc.get();
10519 Built.LB = LB.get();
10520 Built.UB = UB.get();
10521 Built.IL = IL.get();
10522 Built.ST = ST.get();
10523 Built.EUB = EUB.get();
10524 Built.NLB = NextLB.get();
10525 Built.NUB = NextUB.get();
10526 Built.PrevLB = PrevLB.get();
10527 Built.PrevUB = PrevUB.get();
10528 Built.DistInc = DistInc.get();
10529 Built.PrevEUB = PrevEUB.get();
10530 Built.DistCombinedFields.LB = CombLB.get();
10531 Built.DistCombinedFields.UB = CombUB.get();
10532 Built.DistCombinedFields.EUB = CombEUB.get();
10533 Built.DistCombinedFields.Init = CombInit.get();
10534 Built.DistCombinedFields.Cond = CombCond.get();
10535 Built.DistCombinedFields.NLB = CombNextLB.get();
10536 Built.DistCombinedFields.NUB = CombNextUB.get();
10537 Built.DistCombinedFields.DistCond = CombDistCond.get();
10538 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10539
10540 return NestedLoopCount;
10541}
10542
10544 auto CollapseClauses =
10545 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10546 if (CollapseClauses.begin() != CollapseClauses.end())
10547 return (*CollapseClauses.begin())->getNumForLoops();
10548 return nullptr;
10549}
10550
10552 auto OrderedClauses =
10553 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10554 if (OrderedClauses.begin() != OrderedClauses.end())
10555 return (*OrderedClauses.begin())->getNumForLoops();
10556 return nullptr;
10557}
10558
10560 const ArrayRef<OMPClause *> Clauses) {
10561 const OMPSafelenClause *Safelen = nullptr;
10562 const OMPSimdlenClause *Simdlen = nullptr;
10563
10564 for (const OMPClause *Clause : Clauses) {
10565 if (Clause->getClauseKind() == OMPC_safelen)
10566 Safelen = cast<OMPSafelenClause>(Clause);
10567 else if (Clause->getClauseKind() == OMPC_simdlen)
10568 Simdlen = cast<OMPSimdlenClause>(Clause);
10569 if (Safelen && Simdlen)
10570 break;
10571 }
10572
10573 if (Simdlen && Safelen) {
10574 const Expr *SimdlenLength = Simdlen->getSimdlen();
10575 const Expr *SafelenLength = Safelen->getSafelen();
10576 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10577 SimdlenLength->isInstantiationDependent() ||
10578 SimdlenLength->containsUnexpandedParameterPack())
10579 return false;
10580 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10581 SafelenLength->isInstantiationDependent() ||
10582 SafelenLength->containsUnexpandedParameterPack())
10583 return false;
10584 Expr::EvalResult SimdlenResult, SafelenResult;
10585 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10586 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10587 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10588 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10589 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10590 // If both simdlen and safelen clauses are specified, the value of the
10591 // simdlen parameter must be less than or equal to the value of the safelen
10592 // parameter.
10593 if (SimdlenRes > SafelenRes) {
10594 S.Diag(SimdlenLength->getExprLoc(),
10595 diag::err_omp_wrong_simdlen_safelen_values)
10596 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10597 return true;
10598 }
10599 }
10600 return false;
10601}
10602
10605 DSAStackTy *Stack);
10606
10607bool SemaOpenMP::checkLastPrivateForMappedDirectives(
10608 ArrayRef<OMPClause *> Clauses) {
10609
10610 // Check for syntax of lastprivate
10611 // Param of the lastprivate have different meanings in the mapped directives
10612 // e.g. "omp loop" Only loop iteration vars are allowed in lastprivate clause
10613 // "omp for" lastprivate vars must be shared
10614 if (getLangOpts().OpenMP >= 50 &&
10615 DSAStack->getMappedDirective() == OMPD_loop &&
10616 checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack)) {
10617 return false;
10618 }
10619 return true;
10620}
10621
10623 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10624 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10625 if (!AStmt)
10626 return StmtError();
10627
10628 if (!checkLastPrivateForMappedDirectives(Clauses))
10629 return StmtError();
10630
10631 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10633 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10634 // define the nested loops number.
10635 unsigned NestedLoopCount = checkOpenMPLoop(
10636 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10637 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10638 if (NestedLoopCount == 0)
10639 return StmtError();
10640
10641 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10642 "omp simd loop exprs were not built");
10643
10645 // Finalize the clauses that need pre-built expressions for CodeGen.
10646 for (OMPClause *C : Clauses) {
10647 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10648 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10651 return StmtError();
10652 }
10653 }
10654
10656 return StmtError();
10657
10659 auto *SimdDirective = OMPSimdDirective::Create(
10660 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10661 DSAStack->getMappedDirective());
10662 return SimdDirective;
10663}
10664
10666 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10667 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10668 if (!AStmt)
10669 return StmtError();
10670
10671 if (!checkLastPrivateForMappedDirectives(Clauses))
10672 return StmtError();
10673
10674 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10676 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10677 // define the nested loops number.
10678 unsigned NestedLoopCount = checkOpenMPLoop(
10679 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10680 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10681 if (NestedLoopCount == 0)
10682 return StmtError();
10683
10684 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10685 "omp for loop exprs were not built");
10686
10688 // Finalize the clauses that need pre-built expressions for CodeGen.
10689 for (OMPClause *C : Clauses) {
10690 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10691 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10694 return StmtError();
10695 }
10696 }
10697
10698 auto *ForDirective = OMPForDirective::Create(
10699 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10700 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion(),
10701 DSAStack->getMappedDirective());
10702 return ForDirective;
10703}
10704
10706 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10707 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10708 if (!AStmt)
10709 return StmtError();
10710
10711 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10713 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10714 // define the nested loops number.
10715 unsigned NestedLoopCount =
10716 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10717 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10718 VarsWithImplicitDSA, B);
10719 if (NestedLoopCount == 0)
10720 return StmtError();
10721
10722 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10723 "omp for simd loop exprs were not built");
10724
10726 // Finalize the clauses that need pre-built expressions for CodeGen.
10727 for (OMPClause *C : Clauses) {
10728 if (auto *LC = dyn_cast<OMPLinearClause>(C))
10729 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
10732 return StmtError();
10733 }
10734 }
10735
10737 return StmtError();
10738
10740 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10741 NestedLoopCount, Clauses, AStmt, B);
10742}
10743
10746 Stmt *AStmt, SourceLocation StartLoc,
10747 SourceLocation EndLoc) {
10748 if (!AStmt)
10749 return StmtError();
10750
10751 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10752 auto BaseStmt = AStmt;
10753 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10754 BaseStmt = CS->getCapturedStmt();
10755 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10756 auto S = C->children();
10757 if (S.begin() == S.end())
10758 return StmtError();
10759 // All associated statements must be '#pragma omp section' except for
10760 // the first one.
10761 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10762 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10763 if (SectionStmt)
10764 Diag(SectionStmt->getBeginLoc(),
10765 diag::err_omp_sections_substmt_not_section);
10766 return StmtError();
10767 }
10768 cast<OMPSectionDirective>(SectionStmt)
10769 ->setHasCancel(DSAStack->isCancelRegion());
10770 }
10771 } else {
10772 Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt);
10773 return StmtError();
10774 }
10775
10777
10779 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10780 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10781}
10782
10784 SourceLocation StartLoc,
10785 SourceLocation EndLoc) {
10786 if (!AStmt)
10787 return StmtError();
10788
10790 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10791
10792 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10793 DSAStack->isCancelRegion());
10794}
10795
10797 E = E->IgnoreParenCasts()->IgnoreImplicit();
10798 if (auto *CE = dyn_cast<CallExpr>(E))
10799 if (CE->getDirectCallee())
10800 return E;
10801 return nullptr;
10802}
10803
10806 Stmt *AStmt, SourceLocation StartLoc,
10807 SourceLocation EndLoc) {
10808 if (!AStmt)
10809 return StmtError();
10810
10811 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10812
10813 // 5.1 OpenMP
10814 // expression-stmt : an expression statement with one of the following forms:
10815 // expression = target-call ( [expression-list] );
10816 // target-call ( [expression-list] );
10817
10818 SourceLocation TargetCallLoc;
10819
10821 Expr *TargetCall = nullptr;
10822
10823 auto *E = dyn_cast<Expr>(S);
10824 if (!E) {
10825 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10826 return StmtError();
10827 }
10828
10829 E = E->IgnoreParenCasts()->IgnoreImplicit();
10830
10831 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10832 if (BO->getOpcode() == BO_Assign)
10833 TargetCall = getDirectCallExpr(BO->getRHS());
10834 } else {
10835 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10836 if (COCE->getOperator() == OO_Equal)
10837 TargetCall = getDirectCallExpr(COCE->getArg(1));
10838 if (!TargetCall)
10839 TargetCall = getDirectCallExpr(E);
10840 }
10841 if (!TargetCall) {
10842 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10843 return StmtError();
10844 }
10845 TargetCallLoc = TargetCall->getExprLoc();
10846 }
10847
10849
10850 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10851 Clauses, AStmt, TargetCallLoc);
10852}
10853
10856 DSAStackTy *Stack) {
10857 bool ErrorFound = false;
10858 for (OMPClause *C : Clauses) {
10859 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10860 for (Expr *RefExpr : LPC->varlists()) {
10861 SourceLocation ELoc;
10862 SourceRange ERange;
10863 Expr *SimpleRefExpr = RefExpr;
10864 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10865 if (ValueDecl *D = Res.first) {
10866 auto &&Info = Stack->isLoopControlVariable(D);
10867 if (!Info.first) {
10868 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10869 << getOpenMPDirectiveName(K);
10870 ErrorFound = true;
10871 }
10872 }
10873 }
10874 }
10875 }
10876 return ErrorFound;
10877}
10878
10880 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10881 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10882 if (!AStmt)
10883 return StmtError();
10884
10885 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10886 // A list item may not appear in a lastprivate clause unless it is the
10887 // loop iteration variable of a loop that is associated with the construct.
10888 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10889 return StmtError();
10890
10891 auto *CS = cast<CapturedStmt>(AStmt);
10892 // 1.2.2 OpenMP Language Terminology
10893 // Structured block - An executable statement with a single entry at the
10894 // top and a single exit at the bottom.
10895 // The point of exit cannot be a branch out of the structured block.
10896 // longjmp() and throw() must not violate the entry/exit criteria.
10897 CS->getCapturedDecl()->setNothrow();
10898
10900 // In presence of clause 'collapse', it will define the nested loops number.
10901 unsigned NestedLoopCount = checkOpenMPLoop(
10902 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10903 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10904 if (NestedLoopCount == 0)
10905 return StmtError();
10906
10907 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10908 "omp loop exprs were not built");
10909
10911 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10912 NestedLoopCount, Clauses, AStmt, B);
10913}
10914
10916 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10917 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10918 if (!AStmt)
10919 return StmtError();
10920
10921 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10922 // A list item may not appear in a lastprivate clause unless it is the
10923 // loop iteration variable of a loop that is associated with the construct.
10924 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10925 return StmtError();
10926
10927 auto *CS = cast<CapturedStmt>(AStmt);
10928 // 1.2.2 OpenMP Language Terminology
10929 // Structured block - An executable statement with a single entry at the
10930 // top and a single exit at the bottom.
10931 // The point of exit cannot be a branch out of the structured block.
10932 // longjmp() and throw() must not violate the entry/exit criteria.
10933 CS->getCapturedDecl()->setNothrow();
10934 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_loop);
10935 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10936 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10937 // 1.2.2 OpenMP Language Terminology
10938 // Structured block - An executable statement with a single entry at the
10939 // top and a single exit at the bottom.
10940 // The point of exit cannot be a branch out of the structured block.
10941 // longjmp() and throw() must not violate the entry/exit criteria.
10942 CS->getCapturedDecl()->setNothrow();
10943 }
10944
10946 // In presence of clause 'collapse', it will define the nested loops number.
10947 unsigned NestedLoopCount =
10948 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10949 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10950 VarsWithImplicitDSA, B);
10951 if (NestedLoopCount == 0)
10952 return StmtError();
10953
10954 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10955 "omp loop exprs were not built");
10956
10958 DSAStack->setParentTeamsRegionLoc(StartLoc);
10959
10961 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10962}
10963
10965 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10966 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10967 if (!AStmt)
10968 return StmtError();
10969
10970 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10971 // A list item may not appear in a lastprivate clause unless it is the
10972 // loop iteration variable of a loop that is associated with the construct.
10973 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10974 DSAStack))
10975 return StmtError();
10976
10977 auto *CS = cast<CapturedStmt>(AStmt);
10978 // 1.2.2 OpenMP Language Terminology
10979 // Structured block - An executable statement with a single entry at the
10980 // top and a single exit at the bottom.
10981 // The point of exit cannot be a branch out of the structured block.
10982 // longjmp() and throw() must not violate the entry/exit criteria.
10983 CS->getCapturedDecl()->setNothrow();
10984 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams_loop);
10985 ThisCaptureLevel > 1; --ThisCaptureLevel) {
10986 CS = cast<CapturedStmt>(CS->getCapturedStmt());
10987 // 1.2.2 OpenMP Language Terminology
10988 // Structured block - An executable statement with a single entry at the
10989 // top and a single exit at the bottom.
10990 // The point of exit cannot be a branch out of the structured block.
10991 // longjmp() and throw() must not violate the entry/exit criteria.
10992 CS->getCapturedDecl()->setNothrow();
10993 }
10994
10996 // In presence of clause 'collapse', it will define the nested loops number.
10997 unsigned NestedLoopCount =
10998 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10999 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11000 VarsWithImplicitDSA, B);
11001 if (NestedLoopCount == 0)
11002 return StmtError();
11003
11004 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11005 "omp loop exprs were not built");
11006
11008
11010 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11012}
11013
11015 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11016 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11017 if (!AStmt)
11018 return StmtError();
11019
11020 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11021 // A list item may not appear in a lastprivate clause unless it is the
11022 // loop iteration variable of a loop that is associated with the construct.
11023 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
11024 DSAStack))
11025 return StmtError();
11026
11027 auto *CS = cast<CapturedStmt>(AStmt);
11028 // 1.2.2 OpenMP Language Terminology
11029 // Structured block - An executable statement with a single entry at the
11030 // top and a single exit at the bottom.
11031 // The point of exit cannot be a branch out of the structured block.
11032 // longjmp() and throw() must not violate the entry/exit criteria.
11033 CS->getCapturedDecl()->setNothrow();
11034 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_parallel_loop);
11035 ThisCaptureLevel > 1; --ThisCaptureLevel) {
11036 CS = cast<CapturedStmt>(CS->getCapturedStmt());
11037 // 1.2.2 OpenMP Language Terminology
11038 // Structured block - An executable statement with a single entry at the
11039 // top and a single exit at the bottom.
11040 // The point of exit cannot be a branch out of the structured block.
11041 // longjmp() and throw() must not violate the entry/exit criteria.
11042 CS->getCapturedDecl()->setNothrow();
11043 }
11044
11046 // In presence of clause 'collapse', it will define the nested loops number.
11047 unsigned NestedLoopCount =
11048 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
11049 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11050 VarsWithImplicitDSA, B);
11051 if (NestedLoopCount == 0)
11052 return StmtError();
11053
11054 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11055 "omp loop exprs were not built");
11056
11058
11060 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11061}
11062
11064 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11065 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11066 if (!AStmt)
11067 return StmtError();
11068
11069 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11070 // A list item may not appear in a lastprivate clause unless it is the
11071 // loop iteration variable of a loop that is associated with the construct.
11072 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
11073 DSAStack))
11074 return StmtError();
11075
11076 auto *CS = cast<CapturedStmt>(AStmt);
11077 // 1.2.2 OpenMP Language Terminology
11078 // Structured block - An executable statement with a single entry at the
11079 // top and a single exit at the bottom.
11080 // The point of exit cannot be a branch out of the structured block.
11081 // longjmp() and throw() must not violate the entry/exit criteria.
11082 CS->getCapturedDecl()->setNothrow();
11083 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_loop);
11084 ThisCaptureLevel > 1; --ThisCaptureLevel) {
11085 CS = cast<CapturedStmt>(CS->getCapturedStmt());
11086 // 1.2.2 OpenMP Language Terminology
11087 // Structured block - An executable statement with a single entry at the
11088 // top and a single exit at the bottom.
11089 // The point of exit cannot be a branch out of the structured block.
11090 // longjmp() and throw() must not violate the entry/exit criteria.
11091 CS->getCapturedDecl()->setNothrow();
11092 }
11093
11095 // In presence of clause 'collapse', it will define the nested loops number.
11096 unsigned NestedLoopCount =
11097 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11098 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11099 VarsWithImplicitDSA, B);
11100 if (NestedLoopCount == 0)
11101 return StmtError();
11102
11103 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11104 "omp loop exprs were not built");
11105
11107
11109 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11110}
11111
11113 Stmt *AStmt,
11114 SourceLocation StartLoc,
11115 SourceLocation EndLoc) {
11116 if (!AStmt)
11117 return StmtError();
11118
11119 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11120
11122
11123 // OpenMP [2.7.3, single Construct, Restrictions]
11124 // The copyprivate clause must not be used with the nowait clause.
11125 const OMPClause *Nowait = nullptr;
11126 const OMPClause *Copyprivate = nullptr;
11127 for (const OMPClause *Clause : Clauses) {
11128 if (Clause->getClauseKind() == OMPC_nowait)
11129 Nowait = Clause;
11130 else if (Clause->getClauseKind() == OMPC_copyprivate)
11131 Copyprivate = Clause;
11132 if (Copyprivate && Nowait) {
11133 Diag(Copyprivate->getBeginLoc(),
11134 diag::err_omp_single_copyprivate_with_nowait);
11135 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11136 return StmtError();
11137 }
11138 }
11139
11140 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11141 AStmt);
11142}
11143
11145 SourceLocation StartLoc,
11146 SourceLocation EndLoc) {
11147 if (!AStmt)
11148 return StmtError();
11149
11151
11152 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11153}
11154
11156 Stmt *AStmt,
11157 SourceLocation StartLoc,
11158 SourceLocation EndLoc) {
11159 if (!AStmt)
11160 return StmtError();
11161
11163
11164 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11165 AStmt);
11166}
11167
11169 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11170 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11171 if (!AStmt)
11172 return StmtError();
11173
11174 bool ErrorFound = false;
11175 llvm::APSInt Hint;
11176 SourceLocation HintLoc;
11177 bool DependentHint = false;
11178 for (const OMPClause *C : Clauses) {
11179 if (C->getClauseKind() == OMPC_hint) {
11180 if (!DirName.getName()) {
11181 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11182 ErrorFound = true;
11183 }
11184 Expr *E = cast<OMPHintClause>(C)->getHint();
11185 if (E->isTypeDependent() || E->isValueDependent() ||
11187 DependentHint = true;
11188 } else {
11190 HintLoc = C->getBeginLoc();
11191 }
11192 }
11193 }
11194 if (ErrorFound)
11195 return StmtError();
11196 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11197 if (Pair.first && DirName.getName() && !DependentHint) {
11198 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11199 Diag(StartLoc, diag::err_omp_critical_with_hint);
11200 if (HintLoc.isValid())
11201 Diag(HintLoc, diag::note_omp_critical_hint_here)
11202 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11203 else
11204 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11205 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11206 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11207 << 1
11208 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11209 /*Radix=*/10, /*Signed=*/false);
11210 } else {
11211 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11212 }
11213 }
11214 }
11215
11217
11218 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11219 EndLoc, Clauses, AStmt);
11220 if (!Pair.first && DirName.getName() && !DependentHint)
11221 DSAStack->addCriticalWithHint(Dir, Hint);
11222 return Dir;
11223}
11224
11226 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11227 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11228 if (!AStmt)
11229 return StmtError();
11230
11231 auto *CS = cast<CapturedStmt>(AStmt);
11232 // 1.2.2 OpenMP Language Terminology
11233 // Structured block - An executable statement with a single entry at the
11234 // top and a single exit at the bottom.
11235 // The point of exit cannot be a branch out of the structured block.
11236 // longjmp() and throw() must not violate the entry/exit criteria.
11237 CS->getCapturedDecl()->setNothrow();
11238
11240 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11241 // define the nested loops number.
11242 unsigned NestedLoopCount =
11243 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11244 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11245 VarsWithImplicitDSA, B);
11246 if (NestedLoopCount == 0)
11247 return StmtError();
11248
11249 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11250 "omp parallel for loop exprs were not built");
11251
11253 // Finalize the clauses that need pre-built expressions for CodeGen.
11254 for (OMPClause *C : Clauses) {
11255 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11256 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11259 return StmtError();
11260 }
11261 }
11262
11265 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11266 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11267}
11268
11270 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11271 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11272 if (!AStmt)
11273 return StmtError();
11274
11275 auto *CS = cast<CapturedStmt>(AStmt);
11276 // 1.2.2 OpenMP Language Terminology
11277 // Structured block - An executable statement with a single entry at the
11278 // top and a single exit at the bottom.
11279 // The point of exit cannot be a branch out of the structured block.
11280 // longjmp() and throw() must not violate the entry/exit criteria.
11281 CS->getCapturedDecl()->setNothrow();
11282
11284 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11285 // define the nested loops number.
11286 unsigned NestedLoopCount =
11287 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11288 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11289 VarsWithImplicitDSA, B);
11290 if (NestedLoopCount == 0)
11291 return StmtError();
11292
11294 // Finalize the clauses that need pre-built expressions for CodeGen.
11295 for (OMPClause *C : Clauses) {
11296 if (auto *LC = dyn_cast<OMPLinearClause>(C))
11297 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
11300 return StmtError();
11301 }
11302 }
11303
11305 return StmtError();
11306
11309 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11310}
11311
11313 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11314 SourceLocation EndLoc) {
11315 if (!AStmt)
11316 return StmtError();
11317
11318 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11319 auto *CS = cast<CapturedStmt>(AStmt);
11320 // 1.2.2 OpenMP Language Terminology
11321 // Structured block - An executable statement with a single entry at the
11322 // top and a single exit at the bottom.
11323 // The point of exit cannot be a branch out of the structured block.
11324 // longjmp() and throw() must not violate the entry/exit criteria.
11325 CS->getCapturedDecl()->setNothrow();
11326
11328
11330 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11331 DSAStack->getTaskgroupReductionRef());
11332}
11333
11335 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11336 SourceLocation EndLoc) {
11337 if (!AStmt)
11338 return StmtError();
11339
11340 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11341 auto *CS = cast<CapturedStmt>(AStmt);
11342 // 1.2.2 OpenMP Language Terminology
11343 // Structured block - An executable statement with a single entry at the
11344 // top and a single exit at the bottom.
11345 // The point of exit cannot be a branch out of the structured block.
11346 // longjmp() and throw() must not violate the entry/exit criteria.
11347 CS->getCapturedDecl()->setNothrow();
11348
11350
11352 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11353 DSAStack->getTaskgroupReductionRef());
11354}
11355
11357 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11358 SourceLocation EndLoc) {
11359 if (!AStmt)
11360 return StmtError();
11361
11362 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11363 auto BaseStmt = AStmt;
11364 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11365 BaseStmt = CS->getCapturedStmt();
11366 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11367 auto S = C->children();
11368 if (S.begin() == S.end())
11369 return StmtError();
11370 // All associated statements must be '#pragma omp section' except for
11371 // the first one.
11372 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
11373 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
11374 if (SectionStmt)
11375 Diag(SectionStmt->getBeginLoc(),
11376 diag::err_omp_parallel_sections_substmt_not_section);
11377 return StmtError();
11378 }
11379 cast<OMPSectionDirective>(SectionStmt)
11380 ->setHasCancel(DSAStack->isCancelRegion());
11381 }
11382 } else {
11383 Diag(AStmt->getBeginLoc(),
11384 diag::err_omp_parallel_sections_not_compound_stmt);
11385 return StmtError();
11386 }
11387
11389
11391 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11392 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11393}
11394
11395/// Find and diagnose mutually exclusive clause kinds.
11397 Sema &S, ArrayRef<OMPClause *> Clauses,
11398 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11399 const OMPClause *PrevClause = nullptr;
11400 bool ErrorFound = false;
11401 for (const OMPClause *C : Clauses) {
11402 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11403 if (!PrevClause) {
11404 PrevClause = C;
11405 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11406 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11407 << getOpenMPClauseName(C->getClauseKind())
11408 << getOpenMPClauseName(PrevClause->getClauseKind());
11409 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11410 << getOpenMPClauseName(PrevClause->getClauseKind());
11411 ErrorFound = true;
11412 }
11413 }
11414 }
11415 return ErrorFound;
11416}
11417
11419 Stmt *AStmt,
11420 SourceLocation StartLoc,
11421 SourceLocation EndLoc) {
11422 if (!AStmt)
11423 return StmtError();
11424
11425 // OpenMP 5.0, 2.10.1 task Construct
11426 // If a detach clause appears on the directive, then a mergeable clause cannot
11427 // appear on the same directive.
11429 {OMPC_detach, OMPC_mergeable}))
11430 return StmtError();
11431
11432 auto *CS = cast<CapturedStmt>(AStmt);
11433 // 1.2.2 OpenMP Language Terminology
11434 // Structured block - An executable statement with a single entry at the
11435 // top and a single exit at the bottom.
11436 // The point of exit cannot be a branch out of the structured block.
11437 // longjmp() and throw() must not violate the entry/exit criteria.
11438 CS->getCapturedDecl()->setNothrow();
11439
11441
11442 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11443 AStmt, DSAStack->isCancelRegion());
11444}
11445
11447 SourceLocation EndLoc) {
11448 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11449}
11450
11452 SourceLocation EndLoc) {
11453 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11454}
11455
11457 SourceLocation StartLoc,
11458 SourceLocation EndLoc,
11459 bool InExContext) {
11460 const OMPAtClause *AtC =
11461 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11462
11463 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11464 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11465 return StmtError();
11466 }
11467
11468 const OMPSeverityClause *SeverityC =
11469 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11470 const OMPMessageClause *MessageC =
11471 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11472 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11473
11474 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11475 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11476 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11477 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11478 else
11479 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11480 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11481 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11482 return StmtError();
11483 }
11484 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11485}
11486
11489 SourceLocation StartLoc,
11490 SourceLocation EndLoc) {
11491 const OMPNowaitClause *NowaitC =
11492 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11493 bool HasDependC =
11494 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11495 .empty();
11496 if (NowaitC && !HasDependC) {
11497 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11498 return StmtError();
11499 }
11500
11501 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11502 Clauses);
11503}
11504
11507 Stmt *AStmt, SourceLocation StartLoc,
11508 SourceLocation EndLoc) {
11509 if (!AStmt)
11510 return StmtError();
11511
11512 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11513
11515
11516 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11517 Clauses, AStmt,
11518 DSAStack->getTaskgroupReductionRef());
11519}
11520
11522 SourceLocation StartLoc,
11523 SourceLocation EndLoc) {
11524 OMPFlushClause *FC = nullptr;
11525 OMPClause *OrderClause = nullptr;
11526 for (OMPClause *C : Clauses) {
11527 if (C->getClauseKind() == OMPC_flush)
11528 FC = cast<OMPFlushClause>(C);
11529 else
11530 OrderClause = C;
11531 }
11532 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11533 SourceLocation MemOrderLoc;
11534 for (const OMPClause *C : Clauses) {
11535 if (C->getClauseKind() == OMPC_acq_rel ||
11536 C->getClauseKind() == OMPC_acquire ||
11537 C->getClauseKind() == OMPC_release) {
11538 if (MemOrderKind != OMPC_unknown) {
11539 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11540 << getOpenMPDirectiveName(OMPD_flush) << 1
11541 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11542 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11543 << getOpenMPClauseName(MemOrderKind);
11544 } else {
11545 MemOrderKind = C->getClauseKind();
11546 MemOrderLoc = C->getBeginLoc();
11547 }
11548 }
11549 }
11550 if (FC && OrderClause) {
11551 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11552 << getOpenMPClauseName(OrderClause->getClauseKind());
11553 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11554 << getOpenMPClauseName(OrderClause->getClauseKind());
11555 return StmtError();
11556 }
11557 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11558}
11559
11561 SourceLocation StartLoc,
11562 SourceLocation EndLoc) {
11563 if (Clauses.empty()) {
11564 Diag(StartLoc, diag::err_omp_depobj_expected);
11565 return StmtError();
11566 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11567 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11568 return StmtError();
11569 }
11570 // Only depobj expression and another single clause is allowed.
11571 if (Clauses.size() > 2) {
11572 Diag(Clauses[2]->getBeginLoc(),
11573 diag::err_omp_depobj_single_clause_expected);
11574 return StmtError();
11575 } else if (Clauses.size() < 1) {
11576 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11577 return StmtError();
11578 }
11579 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11580}
11581
11583 SourceLocation StartLoc,
11584 SourceLocation EndLoc) {
11585 // Check that exactly one clause is specified.
11586 if (Clauses.size() != 1) {
11587 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11588 diag::err_omp_scan_single_clause_expected);
11589 return StmtError();
11590 }
11591 // Check that scan directive is used in the scopeof the OpenMP loop body.
11592 if (Scope *S = DSAStack->getCurScope()) {
11593 Scope *ParentS = S->getParent();
11594 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11595 !ParentS->getBreakParent()->isOpenMPLoopScope())
11596 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11597 << getOpenMPDirectiveName(OMPD_scan) << 5);
11598 }
11599 // Check that only one instance of scan directives is used in the same outer
11600 // region.
11601 if (DSAStack->doesParentHasScanDirective()) {
11602 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11603 Diag(DSAStack->getParentScanDirectiveLoc(),
11604 diag::note_omp_previous_directive)
11605 << "scan";
11606 return StmtError();
11607 }
11608 DSAStack->setParentHasScanDirective(StartLoc);
11609 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11610}
11611
11614 Stmt *AStmt, SourceLocation StartLoc,
11615 SourceLocation EndLoc) {
11616 const OMPClause *DependFound = nullptr;
11617 const OMPClause *DependSourceClause = nullptr;
11618 const OMPClause *DependSinkClause = nullptr;
11619 const OMPClause *DoacrossFound = nullptr;
11620 const OMPClause *DoacrossSourceClause = nullptr;
11621 const OMPClause *DoacrossSinkClause = nullptr;
11622 bool ErrorFound = false;
11623 const OMPThreadsClause *TC = nullptr;
11624 const OMPSIMDClause *SC = nullptr;
11625 for (const OMPClause *C : Clauses) {
11626 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11627 auto DC = dyn_cast<OMPDependClause>(C);
11628 if (DC || DOC) {
11629 DependFound = DC ? C : nullptr;
11630 DoacrossFound = DOC ? C : nullptr;
11631 OMPDoacrossKind ODK;
11632 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11633 (DOC && (ODK.isSource(DOC)))) {
11634 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11635 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11636 << getOpenMPDirectiveName(OMPD_ordered)
11637 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11638 ErrorFound = true;
11639 } else {
11640 if (DC)
11641 DependSourceClause = C;
11642 else
11643 DoacrossSourceClause = C;
11644 }
11645 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11646 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11647 << (DC ? "depend" : "doacross") << 0;
11648 ErrorFound = true;
11649 }
11650 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11651 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11652 if (DependSourceClause || DoacrossSourceClause) {
11653 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11654 << (DC ? "depend" : "doacross") << 1;
11655 ErrorFound = true;
11656 }
11657 if (DC)
11658 DependSinkClause = C;
11659 else
11660 DoacrossSinkClause = C;
11661 }
11662 } else if (C->getClauseKind() == OMPC_threads) {
11663 TC = cast<OMPThreadsClause>(C);
11664 } else if (C->getClauseKind() == OMPC_simd) {
11665 SC = cast<OMPSIMDClause>(C);
11666 }
11667 }
11668 if (!ErrorFound && !SC &&
11669 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11670 // OpenMP [2.8.1,simd Construct, Restrictions]
11671 // An ordered construct with the simd clause is the only OpenMP construct
11672 // that can appear in the simd region.
11673 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11674 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11675 ErrorFound = true;
11676 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11678 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11679 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11680 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11681 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11682 ErrorFound = true;
11683 } else if ((DependFound || DoacrossFound) &&
11684 !DSAStack->getParentOrderedRegionParam().first) {
11686 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11687 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11688 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11689 ErrorFound = true;
11690 } else if (TC || Clauses.empty()) {
11691 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11692 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11693 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11694 << (TC != nullptr);
11695 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11696 ErrorFound = true;
11697 }
11698 }
11699 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11700 return StmtError();
11701
11702 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11703 // During execution of an iteration of a worksharing-loop or a loop nest
11704 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11705 // must not execute more than one ordered region corresponding to an ordered
11706 // construct without a depend clause.
11707 if (!DependFound && !DoacrossFound) {
11708 if (DSAStack->doesParentHasOrderedDirective()) {
11709 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11710 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11711 diag::note_omp_previous_directive)
11712 << "ordered";
11713 return StmtError();
11714 }
11715 DSAStack->setParentHasOrderedDirective(StartLoc);
11716 }
11717
11718 if (AStmt) {
11719 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11720
11722 }
11723
11724 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11725 AStmt);
11726}
11727
11728namespace {
11729/// Helper class for checking expression in 'omp atomic [update]'
11730/// construct.
11731class OpenMPAtomicUpdateChecker {
11732 /// Error results for atomic update expressions.
11733 enum ExprAnalysisErrorCode {
11734 /// A statement is not an expression statement.
11735 NotAnExpression,
11736 /// Expression is not builtin binary or unary operation.
11737 NotABinaryOrUnaryExpression,
11738 /// Unary operation is not post-/pre- increment/decrement operation.
11739 NotAnUnaryIncDecExpression,
11740 /// An expression is not of scalar type.
11741 NotAScalarType,
11742 /// A binary operation is not an assignment operation.
11743 NotAnAssignmentOp,
11744 /// RHS part of the binary operation is not a binary expression.
11745 NotABinaryExpression,
11746 /// RHS part is not additive/multiplicative/shift/biwise binary
11747 /// expression.
11748 NotABinaryOperator,
11749 /// RHS binary operation does not have reference to the updated LHS
11750 /// part.
11751 NotAnUpdateExpression,
11752 /// An expression contains semantical error not related to
11753 /// 'omp atomic [update]'
11754 NotAValidExpression,
11755 /// No errors is found.
11756 NoError
11757 };
11758 /// Reference to Sema.
11759 Sema &SemaRef;
11760 /// A location for note diagnostics (when error is found).
11761 SourceLocation NoteLoc;
11762 /// 'x' lvalue part of the source atomic expression.
11763 Expr *X;
11764 /// 'expr' rvalue part of the source atomic expression.
11765 Expr *E;
11766 /// Helper expression of the form
11767 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11768 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11769 Expr *UpdateExpr;
11770 /// Is 'x' a LHS in a RHS part of full update expression. It is
11771 /// important for non-associative operations.
11772 bool IsXLHSInRHSPart;
11774 SourceLocation OpLoc;
11775 /// true if the source expression is a postfix unary operation, false
11776 /// if it is a prefix unary operation.
11777 bool IsPostfixUpdate;
11778
11779public:
11780 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11781 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11782 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11783 /// Check specified statement that it is suitable for 'atomic update'
11784 /// constructs and extract 'x', 'expr' and Operation from the original
11785 /// expression. If DiagId and NoteId == 0, then only check is performed
11786 /// without error notification.
11787 /// \param DiagId Diagnostic which should be emitted if error is found.
11788 /// \param NoteId Diagnostic note for the main error message.
11789 /// \return true if statement is not an update expression, false otherwise.
11790 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11791 /// Return the 'x' lvalue part of the source atomic expression.
11792 Expr *getX() const { return X; }
11793 /// Return the 'expr' rvalue part of the source atomic expression.
11794 Expr *getExpr() const { return E; }
11795 /// Return the update expression used in calculation of the updated
11796 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11797 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11798 Expr *getUpdateExpr() const { return UpdateExpr; }
11799 /// Return true if 'x' is LHS in RHS part of full update expression,
11800 /// false otherwise.
11801 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11802
11803 /// true if the source expression is a postfix unary operation, false
11804 /// if it is a prefix unary operation.
11805 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11806
11807private:
11808 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11809 unsigned NoteId = 0);
11810};
11811
11812bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11813 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11814 ExprAnalysisErrorCode ErrorFound = NoError;
11815 SourceLocation ErrorLoc, NoteLoc;
11816 SourceRange ErrorRange, NoteRange;
11817 // Allowed constructs are:
11818 // x = x binop expr;
11819 // x = expr binop x;
11820 if (AtomicBinOp->getOpcode() == BO_Assign) {
11821 X = AtomicBinOp->getLHS();
11822 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11823 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11824 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11825 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11826 AtomicInnerBinOp->isBitwiseOp()) {
11827 Op = AtomicInnerBinOp->getOpcode();
11828 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11829 Expr *LHS = AtomicInnerBinOp->getLHS();
11830 Expr *RHS = AtomicInnerBinOp->getRHS();
11831 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11832 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11833 /*Canonical=*/true);
11834 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11835 /*Canonical=*/true);
11836 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11837 /*Canonical=*/true);
11838 if (XId == LHSId) {
11839 E = RHS;
11840 IsXLHSInRHSPart = true;
11841 } else if (XId == RHSId) {
11842 E = LHS;
11843 IsXLHSInRHSPart = false;
11844 } else {
11845 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11846 ErrorRange = AtomicInnerBinOp->getSourceRange();
11847 NoteLoc = X->getExprLoc();
11848 NoteRange = X->getSourceRange();
11849 ErrorFound = NotAnUpdateExpression;
11850 }
11851 } else {
11852 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11853 ErrorRange = AtomicInnerBinOp->getSourceRange();
11854 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11855 NoteRange = SourceRange(NoteLoc, NoteLoc);
11856 ErrorFound = NotABinaryOperator;
11857 }
11858 } else {
11859 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11860 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11861 ErrorFound = NotABinaryExpression;
11862 }
11863 } else {
11864 ErrorLoc = AtomicBinOp->getExprLoc();
11865 ErrorRange = AtomicBinOp->getSourceRange();
11866 NoteLoc = AtomicBinOp->getOperatorLoc();
11867 NoteRange = SourceRange(NoteLoc, NoteLoc);
11868 ErrorFound = NotAnAssignmentOp;
11869 }
11870 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11871 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11872 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11873 return true;
11874 }
11875 if (SemaRef.CurContext->isDependentContext())
11876 E = X = UpdateExpr = nullptr;
11877 return ErrorFound != NoError;
11878}
11879
11880bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11881 unsigned NoteId) {
11882 ExprAnalysisErrorCode ErrorFound = NoError;
11883 SourceLocation ErrorLoc, NoteLoc;
11884 SourceRange ErrorRange, NoteRange;
11885 // Allowed constructs are:
11886 // x++;
11887 // x--;
11888 // ++x;
11889 // --x;
11890 // x binop= expr;
11891 // x = x binop expr;
11892 // x = expr binop x;
11893 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11894 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11895 if (AtomicBody->getType()->isScalarType() ||
11896 AtomicBody->isInstantiationDependent()) {
11897 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11898 AtomicBody->IgnoreParenImpCasts())) {
11899 // Check for Compound Assignment Operation
11901 AtomicCompAssignOp->getOpcode());
11902 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11903 E = AtomicCompAssignOp->getRHS();
11904 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11905 IsXLHSInRHSPart = true;
11906 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11907 AtomicBody->IgnoreParenImpCasts())) {
11908 // Check for Binary Operation
11909 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11910 return true;
11911 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11912 AtomicBody->IgnoreParenImpCasts())) {
11913 // Check for Unary Operation
11914 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11915 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11916 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11917 OpLoc = AtomicUnaryOp->getOperatorLoc();
11918 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11919 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11920 IsXLHSInRHSPart = true;
11921 } else {
11922 ErrorFound = NotAnUnaryIncDecExpression;
11923 ErrorLoc = AtomicUnaryOp->getExprLoc();
11924 ErrorRange = AtomicUnaryOp->getSourceRange();
11925 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11926 NoteRange = SourceRange(NoteLoc, NoteLoc);
11927 }
11928 } else if (!AtomicBody->isInstantiationDependent()) {
11929 ErrorFound = NotABinaryOrUnaryExpression;
11930 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11931 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11932 } else if (AtomicBody->containsErrors()) {
11933 ErrorFound = NotAValidExpression;
11934 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11935 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11936 }
11937 } else {
11938 ErrorFound = NotAScalarType;
11939 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11940 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11941 }
11942 } else {
11943 ErrorFound = NotAnExpression;
11944 NoteLoc = ErrorLoc = S->getBeginLoc();
11945 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11946 }
11947 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11948 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11949 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11950 return true;
11951 }
11952 if (SemaRef.CurContext->isDependentContext())
11953 E = X = UpdateExpr = nullptr;
11954 if (ErrorFound == NoError && E && X) {
11955 // Build an update expression of form 'OpaqueValueExpr(x) binop
11956 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11957 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11958 auto *OVEX = new (SemaRef.getASTContext())
11959 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11960 auto *OVEExpr = new (SemaRef.getASTContext())
11963 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11964 IsXLHSInRHSPart ? OVEExpr : OVEX);
11965 if (Update.isInvalid())
11966 return true;
11967 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11969 if (Update.isInvalid())
11970 return true;
11971 UpdateExpr = Update.get();
11972 }
11973 return ErrorFound != NoError;
11974}
11975
11976/// Get the node id of the fixed point of an expression \a S.
11977llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11978 llvm::FoldingSetNodeID Id;
11979 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11980 return Id;
11981}
11982
11983/// Check if two expressions are same.
11984bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11985 const Expr *RHS) {
11986 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11987}
11988
11989class OpenMPAtomicCompareChecker {
11990public:
11991 /// All kinds of errors that can occur in `atomic compare`
11992 enum ErrorTy {
11993 /// Empty compound statement.
11994 NoStmt = 0,
11995 /// More than one statement in a compound statement.
11996 MoreThanOneStmt,
11997 /// Not an assignment binary operator.
11998 NotAnAssignment,
11999 /// Not a conditional operator.
12000 NotCondOp,
12001 /// Wrong false expr. According to the spec, 'x' should be at the false
12002 /// expression of a conditional expression.
12003 WrongFalseExpr,
12004 /// The condition of a conditional expression is not a binary operator.
12005 NotABinaryOp,
12006 /// Invalid binary operator (not <, >, or ==).
12007 InvalidBinaryOp,
12008 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
12009 InvalidComparison,
12010 /// X is not a lvalue.
12011 XNotLValue,
12012 /// Not a scalar.
12013 NotScalar,
12014 /// Not an integer.
12015 NotInteger,
12016 /// 'else' statement is not expected.
12017 UnexpectedElse,
12018 /// Not an equality operator.
12019 NotEQ,
12020 /// Invalid assignment (not v == x).
12021 InvalidAssignment,
12022 /// Not if statement
12023 NotIfStmt,
12024 /// More than two statements in a compund statement.
12025 MoreThanTwoStmts,
12026 /// Not a compound statement.
12027 NotCompoundStmt,
12028 /// No else statement.
12029 NoElse,
12030 /// Not 'if (r)'.
12031 InvalidCondition,
12032 /// No error.
12033 NoError,
12034 };
12035
12036 struct ErrorInfoTy {
12037 ErrorTy Error;
12038 SourceLocation ErrorLoc;
12039 SourceRange ErrorRange;
12040 SourceLocation NoteLoc;
12041 SourceRange NoteRange;
12042 };
12043
12044 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
12045
12046 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
12047 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12048
12049 Expr *getX() const { return X; }
12050 Expr *getE() const { return E; }
12051 Expr *getD() const { return D; }
12052 Expr *getCond() const { return C; }
12053 bool isXBinopExpr() const { return IsXBinopExpr; }
12054
12055protected:
12056 /// Reference to ASTContext
12057 ASTContext &ContextRef;
12058 /// 'x' lvalue part of the source atomic expression.
12059 Expr *X = nullptr;
12060 /// 'expr' or 'e' rvalue part of the source atomic expression.
12061 Expr *E = nullptr;
12062 /// 'd' rvalue part of the source atomic expression.
12063 Expr *D = nullptr;
12064 /// 'cond' part of the source atomic expression. It is in one of the following
12065 /// forms:
12066 /// expr ordop x
12067 /// x ordop expr
12068 /// x == e
12069 /// e == x
12070 Expr *C = nullptr;
12071 /// True if the cond expr is in the form of 'x ordop expr'.
12072 bool IsXBinopExpr = true;
12073
12074 /// Check if it is a valid conditional update statement (cond-update-stmt).
12075 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
12076
12077 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
12078 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12079
12080 /// Check if all captured values have right type.
12081 bool checkType(ErrorInfoTy &ErrorInfo) const;
12082
12083 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
12084 bool ShouldBeLValue, bool ShouldBeInteger = false) {
12085 if (E->isInstantiationDependent())
12086 return true;
12087
12088 if (ShouldBeLValue && !E->isLValue()) {
12089 ErrorInfo.Error = ErrorTy::XNotLValue;
12090 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12092 return false;
12093 }
12094
12095 QualType QTy = E->getType();
12096 if (!QTy->isScalarType()) {
12097 ErrorInfo.Error = ErrorTy::NotScalar;
12098 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12099 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12100 return false;
12101 }
12102 if (ShouldBeInteger && !QTy->isIntegerType()) {
12103 ErrorInfo.Error = ErrorTy::NotInteger;
12104 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12105 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12106 return false;
12107 }
12108
12109 return true;
12110 }
12111 };
12112
12113bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
12114 ErrorInfoTy &ErrorInfo) {
12115 auto *Then = S->getThen();
12116 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12117 if (CS->body_empty()) {
12118 ErrorInfo.Error = ErrorTy::NoStmt;
12119 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12120 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12121 return false;
12122 }
12123 if (CS->size() > 1) {
12124 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12125 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12126 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12127 return false;
12128 }
12129 Then = CS->body_front();
12130 }
12131
12132 auto *BO = dyn_cast<BinaryOperator>(Then);
12133 if (!BO) {
12134 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12135 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12136 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12137 return false;
12138 }
12139 if (BO->getOpcode() != BO_Assign) {
12140 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12141 ErrorInfo.ErrorLoc = BO->getExprLoc();
12142 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12143 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12144 return false;
12145 }
12146
12147 X = BO->getLHS();
12148
12149 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12150 if (!Cond) {
12151 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12152 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12153 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12154 return false;
12155 }
12156
12157 switch (Cond->getOpcode()) {
12158 case BO_EQ: {
12159 C = Cond;
12160 D = BO->getRHS();
12161 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12162 E = Cond->getRHS();
12163 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12164 E = Cond->getLHS();
12165 } else {
12166 ErrorInfo.Error = ErrorTy::InvalidComparison;
12167 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12168 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12169 return false;
12170 }
12171 break;
12172 }
12173 case BO_LT:
12174 case BO_GT: {
12175 E = BO->getRHS();
12176 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12177 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12178 C = Cond;
12179 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12180 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12181 C = Cond;
12182 IsXBinopExpr = false;
12183 } else {
12184 ErrorInfo.Error = ErrorTy::InvalidComparison;
12185 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12186 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12187 return false;
12188 }
12189 break;
12190 }
12191 default:
12192 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12193 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12194 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12195 return false;
12196 }
12197
12198 if (S->getElse()) {
12199 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12200 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12201 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12202 return false;
12203 }
12204
12205 return true;
12206}
12207
12208bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12209 ErrorInfoTy &ErrorInfo) {
12210 auto *BO = dyn_cast<BinaryOperator>(S);
12211 if (!BO) {
12212 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12213 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12214 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12215 return false;
12216 }
12217 if (BO->getOpcode() != BO_Assign) {
12218 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12219 ErrorInfo.ErrorLoc = BO->getExprLoc();
12220 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12221 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12222 return false;
12223 }
12224
12225 X = BO->getLHS();
12226
12227 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12228 if (!CO) {
12229 ErrorInfo.Error = ErrorTy::NotCondOp;
12230 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12231 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12232 return false;
12233 }
12234
12235 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12236 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12237 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12238 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12239 CO->getFalseExpr()->getSourceRange();
12240 return false;
12241 }
12242
12243 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12244 if (!Cond) {
12245 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12246 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12247 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12248 CO->getCond()->getSourceRange();
12249 return false;
12250 }
12251
12252 switch (Cond->getOpcode()) {
12253 case BO_EQ: {
12254 C = Cond;
12255 D = CO->getTrueExpr();
12256 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12257 E = Cond->getRHS();
12258 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12259 E = Cond->getLHS();
12260 } else {
12261 ErrorInfo.Error = ErrorTy::InvalidComparison;
12262 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12263 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12264 return false;
12265 }
12266 break;
12267 }
12268 case BO_LT:
12269 case BO_GT: {
12270 E = CO->getTrueExpr();
12271 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
12272 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
12273 C = Cond;
12274 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
12275 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12276 C = Cond;
12277 IsXBinopExpr = false;
12278 } else {
12279 ErrorInfo.Error = ErrorTy::InvalidComparison;
12280 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12281 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12282 return false;
12283 }
12284 break;
12285 }
12286 default:
12287 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12288 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12289 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12290 return false;
12291 }
12292
12293 return true;
12294}
12295
12296bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12297 // 'x' and 'e' cannot be nullptr
12298 assert(X && E && "X and E cannot be nullptr");
12299
12300 if (!CheckValue(X, ErrorInfo, true))
12301 return false;
12302
12303 if (!CheckValue(E, ErrorInfo, false))
12304 return false;
12305
12306 if (D && !CheckValue(D, ErrorInfo, false))
12307 return false;
12308
12309 return true;
12310}
12311
12312bool OpenMPAtomicCompareChecker::checkStmt(
12313 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12314 auto *CS = dyn_cast<CompoundStmt>(S);
12315 if (CS) {
12316 if (CS->body_empty()) {
12317 ErrorInfo.Error = ErrorTy::NoStmt;
12318 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12319 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12320 return false;
12321 }
12322
12323 if (CS->size() != 1) {
12324 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12325 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12326 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12327 return false;
12328 }
12329 S = CS->body_front();
12330 }
12331
12332 auto Res = false;
12333
12334 if (auto *IS = dyn_cast<IfStmt>(S)) {
12335 // Check if the statement is in one of the following forms
12336 // (cond-update-stmt):
12337 // if (expr ordop x) { x = expr; }
12338 // if (x ordop expr) { x = expr; }
12339 // if (x == e) { x = d; }
12340 Res = checkCondUpdateStmt(IS, ErrorInfo);
12341 } else {
12342 // Check if the statement is in one of the following forms (cond-expr-stmt):
12343 // x = expr ordop x ? expr : x;
12344 // x = x ordop expr ? expr : x;
12345 // x = x == e ? d : x;
12346 Res = checkCondExprStmt(S, ErrorInfo);
12347 }
12348
12349 if (!Res)
12350 return false;
12351
12352 return checkType(ErrorInfo);
12353}
12354
12355class OpenMPAtomicCompareCaptureChecker final
12356 : public OpenMPAtomicCompareChecker {
12357public:
12358 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12359
12360 Expr *getV() const { return V; }
12361 Expr *getR() const { return R; }
12362 bool isFailOnly() const { return IsFailOnly; }
12363 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12364
12365 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12366 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12367
12368private:
12369 bool checkType(ErrorInfoTy &ErrorInfo);
12370
12371 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12372 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12373 // spec p.p. 82:
12374 // (1) { v = x; cond-update-stmt }
12375 // (2) { cond-update-stmt v = x; }
12376 // (3) if(x == e) { x = d; } else { v = x; }
12377 // (4) { r = x == e; if(r) { x = d; } }
12378 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12379
12380 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12381 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12382
12383 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12384 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12385 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12386
12387 /// 'v' lvalue part of the source atomic expression.
12388 Expr *V = nullptr;
12389 /// 'r' lvalue part of the source atomic expression.
12390 Expr *R = nullptr;
12391 /// If 'v' is only updated when the comparison fails.
12392 bool IsFailOnly = false;
12393 /// If original value of 'x' must be stored in 'v', not an updated one.
12394 bool IsPostfixUpdate = false;
12395};
12396
12397bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12398 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12399 return false;
12400
12401 if (V && !CheckValue(V, ErrorInfo, true))
12402 return false;
12403
12404 if (R && !CheckValue(R, ErrorInfo, true, true))
12405 return false;
12406
12407 return true;
12408}
12409
12410bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12411 ErrorInfoTy &ErrorInfo) {
12412 IsFailOnly = true;
12413
12414 auto *Then = S->getThen();
12415 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12416 if (CS->body_empty()) {
12417 ErrorInfo.Error = ErrorTy::NoStmt;
12418 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12419 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12420 return false;
12421 }
12422 if (CS->size() > 1) {
12423 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12424 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12425 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12426 return false;
12427 }
12428 Then = CS->body_front();
12429 }
12430
12431 auto *BO = dyn_cast<BinaryOperator>(Then);
12432 if (!BO) {
12433 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12434 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12435 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12436 return false;
12437 }
12438 if (BO->getOpcode() != BO_Assign) {
12439 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12440 ErrorInfo.ErrorLoc = BO->getExprLoc();
12441 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12442 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12443 return false;
12444 }
12445
12446 X = BO->getLHS();
12447 D = BO->getRHS();
12448
12449 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12450 if (!Cond) {
12451 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12452 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12453 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12454 return false;
12455 }
12456 if (Cond->getOpcode() != BO_EQ) {
12457 ErrorInfo.Error = ErrorTy::NotEQ;
12458 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12459 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12460 return false;
12461 }
12462
12463 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12464 E = Cond->getRHS();
12465 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12466 E = Cond->getLHS();
12467 } else {
12468 ErrorInfo.Error = ErrorTy::InvalidComparison;
12469 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12470 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12471 return false;
12472 }
12473
12474 C = Cond;
12475
12476 if (!S->getElse()) {
12477 ErrorInfo.Error = ErrorTy::NoElse;
12478 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12479 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12480 return false;
12481 }
12482
12483 auto *Else = S->getElse();
12484 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12485 if (CS->body_empty()) {
12486 ErrorInfo.Error = ErrorTy::NoStmt;
12487 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12488 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12489 return false;
12490 }
12491 if (CS->size() > 1) {
12492 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12493 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12494 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12495 return false;
12496 }
12497 Else = CS->body_front();
12498 }
12499
12500 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12501 if (!ElseBO) {
12502 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12503 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12504 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12505 return false;
12506 }
12507 if (ElseBO->getOpcode() != BO_Assign) {
12508 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12509 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12510 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12511 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12512 return false;
12513 }
12514
12515 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12516 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12517 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12518 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12519 ElseBO->getRHS()->getSourceRange();
12520 return false;
12521 }
12522
12523 V = ElseBO->getLHS();
12524
12525 return checkType(ErrorInfo);
12526}
12527
12528bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12529 ErrorInfoTy &ErrorInfo) {
12530 // We don't check here as they should be already done before call this
12531 // function.
12532 auto *CS = cast<CompoundStmt>(S);
12533 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12534 auto *S1 = cast<BinaryOperator>(CS->body_front());
12535 auto *S2 = cast<IfStmt>(CS->body_back());
12536 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12537
12538 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12539 ErrorInfo.Error = ErrorTy::InvalidCondition;
12540 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12541 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12542 return false;
12543 }
12544
12545 R = S1->getLHS();
12546
12547 auto *Then = S2->getThen();
12548 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12549 if (ThenCS->body_empty()) {
12550 ErrorInfo.Error = ErrorTy::NoStmt;
12551 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12552 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12553 return false;
12554 }
12555 if (ThenCS->size() > 1) {
12556 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12557 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12558 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12559 return false;
12560 }
12561 Then = ThenCS->body_front();
12562 }
12563
12564 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12565 if (!ThenBO) {
12566 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12567 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12568 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12569 return false;
12570 }
12571 if (ThenBO->getOpcode() != BO_Assign) {
12572 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12573 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12574 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12575 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12576 return false;
12577 }
12578
12579 X = ThenBO->getLHS();
12580 D = ThenBO->getRHS();
12581
12582 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12583 if (BO->getOpcode() != BO_EQ) {
12584 ErrorInfo.Error = ErrorTy::NotEQ;
12585 ErrorInfo.ErrorLoc = BO->getExprLoc();
12586 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12587 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12588 return false;
12589 }
12590
12591 C = BO;
12592
12593 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12594 E = BO->getRHS();
12595 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12596 E = BO->getLHS();
12597 } else {
12598 ErrorInfo.Error = ErrorTy::InvalidComparison;
12599 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12600 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12601 return false;
12602 }
12603
12604 if (S2->getElse()) {
12605 IsFailOnly = true;
12606
12607 auto *Else = S2->getElse();
12608 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12609 if (ElseCS->body_empty()) {
12610 ErrorInfo.Error = ErrorTy::NoStmt;
12611 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12612 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12613 return false;
12614 }
12615 if (ElseCS->size() > 1) {
12616 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12617 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12618 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12619 return false;
12620 }
12621 Else = ElseCS->body_front();
12622 }
12623
12624 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12625 if (!ElseBO) {
12626 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12627 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12628 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12629 return false;
12630 }
12631 if (ElseBO->getOpcode() != BO_Assign) {
12632 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12633 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12634 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12635 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12636 return false;
12637 }
12638 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12639 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12640 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12641 ErrorInfo.NoteLoc = X->getExprLoc();
12642 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12643 ErrorInfo.NoteRange = X->getSourceRange();
12644 return false;
12645 }
12646
12647 V = ElseBO->getLHS();
12648 }
12649
12650 return checkType(ErrorInfo);
12651}
12652
12653bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12654 ErrorInfoTy &ErrorInfo) {
12655 // if(x == e) { x = d; } else { v = x; }
12656 if (auto *IS = dyn_cast<IfStmt>(S))
12657 return checkForm3(IS, ErrorInfo);
12658
12659 auto *CS = dyn_cast<CompoundStmt>(S);
12660 if (!CS) {
12661 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12662 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12663 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12664 return false;
12665 }
12666 if (CS->body_empty()) {
12667 ErrorInfo.Error = ErrorTy::NoStmt;
12668 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12669 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12670 return false;
12671 }
12672
12673 // { if(x == e) { x = d; } else { v = x; } }
12674 if (CS->size() == 1) {
12675 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12676 if (!IS) {
12677 ErrorInfo.Error = ErrorTy::NotIfStmt;
12678 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12679 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12680 CS->body_front()->getSourceRange();
12681 return false;
12682 }
12683
12684 return checkForm3(IS, ErrorInfo);
12685 } else if (CS->size() == 2) {
12686 auto *S1 = CS->body_front();
12687 auto *S2 = CS->body_back();
12688
12689 Stmt *UpdateStmt = nullptr;
12690 Stmt *CondUpdateStmt = nullptr;
12691 Stmt *CondExprStmt = nullptr;
12692
12693 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12694 // It could be one of the following cases:
12695 // { v = x; cond-update-stmt }
12696 // { v = x; cond-expr-stmt }
12697 // { cond-expr-stmt; v = x; }
12698 // form 45
12699 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12700 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12701 // check if form 45
12702 if (isa<IfStmt>(S2))
12703 return checkForm45(CS, ErrorInfo);
12704 // { cond-expr-stmt; v = x; }
12705 CondExprStmt = S1;
12706 UpdateStmt = S2;
12707 } else {
12708 IsPostfixUpdate = true;
12709 UpdateStmt = S1;
12710 if (isa<IfStmt>(S2)) {
12711 // { v = x; cond-update-stmt }
12712 CondUpdateStmt = S2;
12713 } else {
12714 // { v = x; cond-expr-stmt }
12715 CondExprStmt = S2;
12716 }
12717 }
12718 } else {
12719 // { cond-update-stmt v = x; }
12720 UpdateStmt = S2;
12721 CondUpdateStmt = S1;
12722 }
12723
12724 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12725 auto *IS = dyn_cast<IfStmt>(CUS);
12726 if (!IS) {
12727 ErrorInfo.Error = ErrorTy::NotIfStmt;
12728 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12729 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12730 return false;
12731 }
12732
12733 return checkCondUpdateStmt(IS, ErrorInfo);
12734 };
12735
12736 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12737 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12738 auto *BO = dyn_cast<BinaryOperator>(US);
12739 if (!BO) {
12740 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12741 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12742 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12743 return false;
12744 }
12745 if (BO->getOpcode() != BO_Assign) {
12746 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12747 ErrorInfo.ErrorLoc = BO->getExprLoc();
12748 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12749 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12750 return false;
12751 }
12752 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12753 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12754 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12755 ErrorInfo.NoteLoc = this->X->getExprLoc();
12756 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12757 ErrorInfo.NoteRange = this->X->getSourceRange();
12758 return false;
12759 }
12760
12761 this->V = BO->getLHS();
12762
12763 return true;
12764 };
12765
12766 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12767 return false;
12768 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12769 return false;
12770 if (!CheckUpdateStmt(UpdateStmt))
12771 return false;
12772 } else {
12773 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12774 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12775 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12776 return false;
12777 }
12778
12779 return checkType(ErrorInfo);
12780}
12781} // namespace
12782
12784 Stmt *AStmt,
12785 SourceLocation StartLoc,
12786 SourceLocation EndLoc) {
12787 ASTContext &Context = getASTContext();
12788 // Register location of the first atomic directive.
12789 DSAStack->addAtomicDirectiveLoc(StartLoc);
12790 if (!AStmt)
12791 return StmtError();
12792
12793 // 1.2.2 OpenMP Language Terminology
12794 // Structured block - An executable statement with a single entry at the
12795 // top and a single exit at the bottom.
12796 // The point of exit cannot be a branch out of the structured block.
12797 // longjmp() and throw() must not violate the entry/exit criteria.
12798 OpenMPClauseKind AtomicKind = OMPC_unknown;
12799 SourceLocation AtomicKindLoc;
12800 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12801 SourceLocation MemOrderLoc;
12802 bool MutexClauseEncountered = false;
12803 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12804 for (const OMPClause *C : Clauses) {
12805 switch (C->getClauseKind()) {
12806 case OMPC_read:
12807 case OMPC_write:
12808 case OMPC_update:
12809 MutexClauseEncountered = true;
12810 [[fallthrough]];
12811 case OMPC_capture:
12812 case OMPC_compare: {
12813 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12814 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12815 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12816 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12817 << getOpenMPClauseName(AtomicKind);
12818 } else {
12819 AtomicKind = C->getClauseKind();
12820 AtomicKindLoc = C->getBeginLoc();
12821 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12822 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12823 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12824 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12825 << getOpenMPClauseName(AtomicKind);
12826 }
12827 }
12828 break;
12829 }
12830 case OMPC_weak:
12831 case OMPC_fail: {
12832 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12833 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12834 << getOpenMPClauseName(C->getClauseKind())
12835 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12836 return StmtError();
12837 }
12838 break;
12839 }
12840 case OMPC_seq_cst:
12841 case OMPC_acq_rel:
12842 case OMPC_acquire:
12843 case OMPC_release:
12844 case OMPC_relaxed: {
12845 if (MemOrderKind != OMPC_unknown) {
12846 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12847 << getOpenMPDirectiveName(OMPD_atomic) << 0
12848 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12849 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12850 << getOpenMPClauseName(MemOrderKind);
12851 } else {
12852 MemOrderKind = C->getClauseKind();
12853 MemOrderLoc = C->getBeginLoc();
12854 }
12855 break;
12856 }
12857 // The following clauses are allowed, but we don't need to do anything here.
12858 case OMPC_hint:
12859 break;
12860 default:
12861 llvm_unreachable("unknown clause is encountered");
12862 }
12863 }
12864 bool IsCompareCapture = false;
12865 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12866 EncounteredAtomicKinds.contains(OMPC_capture)) {
12867 IsCompareCapture = true;
12868 AtomicKind = OMPC_compare;
12869 }
12870 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12871 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12872 // release.
12873 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12874 // acquire.
12875 // If atomic-clause is update or not present then memory-order-clause must not
12876 // be acq_rel or acquire.
12877 if ((AtomicKind == OMPC_read &&
12878 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12879 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12880 AtomicKind == OMPC_unknown) &&
12881 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12882 SourceLocation Loc = AtomicKindLoc;
12883 if (AtomicKind == OMPC_unknown)
12884 Loc = StartLoc;
12885 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12886 << getOpenMPClauseName(AtomicKind)
12887 << (AtomicKind == OMPC_unknown ? 1 : 0)
12888 << getOpenMPClauseName(MemOrderKind);
12889 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12890 << getOpenMPClauseName(MemOrderKind);
12891 }
12892
12893 Stmt *Body = AStmt;
12894 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12895 Body = EWC->getSubExpr();
12896
12897 Expr *X = nullptr;
12898 Expr *V = nullptr;
12899 Expr *E = nullptr;
12900 Expr *UE = nullptr;
12901 Expr *D = nullptr;
12902 Expr *CE = nullptr;
12903 Expr *R = nullptr;
12904 bool IsXLHSInRHSPart = false;
12905 bool IsPostfixUpdate = false;
12906 bool IsFailOnly = false;
12907 // OpenMP [2.12.6, atomic Construct]
12908 // In the next expressions:
12909 // * x and v (as applicable) are both l-value expressions with scalar type.
12910 // * During the execution of an atomic region, multiple syntactic
12911 // occurrences of x must designate the same storage location.
12912 // * Neither of v and expr (as applicable) may access the storage location
12913 // designated by x.
12914 // * Neither of x and expr (as applicable) may access the storage location
12915 // designated by v.
12916 // * expr is an expression with scalar type.
12917 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12918 // * binop, binop=, ++, and -- are not overloaded operators.
12919 // * The expression x binop expr must be numerically equivalent to x binop
12920 // (expr). This requirement is satisfied if the operators in expr have
12921 // precedence greater than binop, or by using parentheses around expr or
12922 // subexpressions of expr.
12923 // * The expression expr binop x must be numerically equivalent to (expr)
12924 // binop x. This requirement is satisfied if the operators in expr have
12925 // precedence equal to or greater than binop, or by using parentheses around
12926 // expr or subexpressions of expr.
12927 // * For forms that allow multiple occurrences of x, the number of times
12928 // that x is evaluated is unspecified.
12929 if (AtomicKind == OMPC_read) {
12930 enum {
12931 NotAnExpression,
12932 NotAnAssignmentOp,
12933 NotAScalarType,
12934 NotAnLValue,
12935 NoError
12936 } ErrorFound = NoError;
12937 SourceLocation ErrorLoc, NoteLoc;
12938 SourceRange ErrorRange, NoteRange;
12939 // If clause is read:
12940 // v = x;
12941 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12942 const auto *AtomicBinOp =
12943 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12944 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12945 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12946 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12947 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12948 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12949 if (!X->isLValue() || !V->isLValue()) {
12950 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12951 ErrorFound = NotAnLValue;
12952 ErrorLoc = AtomicBinOp->getExprLoc();
12953 ErrorRange = AtomicBinOp->getSourceRange();
12954 NoteLoc = NotLValueExpr->getExprLoc();
12955 NoteRange = NotLValueExpr->getSourceRange();
12956 }
12957 } else if (!X->isInstantiationDependent() ||
12958 !V->isInstantiationDependent()) {
12959 const Expr *NotScalarExpr =
12960 (X->isInstantiationDependent() || X->getType()->isScalarType())
12961 ? V
12962 : X;
12963 ErrorFound = NotAScalarType;
12964 ErrorLoc = AtomicBinOp->getExprLoc();
12965 ErrorRange = AtomicBinOp->getSourceRange();
12966 NoteLoc = NotScalarExpr->getExprLoc();
12967 NoteRange = NotScalarExpr->getSourceRange();
12968 }
12969 } else if (!AtomicBody->isInstantiationDependent()) {
12970 ErrorFound = NotAnAssignmentOp;
12971 ErrorLoc = AtomicBody->getExprLoc();
12972 ErrorRange = AtomicBody->getSourceRange();
12973 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12974 : AtomicBody->getExprLoc();
12975 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12976 : AtomicBody->getSourceRange();
12977 }
12978 } else {
12979 ErrorFound = NotAnExpression;
12980 NoteLoc = ErrorLoc = Body->getBeginLoc();
12981 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12982 }
12983 if (ErrorFound != NoError) {
12984 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12985 << ErrorRange;
12986 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12987 << ErrorFound << NoteRange;
12988 return StmtError();
12989 }
12991 V = X = nullptr;
12992 } else if (AtomicKind == OMPC_write) {
12993 enum {
12994 NotAnExpression,
12995 NotAnAssignmentOp,
12996 NotAScalarType,
12997 NotAnLValue,
12998 NoError
12999 } ErrorFound = NoError;
13000 SourceLocation ErrorLoc, NoteLoc;
13001 SourceRange ErrorRange, NoteRange;
13002 // If clause is write:
13003 // x = expr;
13004 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13005 const auto *AtomicBinOp =
13006 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13007 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13008 X = AtomicBinOp->getLHS();
13009 E = AtomicBinOp->getRHS();
13010 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13011 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
13012 if (!X->isLValue()) {
13013 ErrorFound = NotAnLValue;
13014 ErrorLoc = AtomicBinOp->getExprLoc();
13015 ErrorRange = AtomicBinOp->getSourceRange();
13016 NoteLoc = X->getExprLoc();
13017 NoteRange = X->getSourceRange();
13018 }
13019 } else if (!X->isInstantiationDependent() ||
13021 const Expr *NotScalarExpr =
13022 (X->isInstantiationDependent() || X->getType()->isScalarType())
13023 ? E
13024 : X;
13025 ErrorFound = NotAScalarType;
13026 ErrorLoc = AtomicBinOp->getExprLoc();
13027 ErrorRange = AtomicBinOp->getSourceRange();
13028 NoteLoc = NotScalarExpr->getExprLoc();
13029 NoteRange = NotScalarExpr->getSourceRange();
13030 }
13031 } else if (!AtomicBody->isInstantiationDependent()) {
13032 ErrorFound = NotAnAssignmentOp;
13033 ErrorLoc = AtomicBody->getExprLoc();
13034 ErrorRange = AtomicBody->getSourceRange();
13035 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13036 : AtomicBody->getExprLoc();
13037 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13038 : AtomicBody->getSourceRange();
13039 }
13040 } else {
13041 ErrorFound = NotAnExpression;
13042 NoteLoc = ErrorLoc = Body->getBeginLoc();
13043 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
13044 }
13045 if (ErrorFound != NoError) {
13046 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
13047 << ErrorRange;
13048 Diag(NoteLoc, diag::note_omp_atomic_read_write)
13049 << ErrorFound << NoteRange;
13050 return StmtError();
13051 }
13053 E = X = nullptr;
13054 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13055 // If clause is update:
13056 // x++;
13057 // x--;
13058 // ++x;
13059 // --x;
13060 // x binop= expr;
13061 // x = x binop expr;
13062 // x = expr binop x;
13063 OpenMPAtomicUpdateChecker Checker(SemaRef);
13064 if (Checker.checkStatement(
13065 Body,
13066 (AtomicKind == OMPC_update)
13067 ? diag::err_omp_atomic_update_not_expression_statement
13068 : diag::err_omp_atomic_not_expression_statement,
13069 diag::note_omp_atomic_update))
13070 return StmtError();
13072 E = Checker.getExpr();
13073 X = Checker.getX();
13074 UE = Checker.getUpdateExpr();
13075 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13076 }
13077 } else if (AtomicKind == OMPC_capture) {
13078 enum {
13079 NotAnAssignmentOp,
13080 NotACompoundStatement,
13081 NotTwoSubstatements,
13082 NotASpecificExpression,
13083 NoError
13084 } ErrorFound = NoError;
13085 SourceLocation ErrorLoc, NoteLoc;
13086 SourceRange ErrorRange, NoteRange;
13087 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13088 // If clause is a capture:
13089 // v = x++;
13090 // v = x--;
13091 // v = ++x;
13092 // v = --x;
13093 // v = x binop= expr;
13094 // v = x = x binop expr;
13095 // v = x = expr binop x;
13096 const auto *AtomicBinOp =
13097 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13098 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13099 V = AtomicBinOp->getLHS();
13100 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13101 OpenMPAtomicUpdateChecker Checker(SemaRef);
13102 if (Checker.checkStatement(
13103 Body, diag::err_omp_atomic_capture_not_expression_statement,
13104 diag::note_omp_atomic_update))
13105 return StmtError();
13106 E = Checker.getExpr();
13107 X = Checker.getX();
13108 UE = Checker.getUpdateExpr();
13109 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13110 IsPostfixUpdate = Checker.isPostfixUpdate();
13111 } else if (!AtomicBody->isInstantiationDependent()) {
13112 ErrorLoc = AtomicBody->getExprLoc();
13113 ErrorRange = AtomicBody->getSourceRange();
13114 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13115 : AtomicBody->getExprLoc();
13116 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13117 : AtomicBody->getSourceRange();
13118 ErrorFound = NotAnAssignmentOp;
13119 }
13120 if (ErrorFound != NoError) {
13121 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13122 << ErrorRange;
13123 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13124 return StmtError();
13125 }
13127 UE = V = E = X = nullptr;
13128 } else {
13129 // If clause is a capture:
13130 // { v = x; x = expr; }
13131 // { v = x; x++; }
13132 // { v = x; x--; }
13133 // { v = x; ++x; }
13134 // { v = x; --x; }
13135 // { v = x; x binop= expr; }
13136 // { v = x; x = x binop expr; }
13137 // { v = x; x = expr binop x; }
13138 // { x++; v = x; }
13139 // { x--; v = x; }
13140 // { ++x; v = x; }
13141 // { --x; v = x; }
13142 // { x binop= expr; v = x; }
13143 // { x = x binop expr; v = x; }
13144 // { x = expr binop x; v = x; }
13145 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13146 // Check that this is { expr1; expr2; }
13147 if (CS->size() == 2) {
13148 Stmt *First = CS->body_front();
13149 Stmt *Second = CS->body_back();
13150 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13151 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13152 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13153 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13154 // Need to find what subexpression is 'v' and what is 'x'.
13155 OpenMPAtomicUpdateChecker Checker(SemaRef);
13156 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13157 BinaryOperator *BinOp = nullptr;
13158 if (IsUpdateExprFound) {
13159 BinOp = dyn_cast<BinaryOperator>(First);
13160 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13161 }
13162 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13163 // { v = x; x++; }
13164 // { v = x; x--; }
13165 // { v = x; ++x; }
13166 // { v = x; --x; }
13167 // { v = x; x binop= expr; }
13168 // { v = x; x = x binop expr; }
13169 // { v = x; x = expr binop x; }
13170 // Check that the first expression has form v = x.
13171 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13172 llvm::FoldingSetNodeID XId, PossibleXId;
13173 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13174 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13175 IsUpdateExprFound = XId == PossibleXId;
13176 if (IsUpdateExprFound) {
13177 V = BinOp->getLHS();
13178 X = Checker.getX();
13179 E = Checker.getExpr();
13180 UE = Checker.getUpdateExpr();
13181 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13182 IsPostfixUpdate = true;
13183 }
13184 }
13185 if (!IsUpdateExprFound) {
13186 IsUpdateExprFound = !Checker.checkStatement(First);
13187 BinOp = nullptr;
13188 if (IsUpdateExprFound) {
13189 BinOp = dyn_cast<BinaryOperator>(Second);
13190 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13191 }
13192 if (IsUpdateExprFound &&
13194 // { x++; v = x; }
13195 // { x--; v = x; }
13196 // { ++x; v = x; }
13197 // { --x; v = x; }
13198 // { x binop= expr; v = x; }
13199 // { x = x binop expr; v = x; }
13200 // { x = expr binop x; v = x; }
13201 // Check that the second expression has form v = x.
13202 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13203 llvm::FoldingSetNodeID XId, PossibleXId;
13204 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13205 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13206 IsUpdateExprFound = XId == PossibleXId;
13207 if (IsUpdateExprFound) {
13208 V = BinOp->getLHS();
13209 X = Checker.getX();
13210 E = Checker.getExpr();
13211 UE = Checker.getUpdateExpr();
13212 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13213 IsPostfixUpdate = false;
13214 }
13215 }
13216 }
13217 if (!IsUpdateExprFound) {
13218 // { v = x; x = expr; }
13219 auto *FirstExpr = dyn_cast<Expr>(First);
13220 auto *SecondExpr = dyn_cast<Expr>(Second);
13221 if (!FirstExpr || !SecondExpr ||
13222 !(FirstExpr->isInstantiationDependent() ||
13223 SecondExpr->isInstantiationDependent())) {
13224 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13225 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13226 ErrorFound = NotAnAssignmentOp;
13227 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13228 : First->getBeginLoc();
13229 NoteRange = ErrorRange = FirstBinOp
13230 ? FirstBinOp->getSourceRange()
13231 : SourceRange(ErrorLoc, ErrorLoc);
13232 } else {
13233 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13234 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13235 ErrorFound = NotAnAssignmentOp;
13236 NoteLoc = ErrorLoc = SecondBinOp
13237 ? SecondBinOp->getOperatorLoc()
13238 : Second->getBeginLoc();
13239 NoteRange = ErrorRange =
13240 SecondBinOp ? SecondBinOp->getSourceRange()
13241 : SourceRange(ErrorLoc, ErrorLoc);
13242 } else {
13243 Expr *PossibleXRHSInFirst =
13244 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13245 Expr *PossibleXLHSInSecond =
13246 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13247 llvm::FoldingSetNodeID X1Id, X2Id;
13248 PossibleXRHSInFirst->Profile(X1Id, Context,
13249 /*Canonical=*/true);
13250 PossibleXLHSInSecond->Profile(X2Id, Context,
13251 /*Canonical=*/true);
13252 IsUpdateExprFound = X1Id == X2Id;
13253 if (IsUpdateExprFound) {
13254 V = FirstBinOp->getLHS();
13255 X = SecondBinOp->getLHS();
13256 E = SecondBinOp->getRHS();
13257 UE = nullptr;
13258 IsXLHSInRHSPart = false;
13259 IsPostfixUpdate = true;
13260 } else {
13261 ErrorFound = NotASpecificExpression;
13262 ErrorLoc = FirstBinOp->getExprLoc();
13263 ErrorRange = FirstBinOp->getSourceRange();
13264 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13265 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13266 }
13267 }
13268 }
13269 }
13270 }
13271 } else {
13272 NoteLoc = ErrorLoc = Body->getBeginLoc();
13273 NoteRange = ErrorRange =
13274 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13275 ErrorFound = NotTwoSubstatements;
13276 }
13277 } else {
13278 NoteLoc = ErrorLoc = Body->getBeginLoc();
13279 NoteRange = ErrorRange =
13280 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13281 ErrorFound = NotACompoundStatement;
13282 }
13283 }
13284 if (ErrorFound != NoError) {
13285 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13286 << ErrorRange;
13287 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13288 return StmtError();
13289 }
13291 UE = V = E = X = nullptr;
13292 } else if (AtomicKind == OMPC_compare) {
13293 if (IsCompareCapture) {
13294 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13295 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13296 if (!Checker.checkStmt(Body, ErrorInfo)) {
13297 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13298 << ErrorInfo.ErrorRange;
13299 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13300 << ErrorInfo.Error << ErrorInfo.NoteRange;
13301 return StmtError();
13302 }
13303 X = Checker.getX();
13304 E = Checker.getE();
13305 D = Checker.getD();
13306 CE = Checker.getCond();
13307 V = Checker.getV();
13308 R = Checker.getR();
13309 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13310 IsXLHSInRHSPart = Checker.isXBinopExpr();
13311 IsFailOnly = Checker.isFailOnly();
13312 IsPostfixUpdate = Checker.isPostfixUpdate();
13313 } else {
13314 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13315 OpenMPAtomicCompareChecker Checker(SemaRef);
13316 if (!Checker.checkStmt(Body, ErrorInfo)) {
13317 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13318 << ErrorInfo.ErrorRange;
13319 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13320 << ErrorInfo.Error << ErrorInfo.NoteRange;
13321 return StmtError();
13322 }
13323 X = Checker.getX();
13324 E = Checker.getE();
13325 D = Checker.getD();
13326 CE = Checker.getCond();
13327 // The weak clause may only appear if the resulting atomic operation is
13328 // an atomic conditional update for which the comparison tests for
13329 // equality. It was not possible to do this check in
13330 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13331 // could not be performed (Clauses are not available).
13332 auto *It = find_if(Clauses, [](OMPClause *C) {
13333 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13334 });
13335 if (It != Clauses.end()) {
13336 auto *Cond = dyn_cast<BinaryOperator>(CE);
13337 if (Cond->getOpcode() != BO_EQ) {
13338 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13339 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13340 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13341 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13342
13343 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13344 << ErrorInfo.ErrorRange;
13345 return StmtError();
13346 }
13347 }
13348 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13349 IsXLHSInRHSPart = Checker.isXBinopExpr();
13350 }
13351 }
13352
13354
13356 Context, StartLoc, EndLoc, Clauses, AStmt,
13357 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13358}
13359
13361 Stmt *AStmt,
13362 SourceLocation StartLoc,
13363 SourceLocation EndLoc) {
13364 if (!AStmt)
13365 return StmtError();
13366
13367 auto *CS = cast<CapturedStmt>(AStmt);
13368 // 1.2.2 OpenMP Language Terminology
13369 // Structured block - An executable statement with a single entry at the
13370 // top and a single exit at the bottom.
13371 // The point of exit cannot be a branch out of the structured block.
13372 // longjmp() and throw() must not violate the entry/exit criteria.
13373 CS->getCapturedDecl()->setNothrow();
13374 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target);
13375 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13376 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13377 // 1.2.2 OpenMP Language Terminology
13378 // Structured block - An executable statement with a single entry at the
13379 // top and a single exit at the bottom.
13380 // The point of exit cannot be a branch out of the structured block.
13381 // longjmp() and throw() must not violate the entry/exit criteria.
13382 CS->getCapturedDecl()->setNothrow();
13383 }
13384
13385 // OpenMP [2.16, Nesting of Regions]
13386 // If specified, a teams construct must be contained within a target
13387 // construct. That target construct must contain no statements or directives
13388 // outside of the teams construct.
13389 if (DSAStack->hasInnerTeamsRegion()) {
13390 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13391 bool OMPTeamsFound = true;
13392 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13393 auto I = CS->body_begin();
13394 while (I != CS->body_end()) {
13395 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13396 if (!OED || !isOpenMPTeamsDirective(OED->getDirectiveKind()) ||
13397 OMPTeamsFound) {
13398
13399 OMPTeamsFound = false;
13400 break;
13401 }
13402 ++I;
13403 }
13404 assert(I != CS->body_end() && "Not found statement");
13405 S = *I;
13406 } else {
13407 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13408 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13409 }
13410 if (!OMPTeamsFound) {
13411 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13412 Diag(DSAStack->getInnerTeamsRegionLoc(),
13413 diag::note_omp_nested_teams_construct_here);
13414 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13415 << isa<OMPExecutableDirective>(S);
13416 return StmtError();
13417 }
13418 }
13419
13421
13422 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13423 AStmt);
13424}
13425
13427 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13428 SourceLocation EndLoc) {
13429 if (!AStmt)
13430 return StmtError();
13431
13432 auto *CS = cast<CapturedStmt>(AStmt);
13433 // 1.2.2 OpenMP Language Terminology
13434 // Structured block - An executable statement with a single entry at the
13435 // top and a single exit at the bottom.
13436 // The point of exit cannot be a branch out of the structured block.
13437 // longjmp() and throw() must not violate the entry/exit criteria.
13438 CS->getCapturedDecl()->setNothrow();
13439 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel);
13440 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13441 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13442 // 1.2.2 OpenMP Language Terminology
13443 // Structured block - An executable statement with a single entry at the
13444 // top and a single exit at the bottom.
13445 // The point of exit cannot be a branch out of the structured block.
13446 // longjmp() and throw() must not violate the entry/exit criteria.
13447 CS->getCapturedDecl()->setNothrow();
13448 }
13449
13451
13453 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13454 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13455}
13456
13458 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13459 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13460 if (!AStmt)
13461 return StmtError();
13462
13463 auto *CS = cast<CapturedStmt>(AStmt);
13464 // 1.2.2 OpenMP Language Terminology
13465 // Structured block - An executable statement with a single entry at the
13466 // top and a single exit at the bottom.
13467 // The point of exit cannot be a branch out of the structured block.
13468 // longjmp() and throw() must not violate the entry/exit criteria.
13469 CS->getCapturedDecl()->setNothrow();
13470 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_parallel_for);
13471 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13472 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13473 // 1.2.2 OpenMP Language Terminology
13474 // Structured block - An executable statement with a single entry at the
13475 // top and a single exit at the bottom.
13476 // The point of exit cannot be a branch out of the structured block.
13477 // longjmp() and throw() must not violate the entry/exit criteria.
13478 CS->getCapturedDecl()->setNothrow();
13479 }
13480
13482 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13483 // define the nested loops number.
13484 unsigned NestedLoopCount =
13485 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13486 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13487 VarsWithImplicitDSA, B);
13488 if (NestedLoopCount == 0)
13489 return StmtError();
13490
13491 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13492 "omp target parallel for loop exprs were not built");
13493
13495 // Finalize the clauses that need pre-built expressions for CodeGen.
13496 for (OMPClause *C : Clauses) {
13497 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13498 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13501 return StmtError();
13502 }
13503 }
13504
13507 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13508 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13509}
13510
13511/// Check for existence of a map clause in the list of clauses.
13513 const OpenMPClauseKind K) {
13514 return llvm::any_of(
13515 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13516}
13517
13518template <typename... Params>
13520 const Params... ClauseTypes) {
13521 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13522}
13523
13524/// Check if the variables in the mapping clause are externally visible.
13526 for (const OMPClause *C : Clauses) {
13527 if (auto *TC = dyn_cast<OMPToClause>(C))
13528 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13529 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13530 (VD->isExternallyVisible() &&
13531 VD->getVisibility() != HiddenVisibility);
13532 });
13533 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13534 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13535 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13536 (VD->isExternallyVisible() &&
13537 VD->getVisibility() != HiddenVisibility);
13538 });
13539 }
13540
13541 return true;
13542}
13543
13546 Stmt *AStmt, SourceLocation StartLoc,
13547 SourceLocation EndLoc) {
13548 if (!AStmt)
13549 return StmtError();
13550
13551 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13552
13553 // OpenMP [2.12.2, target data Construct, Restrictions]
13554 // At least one map, use_device_addr or use_device_ptr clause must appear on
13555 // the directive.
13556 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13557 (getLangOpts().OpenMP < 50 ||
13558 !hasClauses(Clauses, OMPC_use_device_addr))) {
13559 StringRef Expected;
13560 if (getLangOpts().OpenMP < 50)
13561 Expected = "'map' or 'use_device_ptr'";
13562 else
13563 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13564 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13565 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13566 return StmtError();
13567 }
13568
13570
13571 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13572 Clauses, AStmt);
13573}
13574
13576 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13577 SourceLocation EndLoc, Stmt *AStmt) {
13578 if (!AStmt)
13579 return StmtError();
13580
13581 auto *CS = cast<CapturedStmt>(AStmt);
13582 // 1.2.2 OpenMP Language Terminology
13583 // Structured block - An executable statement with a single entry at the
13584 // top and a single exit at the bottom.
13585 // The point of exit cannot be a branch out of the structured block.
13586 // longjmp() and throw() must not violate the entry/exit criteria.
13587 CS->getCapturedDecl()->setNothrow();
13588 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_enter_data);
13589 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13590 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13591 // 1.2.2 OpenMP Language Terminology
13592 // Structured block - An executable statement with a single entry at the
13593 // top and a single exit at the bottom.
13594 // The point of exit cannot be a branch out of the structured block.
13595 // longjmp() and throw() must not violate the entry/exit criteria.
13596 CS->getCapturedDecl()->setNothrow();
13597 }
13598
13599 // OpenMP [2.10.2, Restrictions, p. 99]
13600 // At least one map clause must appear on the directive.
13601 if (!hasClauses(Clauses, OMPC_map)) {
13602 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13603 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13604 return StmtError();
13605 }
13606
13607 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13608 Clauses, AStmt);
13609}
13610
13612 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13613 SourceLocation EndLoc, Stmt *AStmt) {
13614 if (!AStmt)
13615 return StmtError();
13616
13617 auto *CS = cast<CapturedStmt>(AStmt);
13618 // 1.2.2 OpenMP Language Terminology
13619 // Structured block - An executable statement with a single entry at the
13620 // top and a single exit at the bottom.
13621 // The point of exit cannot be a branch out of the structured block.
13622 // longjmp() and throw() must not violate the entry/exit criteria.
13623 CS->getCapturedDecl()->setNothrow();
13624 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_exit_data);
13625 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13626 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13627 // 1.2.2 OpenMP Language Terminology
13628 // Structured block - An executable statement with a single entry at the
13629 // top and a single exit at the bottom.
13630 // The point of exit cannot be a branch out of the structured block.
13631 // longjmp() and throw() must not violate the entry/exit criteria.
13632 CS->getCapturedDecl()->setNothrow();
13633 }
13634
13635 // OpenMP [2.10.3, Restrictions, p. 102]
13636 // At least one map clause must appear on the directive.
13637 if (!hasClauses(Clauses, OMPC_map)) {
13638 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13639 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13640 return StmtError();
13641 }
13642
13643 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13644 Clauses, AStmt);
13645}
13646
13648 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13649 SourceLocation EndLoc, Stmt *AStmt) {
13650 if (!AStmt)
13651 return StmtError();
13652
13653 auto *CS = cast<CapturedStmt>(AStmt);
13654 // 1.2.2 OpenMP Language Terminology
13655 // Structured block - An executable statement with a single entry at the
13656 // top and a single exit at the bottom.
13657 // The point of exit cannot be a branch out of the structured block.
13658 // longjmp() and throw() must not violate the entry/exit criteria.
13659 CS->getCapturedDecl()->setNothrow();
13660 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_update);
13661 ThisCaptureLevel > 1; --ThisCaptureLevel) {
13662 CS = cast<CapturedStmt>(CS->getCapturedStmt());
13663 // 1.2.2 OpenMP Language Terminology
13664 // Structured block - An executable statement with a single entry at the
13665 // top and a single exit at the bottom.
13666 // The point of exit cannot be a branch out of the structured block.
13667 // longjmp() and throw() must not violate the entry/exit criteria.
13668 CS->getCapturedDecl()->setNothrow();
13669 }
13670
13671 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13672 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13673 return StmtError();
13674 }
13675
13676 if (!isClauseMappable(Clauses)) {
13677 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13678 return StmtError();
13679 }
13680
13681 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13682 Clauses, AStmt);
13683}
13684
13686 Stmt *AStmt,
13687 SourceLocation StartLoc,
13688 SourceLocation EndLoc) {
13689 if (!AStmt)
13690 return StmtError();
13691
13692 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13693 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13694 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13695
13696 auto *CS = cast<CapturedStmt>(AStmt);
13697 // 1.2.2 OpenMP Language Terminology
13698 // Structured block - An executable statement with a single entry at the
13699 // top and a single exit at the bottom.
13700 // The point of exit cannot be a branch out of the structured block.
13701 // longjmp() and throw() must not violate the entry/exit criteria.
13702 CS->getCapturedDecl()->setNothrow();
13703
13705
13706 DSAStack->setParentTeamsRegionLoc(StartLoc);
13707
13708 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13709 AStmt);
13710}
13711
13713 SourceLocation StartLoc, SourceLocation EndLoc,
13714 OpenMPDirectiveKind CancelRegion) {
13715 if (DSAStack->isParentNowaitRegion()) {
13716 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13717 return StmtError();
13718 }
13719 if (DSAStack->isParentOrderedRegion()) {
13720 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13721 return StmtError();
13722 }
13724 EndLoc, CancelRegion);
13725}
13726
13728 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13729 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13730 if (DSAStack->isParentNowaitRegion()) {
13731 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13732 return StmtError();
13733 }
13734 if (DSAStack->isParentOrderedRegion()) {
13735 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13736 return StmtError();
13737 }
13738 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13739 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13740 CancelRegion);
13741}
13742
13744 ArrayRef<OMPClause *> Clauses) {
13745 const OMPClause *ReductionClause = nullptr;
13746 const OMPClause *NogroupClause = nullptr;
13747 for (const OMPClause *C : Clauses) {
13748 if (C->getClauseKind() == OMPC_reduction) {
13749 ReductionClause = C;
13750 if (NogroupClause)
13751 break;
13752 continue;
13753 }
13754 if (C->getClauseKind() == OMPC_nogroup) {
13755 NogroupClause = C;
13756 if (ReductionClause)
13757 break;
13758 continue;
13759 }
13760 }
13761 if (ReductionClause && NogroupClause) {
13762 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13763 << SourceRange(NogroupClause->getBeginLoc(),
13764 NogroupClause->getEndLoc());
13765 return true;
13766 }
13767 return false;
13768}
13769
13771 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13772 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13773 if (!AStmt)
13774 return StmtError();
13775
13776 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13778 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13779 // define the nested loops number.
13780 unsigned NestedLoopCount =
13781 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13782 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13783 *DSAStack, VarsWithImplicitDSA, B);
13784 if (NestedLoopCount == 0)
13785 return StmtError();
13786
13787 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13788 "omp for loop exprs were not built");
13789
13790 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13791 // The grainsize clause and num_tasks clause are mutually exclusive and may
13792 // not appear on the same taskloop directive.
13794 {OMPC_grainsize, OMPC_num_tasks}))
13795 return StmtError();
13796 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13797 // If a reduction clause is present on the taskloop directive, the nogroup
13798 // clause must not be specified.
13800 return StmtError();
13801
13803 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13804 NestedLoopCount, Clauses, AStmt, B,
13805 DSAStack->isCancelRegion());
13806}
13807
13809 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13810 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13811 if (!AStmt)
13812 return StmtError();
13813
13814 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13816 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13817 // define the nested loops number.
13818 unsigned NestedLoopCount =
13819 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13820 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13821 *DSAStack, VarsWithImplicitDSA, B);
13822 if (NestedLoopCount == 0)
13823 return StmtError();
13824
13825 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13826 "omp for loop exprs were not built");
13827
13829 // Finalize the clauses that need pre-built expressions for CodeGen.
13830 for (OMPClause *C : Clauses) {
13831 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13832 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13835 return StmtError();
13836 }
13837 }
13838
13839 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13840 // The grainsize clause and num_tasks clause are mutually exclusive and may
13841 // not appear on the same taskloop directive.
13843 {OMPC_grainsize, OMPC_num_tasks}))
13844 return StmtError();
13845 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13846 // If a reduction clause is present on the taskloop directive, the nogroup
13847 // clause must not be specified.
13849 return StmtError();
13851 return StmtError();
13852
13854 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13855 NestedLoopCount, Clauses, AStmt, B);
13856}
13857
13859 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13860 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13861 if (!AStmt)
13862 return StmtError();
13863
13864 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13866 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13867 // define the nested loops number.
13868 unsigned NestedLoopCount =
13869 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13870 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13871 *DSAStack, VarsWithImplicitDSA, B);
13872 if (NestedLoopCount == 0)
13873 return StmtError();
13874
13875 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13876 "omp for loop exprs were not built");
13877
13878 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13879 // The grainsize clause and num_tasks clause are mutually exclusive and may
13880 // not appear on the same taskloop directive.
13882 {OMPC_grainsize, OMPC_num_tasks}))
13883 return StmtError();
13884 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13885 // If a reduction clause is present on the taskloop directive, the nogroup
13886 // clause must not be specified.
13888 return StmtError();
13889
13891 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13892 NestedLoopCount, Clauses, AStmt, B,
13893 DSAStack->isCancelRegion());
13894}
13895
13897 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13898 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13899 if (!AStmt)
13900 return StmtError();
13901
13902 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13904 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13905 // define the nested loops number.
13906 unsigned NestedLoopCount =
13907 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13908 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13909 *DSAStack, VarsWithImplicitDSA, B);
13910 if (NestedLoopCount == 0)
13911 return StmtError();
13912
13913 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13914 "omp for loop exprs were not built");
13915
13916 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13917 // The grainsize clause and num_tasks clause are mutually exclusive and may
13918 // not appear on the same taskloop directive.
13920 {OMPC_grainsize, OMPC_num_tasks}))
13921 return StmtError();
13922 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13923 // If a reduction clause is present on the taskloop directive, the nogroup
13924 // clause must not be specified.
13926 return StmtError();
13927
13929 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13930 NestedLoopCount, Clauses, AStmt, B,
13931 DSAStack->isCancelRegion());
13932}
13933
13935 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13936 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13937 if (!AStmt)
13938 return StmtError();
13939
13940 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13942 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13943 // define the nested loops number.
13944 unsigned NestedLoopCount =
13945 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13946 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13947 *DSAStack, VarsWithImplicitDSA, B);
13948 if (NestedLoopCount == 0)
13949 return StmtError();
13950
13951 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13952 "omp for loop exprs were not built");
13953
13955 // Finalize the clauses that need pre-built expressions for CodeGen.
13956 for (OMPClause *C : Clauses) {
13957 if (auto *LC = dyn_cast<OMPLinearClause>(C))
13958 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
13961 return StmtError();
13962 }
13963 }
13964
13965 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13966 // The grainsize clause and num_tasks clause are mutually exclusive and may
13967 // not appear on the same taskloop directive.
13969 {OMPC_grainsize, OMPC_num_tasks}))
13970 return StmtError();
13971 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13972 // If a reduction clause is present on the taskloop directive, the nogroup
13973 // clause must not be specified.
13975 return StmtError();
13977 return StmtError();
13978
13981 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13982}
13983
13985 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13986 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13987 if (!AStmt)
13988 return StmtError();
13989
13990 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13992 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13993 // define the nested loops number.
13994 unsigned NestedLoopCount =
13995 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13996 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13997 *DSAStack, VarsWithImplicitDSA, B);
13998 if (NestedLoopCount == 0)
13999 return StmtError();
14000
14001 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14002 "omp for loop exprs were not built");
14003
14005 // Finalize the clauses that need pre-built expressions for CodeGen.
14006 for (OMPClause *C : Clauses) {
14007 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14008 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14011 return StmtError();
14012 }
14013 }
14014
14015 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14016 // The grainsize clause and num_tasks clause are mutually exclusive and may
14017 // not appear on the same taskloop directive.
14019 {OMPC_grainsize, OMPC_num_tasks}))
14020 return StmtError();
14021 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14022 // If a reduction clause is present on the taskloop directive, the nogroup
14023 // clause must not be specified.
14025 return StmtError();
14027 return StmtError();
14028
14031 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14032}
14033
14035 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14036 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14037 if (!AStmt)
14038 return StmtError();
14039
14040 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14041 auto *CS = cast<CapturedStmt>(AStmt);
14042 // 1.2.2 OpenMP Language Terminology
14043 // Structured block - An executable statement with a single entry at the
14044 // top and a single exit at the bottom.
14045 // The point of exit cannot be a branch out of the structured block.
14046 // longjmp() and throw() must not violate the entry/exit criteria.
14047 CS->getCapturedDecl()->setNothrow();
14048 for (int ThisCaptureLevel =
14049 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop);
14050 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14051 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14052 // 1.2.2 OpenMP Language Terminology
14053 // Structured block - An executable statement with a single entry at the
14054 // top and a single exit at the bottom.
14055 // The point of exit cannot be a branch out of the structured block.
14056 // longjmp() and throw() must not violate the entry/exit criteria.
14057 CS->getCapturedDecl()->setNothrow();
14058 }
14059
14061 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14062 // define the nested loops number.
14063 unsigned NestedLoopCount = checkOpenMPLoop(
14064 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
14065 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14066 VarsWithImplicitDSA, B);
14067 if (NestedLoopCount == 0)
14068 return StmtError();
14069
14070 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14071 "omp for loop exprs were not built");
14072
14073 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14074 // The grainsize clause and num_tasks clause are mutually exclusive and may
14075 // not appear on the same taskloop directive.
14077 {OMPC_grainsize, OMPC_num_tasks}))
14078 return StmtError();
14079 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14080 // If a reduction clause is present on the taskloop directive, the nogroup
14081 // clause must not be specified.
14083 return StmtError();
14084
14087 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14088 DSAStack->isCancelRegion());
14089}
14090
14092 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14093 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14094 if (!AStmt)
14095 return StmtError();
14096
14097 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14098 auto *CS = cast<CapturedStmt>(AStmt);
14099 // 1.2.2 OpenMP Language Terminology
14100 // Structured block - An executable statement with a single entry at the
14101 // top and a single exit at the bottom.
14102 // The point of exit cannot be a branch out of the structured block.
14103 // longjmp() and throw() must not violate the entry/exit criteria.
14104 CS->getCapturedDecl()->setNothrow();
14105 for (int ThisCaptureLevel =
14106 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop);
14107 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14108 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14109 // 1.2.2 OpenMP Language Terminology
14110 // Structured block - An executable statement with a single entry at the
14111 // top and a single exit at the bottom.
14112 // The point of exit cannot be a branch out of the structured block.
14113 // longjmp() and throw() must not violate the entry/exit criteria.
14114 CS->getCapturedDecl()->setNothrow();
14115 }
14116
14118 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14119 // define the nested loops number.
14120 unsigned NestedLoopCount = checkOpenMPLoop(
14121 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
14122 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14123 VarsWithImplicitDSA, B);
14124 if (NestedLoopCount == 0)
14125 return StmtError();
14126
14127 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14128 "omp for loop exprs were not built");
14129
14130 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14131 // The grainsize clause and num_tasks clause are mutually exclusive and may
14132 // not appear on the same taskloop directive.
14134 {OMPC_grainsize, OMPC_num_tasks}))
14135 return StmtError();
14136 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14137 // If a reduction clause is present on the taskloop directive, the nogroup
14138 // clause must not be specified.
14140 return StmtError();
14141
14144 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14145 DSAStack->isCancelRegion());
14146}
14147
14149 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14150 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14151 if (!AStmt)
14152 return StmtError();
14153
14154 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14155 auto *CS = cast<CapturedStmt>(AStmt);
14156 // 1.2.2 OpenMP Language Terminology
14157 // Structured block - An executable statement with a single entry at the
14158 // top and a single exit at the bottom.
14159 // The point of exit cannot be a branch out of the structured block.
14160 // longjmp() and throw() must not violate the entry/exit criteria.
14161 CS->getCapturedDecl()->setNothrow();
14162 for (int ThisCaptureLevel =
14163 getOpenMPCaptureLevels(OMPD_parallel_master_taskloop_simd);
14164 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14165 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14166 // 1.2.2 OpenMP Language Terminology
14167 // Structured block - An executable statement with a single entry at the
14168 // top and a single exit at the bottom.
14169 // The point of exit cannot be a branch out of the structured block.
14170 // longjmp() and throw() must not violate the entry/exit criteria.
14171 CS->getCapturedDecl()->setNothrow();
14172 }
14173
14175 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14176 // define the nested loops number.
14177 unsigned NestedLoopCount = checkOpenMPLoop(
14178 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
14179 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14180 VarsWithImplicitDSA, B);
14181 if (NestedLoopCount == 0)
14182 return StmtError();
14183
14184 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14185 "omp for loop exprs were not built");
14186
14188 // Finalize the clauses that need pre-built expressions for CodeGen.
14189 for (OMPClause *C : Clauses) {
14190 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14191 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14194 return StmtError();
14195 }
14196 }
14197
14198 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14199 // The grainsize clause and num_tasks clause are mutually exclusive and may
14200 // not appear on the same taskloop directive.
14202 {OMPC_grainsize, OMPC_num_tasks}))
14203 return StmtError();
14204 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14205 // If a reduction clause is present on the taskloop directive, the nogroup
14206 // clause must not be specified.
14208 return StmtError();
14210 return StmtError();
14211
14214 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14215}
14216
14218 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14219 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14220 if (!AStmt)
14221 return StmtError();
14222
14223 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14224 auto *CS = cast<CapturedStmt>(AStmt);
14225 // 1.2.2 OpenMP Language Terminology
14226 // Structured block - An executable statement with a single entry at the
14227 // top and a single exit at the bottom.
14228 // The point of exit cannot be a branch out of the structured block.
14229 // longjmp() and throw() must not violate the entry/exit criteria.
14230 CS->getCapturedDecl()->setNothrow();
14231 for (int ThisCaptureLevel =
14232 getOpenMPCaptureLevels(OMPD_parallel_masked_taskloop_simd);
14233 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14234 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14235 // 1.2.2 OpenMP Language Terminology
14236 // Structured block - An executable statement with a single entry at the
14237 // top and a single exit at the bottom.
14238 // The point of exit cannot be a branch out of the structured block.
14239 // longjmp() and throw() must not violate the entry/exit criteria.
14240 CS->getCapturedDecl()->setNothrow();
14241 }
14242
14244 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14245 // define the nested loops number.
14246 unsigned NestedLoopCount = checkOpenMPLoop(
14247 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14248 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14249 VarsWithImplicitDSA, B);
14250 if (NestedLoopCount == 0)
14251 return StmtError();
14252
14253 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14254 "omp for loop exprs were not built");
14255
14257 // Finalize the clauses that need pre-built expressions for CodeGen.
14258 for (OMPClause *C : Clauses) {
14259 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14260 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14263 return StmtError();
14264 }
14265 }
14266
14267 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14268 // The grainsize clause and num_tasks clause are mutually exclusive and may
14269 // not appear on the same taskloop directive.
14271 {OMPC_grainsize, OMPC_num_tasks}))
14272 return StmtError();
14273 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14274 // If a reduction clause is present on the taskloop directive, the nogroup
14275 // clause must not be specified.
14277 return StmtError();
14279 return StmtError();
14280
14283 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14284}
14285
14287 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14288 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14289 if (!AStmt)
14290 return StmtError();
14291
14292 if (!checkLastPrivateForMappedDirectives(Clauses))
14293 return StmtError();
14294
14295 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14297 // In presence of clause 'collapse' with number of loops, it will
14298 // define the nested loops number.
14299 unsigned NestedLoopCount =
14300 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14301 nullptr /*ordered not a clause on distribute*/, AStmt,
14302 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14303 if (NestedLoopCount == 0)
14304 return StmtError();
14305
14306 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14307 "omp for loop exprs were not built");
14308
14310 auto *DistributeDirective = OMPDistributeDirective::Create(
14311 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14312 DSAStack->getMappedDirective());
14313 return DistributeDirective;
14314}
14315
14317 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14318 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14319 if (!AStmt)
14320 return StmtError();
14321
14322 auto *CS = cast<CapturedStmt>(AStmt);
14323 // 1.2.2 OpenMP Language Terminology
14324 // Structured block - An executable statement with a single entry at the
14325 // top and a single exit at the bottom.
14326 // The point of exit cannot be a branch out of the structured block.
14327 // longjmp() and throw() must not violate the entry/exit criteria.
14328 CS->getCapturedDecl()->setNothrow();
14329 for (int ThisCaptureLevel =
14330 getOpenMPCaptureLevels(OMPD_distribute_parallel_for);
14331 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14332 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14333 // 1.2.2 OpenMP Language Terminology
14334 // Structured block - An executable statement with a single entry at the
14335 // top and a single exit at the bottom.
14336 // The point of exit cannot be a branch out of the structured block.
14337 // longjmp() and throw() must not violate the entry/exit criteria.
14338 CS->getCapturedDecl()->setNothrow();
14339 }
14340
14342 // In presence of clause 'collapse' with number of loops, it will
14343 // define the nested loops number.
14344 unsigned NestedLoopCount = checkOpenMPLoop(
14345 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14346 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14347 VarsWithImplicitDSA, B);
14348 if (NestedLoopCount == 0)
14349 return StmtError();
14350
14351 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14352 "omp for loop exprs were not built");
14353
14356 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14357 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14358}
14359
14361 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14362 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14363 if (!AStmt)
14364 return StmtError();
14365
14366 auto *CS = cast<CapturedStmt>(AStmt);
14367 // 1.2.2 OpenMP Language Terminology
14368 // Structured block - An executable statement with a single entry at the
14369 // top and a single exit at the bottom.
14370 // The point of exit cannot be a branch out of the structured block.
14371 // longjmp() and throw() must not violate the entry/exit criteria.
14372 CS->getCapturedDecl()->setNothrow();
14373 for (int ThisCaptureLevel =
14374 getOpenMPCaptureLevels(OMPD_distribute_parallel_for_simd);
14375 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14376 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14377 // 1.2.2 OpenMP Language Terminology
14378 // Structured block - An executable statement with a single entry at the
14379 // top and a single exit at the bottom.
14380 // The point of exit cannot be a branch out of the structured block.
14381 // longjmp() and throw() must not violate the entry/exit criteria.
14382 CS->getCapturedDecl()->setNothrow();
14383 }
14384
14386 // In presence of clause 'collapse' with number of loops, it will
14387 // define the nested loops number.
14388 unsigned NestedLoopCount = checkOpenMPLoop(
14389 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14390 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14391 VarsWithImplicitDSA, B);
14392 if (NestedLoopCount == 0)
14393 return StmtError();
14394
14395 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14396 "omp for loop exprs were not built");
14397
14399 // Finalize the clauses that need pre-built expressions for CodeGen.
14400 for (OMPClause *C : Clauses) {
14401 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14402 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14405 return StmtError();
14406 }
14407 }
14408
14410 return StmtError();
14411
14414 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14415}
14416
14418 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14419 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14420 if (!AStmt)
14421 return StmtError();
14422
14423 auto *CS = cast<CapturedStmt>(AStmt);
14424 // 1.2.2 OpenMP Language Terminology
14425 // Structured block - An executable statement with a single entry at the
14426 // top and a single exit at the bottom.
14427 // The point of exit cannot be a branch out of the structured block.
14428 // longjmp() and throw() must not violate the entry/exit criteria.
14429 CS->getCapturedDecl()->setNothrow();
14430 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_distribute_simd);
14431 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14432 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14433 // 1.2.2 OpenMP Language Terminology
14434 // Structured block - An executable statement with a single entry at the
14435 // top and a single exit at the bottom.
14436 // The point of exit cannot be a branch out of the structured block.
14437 // longjmp() and throw() must not violate the entry/exit criteria.
14438 CS->getCapturedDecl()->setNothrow();
14439 }
14440
14442 // In presence of clause 'collapse' with number of loops, it will
14443 // define the nested loops number.
14444 unsigned NestedLoopCount =
14445 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14446 nullptr /*ordered not a clause on distribute*/, CS,
14447 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14448 if (NestedLoopCount == 0)
14449 return StmtError();
14450
14451 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14452 "omp for loop exprs were not built");
14453
14455 // Finalize the clauses that need pre-built expressions for CodeGen.
14456 for (OMPClause *C : Clauses) {
14457 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14458 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14461 return StmtError();
14462 }
14463 }
14464
14466 return StmtError();
14467
14469 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14470 NestedLoopCount, Clauses, AStmt, B);
14471}
14472
14474 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14475 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14476 if (!AStmt)
14477 return StmtError();
14478
14479 auto *CS = cast<CapturedStmt>(AStmt);
14480 // 1.2.2 OpenMP Language Terminology
14481 // Structured block - An executable statement with a single entry at the
14482 // top and a single exit at the bottom.
14483 // The point of exit cannot be a branch out of the structured block.
14484 // longjmp() and throw() must not violate the entry/exit criteria.
14485 CS->getCapturedDecl()->setNothrow();
14486 for (int ThisCaptureLevel =
14487 getOpenMPCaptureLevels(OMPD_target_parallel_for_simd);
14488 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14489 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14490 // 1.2.2 OpenMP Language Terminology
14491 // Structured block - An executable statement with a single entry at the
14492 // top and a single exit at the bottom.
14493 // The point of exit cannot be a branch out of the structured block.
14494 // longjmp() and throw() must not violate the entry/exit criteria.
14495 CS->getCapturedDecl()->setNothrow();
14496 }
14497
14499 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14500 // define the nested loops number.
14501 unsigned NestedLoopCount = checkOpenMPLoop(
14502 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14503 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14504 VarsWithImplicitDSA, B);
14505 if (NestedLoopCount == 0)
14506 return StmtError();
14507
14508 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14509 "omp target parallel for simd loop exprs were not built");
14510
14512 // Finalize the clauses that need pre-built expressions for CodeGen.
14513 for (OMPClause *C : Clauses) {
14514 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14515 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14518 return StmtError();
14519 }
14520 }
14522 return StmtError();
14523
14526 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14527}
14528
14530 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14531 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14532 if (!AStmt)
14533 return StmtError();
14534
14535 auto *CS = cast<CapturedStmt>(AStmt);
14536 // 1.2.2 OpenMP Language Terminology
14537 // Structured block - An executable statement with a single entry at the
14538 // top and a single exit at the bottom.
14539 // The point of exit cannot be a branch out of the structured block.
14540 // longjmp() and throw() must not violate the entry/exit criteria.
14541 CS->getCapturedDecl()->setNothrow();
14542 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_simd);
14543 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14544 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14545 // 1.2.2 OpenMP Language Terminology
14546 // Structured block - An executable statement with a single entry at the
14547 // top and a single exit at the bottom.
14548 // The point of exit cannot be a branch out of the structured block.
14549 // longjmp() and throw() must not violate the entry/exit criteria.
14550 CS->getCapturedDecl()->setNothrow();
14551 }
14552
14554 // In presence of clause 'collapse' with number of loops, it will define the
14555 // nested loops number.
14556 unsigned NestedLoopCount =
14557 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14558 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14559 VarsWithImplicitDSA, B);
14560 if (NestedLoopCount == 0)
14561 return StmtError();
14562
14563 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14564 "omp target simd loop exprs were not built");
14565
14567 // Finalize the clauses that need pre-built expressions for CodeGen.
14568 for (OMPClause *C : Clauses) {
14569 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14570 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14573 return StmtError();
14574 }
14575 }
14576
14578 return StmtError();
14579
14581 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14582 NestedLoopCount, Clauses, AStmt, B);
14583}
14584
14586 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14587 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14588 if (!AStmt)
14589 return StmtError();
14590
14591 auto *CS = cast<CapturedStmt>(AStmt);
14592 // 1.2.2 OpenMP Language Terminology
14593 // Structured block - An executable statement with a single entry at the
14594 // top and a single exit at the bottom.
14595 // The point of exit cannot be a branch out of the structured block.
14596 // longjmp() and throw() must not violate the entry/exit criteria.
14597 CS->getCapturedDecl()->setNothrow();
14598 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_teams_distribute);
14599 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14600 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14601 // 1.2.2 OpenMP Language Terminology
14602 // Structured block - An executable statement with a single entry at the
14603 // top and a single exit at the bottom.
14604 // The point of exit cannot be a branch out of the structured block.
14605 // longjmp() and throw() must not violate the entry/exit criteria.
14606 CS->getCapturedDecl()->setNothrow();
14607 }
14608
14610 // In presence of clause 'collapse' with number of loops, it will
14611 // define the nested loops number.
14612 unsigned NestedLoopCount =
14613 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14614 nullptr /*ordered not a clause on distribute*/, CS,
14615 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14616 if (NestedLoopCount == 0)
14617 return StmtError();
14618
14619 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14620 "omp teams distribute loop exprs were not built");
14621
14623
14624 DSAStack->setParentTeamsRegionLoc(StartLoc);
14625
14627 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14628}
14629
14631 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14632 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14633 if (!AStmt)
14634 return StmtError();
14635
14636 auto *CS = cast<CapturedStmt>(AStmt);
14637 // 1.2.2 OpenMP Language Terminology
14638 // Structured block - An executable statement with a single entry at the
14639 // top and a single exit at the bottom.
14640 // The point of exit cannot be a branch out of the structured block.
14641 // longjmp() and throw() must not violate the entry/exit criteria.
14642 CS->getCapturedDecl()->setNothrow();
14643 for (int ThisCaptureLevel =
14644 getOpenMPCaptureLevels(OMPD_teams_distribute_simd);
14645 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14646 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14647 // 1.2.2 OpenMP Language Terminology
14648 // Structured block - An executable statement with a single entry at the
14649 // top and a single exit at the bottom.
14650 // The point of exit cannot be a branch out of the structured block.
14651 // longjmp() and throw() must not violate the entry/exit criteria.
14652 CS->getCapturedDecl()->setNothrow();
14653 }
14654
14656 // In presence of clause 'collapse' with number of loops, it will
14657 // define the nested loops number.
14658 unsigned NestedLoopCount = checkOpenMPLoop(
14659 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14660 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14661 VarsWithImplicitDSA, B);
14662
14663 if (NestedLoopCount == 0)
14664 return StmtError();
14665
14666 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14667 "omp teams distribute simd loop exprs were not built");
14668
14670 // Finalize the clauses that need pre-built expressions for CodeGen.
14671 for (OMPClause *C : Clauses) {
14672 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14673 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14676 return StmtError();
14677 }
14678 }
14679
14681 return StmtError();
14682
14684
14685 DSAStack->setParentTeamsRegionLoc(StartLoc);
14686
14688 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14689}
14690
14692 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14693 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14694 if (!AStmt)
14695 return StmtError();
14696
14697 auto *CS = cast<CapturedStmt>(AStmt);
14698 // 1.2.2 OpenMP Language Terminology
14699 // Structured block - An executable statement with a single entry at the
14700 // top and a single exit at the bottom.
14701 // The point of exit cannot be a branch out of the structured block.
14702 // longjmp() and throw() must not violate the entry/exit criteria.
14703 CS->getCapturedDecl()->setNothrow();
14704
14705 for (int ThisCaptureLevel =
14706 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for_simd);
14707 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14708 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14709 // 1.2.2 OpenMP Language Terminology
14710 // Structured block - An executable statement with a single entry at the
14711 // top and a single exit at the bottom.
14712 // The point of exit cannot be a branch out of the structured block.
14713 // longjmp() and throw() must not violate the entry/exit criteria.
14714 CS->getCapturedDecl()->setNothrow();
14715 }
14716
14718 // In presence of clause 'collapse' with number of loops, it will
14719 // define the nested loops number.
14720 unsigned NestedLoopCount = checkOpenMPLoop(
14721 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14722 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14723 VarsWithImplicitDSA, B);
14724
14725 if (NestedLoopCount == 0)
14726 return StmtError();
14727
14728 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14729 "omp for loop exprs were not built");
14730
14732 // Finalize the clauses that need pre-built expressions for CodeGen.
14733 for (OMPClause *C : Clauses) {
14734 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14735 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14738 return StmtError();
14739 }
14740 }
14741
14743 return StmtError();
14744
14746
14747 DSAStack->setParentTeamsRegionLoc(StartLoc);
14748
14750 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14751}
14752
14754 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14755 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14756 if (!AStmt)
14757 return StmtError();
14758
14759 auto *CS = cast<CapturedStmt>(AStmt);
14760 // 1.2.2 OpenMP Language Terminology
14761 // Structured block - An executable statement with a single entry at the
14762 // top and a single exit at the bottom.
14763 // The point of exit cannot be a branch out of the structured block.
14764 // longjmp() and throw() must not violate the entry/exit criteria.
14765 CS->getCapturedDecl()->setNothrow();
14766
14767 for (int ThisCaptureLevel =
14768 getOpenMPCaptureLevels(OMPD_teams_distribute_parallel_for);
14769 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14770 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14771 // 1.2.2 OpenMP Language Terminology
14772 // Structured block - An executable statement with a single entry at the
14773 // top and a single exit at the bottom.
14774 // The point of exit cannot be a branch out of the structured block.
14775 // longjmp() and throw() must not violate the entry/exit criteria.
14776 CS->getCapturedDecl()->setNothrow();
14777 }
14778
14780 // In presence of clause 'collapse' with number of loops, it will
14781 // define the nested loops number.
14782 unsigned NestedLoopCount = checkOpenMPLoop(
14783 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14784 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14785 VarsWithImplicitDSA, B);
14786
14787 if (NestedLoopCount == 0)
14788 return StmtError();
14789
14790 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14791 "omp for loop exprs were not built");
14792
14794
14795 DSAStack->setParentTeamsRegionLoc(StartLoc);
14796
14798 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14799 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14800}
14801
14803 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14804 SourceLocation EndLoc) {
14805 if (!AStmt)
14806 return StmtError();
14807
14808 auto *CS = cast<CapturedStmt>(AStmt);
14809 // 1.2.2 OpenMP Language Terminology
14810 // Structured block - An executable statement with a single entry at the
14811 // top and a single exit at the bottom.
14812 // The point of exit cannot be a branch out of the structured block.
14813 // longjmp() and throw() must not violate the entry/exit criteria.
14814 CS->getCapturedDecl()->setNothrow();
14815
14816 for (int ThisCaptureLevel = getOpenMPCaptureLevels(OMPD_target_teams);
14817 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14818 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14819 // 1.2.2 OpenMP Language Terminology
14820 // Structured block - An executable statement with a single entry at the
14821 // top and a single exit at the bottom.
14822 // The point of exit cannot be a branch out of the structured block.
14823 // longjmp() and throw() must not violate the entry/exit criteria.
14824 CS->getCapturedDecl()->setNothrow();
14825 }
14827
14828 const OMPClause *BareClause = nullptr;
14829 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14830 hasClauses(Clauses, OMPC_thread_limit);
14831 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14832 BareClause = C;
14833 return C->getClauseKind() == OMPC_ompx_bare;
14834 });
14835
14836 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14837 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14838 return StmtError();
14839 }
14840
14841 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14842 Clauses, AStmt);
14843}
14844
14846 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14847 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14848 if (!AStmt)
14849 return StmtError();
14850
14851 auto *CS = cast<CapturedStmt>(AStmt);
14852 // 1.2.2 OpenMP Language Terminology
14853 // Structured block - An executable statement with a single entry at the
14854 // top and a single exit at the bottom.
14855 // The point of exit cannot be a branch out of the structured block.
14856 // longjmp() and throw() must not violate the entry/exit criteria.
14857 CS->getCapturedDecl()->setNothrow();
14858 for (int ThisCaptureLevel =
14859 getOpenMPCaptureLevels(OMPD_target_teams_distribute);
14860 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14861 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14862 // 1.2.2 OpenMP Language Terminology
14863 // Structured block - An executable statement with a single entry at the
14864 // top and a single exit at the bottom.
14865 // The point of exit cannot be a branch out of the structured block.
14866 // longjmp() and throw() must not violate the entry/exit criteria.
14867 CS->getCapturedDecl()->setNothrow();
14868 }
14869
14871 // In presence of clause 'collapse' with number of loops, it will
14872 // define the nested loops number.
14873 unsigned NestedLoopCount = checkOpenMPLoop(
14874 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14875 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14876 VarsWithImplicitDSA, B);
14877 if (NestedLoopCount == 0)
14878 return StmtError();
14879
14880 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14881 "omp target teams distribute loop exprs were not built");
14882
14885 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14886}
14887
14889 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14890 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14891 if (!AStmt)
14892 return StmtError();
14893
14894 auto *CS = cast<CapturedStmt>(AStmt);
14895 // 1.2.2 OpenMP Language Terminology
14896 // Structured block - An executable statement with a single entry at the
14897 // top and a single exit at the bottom.
14898 // The point of exit cannot be a branch out of the structured block.
14899 // longjmp() and throw() must not violate the entry/exit criteria.
14900 CS->getCapturedDecl()->setNothrow();
14901 for (int ThisCaptureLevel =
14902 getOpenMPCaptureLevels(OMPD_target_teams_distribute_parallel_for);
14903 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14904 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14905 // 1.2.2 OpenMP Language Terminology
14906 // Structured block - An executable statement with a single entry at the
14907 // top and a single exit at the bottom.
14908 // The point of exit cannot be a branch out of the structured block.
14909 // longjmp() and throw() must not violate the entry/exit criteria.
14910 CS->getCapturedDecl()->setNothrow();
14911 }
14912
14914 // In presence of clause 'collapse' with number of loops, it will
14915 // define the nested loops number.
14916 unsigned NestedLoopCount = checkOpenMPLoop(
14917 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14918 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14919 VarsWithImplicitDSA, B);
14920 if (NestedLoopCount == 0)
14921 return StmtError();
14922
14923 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14924 "omp target teams distribute parallel for loop exprs were not built");
14925
14927 // Finalize the clauses that need pre-built expressions for CodeGen.
14928 for (OMPClause *C : Clauses) {
14929 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14930 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14933 return StmtError();
14934 }
14935 }
14936
14939 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14940 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14941}
14942
14944 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14945 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14946 if (!AStmt)
14947 return StmtError();
14948
14949 auto *CS = cast<CapturedStmt>(AStmt);
14950 // 1.2.2 OpenMP Language Terminology
14951 // Structured block - An executable statement with a single entry at the
14952 // top and a single exit at the bottom.
14953 // The point of exit cannot be a branch out of the structured block.
14954 // longjmp() and throw() must not violate the entry/exit criteria.
14955 CS->getCapturedDecl()->setNothrow();
14956 for (int ThisCaptureLevel = getOpenMPCaptureLevels(
14957 OMPD_target_teams_distribute_parallel_for_simd);
14958 ThisCaptureLevel > 1; --ThisCaptureLevel) {
14959 CS = cast<CapturedStmt>(CS->getCapturedStmt());
14960 // 1.2.2 OpenMP Language Terminology
14961 // Structured block - An executable statement with a single entry at the
14962 // top and a single exit at the bottom.
14963 // The point of exit cannot be a branch out of the structured block.
14964 // longjmp() and throw() must not violate the entry/exit criteria.
14965 CS->getCapturedDecl()->setNothrow();
14966 }
14967
14969 // In presence of clause 'collapse' with number of loops, it will
14970 // define the nested loops number.
14971 unsigned NestedLoopCount =
14972 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14973 getCollapseNumberExpr(Clauses),
14974 nullptr /*ordered not a clause on distribute*/, CS,
14975 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14976 if (NestedLoopCount == 0)
14977 return StmtError();
14978
14979 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14980 "omp target teams distribute parallel for simd loop exprs were not "
14981 "built");
14982
14984 // Finalize the clauses that need pre-built expressions for CodeGen.
14985 for (OMPClause *C : Clauses) {
14986 if (auto *LC = dyn_cast<OMPLinearClause>(C))
14987 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
14990 return StmtError();
14991 }
14992 }
14993
14995 return StmtError();
14996
14999 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15000}
15001
15003 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15004 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15005 if (!AStmt)
15006 return StmtError();
15007
15008 auto *CS = cast<CapturedStmt>(AStmt);
15009 // 1.2.2 OpenMP Language Terminology
15010 // Structured block - An executable statement with a single entry at the
15011 // top and a single exit at the bottom.
15012 // The point of exit cannot be a branch out of the structured block.
15013 // longjmp() and throw() must not violate the entry/exit criteria.
15014 CS->getCapturedDecl()->setNothrow();
15015 for (int ThisCaptureLevel =
15016 getOpenMPCaptureLevels(OMPD_target_teams_distribute_simd);
15017 ThisCaptureLevel > 1; --ThisCaptureLevel) {
15018 CS = cast<CapturedStmt>(CS->getCapturedStmt());
15019 // 1.2.2 OpenMP Language Terminology
15020 // Structured block - An executable statement with a single entry at the
15021 // top and a single exit at the bottom.
15022 // The point of exit cannot be a branch out of the structured block.
15023 // longjmp() and throw() must not violate the entry/exit criteria.
15024 CS->getCapturedDecl()->setNothrow();
15025 }
15026
15028 // In presence of clause 'collapse' with number of loops, it will
15029 // define the nested loops number.
15030 unsigned NestedLoopCount = checkOpenMPLoop(
15031 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
15032 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15033 VarsWithImplicitDSA, B);
15034 if (NestedLoopCount == 0)
15035 return StmtError();
15036
15037 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15038 "omp target teams distribute simd loop exprs were not built");
15039
15041 // Finalize the clauses that need pre-built expressions for CodeGen.
15042 for (OMPClause *C : Clauses) {
15043 if (auto *LC = dyn_cast<OMPLinearClause>(C))
15044 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
15047 return StmtError();
15048 }
15049 }
15050
15052 return StmtError();
15053
15056 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15057}
15058
15059bool SemaOpenMP::checkTransformableLoopNest(
15060 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
15062 Stmt *&Body,
15063 SmallVectorImpl<SmallVector<llvm::PointerUnion<Stmt *, Decl *>, 0>>
15064 &OriginalInits) {
15065 OriginalInits.emplace_back();
15067 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
15068 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
15069 Stmt *CurStmt) {
15070 VarsWithInheritedDSAType TmpDSA;
15071 unsigned SingleNumLoops =
15072 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
15073 TmpDSA, LoopHelpers[Cnt]);
15074 if (SingleNumLoops == 0)
15075 return true;
15076 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
15077 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
15078 OriginalInits.back().push_back(For->getInit());
15079 Body = For->getBody();
15080 } else {
15081 assert(isa<CXXForRangeStmt>(CurStmt) &&
15082 "Expected canonical for or range-based for loops.");
15083 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
15084 OriginalInits.back().push_back(CXXFor->getBeginStmt());
15085 Body = CXXFor->getBody();
15086 }
15087 OriginalInits.emplace_back();
15088 return false;
15089 },
15090 [&OriginalInits](OMPLoopBasedDirective *Transform) {
15091 Stmt *DependentPreInits;
15092 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
15093 DependentPreInits = Dir->getPreInits();
15094 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
15095 DependentPreInits = Dir->getPreInits();
15096 else
15097 llvm_unreachable("Unhandled loop transformation");
15098 if (!DependentPreInits)
15099 return;
15100 llvm::append_range(OriginalInits.back(),
15101 cast<DeclStmt>(DependentPreInits)->getDeclGroup());
15102 });
15103 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
15104 OriginalInits.pop_back();
15105 return Result;
15106}
15107
15109 Stmt *AStmt,
15110 SourceLocation StartLoc,
15111 SourceLocation EndLoc) {
15112 ASTContext &Context = getASTContext();
15113 Scope *CurScope = SemaRef.getCurScope();
15114
15115 const auto *SizesClause =
15116 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15117 if (!SizesClause ||
15118 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
15119 return StmtError();
15120 unsigned NumLoops = SizesClause->getNumSizes();
15121
15122 // Empty statement should only be possible if there already was an error.
15123 if (!AStmt)
15124 return StmtError();
15125
15126 // Verify and diagnose loop nest.
15128 Stmt *Body = nullptr;
15130 OriginalInits;
15131 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
15132 OriginalInits))
15133 return StmtError();
15134
15135 // Delay tiling to when template is completely instantiated.
15137 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
15138 NumLoops, AStmt, nullptr, nullptr);
15139
15140 assert(LoopHelpers.size() == NumLoops &&
15141 "Expecting loop iteration space dimensionality to match number of "
15142 "affected loops");
15143 assert(OriginalInits.size() == NumLoops &&
15144 "Expecting loop iteration space dimensionality to match number of "
15145 "affected loops");
15146
15147 SmallVector<Decl *, 4> PreInits;
15148 CaptureVars CopyTransformer(SemaRef);
15149
15150 // Create iteration variables for the generated loops.
15151 SmallVector<VarDecl *, 4> FloorIndVars;
15152 SmallVector<VarDecl *, 4> TileIndVars;
15153 FloorIndVars.resize(NumLoops);
15154 TileIndVars.resize(NumLoops);
15155 for (unsigned I = 0; I < NumLoops; ++I) {
15156 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15157
15158 assert(LoopHelper.Counters.size() == 1 &&
15159 "Expect single-dimensional loop iteration space");
15160 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15161 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15162 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15163 QualType CntTy = IterVarRef->getType();
15164
15165 // Iteration variable for the floor (i.e. outer) loop.
15166 {
15167 std::string FloorCntName =
15168 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15169 VarDecl *FloorCntDecl =
15170 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15171 FloorIndVars[I] = FloorCntDecl;
15172 }
15173
15174 // Iteration variable for the tile (i.e. inner) loop.
15175 {
15176 std::string TileCntName =
15177 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15178
15179 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15180 // used by the expressions to derive the original iteration variable's
15181 // value from the logical iteration number.
15182 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15183 TileCntDecl->setDeclName(
15184 &SemaRef.PP.getIdentifierTable().get(TileCntName));
15185 TileIndVars[I] = TileCntDecl;
15186 }
15187 for (auto &P : OriginalInits[I]) {
15188 if (auto *D = P.dyn_cast<Decl *>())
15189 PreInits.push_back(D);
15190 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15191 PreInits.append(PI->decl_begin(), PI->decl_end());
15192 }
15193 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15194 PreInits.append(PI->decl_begin(), PI->decl_end());
15195 // Gather declarations for the data members used as counters.
15196 for (Expr *CounterRef : LoopHelper.Counters) {
15197 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15198 if (isa<OMPCapturedExprDecl>(CounterDecl))
15199 PreInits.push_back(CounterDecl);
15200 }
15201 }
15202
15203 // Once the original iteration values are set, append the innermost body.
15204 Stmt *Inner = Body;
15205
15206 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
15207 SizesClause, CurScope](int I) -> Expr * {
15208 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
15209 if (isa<ConstantExpr>(DimTileSizeExpr))
15210 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
15211
15212 // When the tile size is not a constant but a variable, it is possible to
15213 // pass non-positive numbers. For instance:
15214 // \code{c}
15215 // int a = 0;
15216 // #pragma omp tile sizes(a)
15217 // for (int i = 0; i < 42; ++i)
15218 // body(i);
15219 // \endcode
15220 // Although there is no meaningful interpretation of the tile size, the body
15221 // should still be executed 42 times to avoid surprises. To preserve the
15222 // invariant that every loop iteration is executed exactly once and not
15223 // cause an infinite loop, apply a minimum tile size of one.
15224 // Build expr:
15225 // \code{c}
15226 // (TS <= 0) ? 1 : TS
15227 // \endcode
15228 QualType DimTy = DimTileSizeExpr->getType();
15229 uint64_t DimWidth = Context.getTypeSize(DimTy);
15231 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15232 IntegerLiteral *One =
15233 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15235 CurScope, {}, BO_LE,
15236 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
15237 Expr *MinOne = new (Context) ConditionalOperator(
15238 Cond, {}, One, {},
15239 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
15241 return MinOne;
15242 };
15243
15244 // Create tile loops from the inside to the outside.
15245 for (int I = NumLoops - 1; I >= 0; --I) {
15246 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15247 Expr *NumIterations = LoopHelper.NumIterations;
15248 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15249 QualType CntTy = OrigCntVar->getType();
15250
15251 // Commonly used variables. One of the constraints of an AST is that every
15252 // node object must appear at most once, hence we define lamdas that create
15253 // a new AST node at every use.
15254 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, CntTy,
15255 OrigCntVar]() {
15256 return buildDeclRefExpr(SemaRef, TileIndVars[I], CntTy,
15257 OrigCntVar->getExprLoc());
15258 };
15259 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy,
15260 OrigCntVar]() {
15261 return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy,
15262 OrigCntVar->getExprLoc());
15263 };
15264
15265 // For init-statement: auto .tile.iv = .floor.iv
15267 TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(),
15268 /*DirectInit=*/false);
15269 Decl *CounterDecl = TileIndVars[I];
15270 StmtResult InitStmt = new (Context)
15271 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15272 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15273 if (!InitStmt.isUsable())
15274 return StmtError();
15275
15276 // For cond-expression:
15277 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
15278 ExprResult EndOfTile =
15279 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15280 MakeFloorIVRef(), MakeDimTileSize(I));
15281 if (!EndOfTile.isUsable())
15282 return StmtError();
15283 ExprResult IsPartialTile =
15284 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15285 NumIterations, EndOfTile.get());
15286 if (!IsPartialTile.isUsable())
15287 return StmtError();
15288 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
15289 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15290 IsPartialTile.get(), NumIterations, EndOfTile.get());
15291 if (!MinTileAndIterSpace.isUsable())
15292 return StmtError();
15293 ExprResult CondExpr =
15294 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15295 MakeTileIVRef(), MinTileAndIterSpace.get());
15296 if (!CondExpr.isUsable())
15297 return StmtError();
15298
15299 // For incr-statement: ++.tile.iv
15300 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15301 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15302 if (!IncrStmt.isUsable())
15303 return StmtError();
15304
15305 // Statements to set the original iteration variable's value from the
15306 // logical iteration number.
15307 // Generated for loop is:
15308 // \code
15309 // Original_for_init;
15310 // for (auto .tile.iv = .floor.iv;
15311 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
15312 // ++.tile.iv) {
15313 // Original_Body;
15314 // Original_counter_update;
15315 // }
15316 // \endcode
15317 // FIXME: If the innermost body is an loop itself, inserting these
15318 // statements stops it being recognized as a perfectly nested loop (e.g.
15319 // for applying tiling again). If this is the case, sink the expressions
15320 // further into the inner loop.
15321 SmallVector<Stmt *, 4> BodyParts;
15322 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15323 BodyParts.push_back(Inner);
15324 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15325 Inner->getBeginLoc(), Inner->getEndLoc());
15326 Inner = new (Context)
15327 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15328 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15329 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15330 }
15331
15332 // Create floor loops from the inside to the outside.
15333 for (int I = NumLoops - 1; I >= 0; --I) {
15334 auto &LoopHelper = LoopHelpers[I];
15335 Expr *NumIterations = LoopHelper.NumIterations;
15336 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15337 QualType CntTy = OrigCntVar->getType();
15338
15339 // Commonly used variables.
15340 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, CntTy,
15341 OrigCntVar]() {
15342 return buildDeclRefExpr(SemaRef, FloorIndVars[I], CntTy,
15343 OrigCntVar->getExprLoc());
15344 };
15345
15346 // For init-statement: auto .floor.iv = 0
15348 FloorIndVars[I],
15349 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15350 /*DirectInit=*/false);
15351 Decl *CounterDecl = FloorIndVars[I];
15352 StmtResult InitStmt = new (Context)
15353 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15354 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15355 if (!InitStmt.isUsable())
15356 return StmtError();
15357
15358 // For cond-expression: .floor.iv < NumIterations
15359 ExprResult CondExpr =
15360 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15361 MakeFloorIVRef(), NumIterations);
15362 if (!CondExpr.isUsable())
15363 return StmtError();
15364
15365 // For incr-statement: .floor.iv += DimTileSize
15366 ExprResult IncrStmt =
15367 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15368 MakeFloorIVRef(), MakeDimTileSize(I));
15369 if (!IncrStmt.isUsable())
15370 return StmtError();
15371
15372 Inner = new (Context)
15373 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15374 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15375 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15376 }
15377
15378 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15379 AStmt, Inner,
15380 buildPreInits(Context, PreInits));
15381}
15382
15384 Stmt *AStmt,
15385 SourceLocation StartLoc,
15386 SourceLocation EndLoc) {
15387 ASTContext &Context = getASTContext();
15388 Scope *CurScope = SemaRef.getCurScope();
15389 // Empty statement should only be possible if there already was an error.
15390 if (!AStmt)
15391 return StmtError();
15392
15394 {OMPC_partial, OMPC_full}))
15395 return StmtError();
15396
15397 const OMPFullClause *FullClause =
15398 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15399 const OMPPartialClause *PartialClause =
15400 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15401 assert(!(FullClause && PartialClause) &&
15402 "mutual exclusivity must have been checked before");
15403
15404 constexpr unsigned NumLoops = 1;
15405 Stmt *Body = nullptr;
15407 NumLoops);
15409 OriginalInits;
15410 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15411 Body, OriginalInits))
15412 return StmtError();
15413
15414 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
15415
15416 // Delay unrolling to when template is completely instantiated.
15418 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15419 NumGeneratedLoops, nullptr, nullptr);
15420
15421 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15422
15423 if (FullClause) {
15425 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15426 /*SuppressExprDiags=*/true)
15427 .isUsable()) {
15428 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15429 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15430 << "#pragma omp unroll full";
15431 return StmtError();
15432 }
15433 }
15434
15435 // The generated loop may only be passed to other loop-associated directive
15436 // when a partial clause is specified. Without the requirement it is
15437 // sufficient to generate loop unroll metadata at code-generation.
15438 if (NumGeneratedLoops == 0)
15439 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15440 NumGeneratedLoops, nullptr, nullptr);
15441
15442 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15443 // associated with another loop directive.
15444 //
15445 // The canonical loop analysis return by checkTransformableLoopNest assumes
15446 // the following structure to be the same loop without transformations or
15447 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15448 // LoopHelper.Counters;
15449 // for (; IV < LoopHelper.NumIterations; ++IV) {
15450 // LoopHelper.Updates;
15451 // Body;
15452 // }
15453 // \endcode
15454 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15455 // and referenced by LoopHelper.IterationVarRef.
15456 //
15457 // The unrolling directive transforms this into the following loop:
15458 // \code
15459 // OriginalInits; \
15460 // LoopHelper.PreInits; > NewPreInits
15461 // LoopHelper.Counters; /
15462 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15463 // #pragma clang loop unroll_count(Factor)
15464 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15465 // {
15466 // LoopHelper.Updates;
15467 // Body;
15468 // }
15469 // }
15470 // \endcode
15471 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15472 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15473 // references it. If the partially unrolled loop is associated with another
15474 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15475 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15476 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15477 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15478 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15479 // property of the OMPLoopBasedDirective instead of statements in
15480 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15481 // of a canonical loop nest where these PreInits are emitted before the
15482 // outermost directive.
15483
15484 // Determine the PreInit declarations.
15485 SmallVector<Decl *, 4> PreInits;
15486 assert(OriginalInits.size() == 1 &&
15487 "Expecting a single-dimensional loop iteration space");
15488 for (auto &P : OriginalInits[0]) {
15489 if (auto *D = P.dyn_cast<Decl *>())
15490 PreInits.push_back(D);
15491 else if (auto *PI = dyn_cast_or_null<DeclStmt>(P.dyn_cast<Stmt *>()))
15492 PreInits.append(PI->decl_begin(), PI->decl_end());
15493 }
15494 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits))
15495 PreInits.append(PI->decl_begin(), PI->decl_end());
15496 // Gather declarations for the data members used as counters.
15497 for (Expr *CounterRef : LoopHelper.Counters) {
15498 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
15499 if (isa<OMPCapturedExprDecl>(CounterDecl))
15500 PreInits.push_back(CounterDecl);
15501 }
15502
15503 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15504 QualType IVTy = IterationVarRef->getType();
15505 assert(LoopHelper.Counters.size() == 1 &&
15506 "Expecting a single-dimensional loop iteration space");
15507 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15508
15509 // Determine the unroll factor.
15510 uint64_t Factor;
15511 SourceLocation FactorLoc;
15512 if (Expr *FactorVal = PartialClause->getFactor()) {
15513 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15514 FactorLoc = FactorVal->getExprLoc();
15515 } else {
15516 // TODO: Use a better profitability model.
15517 Factor = 2;
15518 }
15519 assert(Factor > 0 && "Expected positive unroll factor");
15520 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15522 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15523 IVTy, FactorLoc);
15524 };
15525
15526 // Iteration variable SourceLocations.
15527 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15528 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15529 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15530
15531 // Internal variable names.
15532 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15533 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15534 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15535 std::string InnerTripCountName =
15536 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
15537
15538 // Create the iteration variable for the unrolled loop.
15539 VarDecl *OuterIVDecl =
15540 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15541 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15542 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15543 };
15544
15545 // Iteration variable for the inner loop: Reuse the iteration variable created
15546 // by checkOpenMPLoop.
15547 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15548 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15549 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15550 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15551 };
15552
15553 // Make a copy of the NumIterations expression for each use: By the AST
15554 // constraints, every expression object in a DeclContext must be unique.
15555 CaptureVars CopyTransformer(SemaRef);
15556 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15557 return AssertSuccess(
15558 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15559 };
15560
15561 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15562 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15563 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15564 /*DirectInit=*/false);
15565 StmtResult InnerInit = new (Context)
15566 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15567 if (!InnerInit.isUsable())
15568 return StmtError();
15569
15570 // Inner For cond-expression:
15571 // \code
15572 // .unroll_inner.iv < .unrolled.iv + Factor &&
15573 // .unroll_inner.iv < NumIterations
15574 // \endcode
15575 // This conjunction of two conditions allows ScalarEvolution to derive the
15576 // maximum trip count of the inner loop.
15577 ExprResult EndOfTile =
15578 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15579 MakeOuterRef(), MakeFactorExpr());
15580 if (!EndOfTile.isUsable())
15581 return StmtError();
15582 ExprResult InnerCond1 =
15583 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15584 MakeInnerRef(), EndOfTile.get());
15585 if (!InnerCond1.isUsable())
15586 return StmtError();
15587 ExprResult InnerCond2 =
15588 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15589 MakeInnerRef(), MakeNumIterations());
15590 if (!InnerCond2.isUsable())
15591 return StmtError();
15592 ExprResult InnerCond =
15593 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15594 InnerCond1.get(), InnerCond2.get());
15595 if (!InnerCond.isUsable())
15596 return StmtError();
15597
15598 // Inner For incr-statement: ++.unroll_inner.iv
15599 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15600 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15601 if (!InnerIncr.isUsable())
15602 return StmtError();
15603
15604 // Inner For statement.
15605 SmallVector<Stmt *> InnerBodyStmts;
15606 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15607 InnerBodyStmts.push_back(Body);
15608 CompoundStmt *InnerBody =
15610 Body->getBeginLoc(), Body->getEndLoc());
15611 ForStmt *InnerFor = new (Context)
15612 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15613 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15614 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15615
15616 // Unroll metadata for the inner loop.
15617 // This needs to take into account the remainder portion of the unrolled loop,
15618 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15619 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15620 // the maximum trip count, which will also generate a remainder loop. Just
15621 // `unroll(enable)` (which could have been useful if the user has not
15622 // specified a concrete factor; even though the outer loop cannot be
15623 // influenced anymore, would avoid more code bloat than necessary) will refuse
15624 // the loop because "Won't unroll; remainder loop could not be generated when
15625 // assuming runtime trip count". Even if it did work, it must not choose a
15626 // larger unroll factor than the maximum loop length, or it would always just
15627 // execute the remainder loop.
15628 LoopHintAttr *UnrollHintAttr =
15629 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15630 LoopHintAttr::Numeric, MakeFactorExpr());
15631 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15632 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15633
15634 // Outer For init-statement: auto .unrolled.iv = 0
15636 OuterIVDecl,
15637 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15638 /*DirectInit=*/false);
15639 StmtResult OuterInit = new (Context)
15640 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15641 if (!OuterInit.isUsable())
15642 return StmtError();
15643
15644 // Outer For cond-expression: .unrolled.iv < NumIterations
15645 ExprResult OuterConde =
15646 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15647 MakeOuterRef(), MakeNumIterations());
15648 if (!OuterConde.isUsable())
15649 return StmtError();
15650
15651 // Outer For incr-statement: .unrolled.iv += Factor
15652 ExprResult OuterIncr =
15653 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15654 MakeOuterRef(), MakeFactorExpr());
15655 if (!OuterIncr.isUsable())
15656 return StmtError();
15657
15658 // Outer For statement.
15659 ForStmt *OuterFor = new (Context)
15660 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15661 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15662 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15663
15664 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15665 NumGeneratedLoops, OuterFor,
15666 buildPreInits(Context, PreInits));
15667}
15668
15670 Expr *Expr,
15671 SourceLocation StartLoc,
15672 SourceLocation LParenLoc,
15673 SourceLocation EndLoc) {
15674 OMPClause *Res = nullptr;
15675 switch (Kind) {
15676 case OMPC_final:
15677 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15678 break;
15679 case OMPC_num_threads:
15680 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15681 break;
15682 case OMPC_safelen:
15683 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15684 break;
15685 case OMPC_simdlen:
15686 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15687 break;
15688 case OMPC_allocator:
15689 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15690 break;
15691 case OMPC_collapse:
15692 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15693 break;
15694 case OMPC_ordered:
15695 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15696 break;
15697 case OMPC_num_teams:
15698 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
15699 break;
15700 case OMPC_thread_limit:
15701 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
15702 break;
15703 case OMPC_priority:
15704 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15705 break;
15706 case OMPC_hint:
15707 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15708 break;
15709 case OMPC_depobj:
15710 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15711 break;
15712 case OMPC_detach:
15713 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15714 break;
15715 case OMPC_novariants:
15716 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15717 break;
15718 case OMPC_nocontext:
15719 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15720 break;
15721 case OMPC_filter:
15722 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15723 break;
15724 case OMPC_partial:
15725 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15726 break;
15727 case OMPC_message:
15728 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15729 break;
15730 case OMPC_align:
15731 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15732 break;
15733 case OMPC_ompx_dyn_cgroup_mem:
15734 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15735 break;
15736 case OMPC_grainsize:
15737 case OMPC_num_tasks:
15738 case OMPC_device:
15739 case OMPC_if:
15740 case OMPC_default:
15741 case OMPC_proc_bind:
15742 case OMPC_schedule:
15743 case OMPC_private:
15744 case OMPC_firstprivate:
15745 case OMPC_lastprivate:
15746 case OMPC_shared:
15747 case OMPC_reduction:
15748 case OMPC_task_reduction:
15749 case OMPC_in_reduction:
15750 case OMPC_linear:
15751 case OMPC_aligned:
15752 case OMPC_copyin:
15753 case OMPC_copyprivate:
15754 case OMPC_nowait:
15755 case OMPC_untied:
15756 case OMPC_mergeable:
15757 case OMPC_threadprivate:
15758 case OMPC_sizes:
15759 case OMPC_allocate:
15760 case OMPC_flush:
15761 case OMPC_read:
15762 case OMPC_write:
15763 case OMPC_update:
15764 case OMPC_capture:
15765 case OMPC_compare:
15766 case OMPC_seq_cst:
15767 case OMPC_acq_rel:
15768 case OMPC_acquire:
15769 case OMPC_release:
15770 case OMPC_relaxed:
15771 case OMPC_depend:
15772 case OMPC_threads:
15773 case OMPC_simd:
15774 case OMPC_map:
15775 case OMPC_nogroup:
15776 case OMPC_dist_schedule:
15777 case OMPC_defaultmap:
15778 case OMPC_unknown:
15779 case OMPC_uniform:
15780 case OMPC_to:
15781 case OMPC_from:
15782 case OMPC_use_device_ptr:
15783 case OMPC_use_device_addr:
15784 case OMPC_is_device_ptr:
15785 case OMPC_unified_address:
15786 case OMPC_unified_shared_memory:
15787 case OMPC_reverse_offload:
15788 case OMPC_dynamic_allocators:
15789 case OMPC_atomic_default_mem_order:
15790 case OMPC_device_type:
15791 case OMPC_match:
15792 case OMPC_nontemporal:
15793 case OMPC_order:
15794 case OMPC_at:
15795 case OMPC_severity:
15796 case OMPC_destroy:
15797 case OMPC_inclusive:
15798 case OMPC_exclusive:
15799 case OMPC_uses_allocators:
15800 case OMPC_affinity:
15801 case OMPC_when:
15802 case OMPC_bind:
15803 default:
15804 llvm_unreachable("Clause is not allowed.");
15805 }
15806 return Res;
15807}
15808
15809// An OpenMP directive such as 'target parallel' has two captured regions:
15810// for the 'target' and 'parallel' respectively. This function returns
15811// the region in which to capture expressions associated with a clause.
15812// A return value of OMPD_unknown signifies that the expression should not
15813// be captured.
15815 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15816 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15817 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15818 switch (CKind) {
15819 case OMPC_if:
15820 switch (DKind) {
15821 case OMPD_target_parallel_for_simd:
15822 if (OpenMPVersion >= 50 &&
15823 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15824 CaptureRegion = OMPD_parallel;
15825 break;
15826 }
15827 [[fallthrough]];
15828 case OMPD_target_parallel:
15829 case OMPD_target_parallel_for:
15830 case OMPD_target_parallel_loop:
15831 // If this clause applies to the nested 'parallel' region, capture within
15832 // the 'target' region, otherwise do not capture.
15833 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15834 CaptureRegion = OMPD_target;
15835 break;
15836 case OMPD_teams_loop:
15837 case OMPD_target_teams_loop:
15838 // For [target] teams loop, assume capture region is 'teams' so it's
15839 // available for codegen later to use if/when necessary.
15840 CaptureRegion = OMPD_teams;
15841 break;
15842 case OMPD_target_teams_distribute_parallel_for_simd:
15843 if (OpenMPVersion >= 50 &&
15844 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15845 CaptureRegion = OMPD_parallel;
15846 break;
15847 }
15848 [[fallthrough]];
15849 case OMPD_target_teams_distribute_parallel_for:
15850 // If this clause applies to the nested 'parallel' region, capture within
15851 // the 'teams' region, otherwise do not capture.
15852 if (NameModifier == OMPD_unknown || NameModifier == OMPD_parallel)
15853 CaptureRegion = OMPD_teams;
15854 break;
15855 case OMPD_teams_distribute_parallel_for_simd:
15856 if (OpenMPVersion >= 50 &&
15857 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)) {
15858 CaptureRegion = OMPD_parallel;
15859 break;
15860 }
15861 [[fallthrough]];
15862 case OMPD_teams_distribute_parallel_for:
15863 CaptureRegion = OMPD_teams;
15864 break;
15865 case OMPD_target_update:
15866 case OMPD_target_enter_data:
15867 case OMPD_target_exit_data:
15868 CaptureRegion = OMPD_task;
15869 break;
15870 case OMPD_parallel_masked_taskloop:
15871 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15872 CaptureRegion = OMPD_parallel;
15873 break;
15874 case OMPD_parallel_master_taskloop:
15875 if (NameModifier == OMPD_unknown || NameModifier == OMPD_taskloop)
15876 CaptureRegion = OMPD_parallel;
15877 break;
15878 case OMPD_parallel_masked_taskloop_simd:
15879 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15880 NameModifier == OMPD_taskloop) {
15881 CaptureRegion = OMPD_parallel;
15882 break;
15883 }
15884 if (OpenMPVersion <= 45)
15885 break;
15886 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15887 CaptureRegion = OMPD_taskloop;
15888 break;
15889 case OMPD_parallel_master_taskloop_simd:
15890 if ((OpenMPVersion <= 45 && NameModifier == OMPD_unknown) ||
15891 NameModifier == OMPD_taskloop) {
15892 CaptureRegion = OMPD_parallel;
15893 break;
15894 }
15895 if (OpenMPVersion <= 45)
15896 break;
15897 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15898 CaptureRegion = OMPD_taskloop;
15899 break;
15900 case OMPD_parallel_for_simd:
15901 if (OpenMPVersion <= 45)
15902 break;
15903 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15904 CaptureRegion = OMPD_parallel;
15905 break;
15906 case OMPD_taskloop_simd:
15907 case OMPD_master_taskloop_simd:
15908 case OMPD_masked_taskloop_simd:
15909 if (OpenMPVersion <= 45)
15910 break;
15911 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15912 CaptureRegion = OMPD_taskloop;
15913 break;
15914 case OMPD_distribute_parallel_for_simd:
15915 if (OpenMPVersion <= 45)
15916 break;
15917 if (NameModifier == OMPD_unknown || NameModifier == OMPD_simd)
15918 CaptureRegion = OMPD_parallel;
15919 break;
15920 case OMPD_target_simd:
15921 if (OpenMPVersion >= 50 &&
15922 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15923 CaptureRegion = OMPD_target;
15924 break;
15925 case OMPD_teams_distribute_simd:
15926 case OMPD_target_teams_distribute_simd:
15927 if (OpenMPVersion >= 50 &&
15928 (NameModifier == OMPD_unknown || NameModifier == OMPD_simd))
15929 CaptureRegion = OMPD_teams;
15930 break;
15931 case OMPD_cancel:
15932 case OMPD_parallel:
15933 case OMPD_parallel_master:
15934 case OMPD_parallel_masked:
15935 case OMPD_parallel_sections:
15936 case OMPD_parallel_for:
15937 case OMPD_parallel_loop:
15938 case OMPD_target:
15939 case OMPD_target_teams:
15940 case OMPD_target_teams_distribute:
15941 case OMPD_distribute_parallel_for:
15942 case OMPD_task:
15943 case OMPD_taskloop:
15944 case OMPD_master_taskloop:
15945 case OMPD_masked_taskloop:
15946 case OMPD_target_data:
15947 case OMPD_simd:
15948 case OMPD_for_simd:
15949 case OMPD_distribute_simd:
15950 // Do not capture if-clause expressions.
15951 break;
15952 case OMPD_threadprivate:
15953 case OMPD_allocate:
15954 case OMPD_taskyield:
15955 case OMPD_error:
15956 case OMPD_barrier:
15957 case OMPD_taskwait:
15958 case OMPD_cancellation_point:
15959 case OMPD_flush:
15960 case OMPD_depobj:
15961 case OMPD_scan:
15962 case OMPD_declare_reduction:
15963 case OMPD_declare_mapper:
15964 case OMPD_declare_simd:
15965 case OMPD_declare_variant:
15966 case OMPD_begin_declare_variant:
15967 case OMPD_end_declare_variant:
15968 case OMPD_declare_target:
15969 case OMPD_end_declare_target:
15970 case OMPD_loop:
15971 case OMPD_teams:
15972 case OMPD_tile:
15973 case OMPD_unroll:
15974 case OMPD_for:
15975 case OMPD_sections:
15976 case OMPD_section:
15977 case OMPD_single:
15978 case OMPD_master:
15979 case OMPD_masked:
15980 case OMPD_critical:
15981 case OMPD_taskgroup:
15982 case OMPD_distribute:
15983 case OMPD_ordered:
15984 case OMPD_atomic:
15985 case OMPD_teams_distribute:
15986 case OMPD_requires:
15987 case OMPD_metadirective:
15988 llvm_unreachable("Unexpected OpenMP directive with if-clause");
15989 case OMPD_unknown:
15990 default:
15991 llvm_unreachable("Unknown OpenMP directive");
15992 }
15993 break;
15994 case OMPC_num_threads:
15995 switch (DKind) {
15996 case OMPD_target_parallel:
15997 case OMPD_target_parallel_for:
15998 case OMPD_target_parallel_for_simd:
15999 case OMPD_target_parallel_loop:
16000 CaptureRegion = OMPD_target;
16001 break;
16002 case OMPD_teams_distribute_parallel_for:
16003 case OMPD_teams_distribute_parallel_for_simd:
16004 case OMPD_target_teams_distribute_parallel_for:
16005 case OMPD_target_teams_distribute_parallel_for_simd:
16006 CaptureRegion = OMPD_teams;
16007 break;
16008 case OMPD_parallel:
16009 case OMPD_parallel_master:
16010 case OMPD_parallel_masked:
16011 case OMPD_parallel_sections:
16012 case OMPD_parallel_for:
16013 case OMPD_parallel_for_simd:
16014 case OMPD_parallel_loop:
16015 case OMPD_distribute_parallel_for:
16016 case OMPD_distribute_parallel_for_simd:
16017 case OMPD_parallel_master_taskloop:
16018 case OMPD_parallel_masked_taskloop:
16019 case OMPD_parallel_master_taskloop_simd:
16020 case OMPD_parallel_masked_taskloop_simd:
16021 // Do not capture num_threads-clause expressions.
16022 break;
16023 case OMPD_target_data:
16024 case OMPD_target_enter_data:
16025 case OMPD_target_exit_data:
16026 case OMPD_target_update:
16027 case OMPD_target:
16028 case OMPD_target_simd:
16029 case OMPD_target_teams:
16030 case OMPD_target_teams_distribute:
16031 case OMPD_target_teams_distribute_simd:
16032 case OMPD_cancel:
16033 case OMPD_task:
16034 case OMPD_taskloop:
16035 case OMPD_taskloop_simd:
16036 case OMPD_master_taskloop:
16037 case OMPD_masked_taskloop:
16038 case OMPD_master_taskloop_simd:
16039 case OMPD_masked_taskloop_simd:
16040 case OMPD_threadprivate:
16041 case OMPD_allocate:
16042 case OMPD_taskyield:
16043 case OMPD_error:
16044 case OMPD_barrier:
16045 case OMPD_taskwait:
16046 case OMPD_cancellation_point:
16047 case OMPD_flush:
16048 case OMPD_depobj:
16049 case OMPD_scan:
16050 case OMPD_declare_reduction:
16051 case OMPD_declare_mapper:
16052 case OMPD_declare_simd:
16053 case OMPD_declare_variant:
16054 case OMPD_begin_declare_variant:
16055 case OMPD_end_declare_variant:
16056 case OMPD_declare_target:
16057 case OMPD_end_declare_target:
16058 case OMPD_loop:
16059 case OMPD_teams_loop:
16060 case OMPD_target_teams_loop:
16061 case OMPD_teams:
16062 case OMPD_simd:
16063 case OMPD_tile:
16064 case OMPD_unroll:
16065 case OMPD_for:
16066 case OMPD_for_simd:
16067 case OMPD_sections:
16068 case OMPD_section:
16069 case OMPD_single:
16070 case OMPD_master:
16071 case OMPD_masked:
16072 case OMPD_critical:
16073 case OMPD_taskgroup:
16074 case OMPD_distribute:
16075 case OMPD_ordered:
16076 case OMPD_atomic:
16077 case OMPD_distribute_simd:
16078 case OMPD_teams_distribute:
16079 case OMPD_teams_distribute_simd:
16080 case OMPD_requires:
16081 case OMPD_metadirective:
16082 llvm_unreachable("Unexpected OpenMP directive with num_threads-clause");
16083 case OMPD_unknown:
16084 default:
16085 llvm_unreachable("Unknown OpenMP directive");
16086 }
16087 break;
16088 case OMPC_num_teams:
16089 switch (DKind) {
16090 case OMPD_target_teams:
16091 case OMPD_target_teams_distribute:
16092 case OMPD_target_teams_distribute_simd:
16093 case OMPD_target_teams_distribute_parallel_for:
16094 case OMPD_target_teams_distribute_parallel_for_simd:
16095 case OMPD_target_teams_loop:
16096 CaptureRegion = OMPD_target;
16097 break;
16098 case OMPD_teams_distribute_parallel_for:
16099 case OMPD_teams_distribute_parallel_for_simd:
16100 case OMPD_teams:
16101 case OMPD_teams_distribute:
16102 case OMPD_teams_distribute_simd:
16103 case OMPD_teams_loop:
16104 // Do not capture num_teams-clause expressions.
16105 break;
16106 case OMPD_distribute_parallel_for:
16107 case OMPD_distribute_parallel_for_simd:
16108 case OMPD_task:
16109 case OMPD_taskloop:
16110 case OMPD_taskloop_simd:
16111 case OMPD_master_taskloop:
16112 case OMPD_masked_taskloop:
16113 case OMPD_master_taskloop_simd:
16114 case OMPD_masked_taskloop_simd:
16115 case OMPD_parallel_master_taskloop:
16116 case OMPD_parallel_masked_taskloop:
16117 case OMPD_parallel_master_taskloop_simd:
16118 case OMPD_parallel_masked_taskloop_simd:
16119 case OMPD_target_data:
16120 case OMPD_target_enter_data:
16121 case OMPD_target_exit_data:
16122 case OMPD_target_update:
16123 case OMPD_cancel:
16124 case OMPD_parallel:
16125 case OMPD_parallel_master:
16126 case OMPD_parallel_masked:
16127 case OMPD_parallel_sections:
16128 case OMPD_parallel_for:
16129 case OMPD_parallel_for_simd:
16130 case OMPD_parallel_loop:
16131 case OMPD_target:
16132 case OMPD_target_simd:
16133 case OMPD_target_parallel:
16134 case OMPD_target_parallel_for:
16135 case OMPD_target_parallel_for_simd:
16136 case OMPD_target_parallel_loop:
16137 case OMPD_threadprivate:
16138 case OMPD_allocate:
16139 case OMPD_taskyield:
16140 case OMPD_error:
16141 case OMPD_barrier:
16142 case OMPD_taskwait:
16143 case OMPD_cancellation_point:
16144 case OMPD_flush:
16145 case OMPD_depobj:
16146 case OMPD_scan:
16147 case OMPD_declare_reduction:
16148 case OMPD_declare_mapper:
16149 case OMPD_declare_simd:
16150 case OMPD_declare_variant:
16151 case OMPD_begin_declare_variant:
16152 case OMPD_end_declare_variant:
16153 case OMPD_declare_target:
16154 case OMPD_end_declare_target:
16155 case OMPD_loop:
16156 case OMPD_simd:
16157 case OMPD_tile:
16158 case OMPD_unroll:
16159 case OMPD_for:
16160 case OMPD_for_simd:
16161 case OMPD_sections:
16162 case OMPD_section:
16163 case OMPD_single:
16164 case OMPD_master:
16165 case OMPD_masked:
16166 case OMPD_critical:
16167 case OMPD_taskgroup:
16168 case OMPD_distribute:
16169 case OMPD_ordered:
16170 case OMPD_atomic:
16171 case OMPD_distribute_simd:
16172 case OMPD_requires:
16173 case OMPD_metadirective:
16174 llvm_unreachable("Unexpected OpenMP directive with num_teams-clause");
16175 case OMPD_unknown:
16176 default:
16177 llvm_unreachable("Unknown OpenMP directive");
16178 }
16179 break;
16180 case OMPC_thread_limit:
16181 switch (DKind) {
16182 case OMPD_target:
16183 case OMPD_target_teams:
16184 case OMPD_target_teams_distribute:
16185 case OMPD_target_teams_distribute_simd:
16186 case OMPD_target_teams_distribute_parallel_for:
16187 case OMPD_target_teams_distribute_parallel_for_simd:
16188 case OMPD_target_teams_loop:
16189 case OMPD_target_simd:
16190 case OMPD_target_parallel:
16191 case OMPD_target_parallel_for:
16192 case OMPD_target_parallel_for_simd:
16193 case OMPD_target_parallel_loop:
16194 CaptureRegion = OMPD_target;
16195 break;
16196 case OMPD_teams_distribute_parallel_for:
16197 case OMPD_teams_distribute_parallel_for_simd:
16198 case OMPD_teams:
16199 case OMPD_teams_distribute:
16200 case OMPD_teams_distribute_simd:
16201 case OMPD_teams_loop:
16202 // Do not capture thread_limit-clause expressions.
16203 break;
16204 case OMPD_distribute_parallel_for:
16205 case OMPD_distribute_parallel_for_simd:
16206 case OMPD_task:
16207 case OMPD_taskloop:
16208 case OMPD_taskloop_simd:
16209 case OMPD_master_taskloop:
16210 case OMPD_masked_taskloop:
16211 case OMPD_master_taskloop_simd:
16212 case OMPD_masked_taskloop_simd:
16213 case OMPD_parallel_master_taskloop:
16214 case OMPD_parallel_masked_taskloop:
16215 case OMPD_parallel_master_taskloop_simd:
16216 case OMPD_parallel_masked_taskloop_simd:
16217 case OMPD_target_data:
16218 case OMPD_target_enter_data:
16219 case OMPD_target_exit_data:
16220 case OMPD_target_update:
16221 case OMPD_cancel:
16222 case OMPD_parallel:
16223 case OMPD_parallel_master:
16224 case OMPD_parallel_masked:
16225 case OMPD_parallel_sections:
16226 case OMPD_parallel_for:
16227 case OMPD_parallel_for_simd:
16228 case OMPD_parallel_loop:
16229 case OMPD_threadprivate:
16230 case OMPD_allocate:
16231 case OMPD_taskyield:
16232 case OMPD_error:
16233 case OMPD_barrier:
16234 case OMPD_taskwait:
16235 case OMPD_cancellation_point:
16236 case OMPD_flush:
16237 case OMPD_depobj:
16238 case OMPD_scan:
16239 case OMPD_declare_reduction:
16240 case OMPD_declare_mapper:
16241 case OMPD_declare_simd:
16242 case OMPD_declare_variant:
16243 case OMPD_begin_declare_variant:
16244 case OMPD_end_declare_variant:
16245 case OMPD_declare_target:
16246 case OMPD_end_declare_target:
16247 case OMPD_loop:
16248 case OMPD_simd:
16249 case OMPD_tile:
16250 case OMPD_unroll:
16251 case OMPD_for:
16252 case OMPD_for_simd:
16253 case OMPD_sections:
16254 case OMPD_section:
16255 case OMPD_single:
16256 case OMPD_master:
16257 case OMPD_masked:
16258 case OMPD_critical:
16259 case OMPD_taskgroup:
16260 case OMPD_distribute:
16261 case OMPD_ordered:
16262 case OMPD_atomic:
16263 case OMPD_distribute_simd:
16264 case OMPD_requires:
16265 case OMPD_metadirective:
16266 llvm_unreachable("Unexpected OpenMP directive with thread_limit-clause");
16267 case OMPD_unknown:
16268 default:
16269 llvm_unreachable("Unknown OpenMP directive");
16270 }
16271 break;
16272 case OMPC_schedule:
16273 switch (DKind) {
16274 case OMPD_parallel_for:
16275 case OMPD_parallel_for_simd:
16276 case OMPD_distribute_parallel_for:
16277 case OMPD_distribute_parallel_for_simd:
16278 case OMPD_teams_distribute_parallel_for:
16279 case OMPD_teams_distribute_parallel_for_simd:
16280 case OMPD_target_parallel_for:
16281 case OMPD_target_parallel_for_simd:
16282 case OMPD_target_teams_distribute_parallel_for:
16283 case OMPD_target_teams_distribute_parallel_for_simd:
16284 CaptureRegion = OMPD_parallel;
16285 break;
16286 case OMPD_for:
16287 case OMPD_for_simd:
16288 // Do not capture schedule-clause expressions.
16289 break;
16290 case OMPD_task:
16291 case OMPD_taskloop:
16292 case OMPD_taskloop_simd:
16293 case OMPD_master_taskloop:
16294 case OMPD_masked_taskloop:
16295 case OMPD_master_taskloop_simd:
16296 case OMPD_masked_taskloop_simd:
16297 case OMPD_parallel_master_taskloop:
16298 case OMPD_parallel_masked_taskloop:
16299 case OMPD_parallel_master_taskloop_simd:
16300 case OMPD_parallel_masked_taskloop_simd:
16301 case OMPD_target_data:
16302 case OMPD_target_enter_data:
16303 case OMPD_target_exit_data:
16304 case OMPD_target_update:
16305 case OMPD_teams:
16306 case OMPD_teams_distribute:
16307 case OMPD_teams_distribute_simd:
16308 case OMPD_target_teams_distribute:
16309 case OMPD_target_teams_distribute_simd:
16310 case OMPD_target:
16311 case OMPD_target_simd:
16312 case OMPD_target_parallel:
16313 case OMPD_cancel:
16314 case OMPD_parallel:
16315 case OMPD_parallel_master:
16316 case OMPD_parallel_masked:
16317 case OMPD_parallel_sections:
16318 case OMPD_threadprivate:
16319 case OMPD_allocate:
16320 case OMPD_taskyield:
16321 case OMPD_error:
16322 case OMPD_barrier:
16323 case OMPD_taskwait:
16324 case OMPD_cancellation_point:
16325 case OMPD_flush:
16326 case OMPD_depobj:
16327 case OMPD_scan:
16328 case OMPD_declare_reduction:
16329 case OMPD_declare_mapper:
16330 case OMPD_declare_simd:
16331 case OMPD_declare_variant:
16332 case OMPD_begin_declare_variant:
16333 case OMPD_end_declare_variant:
16334 case OMPD_declare_target:
16335 case OMPD_end_declare_target:
16336 case OMPD_loop:
16337 case OMPD_teams_loop:
16338 case OMPD_target_teams_loop:
16339 case OMPD_parallel_loop:
16340 case OMPD_target_parallel_loop:
16341 case OMPD_simd:
16342 case OMPD_tile:
16343 case OMPD_unroll:
16344 case OMPD_sections:
16345 case OMPD_section:
16346 case OMPD_single:
16347 case OMPD_master:
16348 case OMPD_masked:
16349 case OMPD_critical:
16350 case OMPD_taskgroup:
16351 case OMPD_distribute:
16352 case OMPD_ordered:
16353 case OMPD_atomic:
16354 case OMPD_distribute_simd:
16355 case OMPD_target_teams:
16356 case OMPD_requires:
16357 case OMPD_metadirective:
16358 llvm_unreachable("Unexpected OpenMP directive with schedule clause");
16359 case OMPD_unknown:
16360 default:
16361 llvm_unreachable("Unknown OpenMP directive");
16362 }
16363 break;
16364 case OMPC_dist_schedule:
16365 switch (DKind) {
16366 case OMPD_teams_distribute_parallel_for:
16367 case OMPD_teams_distribute_parallel_for_simd:
16368 case OMPD_teams_distribute:
16369 case OMPD_teams_distribute_simd:
16370 case OMPD_target_teams_distribute_parallel_for:
16371 case OMPD_target_teams_distribute_parallel_for_simd:
16372 case OMPD_target_teams_distribute:
16373 case OMPD_target_teams_distribute_simd:
16374 CaptureRegion = OMPD_teams;
16375 break;
16376 case OMPD_distribute_parallel_for:
16377 case OMPD_distribute_parallel_for_simd:
16378 case OMPD_distribute:
16379 case OMPD_distribute_simd:
16380 // Do not capture dist_schedule-clause expressions.
16381 break;
16382 case OMPD_parallel_for:
16383 case OMPD_parallel_for_simd:
16384 case OMPD_target_parallel_for_simd:
16385 case OMPD_target_parallel_for:
16386 case OMPD_task:
16387 case OMPD_taskloop:
16388 case OMPD_taskloop_simd:
16389 case OMPD_master_taskloop:
16390 case OMPD_masked_taskloop:
16391 case OMPD_master_taskloop_simd:
16392 case OMPD_masked_taskloop_simd:
16393 case OMPD_parallel_master_taskloop:
16394 case OMPD_parallel_masked_taskloop:
16395 case OMPD_parallel_master_taskloop_simd:
16396 case OMPD_parallel_masked_taskloop_simd:
16397 case OMPD_target_data:
16398 case OMPD_target_enter_data:
16399 case OMPD_target_exit_data:
16400 case OMPD_target_update:
16401 case OMPD_teams:
16402 case OMPD_target:
16403 case OMPD_target_simd:
16404 case OMPD_target_parallel:
16405 case OMPD_cancel:
16406 case OMPD_parallel:
16407 case OMPD_parallel_master:
16408 case OMPD_parallel_masked:
16409 case OMPD_parallel_sections:
16410 case OMPD_threadprivate:
16411 case OMPD_allocate:
16412 case OMPD_taskyield:
16413 case OMPD_error:
16414 case OMPD_barrier:
16415 case OMPD_taskwait:
16416 case OMPD_cancellation_point:
16417 case OMPD_flush:
16418 case OMPD_depobj:
16419 case OMPD_scan:
16420 case OMPD_declare_reduction:
16421 case OMPD_declare_mapper:
16422 case OMPD_declare_simd:
16423 case OMPD_declare_variant:
16424 case OMPD_begin_declare_variant:
16425 case OMPD_end_declare_variant:
16426 case OMPD_declare_target:
16427 case OMPD_end_declare_target:
16428 case OMPD_loop:
16429 case OMPD_teams_loop:
16430 case OMPD_target_teams_loop:
16431 case OMPD_parallel_loop:
16432 case OMPD_target_parallel_loop:
16433 case OMPD_simd:
16434 case OMPD_tile:
16435 case OMPD_unroll:
16436 case OMPD_for:
16437 case OMPD_for_simd:
16438 case OMPD_sections:
16439 case OMPD_section:
16440 case OMPD_single:
16441 case OMPD_master:
16442 case OMPD_masked:
16443 case OMPD_critical:
16444 case OMPD_taskgroup:
16445 case OMPD_ordered:
16446 case OMPD_atomic:
16447 case OMPD_target_teams:
16448 case OMPD_requires:
16449 case OMPD_metadirective:
16450 llvm_unreachable("Unexpected OpenMP directive with dist_schedule clause");
16451 case OMPD_unknown:
16452 default:
16453 llvm_unreachable("Unknown OpenMP directive");
16454 }
16455 break;
16456 case OMPC_ompx_dyn_cgroup_mem:
16457 switch (DKind) {
16458 case OMPD_target:
16459 case OMPD_target_simd:
16460 case OMPD_target_teams:
16461 case OMPD_target_parallel:
16462 case OMPD_target_teams_distribute:
16463 case OMPD_target_teams_distribute_simd:
16464 case OMPD_target_parallel_for:
16465 case OMPD_target_parallel_for_simd:
16466 case OMPD_target_parallel_loop:
16467 case OMPD_target_teams_distribute_parallel_for:
16468 case OMPD_target_teams_distribute_parallel_for_simd:
16469 case OMPD_target_teams_loop:
16470 CaptureRegion = OMPD_target;
16471 break;
16472 default:
16473 llvm_unreachable("Unknown OpenMP directive");
16474 }
16475 break;
16476 case OMPC_device:
16477 switch (DKind) {
16478 case OMPD_target_update:
16479 case OMPD_target_enter_data:
16480 case OMPD_target_exit_data:
16481 case OMPD_target:
16482 case OMPD_target_simd:
16483 case OMPD_target_teams:
16484 case OMPD_target_parallel:
16485 case OMPD_target_teams_distribute:
16486 case OMPD_target_teams_distribute_simd:
16487 case OMPD_target_parallel_for:
16488 case OMPD_target_parallel_for_simd:
16489 case OMPD_target_parallel_loop:
16490 case OMPD_target_teams_distribute_parallel_for:
16491 case OMPD_target_teams_distribute_parallel_for_simd:
16492 case OMPD_target_teams_loop:
16493 case OMPD_dispatch:
16494 CaptureRegion = OMPD_task;
16495 break;
16496 case OMPD_target_data:
16497 case OMPD_interop:
16498 // Do not capture device-clause expressions.
16499 break;
16500 case OMPD_teams_distribute_parallel_for:
16501 case OMPD_teams_distribute_parallel_for_simd:
16502 case OMPD_teams:
16503 case OMPD_teams_distribute:
16504 case OMPD_teams_distribute_simd:
16505 case OMPD_distribute_parallel_for:
16506 case OMPD_distribute_parallel_for_simd:
16507 case OMPD_task:
16508 case OMPD_taskloop:
16509 case OMPD_taskloop_simd:
16510 case OMPD_master_taskloop:
16511 case OMPD_masked_taskloop:
16512 case OMPD_master_taskloop_simd:
16513 case OMPD_masked_taskloop_simd:
16514 case OMPD_parallel_master_taskloop:
16515 case OMPD_parallel_masked_taskloop:
16516 case OMPD_parallel_master_taskloop_simd:
16517 case OMPD_parallel_masked_taskloop_simd:
16518 case OMPD_cancel:
16519 case OMPD_parallel:
16520 case OMPD_parallel_master:
16521 case OMPD_parallel_masked:
16522 case OMPD_parallel_sections:
16523 case OMPD_parallel_for:
16524 case OMPD_parallel_for_simd:
16525 case OMPD_threadprivate:
16526 case OMPD_allocate:
16527 case OMPD_taskyield:
16528 case OMPD_error:
16529 case OMPD_barrier:
16530 case OMPD_taskwait:
16531 case OMPD_cancellation_point:
16532 case OMPD_flush:
16533 case OMPD_depobj:
16534 case OMPD_scan:
16535 case OMPD_declare_reduction:
16536 case OMPD_declare_mapper:
16537 case OMPD_declare_simd:
16538 case OMPD_declare_variant:
16539 case OMPD_begin_declare_variant:
16540 case OMPD_end_declare_variant:
16541 case OMPD_declare_target:
16542 case OMPD_end_declare_target:
16543 case OMPD_loop:
16544 case OMPD_teams_loop:
16545 case OMPD_parallel_loop:
16546 case OMPD_simd:
16547 case OMPD_tile:
16548 case OMPD_unroll:
16549 case OMPD_for:
16550 case OMPD_for_simd:
16551 case OMPD_sections:
16552 case OMPD_section:
16553 case OMPD_single:
16554 case OMPD_master:
16555 case OMPD_masked:
16556 case OMPD_critical:
16557 case OMPD_taskgroup:
16558 case OMPD_distribute:
16559 case OMPD_ordered:
16560 case OMPD_atomic:
16561 case OMPD_distribute_simd:
16562 case OMPD_requires:
16563 case OMPD_metadirective:
16564 llvm_unreachable("Unexpected OpenMP directive with device-clause");
16565 case OMPD_unknown:
16566 default:
16567 llvm_unreachable("Unknown OpenMP directive");
16568 }
16569 break;
16570 case OMPC_grainsize:
16571 case OMPC_num_tasks:
16572 case OMPC_final:
16573 case OMPC_priority:
16574 switch (DKind) {
16575 case OMPD_task:
16576 case OMPD_taskloop:
16577 case OMPD_taskloop_simd:
16578 case OMPD_master_taskloop:
16579 case OMPD_masked_taskloop:
16580 case OMPD_master_taskloop_simd:
16581 case OMPD_masked_taskloop_simd:
16582 break;
16583 case OMPD_parallel_masked_taskloop:
16584 case OMPD_parallel_masked_taskloop_simd:
16585 case OMPD_parallel_master_taskloop:
16586 case OMPD_parallel_master_taskloop_simd:
16587 CaptureRegion = OMPD_parallel;
16588 break;
16589 case OMPD_target_update:
16590 case OMPD_target_enter_data:
16591 case OMPD_target_exit_data:
16592 case OMPD_target:
16593 case OMPD_target_simd:
16594 case OMPD_target_teams:
16595 case OMPD_target_parallel:
16596 case OMPD_target_teams_distribute:
16597 case OMPD_target_teams_distribute_simd:
16598 case OMPD_target_parallel_for:
16599 case OMPD_target_parallel_for_simd:
16600 case OMPD_target_teams_distribute_parallel_for:
16601 case OMPD_target_teams_distribute_parallel_for_simd:
16602 case OMPD_target_data:
16603 case OMPD_teams_distribute_parallel_for:
16604 case OMPD_teams_distribute_parallel_for_simd:
16605 case OMPD_teams:
16606 case OMPD_teams_distribute:
16607 case OMPD_teams_distribute_simd:
16608 case OMPD_distribute_parallel_for:
16609 case OMPD_distribute_parallel_for_simd:
16610 case OMPD_cancel:
16611 case OMPD_parallel:
16612 case OMPD_parallel_master:
16613 case OMPD_parallel_masked:
16614 case OMPD_parallel_sections:
16615 case OMPD_parallel_for:
16616 case OMPD_parallel_for_simd:
16617 case OMPD_threadprivate:
16618 case OMPD_allocate:
16619 case OMPD_taskyield:
16620 case OMPD_error:
16621 case OMPD_barrier:
16622 case OMPD_taskwait:
16623 case OMPD_cancellation_point:
16624 case OMPD_flush:
16625 case OMPD_depobj:
16626 case OMPD_scan:
16627 case OMPD_declare_reduction:
16628 case OMPD_declare_mapper:
16629 case OMPD_declare_simd:
16630 case OMPD_declare_variant:
16631 case OMPD_begin_declare_variant:
16632 case OMPD_end_declare_variant:
16633 case OMPD_declare_target:
16634 case OMPD_end_declare_target:
16635 case OMPD_loop:
16636 case OMPD_teams_loop:
16637 case OMPD_target_teams_loop:
16638 case OMPD_parallel_loop:
16639 case OMPD_target_parallel_loop:
16640 case OMPD_simd:
16641 case OMPD_tile:
16642 case OMPD_unroll:
16643 case OMPD_for:
16644 case OMPD_for_simd:
16645 case OMPD_sections:
16646 case OMPD_section:
16647 case OMPD_single:
16648 case OMPD_master:
16649 case OMPD_masked:
16650 case OMPD_critical:
16651 case OMPD_taskgroup:
16652 case OMPD_distribute:
16653 case OMPD_ordered:
16654 case OMPD_atomic:
16655 case OMPD_distribute_simd:
16656 case OMPD_requires:
16657 case OMPD_metadirective:
16658 llvm_unreachable("Unexpected OpenMP directive with grainsize-clause");
16659 case OMPD_unknown:
16660 default:
16661 llvm_unreachable("Unknown OpenMP directive");
16662 }
16663 break;
16664 case OMPC_novariants:
16665 case OMPC_nocontext:
16666 switch (DKind) {
16667 case OMPD_dispatch:
16668 CaptureRegion = OMPD_task;
16669 break;
16670 default:
16671 llvm_unreachable("Unexpected OpenMP directive");
16672 }
16673 break;
16674 case OMPC_filter:
16675 // Do not capture filter-clause expressions.
16676 break;
16677 case OMPC_when:
16678 if (DKind == OMPD_metadirective) {
16679 CaptureRegion = OMPD_metadirective;
16680 } else if (DKind == OMPD_unknown) {
16681 llvm_unreachable("Unknown OpenMP directive");
16682 } else {
16683 llvm_unreachable("Unexpected OpenMP directive with when clause");
16684 }
16685 break;
16686 case OMPC_firstprivate:
16687 case OMPC_lastprivate:
16688 case OMPC_reduction:
16689 case OMPC_task_reduction:
16690 case OMPC_in_reduction:
16691 case OMPC_linear:
16692 case OMPC_default:
16693 case OMPC_proc_bind:
16694 case OMPC_safelen:
16695 case OMPC_simdlen:
16696 case OMPC_sizes:
16697 case OMPC_allocator:
16698 case OMPC_collapse:
16699 case OMPC_private:
16700 case OMPC_shared:
16701 case OMPC_aligned:
16702 case OMPC_copyin:
16703 case OMPC_copyprivate:
16704 case OMPC_ordered:
16705 case OMPC_nowait:
16706 case OMPC_untied:
16707 case OMPC_mergeable:
16708 case OMPC_threadprivate:
16709 case OMPC_allocate:
16710 case OMPC_flush:
16711 case OMPC_depobj:
16712 case OMPC_read:
16713 case OMPC_write:
16714 case OMPC_update:
16715 case OMPC_capture:
16716 case OMPC_compare:
16717 case OMPC_seq_cst:
16718 case OMPC_acq_rel:
16719 case OMPC_acquire:
16720 case OMPC_release:
16721 case OMPC_relaxed:
16722 case OMPC_depend:
16723 case OMPC_threads:
16724 case OMPC_simd:
16725 case OMPC_map:
16726 case OMPC_nogroup:
16727 case OMPC_hint:
16728 case OMPC_defaultmap:
16729 case OMPC_unknown:
16730 case OMPC_uniform:
16731 case OMPC_to:
16732 case OMPC_from:
16733 case OMPC_use_device_ptr:
16734 case OMPC_use_device_addr:
16735 case OMPC_is_device_ptr:
16736 case OMPC_unified_address:
16737 case OMPC_unified_shared_memory:
16738 case OMPC_reverse_offload:
16739 case OMPC_dynamic_allocators:
16740 case OMPC_atomic_default_mem_order:
16741 case OMPC_device_type:
16742 case OMPC_match:
16743 case OMPC_nontemporal:
16744 case OMPC_order:
16745 case OMPC_at:
16746 case OMPC_severity:
16747 case OMPC_message:
16748 case OMPC_destroy:
16749 case OMPC_detach:
16750 case OMPC_inclusive:
16751 case OMPC_exclusive:
16752 case OMPC_uses_allocators:
16753 case OMPC_affinity:
16754 case OMPC_bind:
16755 default:
16756 llvm_unreachable("Unexpected OpenMP clause.");
16757 }
16758 return CaptureRegion;
16759}
16760
16762 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
16763 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
16764 SourceLocation ColonLoc, SourceLocation EndLoc) {
16765 Expr *ValExpr = Condition;
16766 Stmt *HelperValStmt = nullptr;
16767 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16768 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16769 !Condition->isInstantiationDependent() &&
16770 !Condition->containsUnexpandedParameterPack()) {
16772 if (Val.isInvalid())
16773 return nullptr;
16774
16775 ValExpr = Val.get();
16776
16777 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16778 CaptureRegion = getOpenMPCaptureRegionForClause(
16779 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
16780 if (CaptureRegion != OMPD_unknown &&
16782 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16783 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16784 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16785 HelperValStmt = buildPreInits(getASTContext(), Captures);
16786 }
16787 }
16788
16789 return new (getASTContext())
16790 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16791 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16792}
16793
16795 SourceLocation StartLoc,
16796 SourceLocation LParenLoc,
16797 SourceLocation EndLoc) {
16798 Expr *ValExpr = Condition;
16799 Stmt *HelperValStmt = nullptr;
16800 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16801 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16802 !Condition->isInstantiationDependent() &&
16803 !Condition->containsUnexpandedParameterPack()) {
16805 if (Val.isInvalid())
16806 return nullptr;
16807
16808 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16809
16810 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16811 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16812 getLangOpts().OpenMP);
16813 if (CaptureRegion != OMPD_unknown &&
16815 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16816 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16817 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16818 HelperValStmt = buildPreInits(getASTContext(), Captures);
16819 }
16820 }
16821
16822 return new (getASTContext()) OMPFinalClause(
16823 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16824}
16825
16828 Expr *Op) {
16829 if (!Op)
16830 return ExprError();
16831
16832 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16833 public:
16834 IntConvertDiagnoser()
16835 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
16836 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16837 QualType T) override {
16838 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16839 }
16840 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16841 QualType T) override {
16842 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16843 }
16844 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16845 QualType T,
16846 QualType ConvTy) override {
16847 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16848 }
16849 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16850 QualType ConvTy) override {
16851 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16852 << ConvTy->isEnumeralType() << ConvTy;
16853 }
16854 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16855 QualType T) override {
16856 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16857 }
16858 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16859 QualType ConvTy) override {
16860 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16861 << ConvTy->isEnumeralType() << ConvTy;
16862 }
16863 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16864 QualType) override {
16865 llvm_unreachable("conversion functions are permitted");
16866 }
16867 } ConvertDiagnoser;
16868 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16869}
16870
16871static bool
16873 bool StrictlyPositive, bool BuildCapture = false,
16874 OpenMPDirectiveKind DKind = OMPD_unknown,
16875 OpenMPDirectiveKind *CaptureRegion = nullptr,
16876 Stmt **HelperValStmt = nullptr) {
16877 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16878 !ValExpr->isInstantiationDependent()) {
16879 SourceLocation Loc = ValExpr->getExprLoc();
16882 if (Value.isInvalid())
16883 return false;
16884
16885 ValExpr = Value.get();
16886 // The expression must evaluate to a non-negative integer value.
16887 if (std::optional<llvm::APSInt> Result =
16888 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16889 if (Result->isSigned() &&
16890 !((!StrictlyPositive && Result->isNonNegative()) ||
16891 (StrictlyPositive && Result->isStrictlyPositive()))) {
16892 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16893 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16894 << ValExpr->getSourceRange();
16895 return false;
16896 }
16897 }
16898 if (!BuildCapture)
16899 return true;
16900 *CaptureRegion =
16901 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16902 if (*CaptureRegion != OMPD_unknown &&
16903 !SemaRef.CurContext->isDependentContext()) {
16904 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16905 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16906 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16907 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16908 }
16909 }
16910 return true;
16911}
16912
16914 SourceLocation StartLoc,
16915 SourceLocation LParenLoc,
16916 SourceLocation EndLoc) {
16917 Expr *ValExpr = NumThreads;
16918 Stmt *HelperValStmt = nullptr;
16919
16920 // OpenMP [2.5, Restrictions]
16921 // The num_threads expression must evaluate to a positive integer value.
16922 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
16923 /*StrictlyPositive=*/true))
16924 return nullptr;
16925
16926 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16928 DKind, OMPC_num_threads, getLangOpts().OpenMP);
16929 if (CaptureRegion != OMPD_unknown &&
16931 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16932 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16933 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16934 HelperValStmt = buildPreInits(getASTContext(), Captures);
16935 }
16936
16937 return new (getASTContext()) OMPNumThreadsClause(
16938 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16939}
16940
16942 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
16943 bool SuppressExprDiags) {
16944 if (!E)
16945 return ExprError();
16946 if (E->isValueDependent() || E->isTypeDependent() ||
16948 return E;
16949
16950 llvm::APSInt Result;
16951 ExprResult ICE;
16952 if (SuppressExprDiags) {
16953 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16954 // expression.
16955 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16956 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16958 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16959 llvm_unreachable("Diagnostic suppressed");
16960 }
16961 } Diagnoser;
16962 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
16964 } else {
16966 /*FIXME*/ Sema::AllowFold);
16967 }
16968 if (ICE.isInvalid())
16969 return ExprError();
16970
16971 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16972 (!StrictlyPositive && !Result.isNonNegative())) {
16973 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16974 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
16975 << E->getSourceRange();
16976 return ExprError();
16977 }
16978 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
16979 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16980 << E->getSourceRange();
16981 return ExprError();
16982 }
16983 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16984 DSAStack->setAssociatedLoops(Result.getExtValue());
16985 else if (CKind == OMPC_ordered)
16986 DSAStack->setAssociatedLoops(Result.getExtValue());
16987 return ICE;
16988}
16989
16991 SourceLocation StartLoc,
16992 SourceLocation LParenLoc,
16993 SourceLocation EndLoc) {
16994 // OpenMP [2.8.1, simd construct, Description]
16995 // The parameter of the safelen clause must be a constant
16996 // positive integer expression.
16997 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16998 if (Safelen.isInvalid())
16999 return nullptr;
17000 return new (getASTContext())
17001 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17002}
17003
17005 SourceLocation StartLoc,
17006 SourceLocation LParenLoc,
17007 SourceLocation EndLoc) {
17008 // OpenMP [2.8.1, simd construct, Description]
17009 // The parameter of the simdlen clause must be a constant
17010 // positive integer expression.
17011 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
17012 if (Simdlen.isInvalid())
17013 return nullptr;
17014 return new (getASTContext())
17015 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17016}
17017
17018/// Tries to find omp_allocator_handle_t type.
17020 DSAStackTy *Stack) {
17021 if (!Stack->getOMPAllocatorHandleT().isNull())
17022 return true;
17023
17024 // Set the allocator handle type.
17025 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
17026 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
17027 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17028 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17029 << "omp_allocator_handle_t";
17030 return false;
17031 }
17032 QualType AllocatorHandleEnumTy = PT.get();
17033 AllocatorHandleEnumTy.addConst();
17034 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17035
17036 // Fill the predefined allocator map.
17037 bool ErrorFound = false;
17038 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17039 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17040 StringRef Allocator =
17041 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17042 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
17043 auto *VD = dyn_cast_or_null<ValueDecl>(
17044 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
17045 if (!VD) {
17046 ErrorFound = true;
17047 break;
17048 }
17049 QualType AllocatorType =
17051 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
17052 if (!Res.isUsable()) {
17053 ErrorFound = true;
17054 break;
17055 }
17056 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
17058 /* AllowExplicit */ true);
17059 if (!Res.isUsable()) {
17060 ErrorFound = true;
17061 break;
17062 }
17063 Stack->setAllocator(AllocatorKind, Res.get());
17064 }
17065 if (ErrorFound) {
17066 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17067 << "omp_allocator_handle_t";
17068 return false;
17069 }
17070
17071 return true;
17072}
17073
17075 SourceLocation StartLoc,
17076 SourceLocation LParenLoc,
17077 SourceLocation EndLoc) {
17078 // OpenMP [2.11.3, allocate Directive, Description]
17079 // allocator is an expression of omp_allocator_handle_t type.
17081 return nullptr;
17082
17084 if (Allocator.isInvalid())
17085 return nullptr;
17087 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17089 /*AllowExplicit=*/true);
17090 if (Allocator.isInvalid())
17091 return nullptr;
17092 return new (getASTContext())
17093 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17094}
17095
17097 SourceLocation StartLoc,
17098 SourceLocation LParenLoc,
17099 SourceLocation EndLoc) {
17100 // OpenMP [2.7.1, loop construct, Description]
17101 // OpenMP [2.8.1, simd construct, Description]
17102 // OpenMP [2.9.6, distribute construct, Description]
17103 // The parameter of the collapse clause must be a constant
17104 // positive integer expression.
17105 ExprResult NumForLoopsResult =
17106 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17107 if (NumForLoopsResult.isInvalid())
17108 return nullptr;
17109 return new (getASTContext())
17110 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17111}
17112
17114 SourceLocation EndLoc,
17115 SourceLocation LParenLoc,
17116 Expr *NumForLoops) {
17117 // OpenMP [2.7.1, loop construct, Description]
17118 // OpenMP [2.8.1, simd construct, Description]
17119 // OpenMP [2.9.6, distribute construct, Description]
17120 // The parameter of the ordered clause must be a constant
17121 // positive integer expression if any.
17122 if (NumForLoops && LParenLoc.isValid()) {
17123 ExprResult NumForLoopsResult =
17124 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17125 if (NumForLoopsResult.isInvalid())
17126 return nullptr;
17127 NumForLoops = NumForLoopsResult.get();
17128 } else {
17129 NumForLoops = nullptr;
17130 }
17131 auto *Clause =
17133 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17134 StartLoc, LParenLoc, EndLoc);
17135 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17136 return Clause;
17137}
17138
17140 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17141 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17142 OMPClause *Res = nullptr;
17143 switch (Kind) {
17144 case OMPC_default:
17145 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
17146 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17147 break;
17148 case OMPC_proc_bind:
17149 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17150 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17151 break;
17152 case OMPC_atomic_default_mem_order:
17154 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17155 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17156 break;
17157 case OMPC_fail:
17159 static_cast<OpenMPClauseKind>(Argument),
17160 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17161 break;
17162 case OMPC_update:
17163 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17164 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17165 break;
17166 case OMPC_bind:
17167 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17168 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17169 break;
17170 case OMPC_at:
17171 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17172 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17173 break;
17174 case OMPC_severity:
17176 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17177 LParenLoc, EndLoc);
17178 break;
17179 case OMPC_if:
17180 case OMPC_final:
17181 case OMPC_num_threads:
17182 case OMPC_safelen:
17183 case OMPC_simdlen:
17184 case OMPC_sizes:
17185 case OMPC_allocator:
17186 case OMPC_collapse:
17187 case OMPC_schedule:
17188 case OMPC_private:
17189 case OMPC_firstprivate:
17190 case OMPC_lastprivate:
17191 case OMPC_shared:
17192 case OMPC_reduction:
17193 case OMPC_task_reduction:
17194 case OMPC_in_reduction:
17195 case OMPC_linear:
17196 case OMPC_aligned:
17197 case OMPC_copyin:
17198 case OMPC_copyprivate:
17199 case OMPC_ordered:
17200 case OMPC_nowait:
17201 case OMPC_untied:
17202 case OMPC_mergeable:
17203 case OMPC_threadprivate:
17204 case OMPC_allocate:
17205 case OMPC_flush:
17206 case OMPC_depobj:
17207 case OMPC_read:
17208 case OMPC_write:
17209 case OMPC_capture:
17210 case OMPC_compare:
17211 case OMPC_seq_cst:
17212 case OMPC_acq_rel:
17213 case OMPC_acquire:
17214 case OMPC_release:
17215 case OMPC_relaxed:
17216 case OMPC_depend:
17217 case OMPC_device:
17218 case OMPC_threads:
17219 case OMPC_simd:
17220 case OMPC_map:
17221 case OMPC_num_teams:
17222 case OMPC_thread_limit:
17223 case OMPC_priority:
17224 case OMPC_grainsize:
17225 case OMPC_nogroup:
17226 case OMPC_num_tasks:
17227 case OMPC_hint:
17228 case OMPC_dist_schedule:
17229 case OMPC_defaultmap:
17230 case OMPC_unknown:
17231 case OMPC_uniform:
17232 case OMPC_to:
17233 case OMPC_from:
17234 case OMPC_use_device_ptr:
17235 case OMPC_use_device_addr:
17236 case OMPC_is_device_ptr:
17237 case OMPC_has_device_addr:
17238 case OMPC_unified_address:
17239 case OMPC_unified_shared_memory:
17240 case OMPC_reverse_offload:
17241 case OMPC_dynamic_allocators:
17242 case OMPC_device_type:
17243 case OMPC_match:
17244 case OMPC_nontemporal:
17245 case OMPC_destroy:
17246 case OMPC_novariants:
17247 case OMPC_nocontext:
17248 case OMPC_detach:
17249 case OMPC_inclusive:
17250 case OMPC_exclusive:
17251 case OMPC_uses_allocators:
17252 case OMPC_affinity:
17253 case OMPC_when:
17254 case OMPC_message:
17255 default:
17256 llvm_unreachable("Clause is not allowed.");
17257 }
17258 return Res;
17259}
17260
17261static std::string
17263 ArrayRef<unsigned> Exclude = std::nullopt) {
17264 SmallString<256> Buffer;
17265 llvm::raw_svector_ostream Out(Buffer);
17266 unsigned Skipped = Exclude.size();
17267 for (unsigned I = First; I < Last; ++I) {
17268 if (llvm::is_contained(Exclude, I)) {
17269 --Skipped;
17270 continue;
17271 }
17272 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
17273 if (I + Skipped + 2 == Last)
17274 Out << " or ";
17275 else if (I + Skipped + 1 != Last)
17276 Out << ", ";
17277 }
17278 return std::string(Out.str());
17279}
17280
17282 SourceLocation KindKwLoc,
17283 SourceLocation StartLoc,
17284 SourceLocation LParenLoc,
17285 SourceLocation EndLoc) {
17286 if (Kind == OMP_DEFAULT_unknown) {
17287 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17288 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17289 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17290 << getOpenMPClauseName(OMPC_default);
17291 return nullptr;
17292 }
17293
17294 switch (Kind) {
17295 case OMP_DEFAULT_none:
17296 DSAStack->setDefaultDSANone(KindKwLoc);
17297 break;
17298 case OMP_DEFAULT_shared:
17299 DSAStack->setDefaultDSAShared(KindKwLoc);
17300 break;
17301 case OMP_DEFAULT_firstprivate:
17302 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
17303 break;
17304 case OMP_DEFAULT_private:
17305 DSAStack->setDefaultDSAPrivate(KindKwLoc);
17306 break;
17307 default:
17308 llvm_unreachable("DSA unexpected in OpenMP default clause");
17309 }
17310
17311 return new (getASTContext())
17312 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17313}
17314
17316 SourceLocation KindKwLoc,
17317 SourceLocation StartLoc,
17318 SourceLocation LParenLoc,
17319 SourceLocation EndLoc) {
17320 if (Kind == OMP_PROC_BIND_unknown) {
17321 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17322 << getListOfPossibleValues(OMPC_proc_bind,
17323 /*First=*/unsigned(OMP_PROC_BIND_master),
17324 /*Last=*/
17325 unsigned(getLangOpts().OpenMP > 50
17326 ? OMP_PROC_BIND_primary
17327 : OMP_PROC_BIND_spread) +
17328 1)
17329 << getOpenMPClauseName(OMPC_proc_bind);
17330 return nullptr;
17331 }
17332 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17333 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17334 << getListOfPossibleValues(OMPC_proc_bind,
17335 /*First=*/unsigned(OMP_PROC_BIND_master),
17336 /*Last=*/
17337 unsigned(OMP_PROC_BIND_spread) + 1)
17338 << getOpenMPClauseName(OMPC_proc_bind);
17339 return new (getASTContext())
17340 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17341}
17342
17345 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17347 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17349 OMPC_atomic_default_mem_order, /*First=*/0,
17351 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
17352 return nullptr;
17353 }
17355 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17356}
17357
17359 SourceLocation KindKwLoc,
17360 SourceLocation StartLoc,
17361 SourceLocation LParenLoc,
17362 SourceLocation EndLoc) {
17363 if (Kind == OMPC_AT_unknown) {
17364 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17365 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17366 /*Last=*/OMPC_AT_unknown)
17367 << getOpenMPClauseName(OMPC_at);
17368 return nullptr;
17369 }
17370 return new (getASTContext())
17371 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17372}
17373
17375 SourceLocation KindKwLoc,
17376 SourceLocation StartLoc,
17377 SourceLocation LParenLoc,
17378 SourceLocation EndLoc) {
17379 if (Kind == OMPC_SEVERITY_unknown) {
17380 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17381 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17382 /*Last=*/OMPC_SEVERITY_unknown)
17383 << getOpenMPClauseName(OMPC_severity);
17384 return nullptr;
17385 }
17386 return new (getASTContext())
17387 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17388}
17389
17391 SourceLocation StartLoc,
17392 SourceLocation LParenLoc,
17393 SourceLocation EndLoc) {
17394 assert(ME && "NULL expr in Message clause");
17395 if (!isa<StringLiteral>(ME)) {
17396 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17397 << getOpenMPClauseName(OMPC_message);
17398 return nullptr;
17399 }
17400 return new (getASTContext())
17401 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
17402}
17403
17406 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17407 SourceLocation KindLoc, SourceLocation EndLoc) {
17408 if (Kind != OMPC_ORDER_concurrent ||
17409 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
17410 // Kind should be concurrent,
17411 // Modifiers introduced in OpenMP 5.1
17412 static_assert(OMPC_ORDER_unknown > 0,
17413 "OMPC_ORDER_unknown not greater than 0");
17414
17415 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17416 << getListOfPossibleValues(OMPC_order,
17417 /*First=*/0,
17418 /*Last=*/OMPC_ORDER_unknown)
17419 << getOpenMPClauseName(OMPC_order);
17420 return nullptr;
17421 }
17422 if (getLangOpts().OpenMP >= 51) {
17423 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
17424 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17425 << getListOfPossibleValues(OMPC_order,
17426 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17427 /*Last=*/OMPC_ORDER_MODIFIER_last)
17428 << getOpenMPClauseName(OMPC_order);
17429 } else {
17430 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17431 if (DSAStack->getCurScope()) {
17432 // mark the current scope with 'order' flag
17433 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17434 DSAStack->getCurScope()->setFlags(existingFlags |
17436 }
17437 }
17438 }
17439 return new (getASTContext()) OMPOrderClause(
17440 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17441}
17442
17444 SourceLocation KindKwLoc,
17445 SourceLocation StartLoc,
17446 SourceLocation LParenLoc,
17447 SourceLocation EndLoc) {
17448 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17449 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17450 SmallVector<unsigned> Except = {
17451 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17452 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17453 if (getLangOpts().OpenMP < 51)
17454 Except.push_back(OMPC_DEPEND_inoutset);
17455 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17456 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17457 /*Last=*/OMPC_DEPEND_unknown, Except)
17458 << getOpenMPClauseName(OMPC_update);
17459 return nullptr;
17460 }
17461 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
17462 KindKwLoc, Kind, EndLoc);
17463}
17464
17466 SourceLocation StartLoc,
17467 SourceLocation LParenLoc,
17468 SourceLocation EndLoc) {
17469 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
17470
17471 for (Expr *&SizeExpr : SanitizedSizeExprs) {
17472 // Skip if already sanitized, e.g. during a partial template instantiation.
17473 if (!SizeExpr)
17474 continue;
17475
17476 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
17477 /*StrictlyPositive=*/true);
17478
17479 // isNonNegativeIntegerValue returns true for non-integral types (but still
17480 // emits error diagnostic), so check for the expected type explicitly.
17481 QualType SizeTy = SizeExpr->getType();
17482 if (!SizeTy->isIntegerType())
17483 IsValid = false;
17484
17485 // Handling in templates is tricky. There are four possibilities to
17486 // consider:
17487 //
17488 // 1a. The expression is valid and we are in a instantiated template or not
17489 // in a template:
17490 // Pass valid expression to be further analysed later in Sema.
17491 // 1b. The expression is valid and we are in a template (including partial
17492 // instantiation):
17493 // isNonNegativeIntegerValue skipped any checks so there is no
17494 // guarantee it will be correct after instantiation.
17495 // ActOnOpenMPSizesClause will be called again at instantiation when
17496 // it is not in a dependent context anymore. This may cause warnings
17497 // to be emitted multiple times.
17498 // 2a. The expression is invalid and we are in an instantiated template or
17499 // not in a template:
17500 // Invalidate the expression with a clearly wrong value (nullptr) so
17501 // later in Sema we do not have to do the same validity analysis again
17502 // or crash from unexpected data. Error diagnostics have already been
17503 // emitted.
17504 // 2b. The expression is invalid and we are in a template (including partial
17505 // instantiation):
17506 // Pass the invalid expression as-is, template instantiation may
17507 // replace unexpected types/values with valid ones. The directives
17508 // with this clause must not try to use these expressions in dependent
17509 // contexts, but delay analysis until full instantiation.
17510 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17511 SizeExpr = nullptr;
17512 }
17513
17514 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17515 SanitizedSizeExprs);
17516}
17517
17519 SourceLocation EndLoc) {
17520 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
17521}
17522
17524 SourceLocation StartLoc,
17525 SourceLocation LParenLoc,
17526 SourceLocation EndLoc) {
17527 if (FactorExpr) {
17528 // If an argument is specified, it must be a constant (or an unevaluated
17529 // template expression).
17531 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17532 if (FactorResult.isInvalid())
17533 return nullptr;
17534 FactorExpr = FactorResult.get();
17535 }
17536
17537 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17538 FactorExpr);
17539}
17540
17542 SourceLocation LParenLoc,
17543 SourceLocation EndLoc) {
17544 ExprResult AlignVal;
17545 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17546 if (AlignVal.isInvalid())
17547 return nullptr;
17548 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
17549 LParenLoc, EndLoc);
17550}
17551
17554 SourceLocation StartLoc, SourceLocation LParenLoc,
17555 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17556 SourceLocation EndLoc) {
17557 OMPClause *Res = nullptr;
17558 switch (Kind) {
17559 case OMPC_schedule:
17560 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17561 assert(Argument.size() == NumberOfElements &&
17562 ArgumentLoc.size() == NumberOfElements);
17564 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17565 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17566 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17567 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17568 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17569 break;
17570 case OMPC_if:
17571 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17572 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17573 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17574 DelimLoc, EndLoc);
17575 break;
17576 case OMPC_dist_schedule:
17578 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17579 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17580 break;
17581 case OMPC_defaultmap:
17582 enum { Modifier, DefaultmapKind };
17584 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17585 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17586 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17587 EndLoc);
17588 break;
17589 case OMPC_order:
17590 enum { OrderModifier, OrderKind };
17592 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17593 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17594 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17595 break;
17596 case OMPC_device:
17597 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17599 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17600 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17601 break;
17602 case OMPC_grainsize:
17603 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17604 "Modifier for grainsize clause and its location are expected.");
17606 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17607 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17608 break;
17609 case OMPC_num_tasks:
17610 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17611 "Modifier for num_tasks clause and its location are expected.");
17613 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17614 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17615 break;
17616 case OMPC_final:
17617 case OMPC_num_threads:
17618 case OMPC_safelen:
17619 case OMPC_simdlen:
17620 case OMPC_sizes:
17621 case OMPC_allocator:
17622 case OMPC_collapse:
17623 case OMPC_default:
17624 case OMPC_proc_bind:
17625 case OMPC_private:
17626 case OMPC_firstprivate:
17627 case OMPC_lastprivate:
17628 case OMPC_shared:
17629 case OMPC_reduction:
17630 case OMPC_task_reduction:
17631 case OMPC_in_reduction:
17632 case OMPC_linear:
17633 case OMPC_aligned:
17634 case OMPC_copyin:
17635 case OMPC_copyprivate:
17636 case OMPC_ordered:
17637 case OMPC_nowait:
17638 case OMPC_untied:
17639 case OMPC_mergeable:
17640 case OMPC_threadprivate:
17641 case OMPC_allocate:
17642 case OMPC_flush:
17643 case OMPC_depobj:
17644 case OMPC_read:
17645 case OMPC_write:
17646 case OMPC_update:
17647 case OMPC_capture:
17648 case OMPC_compare:
17649 case OMPC_seq_cst:
17650 case OMPC_acq_rel:
17651 case OMPC_acquire:
17652 case OMPC_release:
17653 case OMPC_relaxed:
17654 case OMPC_depend:
17655 case OMPC_threads:
17656 case OMPC_simd:
17657 case OMPC_map:
17658 case OMPC_num_teams:
17659 case OMPC_thread_limit:
17660 case OMPC_priority:
17661 case OMPC_nogroup:
17662 case OMPC_hint:
17663 case OMPC_unknown:
17664 case OMPC_uniform:
17665 case OMPC_to:
17666 case OMPC_from:
17667 case OMPC_use_device_ptr:
17668 case OMPC_use_device_addr:
17669 case OMPC_is_device_ptr:
17670 case OMPC_has_device_addr:
17671 case OMPC_unified_address:
17672 case OMPC_unified_shared_memory:
17673 case OMPC_reverse_offload:
17674 case OMPC_dynamic_allocators:
17675 case OMPC_atomic_default_mem_order:
17676 case OMPC_device_type:
17677 case OMPC_match:
17678 case OMPC_nontemporal:
17679 case OMPC_at:
17680 case OMPC_severity:
17681 case OMPC_message:
17682 case OMPC_destroy:
17683 case OMPC_novariants:
17684 case OMPC_nocontext:
17685 case OMPC_detach:
17686 case OMPC_inclusive:
17687 case OMPC_exclusive:
17688 case OMPC_uses_allocators:
17689 case OMPC_affinity:
17690 case OMPC_when:
17691 case OMPC_bind:
17692 default:
17693 llvm_unreachable("Clause is not allowed.");
17694 }
17695 return Res;
17696}
17697
17700 SourceLocation M1Loc, SourceLocation M2Loc) {
17701 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
17702 SmallVector<unsigned, 2> Excluded;
17704 Excluded.push_back(M2);
17705 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
17706 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
17707 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
17708 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
17709 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
17710 << getListOfPossibleValues(OMPC_schedule,
17711 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
17713 Excluded)
17714 << getOpenMPClauseName(OMPC_schedule);
17715 return true;
17716 }
17717 return false;
17718}
17719
17722 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
17723 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
17724 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
17725 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
17726 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
17727 return nullptr;
17728 // OpenMP, 2.7.1, Loop Construct, Restrictions
17729 // Either the monotonic modifier or the nonmonotonic modifier can be specified
17730 // but not both.
17731 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
17732 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
17733 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
17734 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
17735 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
17736 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
17737 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
17738 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
17739 return nullptr;
17740 }
17741 if (Kind == OMPC_SCHEDULE_unknown) {
17742 std::string Values;
17743 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
17744 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
17745 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17747 Exclude);
17748 } else {
17749 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
17750 /*Last=*/OMPC_SCHEDULE_unknown);
17751 }
17752 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17753 << Values << getOpenMPClauseName(OMPC_schedule);
17754 return nullptr;
17755 }
17756 // OpenMP, 2.7.1, Loop Construct, Restrictions
17757 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
17758 // schedule(guided).
17759 // OpenMP 5.0 does not have this restriction.
17760 if (getLangOpts().OpenMP < 50 &&
17761 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
17762 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
17763 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
17764 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
17765 diag::err_omp_schedule_nonmonotonic_static);
17766 return nullptr;
17767 }
17768 Expr *ValExpr = ChunkSize;
17769 Stmt *HelperValStmt = nullptr;
17770 if (ChunkSize) {
17771 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
17772 !ChunkSize->isInstantiationDependent() &&
17773 !ChunkSize->containsUnexpandedParameterPack()) {
17774 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
17775 ExprResult Val =
17776 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
17777 if (Val.isInvalid())
17778 return nullptr;
17779
17780 ValExpr = Val.get();
17781
17782 // OpenMP [2.7.1, Restrictions]
17783 // chunk_size must be a loop invariant integer expression with a positive
17784 // value.
17785 if (std::optional<llvm::APSInt> Result =
17787 if (Result->isSigned() && !Result->isStrictlyPositive()) {
17788 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
17789 << "schedule" << 1 << ChunkSize->getSourceRange();
17790 return nullptr;
17791 }
17793 DSAStack->getCurrentDirective(), OMPC_schedule,
17794 getLangOpts().OpenMP) != OMPD_unknown &&
17796 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17797 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17798 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17799 HelperValStmt = buildPreInits(getASTContext(), Captures);
17800 }
17801 }
17802 }
17803
17804 return new (getASTContext())
17805 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
17806 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
17807}
17808
17810 SourceLocation StartLoc,
17811 SourceLocation EndLoc) {
17812 OMPClause *Res = nullptr;
17813 switch (Kind) {
17814 case OMPC_ordered:
17815 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
17816 break;
17817 case OMPC_nowait:
17818 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
17819 break;
17820 case OMPC_untied:
17821 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
17822 break;
17823 case OMPC_mergeable:
17824 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
17825 break;
17826 case OMPC_read:
17827 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
17828 break;
17829 case OMPC_write:
17830 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
17831 break;
17832 case OMPC_update:
17833 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
17834 break;
17835 case OMPC_capture:
17836 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
17837 break;
17838 case OMPC_compare:
17839 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
17840 break;
17841 case OMPC_fail:
17842 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
17843 break;
17844 case OMPC_seq_cst:
17845 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
17846 break;
17847 case OMPC_acq_rel:
17848 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
17849 break;
17850 case OMPC_acquire:
17851 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
17852 break;
17853 case OMPC_release:
17854 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
17855 break;
17856 case OMPC_relaxed:
17857 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17858 break;
17859 case OMPC_weak:
17860 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
17861 break;
17862 case OMPC_threads:
17863 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17864 break;
17865 case OMPC_simd:
17866 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17867 break;
17868 case OMPC_nogroup:
17869 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17870 break;
17871 case OMPC_unified_address:
17872 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17873 break;
17874 case OMPC_unified_shared_memory:
17875 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17876 break;
17877 case OMPC_reverse_offload:
17878 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17879 break;
17880 case OMPC_dynamic_allocators:
17881 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17882 break;
17883 case OMPC_destroy:
17884 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17885 /*LParenLoc=*/SourceLocation(),
17886 /*VarLoc=*/SourceLocation(), EndLoc);
17887 break;
17888 case OMPC_full:
17889 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17890 break;
17891 case OMPC_partial:
17892 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17893 break;
17894 case OMPC_ompx_bare:
17895 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
17896 break;
17897 case OMPC_if:
17898 case OMPC_final:
17899 case OMPC_num_threads:
17900 case OMPC_safelen:
17901 case OMPC_simdlen:
17902 case OMPC_sizes:
17903 case OMPC_allocator:
17904 case OMPC_collapse:
17905 case OMPC_schedule:
17906 case OMPC_private:
17907 case OMPC_firstprivate:
17908 case OMPC_lastprivate:
17909 case OMPC_shared:
17910 case OMPC_reduction:
17911 case OMPC_task_reduction:
17912 case OMPC_in_reduction:
17913 case OMPC_linear:
17914 case OMPC_aligned:
17915 case OMPC_copyin:
17916 case OMPC_copyprivate:
17917 case OMPC_default:
17918 case OMPC_proc_bind:
17919 case OMPC_threadprivate:
17920 case OMPC_allocate:
17921 case OMPC_flush:
17922 case OMPC_depobj:
17923 case OMPC_depend:
17924 case OMPC_device:
17925 case OMPC_map:
17926 case OMPC_num_teams:
17927 case OMPC_thread_limit:
17928 case OMPC_priority:
17929 case OMPC_grainsize:
17930 case OMPC_num_tasks:
17931 case OMPC_hint:
17932 case OMPC_dist_schedule:
17933 case OMPC_defaultmap:
17934 case OMPC_unknown:
17935 case OMPC_uniform:
17936 case OMPC_to:
17937 case OMPC_from:
17938 case OMPC_use_device_ptr:
17939 case OMPC_use_device_addr:
17940 case OMPC_is_device_ptr:
17941 case OMPC_has_device_addr:
17942 case OMPC_atomic_default_mem_order:
17943 case OMPC_device_type:
17944 case OMPC_match:
17945 case OMPC_nontemporal:
17946 case OMPC_order:
17947 case OMPC_at:
17948 case OMPC_severity:
17949 case OMPC_message:
17950 case OMPC_novariants:
17951 case OMPC_nocontext:
17952 case OMPC_detach:
17953 case OMPC_inclusive:
17954 case OMPC_exclusive:
17955 case OMPC_uses_allocators:
17956 case OMPC_affinity:
17957 case OMPC_when:
17958 case OMPC_ompx_dyn_cgroup_mem:
17959 default:
17960 llvm_unreachable("Clause is not allowed.");
17961 }
17962 return Res;
17963}
17964
17966 SourceLocation EndLoc) {
17967 DSAStack->setNowaitRegion();
17968 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
17969}
17970
17972 SourceLocation EndLoc) {
17973 DSAStack->setUntiedRegion();
17974 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
17975}
17976
17978 SourceLocation EndLoc) {
17979 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
17980}
17981
17983 SourceLocation EndLoc) {
17984 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
17985}
17986
17988 SourceLocation EndLoc) {
17989 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
17990}
17991
17993 SourceLocation EndLoc) {
17994 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
17995}
17996
17998 SourceLocation EndLoc) {
17999 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18000}
18001
18003 SourceLocation EndLoc) {
18004 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18005}
18006
18008 SourceLocation EndLoc) {
18009 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18010}
18011
18013 SourceLocation KindLoc,
18014 SourceLocation StartLoc,
18015 SourceLocation LParenLoc,
18016 SourceLocation EndLoc) {
18017
18019 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18020 return nullptr;
18021 }
18022 return new (getASTContext())
18023 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18024}
18025
18027 SourceLocation EndLoc) {
18028 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18029}
18030
18032 SourceLocation EndLoc) {
18033 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18034}
18035
18037 SourceLocation EndLoc) {
18038 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18039}
18040
18042 SourceLocation EndLoc) {
18043 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18044}
18045
18047 SourceLocation EndLoc) {
18048 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18049}
18050
18052 SourceLocation EndLoc) {
18053 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18054}
18055
18057 SourceLocation EndLoc) {
18058 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18059}
18060
18062 SourceLocation EndLoc) {
18063 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18064}
18065
18067 SourceLocation EndLoc) {
18068 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18069}
18070
18072 SourceLocation EndLoc) {
18073 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18074}
18075
18076OMPClause *
18078 SourceLocation EndLoc) {
18079 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18080}
18081
18083 SourceLocation EndLoc) {
18084 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18085}
18086
18087OMPClause *
18089 SourceLocation EndLoc) {
18090 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18091}
18092
18095 SourceLocation StartLoc,
18096 SourceLocation EndLoc) {
18097
18098 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18099 // At least one action-clause must appear on a directive.
18100 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18101 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18102 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18103 << Expected << getOpenMPDirectiveName(OMPD_interop);
18104 return StmtError();
18105 }
18106
18107 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18108 // A depend clause can only appear on the directive if a targetsync
18109 // interop-type is present or the interop-var was initialized with
18110 // the targetsync interop-type.
18111
18112 // If there is any 'init' clause diagnose if there is no 'init' clause with
18113 // interop-type of 'targetsync'. Cases involving other directives cannot be
18114 // diagnosed.
18115 const OMPDependClause *DependClause = nullptr;
18116 bool HasInitClause = false;
18117 bool IsTargetSync = false;
18118 for (const OMPClause *C : Clauses) {
18119 if (IsTargetSync)
18120 break;
18121 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18122 HasInitClause = true;
18123 if (InitClause->getIsTargetSync())
18124 IsTargetSync = true;
18125 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18126 DependClause = DC;
18127 }
18128 }
18129 if (DependClause && HasInitClause && !IsTargetSync) {
18130 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18131 return StmtError();
18132 }
18133
18134 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18135 // Each interop-var may be specified for at most one action-clause of each
18136 // interop construct.
18138 for (OMPClause *C : Clauses) {
18139 OpenMPClauseKind ClauseKind = C->getClauseKind();
18140 std::pair<ValueDecl *, bool> DeclResult;
18141 SourceLocation ELoc;
18142 SourceRange ERange;
18143
18144 if (ClauseKind == OMPC_init) {
18145 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18146 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18147 } else if (ClauseKind == OMPC_use) {
18148 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18149 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18150 } else if (ClauseKind == OMPC_destroy) {
18151 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18152 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18153 }
18154
18155 if (DeclResult.first) {
18156 if (!InteropVars.insert(DeclResult.first).second) {
18157 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18158 << DeclResult.first;
18159 return StmtError();
18160 }
18161 }
18162 }
18163
18164 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18165 Clauses);
18166}
18167
18168static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18169 SourceLocation VarLoc,
18170 OpenMPClauseKind Kind) {
18171 SourceLocation ELoc;
18172 SourceRange ERange;
18173 Expr *RefExpr = InteropVarExpr;
18174 auto Res =
18175 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18176 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
18177
18178 if (Res.second) {
18179 // It will be analyzed later.
18180 return true;
18181 }
18182
18183 if (!Res.first)
18184 return false;
18185
18186 // Interop variable should be of type omp_interop_t.
18187 bool HasError = false;
18188 QualType InteropType;
18189 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18190 VarLoc, Sema::LookupOrdinaryName);
18191 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18192 NamedDecl *ND = Result.getFoundDecl();
18193 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18194 InteropType = QualType(TD->getTypeForDecl(), 0);
18195 } else {
18196 HasError = true;
18197 }
18198 } else {
18199 HasError = true;
18200 }
18201
18202 if (HasError) {
18203 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18204 << "omp_interop_t";
18205 return false;
18206 }
18207
18208 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18209 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18210 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18211 return false;
18212 }
18213
18214 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18215 // The interop-var passed to init or destroy must be non-const.
18216 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18217 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
18218 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
18219 << /*non-const*/ 1;
18220 return false;
18221 }
18222 return true;
18223}
18224
18226 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
18227 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
18228
18229 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
18230 return nullptr;
18231
18232 // Check prefer_type values. These foreign-runtime-id values are either
18233 // string literals or constant integral expressions.
18234 for (const Expr *E : InteropInfo.PreferTypes) {
18235 if (E->isValueDependent() || E->isTypeDependent() ||
18237 continue;
18239 continue;
18240 if (isa<StringLiteral>(E))
18241 continue;
18242 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18243 return nullptr;
18244 }
18245
18246 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
18247 StartLoc, LParenLoc, VarLoc, EndLoc);
18248}
18249
18251 SourceLocation StartLoc,
18252 SourceLocation LParenLoc,
18253 SourceLocation VarLoc,
18254 SourceLocation EndLoc) {
18255
18256 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
18257 return nullptr;
18258
18259 return new (getASTContext())
18260 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18261}
18262
18264 SourceLocation StartLoc,
18265 SourceLocation LParenLoc,
18266 SourceLocation VarLoc,
18267 SourceLocation EndLoc) {
18268 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
18269 DSAStack->getCurrentDirective() == OMPD_depobj) {
18270 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18271 << getOpenMPClauseName(OMPC_destroy)
18272 << getOpenMPDirectiveName(OMPD_depobj);
18273 return nullptr;
18274 }
18275 if (InteropVar &&
18276 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
18277 return nullptr;
18278
18279 return new (getASTContext())
18280 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18281}
18282
18284 SourceLocation StartLoc,
18285 SourceLocation LParenLoc,
18286 SourceLocation EndLoc) {
18287 Expr *ValExpr = Condition;
18288 Stmt *HelperValStmt = nullptr;
18289 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18290 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18291 !Condition->isInstantiationDependent() &&
18292 !Condition->containsUnexpandedParameterPack()) {
18294 if (Val.isInvalid())
18295 return nullptr;
18296
18297 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18298
18299 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18300 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18301 getLangOpts().OpenMP);
18302 if (CaptureRegion != OMPD_unknown &&
18304 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18305 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18306 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18307 HelperValStmt = buildPreInits(getASTContext(), Captures);
18308 }
18309 }
18310
18311 return new (getASTContext()) OMPNovariantsClause(
18312 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18313}
18314
18316 SourceLocation StartLoc,
18317 SourceLocation LParenLoc,
18318 SourceLocation EndLoc) {
18319 Expr *ValExpr = Condition;
18320 Stmt *HelperValStmt = nullptr;
18321 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18322 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18323 !Condition->isInstantiationDependent() &&
18324 !Condition->containsUnexpandedParameterPack()) {
18326 if (Val.isInvalid())
18327 return nullptr;
18328
18329 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18330
18331 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18332 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
18333 getLangOpts().OpenMP);
18334 if (CaptureRegion != OMPD_unknown &&
18336 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18337 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18338 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18339 HelperValStmt = buildPreInits(getASTContext(), Captures);
18340 }
18341 }
18342
18343 return new (getASTContext()) OMPNocontextClause(
18344 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18345}
18346
18348 SourceLocation StartLoc,
18349 SourceLocation LParenLoc,
18350 SourceLocation EndLoc) {
18351 Expr *ValExpr = ThreadID;
18352 Stmt *HelperValStmt = nullptr;
18353
18354 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18355 OpenMPDirectiveKind CaptureRegion =
18356 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
18357 if (CaptureRegion != OMPD_unknown &&
18359 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18360 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18361 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18362 HelperValStmt = buildPreInits(getASTContext(), Captures);
18363 }
18364
18365 return new (getASTContext()) OMPFilterClause(
18366 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18367}
18368
18370 ArrayRef<Expr *> VarList,
18371 const OMPVarListLocTy &Locs,
18373 SourceLocation StartLoc = Locs.StartLoc;
18374 SourceLocation LParenLoc = Locs.LParenLoc;
18375 SourceLocation EndLoc = Locs.EndLoc;
18376 OMPClause *Res = nullptr;
18377 int ExtraModifier = Data.ExtraModifier;
18378 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18379 SourceLocation ColonLoc = Data.ColonLoc;
18380 switch (Kind) {
18381 case OMPC_private:
18382 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18383 break;
18384 case OMPC_firstprivate:
18385 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18386 break;
18387 case OMPC_lastprivate:
18388 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18389 "Unexpected lastprivate modifier.");
18391 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18392 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18393 break;
18394 case OMPC_shared:
18395 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18396 break;
18397 case OMPC_reduction:
18398 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18399 "Unexpected lastprivate modifier.");
18401 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
18402 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18403 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18404 break;
18405 case OMPC_task_reduction:
18407 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18408 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18409 break;
18410 case OMPC_in_reduction:
18412 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18413 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18414 break;
18415 case OMPC_linear:
18416 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18417 "Unexpected linear modifier.");
18419 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18420 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18421 ColonLoc, Data.StepModifierLoc, EndLoc);
18422 break;
18423 case OMPC_aligned:
18424 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18425 LParenLoc, ColonLoc, EndLoc);
18426 break;
18427 case OMPC_copyin:
18428 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18429 break;
18430 case OMPC_copyprivate:
18431 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18432 break;
18433 case OMPC_flush:
18434 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18435 break;
18436 case OMPC_depend:
18437 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18438 "Unexpected depend modifier.");
18440 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18441 ColonLoc, Data.OmpAllMemoryLoc},
18442 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18443 break;
18444 case OMPC_map:
18445 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18446 "Unexpected map modifier.");
18448 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18449 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18450 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18451 ExtraModifierLoc, ColonLoc, VarList, Locs);
18452 break;
18453 case OMPC_to:
18454 Res =
18455 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18456 Data.ReductionOrMapperIdScopeSpec,
18457 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
18458 break;
18459 case OMPC_from:
18460 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
18461 Data.ReductionOrMapperIdScopeSpec,
18462 Data.ReductionOrMapperId, ColonLoc, VarList,
18463 Locs);
18464 break;
18465 case OMPC_use_device_ptr:
18466 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
18467 break;
18468 case OMPC_use_device_addr:
18469 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18470 break;
18471 case OMPC_is_device_ptr:
18472 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18473 break;
18474 case OMPC_has_device_addr:
18475 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18476 break;
18477 case OMPC_allocate:
18478 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
18479 LParenLoc, ColonLoc, EndLoc);
18480 break;
18481 case OMPC_nontemporal:
18482 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18483 break;
18484 case OMPC_inclusive:
18485 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18486 break;
18487 case OMPC_exclusive:
18488 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18489 break;
18490 case OMPC_affinity:
18491 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18492 Data.DepModOrTailExpr, VarList);
18493 break;
18494 case OMPC_doacross:
18496 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18497 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18498 break;
18499 case OMPC_if:
18500 case OMPC_depobj:
18501 case OMPC_final:
18502 case OMPC_num_threads:
18503 case OMPC_safelen:
18504 case OMPC_simdlen:
18505 case OMPC_sizes:
18506 case OMPC_allocator:
18507 case OMPC_collapse:
18508 case OMPC_default:
18509 case OMPC_proc_bind:
18510 case OMPC_schedule:
18511 case OMPC_ordered:
18512 case OMPC_nowait:
18513 case OMPC_untied:
18514 case OMPC_mergeable:
18515 case OMPC_threadprivate:
18516 case OMPC_read:
18517 case OMPC_write:
18518 case OMPC_update:
18519 case OMPC_capture:
18520 case OMPC_compare:
18521 case OMPC_seq_cst:
18522 case OMPC_acq_rel:
18523 case OMPC_acquire:
18524 case OMPC_release:
18525 case OMPC_relaxed:
18526 case OMPC_device:
18527 case OMPC_threads:
18528 case OMPC_simd:
18529 case OMPC_num_teams:
18530 case OMPC_thread_limit:
18531 case OMPC_priority:
18532 case OMPC_grainsize:
18533 case OMPC_nogroup:
18534 case OMPC_num_tasks:
18535 case OMPC_hint:
18536 case OMPC_dist_schedule:
18537 case OMPC_defaultmap:
18538 case OMPC_unknown:
18539 case OMPC_uniform:
18540 case OMPC_unified_address:
18541 case OMPC_unified_shared_memory:
18542 case OMPC_reverse_offload:
18543 case OMPC_dynamic_allocators:
18544 case OMPC_atomic_default_mem_order:
18545 case OMPC_device_type:
18546 case OMPC_match:
18547 case OMPC_order:
18548 case OMPC_at:
18549 case OMPC_severity:
18550 case OMPC_message:
18551 case OMPC_destroy:
18552 case OMPC_novariants:
18553 case OMPC_nocontext:
18554 case OMPC_detach:
18555 case OMPC_uses_allocators:
18556 case OMPC_when:
18557 case OMPC_bind:
18558 default:
18559 llvm_unreachable("Clause is not allowed.");
18560 }
18561 return Res;
18562}
18563
18565 ExprObjectKind OK,
18568 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
18569 if (!Res.isUsable())
18570 return ExprError();
18571 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
18572 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
18573 if (!Res.isUsable())
18574 return ExprError();
18575 }
18576 if (VK != VK_LValue && Res.get()->isGLValue()) {
18577 Res = SemaRef.DefaultLvalueConversion(Res.get());
18578 if (!Res.isUsable())
18579 return ExprError();
18580 }
18581 return Res;
18582}
18583
18585 SourceLocation StartLoc,
18586 SourceLocation LParenLoc,
18587 SourceLocation EndLoc) {
18589 SmallVector<Expr *, 8> PrivateCopies;
18590 bool IsImplicitClause =
18591 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18592 for (Expr *RefExpr : VarList) {
18593 assert(RefExpr && "NULL expr in OpenMP private clause.");
18594 SourceLocation ELoc;
18595 SourceRange ERange;
18596 Expr *SimpleRefExpr = RefExpr;
18597 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18598 if (Res.second) {
18599 // It will be analyzed later.
18600 Vars.push_back(RefExpr);
18601 PrivateCopies.push_back(nullptr);
18602 }
18603 ValueDecl *D = Res.first;
18604 if (!D)
18605 continue;
18606
18607 QualType Type = D->getType();
18608 auto *VD = dyn_cast<VarDecl>(D);
18609
18610 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18611 // A variable that appears in a private clause must not have an incomplete
18612 // type or a reference type.
18614 diag::err_omp_private_incomplete_type))
18615 continue;
18616 Type = Type.getNonReferenceType();
18617
18618 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18619 // A variable that is privatized must not have a const-qualified type
18620 // unless it is of class type with a mutable member. This restriction does
18621 // not apply to the firstprivate clause.
18622 //
18623 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
18624 // A variable that appears in a private clause must not have a
18625 // const-qualified type unless it is of class type with a mutable member.
18626 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
18627 continue;
18628
18629 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18630 // in a Construct]
18631 // Variables with the predetermined data-sharing attributes may not be
18632 // listed in data-sharing attributes clauses, except for the cases
18633 // listed below. For these exceptions only, listing a predetermined
18634 // variable in a data-sharing attribute clause is allowed and overrides
18635 // the variable's predetermined data-sharing attributes.
18636 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18637 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
18638 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
18639 << getOpenMPClauseName(OMPC_private);
18641 continue;
18642 }
18643
18644 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18645 // Variably modified types are not supported for tasks.
18647 isOpenMPTaskingDirective(CurrDir)) {
18648 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18649 << getOpenMPClauseName(OMPC_private) << Type
18650 << getOpenMPDirectiveName(CurrDir);
18651 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18653 Diag(D->getLocation(),
18654 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18655 << D;
18656 continue;
18657 }
18658
18659 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18660 // A list item cannot appear in both a map clause and a data-sharing
18661 // attribute clause on the same construct
18662 //
18663 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18664 // A list item cannot appear in both a map clause and a data-sharing
18665 // attribute clause on the same construct unless the construct is a
18666 // combined construct.
18667 if ((getLangOpts().OpenMP <= 45 &&
18669 CurrDir == OMPD_target) {
18670 OpenMPClauseKind ConflictKind;
18671 if (DSAStack->checkMappableExprComponentListsForDecl(
18672 VD, /*CurrentRegionOnly=*/true,
18674 OpenMPClauseKind WhereFoundClauseKind) -> bool {
18675 ConflictKind = WhereFoundClauseKind;
18676 return true;
18677 })) {
18678 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18679 << getOpenMPClauseName(OMPC_private)
18680 << getOpenMPClauseName(ConflictKind)
18681 << getOpenMPDirectiveName(CurrDir);
18683 continue;
18684 }
18685 }
18686
18687 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
18688 // A variable of class type (or array thereof) that appears in a private
18689 // clause requires an accessible, unambiguous default constructor for the
18690 // class type.
18691 // Generate helper private variable and initialize it with the default
18692 // value. The address of the original variable is replaced by the address of
18693 // the new private variable in CodeGen. This new variable is not added to
18694 // IdResolver, so the code in the OpenMP region uses original variable for
18695 // proper diagnostics.
18696 Type = Type.getUnqualifiedType();
18697 VarDecl *VDPrivate =
18698 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18699 D->hasAttrs() ? &D->getAttrs() : nullptr,
18700 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18702 if (VDPrivate->isInvalidDecl())
18703 continue;
18704 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18705 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
18706
18707 DeclRefExpr *Ref = nullptr;
18708 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18709 auto *FD = dyn_cast<FieldDecl>(D);
18710 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18711 if (VD)
18713 RefExpr->getExprLoc());
18714 else
18715 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
18716 }
18717 if (!IsImplicitClause)
18718 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
18719 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18720 ? RefExpr->IgnoreParens()
18721 : Ref);
18722 PrivateCopies.push_back(VDPrivateRefExpr);
18723 }
18724
18725 if (Vars.empty())
18726 return nullptr;
18727
18728 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18729 Vars, PrivateCopies);
18730}
18731
18733 SourceLocation StartLoc,
18734 SourceLocation LParenLoc,
18735 SourceLocation EndLoc) {
18737 SmallVector<Expr *, 8> PrivateCopies;
18739 SmallVector<Decl *, 4> ExprCaptures;
18740 bool IsImplicitClause =
18741 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
18742 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
18743
18744 for (Expr *RefExpr : VarList) {
18745 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
18746 SourceLocation ELoc;
18747 SourceRange ERange;
18748 Expr *SimpleRefExpr = RefExpr;
18749 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18750 if (Res.second) {
18751 // It will be analyzed later.
18752 Vars.push_back(RefExpr);
18753 PrivateCopies.push_back(nullptr);
18754 Inits.push_back(nullptr);
18755 }
18756 ValueDecl *D = Res.first;
18757 if (!D)
18758 continue;
18759
18760 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
18761 QualType Type = D->getType();
18762 auto *VD = dyn_cast<VarDecl>(D);
18763
18764 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18765 // A variable that appears in a private clause must not have an incomplete
18766 // type or a reference type.
18768 diag::err_omp_firstprivate_incomplete_type))
18769 continue;
18770 Type = Type.getNonReferenceType();
18771
18772 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
18773 // A variable of class type (or array thereof) that appears in a private
18774 // clause requires an accessible, unambiguous copy constructor for the
18775 // class type.
18776 QualType ElemType =
18778
18779 // If an implicit firstprivate variable found it was checked already.
18780 DSAStackTy::DSAVarData TopDVar;
18781 if (!IsImplicitClause) {
18782 DSAStackTy::DSAVarData DVar =
18783 DSAStack->getTopDSA(D, /*FromParent=*/false);
18784 TopDVar = DVar;
18785 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18786 bool IsConstant = ElemType.isConstant(getASTContext());
18787 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
18788 // A list item that specifies a given variable may not appear in more
18789 // than one clause on the same directive, except that a variable may be
18790 // specified in both firstprivate and lastprivate clauses.
18791 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18792 // A list item may appear in a firstprivate or lastprivate clause but not
18793 // both.
18794 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
18795 (isOpenMPDistributeDirective(CurrDir) ||
18796 DVar.CKind != OMPC_lastprivate) &&
18797 DVar.RefExpr) {
18798 Diag(ELoc, diag::err_omp_wrong_dsa)
18799 << getOpenMPClauseName(DVar.CKind)
18800 << getOpenMPClauseName(OMPC_firstprivate);
18802 continue;
18803 }
18804
18805 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18806 // in a Construct]
18807 // Variables with the predetermined data-sharing attributes may not be
18808 // listed in data-sharing attributes clauses, except for the cases
18809 // listed below. For these exceptions only, listing a predetermined
18810 // variable in a data-sharing attribute clause is allowed and overrides
18811 // the variable's predetermined data-sharing attributes.
18812 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18813 // in a Construct, C/C++, p.2]
18814 // Variables with const-qualified type having no mutable member may be
18815 // listed in a firstprivate clause, even if they are static data members.
18816 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
18817 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
18818 Diag(ELoc, diag::err_omp_wrong_dsa)
18819 << getOpenMPClauseName(DVar.CKind)
18820 << getOpenMPClauseName(OMPC_firstprivate);
18822 continue;
18823 }
18824
18825 // OpenMP [2.9.3.4, Restrictions, p.2]
18826 // A list item that is private within a parallel region must not appear
18827 // in a firstprivate clause on a worksharing construct if any of the
18828 // worksharing regions arising from the worksharing construct ever bind
18829 // to any of the parallel regions arising from the parallel construct.
18830 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18831 // A list item that is private within a teams region must not appear in a
18832 // firstprivate clause on a distribute construct if any of the distribute
18833 // regions arising from the distribute construct ever bind to any of the
18834 // teams regions arising from the teams construct.
18835 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18836 // A list item that appears in a reduction clause of a teams construct
18837 // must not appear in a firstprivate clause on a distribute construct if
18838 // any of the distribute regions arising from the distribute construct
18839 // ever bind to any of the teams regions arising from the teams construct.
18840 if ((isOpenMPWorksharingDirective(CurrDir) ||
18841 isOpenMPDistributeDirective(CurrDir)) &&
18842 !isOpenMPParallelDirective(CurrDir) &&
18843 !isOpenMPTeamsDirective(CurrDir)) {
18844 DVar = DSAStack->getImplicitDSA(D, true);
18845 if (DVar.CKind != OMPC_shared &&
18846 (isOpenMPParallelDirective(DVar.DKind) ||
18847 isOpenMPTeamsDirective(DVar.DKind) ||
18848 DVar.DKind == OMPD_unknown)) {
18849 Diag(ELoc, diag::err_omp_required_access)
18850 << getOpenMPClauseName(OMPC_firstprivate)
18851 << getOpenMPClauseName(OMPC_shared);
18853 continue;
18854 }
18855 }
18856 // OpenMP [2.9.3.4, Restrictions, p.3]
18857 // A list item that appears in a reduction clause of a parallel construct
18858 // must not appear in a firstprivate clause on a worksharing or task
18859 // construct if any of the worksharing or task regions arising from the
18860 // worksharing or task construct ever bind to any of the parallel regions
18861 // arising from the parallel construct.
18862 // OpenMP [2.9.3.4, Restrictions, p.4]
18863 // A list item that appears in a reduction clause in worksharing
18864 // construct must not appear in a firstprivate clause in a task construct
18865 // encountered during execution of any of the worksharing regions arising
18866 // from the worksharing construct.
18867 if (isOpenMPTaskingDirective(CurrDir)) {
18868 DVar = DSAStack->hasInnermostDSA(
18869 D,
18870 [](OpenMPClauseKind C, bool AppliedToPointee) {
18871 return C == OMPC_reduction && !AppliedToPointee;
18872 },
18873 [](OpenMPDirectiveKind K) {
18874 return isOpenMPParallelDirective(K) ||
18877 },
18878 /*FromParent=*/true);
18879 if (DVar.CKind == OMPC_reduction &&
18880 (isOpenMPParallelDirective(DVar.DKind) ||
18881 isOpenMPWorksharingDirective(DVar.DKind) ||
18882 isOpenMPTeamsDirective(DVar.DKind))) {
18883 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18884 << getOpenMPDirectiveName(DVar.DKind);
18886 continue;
18887 }
18888 }
18889
18890 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18891 // A list item cannot appear in both a map clause and a data-sharing
18892 // attribute clause on the same construct
18893 //
18894 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18895 // A list item cannot appear in both a map clause and a data-sharing
18896 // attribute clause on the same construct unless the construct is a
18897 // combined construct.
18898 if ((getLangOpts().OpenMP <= 45 &&
18900 CurrDir == OMPD_target) {
18901 OpenMPClauseKind ConflictKind;
18902 if (DSAStack->checkMappableExprComponentListsForDecl(
18903 VD, /*CurrentRegionOnly=*/true,
18904 [&ConflictKind](
18906 OpenMPClauseKind WhereFoundClauseKind) {
18907 ConflictKind = WhereFoundClauseKind;
18908 return true;
18909 })) {
18910 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18911 << getOpenMPClauseName(OMPC_firstprivate)
18912 << getOpenMPClauseName(ConflictKind)
18913 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18915 continue;
18916 }
18917 }
18918 }
18919
18920 // Variably modified types are not supported for tasks.
18922 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18923 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18924 << getOpenMPClauseName(OMPC_firstprivate) << Type
18925 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
18926 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18928 Diag(D->getLocation(),
18929 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18930 << D;
18931 continue;
18932 }
18933
18934 Type = Type.getUnqualifiedType();
18935 VarDecl *VDPrivate =
18936 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18937 D->hasAttrs() ? &D->getAttrs() : nullptr,
18938 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18939 // Generate helper private variable and initialize it with the value of the
18940 // original variable. The address of the original variable is replaced by
18941 // the address of the new private variable in the CodeGen. This new variable
18942 // is not added to IdResolver, so the code in the OpenMP region uses
18943 // original variable for proper diagnostics and variable capturing.
18944 Expr *VDInitRefExpr = nullptr;
18945 // For arrays generate initializer for single element and replace it by the
18946 // original array element in CodeGen.
18947 if (Type->isArrayType()) {
18948 VarDecl *VDInit =
18949 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
18950 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
18951 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
18952 ElemType = ElemType.getUnqualifiedType();
18953 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
18954 ElemType, ".firstprivate.temp");
18955 InitializedEntity Entity =
18958
18959 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
18960 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
18961 if (Result.isInvalid())
18962 VDPrivate->setInvalidDecl();
18963 else
18964 VDPrivate->setInit(Result.getAs<Expr>());
18965 // Remove temp variable declaration.
18966 getASTContext().Deallocate(VDInitTemp);
18967 } else {
18968 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
18969 ".firstprivate.temp");
18970 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
18971 RefExpr->getExprLoc());
18973 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
18974 /*DirectInit=*/false);
18975 }
18976 if (VDPrivate->isInvalidDecl()) {
18977 if (IsImplicitClause) {
18978 Diag(RefExpr->getExprLoc(),
18979 diag::note_omp_task_predetermined_firstprivate_here);
18980 }
18981 continue;
18982 }
18983 SemaRef.CurContext->addDecl(VDPrivate);
18984 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18985 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18986 RefExpr->getExprLoc());
18987 DeclRefExpr *Ref = nullptr;
18988 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18989 if (TopDVar.CKind == OMPC_lastprivate) {
18990 Ref = TopDVar.PrivateCopy;
18991 } else {
18992 auto *FD = dyn_cast<FieldDecl>(D);
18993 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18994 if (VD)
18995 Ref =
18997 RefExpr->getExprLoc());
18998 else
18999 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19000 if (VD || !isOpenMPCapturedDecl(D))
19001 ExprCaptures.push_back(Ref->getDecl());
19002 }
19003 }
19004 if (!IsImplicitClause)
19005 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19006 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19007 ? RefExpr->IgnoreParens()
19008 : Ref);
19009 PrivateCopies.push_back(VDPrivateRefExpr);
19010 Inits.push_back(VDInitRefExpr);
19011 }
19012
19013 if (Vars.empty())
19014 return nullptr;
19015
19017 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19018 buildPreInits(getASTContext(), ExprCaptures));
19019}
19020
19023 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19024 SourceLocation LParenLoc, SourceLocation EndLoc) {
19025 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19026 assert(ColonLoc.isValid() && "Colon location must be valid.");
19027 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19028 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
19029 /*Last=*/OMPC_LASTPRIVATE_unknown)
19030 << getOpenMPClauseName(OMPC_lastprivate);
19031 return nullptr;
19032 }
19033
19035 SmallVector<Expr *, 8> SrcExprs;
19036 SmallVector<Expr *, 8> DstExprs;
19037 SmallVector<Expr *, 8> AssignmentOps;
19038 SmallVector<Decl *, 4> ExprCaptures;
19039 SmallVector<Expr *, 4> ExprPostUpdates;
19040 for (Expr *RefExpr : VarList) {
19041 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19042 SourceLocation ELoc;
19043 SourceRange ERange;
19044 Expr *SimpleRefExpr = RefExpr;
19045 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19046 if (Res.second) {
19047 // It will be analyzed later.
19048 Vars.push_back(RefExpr);
19049 SrcExprs.push_back(nullptr);
19050 DstExprs.push_back(nullptr);
19051 AssignmentOps.push_back(nullptr);
19052 }
19053 ValueDecl *D = Res.first;
19054 if (!D)
19055 continue;
19056
19057 QualType Type = D->getType();
19058 auto *VD = dyn_cast<VarDecl>(D);
19059
19060 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19061 // A variable that appears in a lastprivate clause must not have an
19062 // incomplete type or a reference type.
19064 diag::err_omp_lastprivate_incomplete_type))
19065 continue;
19066 Type = Type.getNonReferenceType();
19067
19068 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19069 // A variable that is privatized must not have a const-qualified type
19070 // unless it is of class type with a mutable member. This restriction does
19071 // not apply to the firstprivate clause.
19072 //
19073 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19074 // A variable that appears in a lastprivate clause must not have a
19075 // const-qualified type unless it is of class type with a mutable member.
19076 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
19077 continue;
19078
19079 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19080 // A list item that appears in a lastprivate clause with the conditional
19081 // modifier must be a scalar variable.
19082 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19083 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19084 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19086 Diag(D->getLocation(),
19087 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19088 << D;
19089 continue;
19090 }
19091
19092 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19093 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19094 // in a Construct]
19095 // Variables with the predetermined data-sharing attributes may not be
19096 // listed in data-sharing attributes clauses, except for the cases
19097 // listed below.
19098 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19099 // A list item may appear in a firstprivate or lastprivate clause but not
19100 // both.
19101 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19102 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19103 (isOpenMPDistributeDirective(CurrDir) ||
19104 DVar.CKind != OMPC_firstprivate) &&
19105 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19106 Diag(ELoc, diag::err_omp_wrong_dsa)
19107 << getOpenMPClauseName(DVar.CKind)
19108 << getOpenMPClauseName(OMPC_lastprivate);
19110 continue;
19111 }
19112
19113 // OpenMP [2.14.3.5, Restrictions, p.2]
19114 // A list item that is private within a parallel region, or that appears in
19115 // the reduction clause of a parallel construct, must not appear in a
19116 // lastprivate clause on a worksharing construct if any of the corresponding
19117 // worksharing regions ever binds to any of the corresponding parallel
19118 // regions.
19119 DSAStackTy::DSAVarData TopDVar = DVar;
19120 if (isOpenMPWorksharingDirective(CurrDir) &&
19121 !isOpenMPParallelDirective(CurrDir) &&
19122 !isOpenMPTeamsDirective(CurrDir)) {
19123 DVar = DSAStack->getImplicitDSA(D, true);
19124 if (DVar.CKind != OMPC_shared) {
19125 Diag(ELoc, diag::err_omp_required_access)
19126 << getOpenMPClauseName(OMPC_lastprivate)
19127 << getOpenMPClauseName(OMPC_shared);
19129 continue;
19130 }
19131 }
19132
19133 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19134 // A variable of class type (or array thereof) that appears in a
19135 // lastprivate clause requires an accessible, unambiguous default
19136 // constructor for the class type, unless the list item is also specified
19137 // in a firstprivate clause.
19138 // A variable of class type (or array thereof) that appears in a
19139 // lastprivate clause requires an accessible, unambiguous copy assignment
19140 // operator for the class type.
19142 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19143 Type.getUnqualifiedType(), ".lastprivate.src",
19144 D->hasAttrs() ? &D->getAttrs() : nullptr);
19145 DeclRefExpr *PseudoSrcExpr =
19146 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19147 VarDecl *DstVD =
19148 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
19149 D->hasAttrs() ? &D->getAttrs() : nullptr);
19150 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19151 // For arrays generate assignment operation for single element and replace
19152 // it by the original array element in CodeGen.
19153 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
19154 PseudoDstExpr, PseudoSrcExpr);
19155 if (AssignmentOp.isInvalid())
19156 continue;
19157 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19158 /*DiscardedValue*/ false);
19159 if (AssignmentOp.isInvalid())
19160 continue;
19161
19162 DeclRefExpr *Ref = nullptr;
19163 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19164 if (TopDVar.CKind == OMPC_firstprivate) {
19165 Ref = TopDVar.PrivateCopy;
19166 } else {
19167 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19168 if (!isOpenMPCapturedDecl(D))
19169 ExprCaptures.push_back(Ref->getDecl());
19170 }
19171 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19172 (!isOpenMPCapturedDecl(D) &&
19173 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
19175 if (!RefRes.isUsable())
19176 continue;
19177 ExprResult PostUpdateRes =
19178 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19179 SimpleRefExpr, RefRes.get());
19180 if (!PostUpdateRes.isUsable())
19181 continue;
19182 ExprPostUpdates.push_back(
19183 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19184 }
19185 }
19186 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19187 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19188 ? RefExpr->IgnoreParens()
19189 : Ref);
19190 SrcExprs.push_back(PseudoSrcExpr);
19191 DstExprs.push_back(PseudoDstExpr);
19192 AssignmentOps.push_back(AssignmentOp.get());
19193 }
19194
19195 if (Vars.empty())
19196 return nullptr;
19197
19199 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19200 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19201 buildPreInits(getASTContext(), ExprCaptures),
19202 buildPostUpdate(SemaRef, ExprPostUpdates));
19203}
19204
19206 SourceLocation StartLoc,
19207 SourceLocation LParenLoc,
19208 SourceLocation EndLoc) {
19210 for (Expr *RefExpr : VarList) {
19211 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19212 SourceLocation ELoc;
19213 SourceRange ERange;
19214 Expr *SimpleRefExpr = RefExpr;
19215 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19216 if (Res.second) {
19217 // It will be analyzed later.
19218 Vars.push_back(RefExpr);
19219 }
19220 ValueDecl *D = Res.first;
19221 if (!D)
19222 continue;
19223
19224 auto *VD = dyn_cast<VarDecl>(D);
19225 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19226 // in a Construct]
19227 // Variables with the predetermined data-sharing attributes may not be
19228 // listed in data-sharing attributes clauses, except for the cases
19229 // listed below. For these exceptions only, listing a predetermined
19230 // variable in a data-sharing attribute clause is allowed and overrides
19231 // the variable's predetermined data-sharing attributes.
19232 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19233 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19234 DVar.RefExpr) {
19235 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19236 << getOpenMPClauseName(OMPC_shared);
19238 continue;
19239 }
19240
19241 DeclRefExpr *Ref = nullptr;
19242 if (!VD && isOpenMPCapturedDecl(D) &&
19244 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19245 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19246 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
19247 ? RefExpr->IgnoreParens()
19248 : Ref);
19249 }
19250
19251 if (Vars.empty())
19252 return nullptr;
19253
19254 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19255 Vars);
19256}
19257
19258namespace {
19259class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19260 DSAStackTy *Stack;
19261
19262public:
19263 bool VisitDeclRefExpr(DeclRefExpr *E) {
19264 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19265 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19266 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19267 return false;
19268 if (DVar.CKind != OMPC_unknown)
19269 return true;
19270 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19271 VD,
19272 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19273 return isOpenMPPrivate(C) && !AppliedToPointee;
19274 },
19275 [](OpenMPDirectiveKind) { return true; },
19276 /*FromParent=*/true);
19277 return DVarPrivate.CKind != OMPC_unknown;
19278 }
19279 return false;
19280 }
19281 bool VisitStmt(Stmt *S) {
19282 for (Stmt *Child : S->children()) {
19283 if (Child && Visit(Child))
19284 return true;
19285 }
19286 return false;
19287 }
19288 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19289};
19290} // namespace
19291
19292namespace {
19293// Transform MemberExpression for specified FieldDecl of current class to
19294// DeclRefExpr to specified OMPCapturedExprDecl.
19295class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19296 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19297 ValueDecl *Field = nullptr;
19298 DeclRefExpr *CapturedExpr = nullptr;
19299
19300public:
19301 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19302 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19303
19304 ExprResult TransformMemberExpr(MemberExpr *E) {
19305 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
19306 E->getMemberDecl() == Field) {
19307 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19308 return CapturedExpr;
19309 }
19310 return BaseTransform::TransformMemberExpr(E);
19311 }
19312 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19313};
19314} // namespace
19315
19316template <typename T, typename U>
19318 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19319 for (U &Set : Lookups) {
19320 for (auto *D : Set) {
19321 if (T Res = Gen(cast<ValueDecl>(D)))
19322 return Res;
19323 }
19324 }
19325 return T();
19326}
19327
19329 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19330
19331 for (auto *RD : D->redecls()) {
19332 // Don't bother with extra checks if we already know this one isn't visible.
19333 if (RD == D)
19334 continue;
19335
19336 auto ND = cast<NamedDecl>(RD);
19337 if (LookupResult::isVisible(SemaRef, ND))
19338 return ND;
19339 }
19340
19341 return nullptr;
19342}
19343
19344static void
19348 // Find all of the associated namespaces and classes based on the
19349 // arguments we have.
19350 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19351 Sema::AssociatedClassSet AssociatedClasses;
19352 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19353 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19354 AssociatedClasses);
19355
19356 // C++ [basic.lookup.argdep]p3:
19357 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19358 // and let Y be the lookup set produced by argument dependent
19359 // lookup (defined as follows). If X contains [...] then Y is
19360 // empty. Otherwise Y is the set of declarations found in the
19361 // namespaces associated with the argument types as described
19362 // below. The set of declarations found by the lookup of the name
19363 // is the union of X and Y.
19364 //
19365 // Here, we compute Y and add its members to the overloaded
19366 // candidate set.
19367 for (auto *NS : AssociatedNamespaces) {
19368 // When considering an associated namespace, the lookup is the
19369 // same as the lookup performed when the associated namespace is
19370 // used as a qualifier (3.4.3.2) except that:
19371 //
19372 // -- Any using-directives in the associated namespace are
19373 // ignored.
19374 //
19375 // -- Any namespace-scope friend functions declared in
19376 // associated classes are visible within their respective
19377 // namespaces even if they are not visible during an ordinary
19378 // lookup (11.4).
19379 DeclContext::lookup_result R = NS->lookup(Id.getName());
19380 for (auto *D : R) {
19381 auto *Underlying = D;
19382 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19383 Underlying = USD->getTargetDecl();
19384
19385 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19386 !isa<OMPDeclareMapperDecl>(Underlying))
19387 continue;
19388
19389 if (!SemaRef.isVisible(D)) {
19390 D = findAcceptableDecl(SemaRef, D);
19391 if (!D)
19392 continue;
19393 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19394 Underlying = USD->getTargetDecl();
19395 }
19396 Lookups.emplace_back();
19397 Lookups.back().addDecl(Underlying);
19398 }
19399 }
19400}
19401
19402static ExprResult
19404 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19405 const DeclarationNameInfo &ReductionId, QualType Ty,
19406 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19407 if (ReductionIdScopeSpec.isInvalid())
19408 return ExprError();
19409 SmallVector<UnresolvedSet<8>, 4> Lookups;
19410 if (S) {
19411 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19412 Lookup.suppressDiagnostics();
19413 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
19414 /*ObjectType=*/QualType())) {
19415 NamedDecl *D = Lookup.getRepresentativeDecl();
19416 do {
19417 S = S->getParent();
19418 } while (S && !S->isDeclScope(D));
19419 if (S)
19420 S = S->getParent();
19421 Lookups.emplace_back();
19422 Lookups.back().append(Lookup.begin(), Lookup.end());
19423 Lookup.clear();
19424 }
19425 } else if (auto *ULE =
19426 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19427 Lookups.push_back(UnresolvedSet<8>());
19428 Decl *PrevD = nullptr;
19429 for (NamedDecl *D : ULE->decls()) {
19430 if (D == PrevD)
19431 Lookups.push_back(UnresolvedSet<8>());
19432 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19433 Lookups.back().addDecl(DRD);
19434 PrevD = D;
19435 }
19436 }
19437 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19440 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
19441 return !D->isInvalidDecl() &&
19442 (D->getType()->isDependentType() ||
19443 D->getType()->isInstantiationDependentType() ||
19444 D->getType()->containsUnexpandedParameterPack());
19445 })) {
19446 UnresolvedSet<8> ResSet;
19447 for (const UnresolvedSet<8> &Set : Lookups) {
19448 if (Set.empty())
19449 continue;
19450 ResSet.append(Set.begin(), Set.end());
19451 // The last item marks the end of all declarations at the specified scope.
19452 ResSet.addDecl(Set[Set.size() - 1]);
19453 }
19455 SemaRef.Context, /*NamingClass=*/nullptr,
19456 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19457 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false);
19458 }
19459 // Lookup inside the classes.
19460 // C++ [over.match.oper]p3:
19461 // For a unary operator @ with an operand of a type whose
19462 // cv-unqualified version is T1, and for a binary operator @ with
19463 // a left operand of a type whose cv-unqualified version is T1 and
19464 // a right operand of a type whose cv-unqualified version is T2,
19465 // three sets of candidate functions, designated member
19466 // candidates, non-member candidates and built-in candidates, are
19467 // constructed as follows:
19468 // -- If T1 is a complete class type or a class currently being
19469 // defined, the set of member candidates is the result of the
19470 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19471 // the set of member candidates is empty.
19472 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19473 Lookup.suppressDiagnostics();
19474 if (const auto *TyRec = Ty->getAs<RecordType>()) {
19475 // Complete the type if it can be completed.
19476 // If the type is neither complete nor being defined, bail out now.
19477 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
19478 TyRec->getDecl()->getDefinition()) {
19479 Lookup.clear();
19480 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
19481 if (Lookup.empty()) {
19482 Lookups.emplace_back();
19483 Lookups.back().append(Lookup.begin(), Lookup.end());
19484 }
19485 }
19486 }
19487 // Perform ADL.
19488 if (SemaRef.getLangOpts().CPlusPlus)
19489 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19490 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19491 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19492 if (!D->isInvalidDecl() &&
19493 SemaRef.Context.hasSameType(D->getType(), Ty))
19494 return D;
19495 return nullptr;
19496 }))
19497 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19498 VK_LValue, Loc);
19499 if (SemaRef.getLangOpts().CPlusPlus) {
19500 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
19501 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19502 if (!D->isInvalidDecl() &&
19503 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19504 !Ty.isMoreQualifiedThan(D->getType()))
19505 return D;
19506 return nullptr;
19507 })) {
19508 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19509 /*DetectVirtual=*/false);
19510 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19511 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19512 VD->getType().getUnqualifiedType()))) {
19513 if (SemaRef.CheckBaseClassAccess(
19514 Loc, VD->getType(), Ty, Paths.front(),
19515 /*DiagID=*/0) != Sema::AR_inaccessible) {
19516 SemaRef.BuildBasePathArray(Paths, BasePath);
19517 return SemaRef.BuildDeclRefExpr(
19519 }
19520 }
19521 }
19522 }
19523 }
19524 if (ReductionIdScopeSpec.isSet()) {
19525 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19526 << Ty << Range;
19527 return ExprError();
19528 }
19529 return ExprEmpty();
19530}
19531
19532namespace {
19533/// Data for the reduction-based clauses.
19534struct ReductionData {
19535 /// List of original reduction items.
19537 /// List of private copies of the reduction items.
19538 SmallVector<Expr *, 8> Privates;
19539 /// LHS expressions for the reduction_op expressions.
19541 /// RHS expressions for the reduction_op expressions.
19543 /// Reduction operation expression.
19544 SmallVector<Expr *, 8> ReductionOps;
19545 /// inscan copy operation expressions.
19546 SmallVector<Expr *, 8> InscanCopyOps;
19547 /// inscan copy temp array expressions for prefix sums.
19548 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19549 /// inscan copy temp array element expressions for prefix sums.
19550 SmallVector<Expr *, 8> InscanCopyArrayElems;
19551 /// Taskgroup descriptors for the corresponding reduction items in
19552 /// in_reduction clauses.
19553 SmallVector<Expr *, 8> TaskgroupDescriptors;
19554 /// List of captures for clause.
19555 SmallVector<Decl *, 4> ExprCaptures;
19556 /// List of postupdate expressions.
19557 SmallVector<Expr *, 4> ExprPostUpdates;
19558 /// Reduction modifier.
19559 unsigned RedModifier = 0;
19560 ReductionData() = delete;
19561 /// Reserves required memory for the reduction data.
19562 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
19563 Vars.reserve(Size);
19564 Privates.reserve(Size);
19565 LHSs.reserve(Size);
19566 RHSs.reserve(Size);
19567 ReductionOps.reserve(Size);
19568 if (RedModifier == OMPC_REDUCTION_inscan) {
19569 InscanCopyOps.reserve(Size);
19570 InscanCopyArrayTemps.reserve(Size);
19571 InscanCopyArrayElems.reserve(Size);
19572 }
19573 TaskgroupDescriptors.reserve(Size);
19574 ExprCaptures.reserve(Size);
19575 ExprPostUpdates.reserve(Size);
19576 }
19577 /// Stores reduction item and reduction operation only (required for dependent
19578 /// reduction item).
19579 void push(Expr *Item, Expr *ReductionOp) {
19580 Vars.emplace_back(Item);
19581 Privates.emplace_back(nullptr);
19582 LHSs.emplace_back(nullptr);
19583 RHSs.emplace_back(nullptr);
19584 ReductionOps.emplace_back(ReductionOp);
19585 TaskgroupDescriptors.emplace_back(nullptr);
19586 if (RedModifier == OMPC_REDUCTION_inscan) {
19587 InscanCopyOps.push_back(nullptr);
19588 InscanCopyArrayTemps.push_back(nullptr);
19589 InscanCopyArrayElems.push_back(nullptr);
19590 }
19591 }
19592 /// Stores reduction data.
19593 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
19594 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
19595 Expr *CopyArrayElem) {
19596 Vars.emplace_back(Item);
19597 Privates.emplace_back(Private);
19598 LHSs.emplace_back(LHS);
19599 RHSs.emplace_back(RHS);
19600 ReductionOps.emplace_back(ReductionOp);
19601 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
19602 if (RedModifier == OMPC_REDUCTION_inscan) {
19603 InscanCopyOps.push_back(CopyOp);
19604 InscanCopyArrayTemps.push_back(CopyArrayTemp);
19605 InscanCopyArrayElems.push_back(CopyArrayElem);
19606 } else {
19607 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
19608 CopyArrayElem == nullptr &&
19609 "Copy operation must be used for inscan reductions only.");
19610 }
19611 }
19612};
19613} // namespace
19614
19616 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
19617 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
19618 const Expr *Length = OASE->getLength();
19619 if (Length == nullptr) {
19620 // For array sections of the form [1:] or [:], we would need to analyze
19621 // the lower bound...
19622 if (OASE->getColonLocFirst().isValid())
19623 return false;
19624
19625 // This is an array subscript which has implicit length 1!
19626 SingleElement = true;
19627 ArraySizes.push_back(llvm::APSInt::get(1));
19628 } else {
19630 if (!Length->EvaluateAsInt(Result, Context))
19631 return false;
19632
19633 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19634 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
19635 ArraySizes.push_back(ConstantLengthValue);
19636 }
19637
19638 // Get the base of this array section and walk up from there.
19639 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
19640
19641 // We require length = 1 for all array sections except the right-most to
19642 // guarantee that the memory region is contiguous and has no holes in it.
19643 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
19644 Length = TempOASE->getLength();
19645 if (Length == nullptr) {
19646 // For array sections of the form [1:] or [:], we would need to analyze
19647 // the lower bound...
19648 if (OASE->getColonLocFirst().isValid())
19649 return false;
19650
19651 // This is an array subscript which has implicit length 1!
19652 ArraySizes.push_back(llvm::APSInt::get(1));
19653 } else {
19655 if (!Length->EvaluateAsInt(Result, Context))
19656 return false;
19657
19658 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
19659 if (ConstantLengthValue.getSExtValue() != 1)
19660 return false;
19661
19662 ArraySizes.push_back(ConstantLengthValue);
19663 }
19664 Base = TempOASE->getBase()->IgnoreParenImpCasts();
19665 }
19666
19667 // If we have a single element, we don't need to add the implicit lengths.
19668 if (!SingleElement) {
19669 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
19670 // Has implicit length 1!
19671 ArraySizes.push_back(llvm::APSInt::get(1));
19672 Base = TempASE->getBase()->IgnoreParenImpCasts();
19673 }
19674 }
19675
19676 // This array section can be privatized as a single value or as a constant
19677 // sized array.
19678 return true;
19679}
19680
19681static BinaryOperatorKind
19683 if (BOK == BO_Add)
19684 return BO_AddAssign;
19685 if (BOK == BO_Mul)
19686 return BO_MulAssign;
19687 if (BOK == BO_And)
19688 return BO_AndAssign;
19689 if (BOK == BO_Or)
19690 return BO_OrAssign;
19691 if (BOK == BO_Xor)
19692 return BO_XorAssign;
19693 return BOK;
19694}
19695
19697 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
19698 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19699 SourceLocation ColonLoc, SourceLocation EndLoc,
19700 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19701 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
19702 DeclarationName DN = ReductionId.getName();
19704 BinaryOperatorKind BOK = BO_Comma;
19705
19706 ASTContext &Context = S.Context;
19707 // OpenMP [2.14.3.6, reduction clause]
19708 // C
19709 // reduction-identifier is either an identifier or one of the following
19710 // operators: +, -, *, &, |, ^, && and ||
19711 // C++
19712 // reduction-identifier is either an id-expression or one of the following
19713 // operators: +, -, *, &, |, ^, && and ||
19714 switch (OOK) {
19715 case OO_Plus:
19716 BOK = BO_Add;
19717 break;
19718 case OO_Minus:
19719 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
19720 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
19721 // reduction identifier.
19722 if (S.LangOpts.OpenMP > 52)
19723 BOK = BO_Comma;
19724 else
19725 BOK = BO_Add;
19726 break;
19727 case OO_Star:
19728 BOK = BO_Mul;
19729 break;
19730 case OO_Amp:
19731 BOK = BO_And;
19732 break;
19733 case OO_Pipe:
19734 BOK = BO_Or;
19735 break;
19736 case OO_Caret:
19737 BOK = BO_Xor;
19738 break;
19739 case OO_AmpAmp:
19740 BOK = BO_LAnd;
19741 break;
19742 case OO_PipePipe:
19743 BOK = BO_LOr;
19744 break;
19745 case OO_New:
19746 case OO_Delete:
19747 case OO_Array_New:
19748 case OO_Array_Delete:
19749 case OO_Slash:
19750 case OO_Percent:
19751 case OO_Tilde:
19752 case OO_Exclaim:
19753 case OO_Equal:
19754 case OO_Less:
19755 case OO_Greater:
19756 case OO_LessEqual:
19757 case OO_GreaterEqual:
19758 case OO_PlusEqual:
19759 case OO_MinusEqual:
19760 case OO_StarEqual:
19761 case OO_SlashEqual:
19762 case OO_PercentEqual:
19763 case OO_CaretEqual:
19764 case OO_AmpEqual:
19765 case OO_PipeEqual:
19766 case OO_LessLess:
19767 case OO_GreaterGreater:
19768 case OO_LessLessEqual:
19769 case OO_GreaterGreaterEqual:
19770 case OO_EqualEqual:
19771 case OO_ExclaimEqual:
19772 case OO_Spaceship:
19773 case OO_PlusPlus:
19774 case OO_MinusMinus:
19775 case OO_Comma:
19776 case OO_ArrowStar:
19777 case OO_Arrow:
19778 case OO_Call:
19779 case OO_Subscript:
19780 case OO_Conditional:
19781 case OO_Coawait:
19783 llvm_unreachable("Unexpected reduction identifier");
19784 case OO_None:
19785 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
19786 if (II->isStr("max"))
19787 BOK = BO_GT;
19788 else if (II->isStr("min"))
19789 BOK = BO_LT;
19790 }
19791 break;
19792 }
19793
19794 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
19795 // A reduction clause with the minus (-) operator was deprecated
19796 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
19797 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
19798
19799 SourceRange ReductionIdRange;
19800 if (ReductionIdScopeSpec.isValid())
19801 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
19802 else
19803 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19804 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19805
19806 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19807 bool FirstIter = true;
19808 for (Expr *RefExpr : VarList) {
19809 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19810 // OpenMP [2.1, C/C++]
19811 // A list item is a variable or array section, subject to the restrictions
19812 // specified in Section 2.4 on page 42 and in each of the sections
19813 // describing clauses and directives for which a list appears.
19814 // OpenMP [2.14.3.3, Restrictions, p.1]
19815 // A variable that is part of another variable (as an array or
19816 // structure element) cannot appear in a private clause.
19817 if (!FirstIter && IR != ER)
19818 ++IR;
19819 FirstIter = false;
19820 SourceLocation ELoc;
19821 SourceRange ERange;
19822 Expr *SimpleRefExpr = RefExpr;
19823 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19824 /*AllowArraySection=*/true);
19825 if (Res.second) {
19826 // Try to find 'declare reduction' corresponding construct before using
19827 // builtin/overloaded operators.
19828 QualType Type = Context.DependentTy;
19829 CXXCastPath BasePath;
19830 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19831 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19832 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19833 Expr *ReductionOp = nullptr;
19834 if (S.CurContext->isDependentContext() &&
19835 (DeclareReductionRef.isUnset() ||
19836 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19837 ReductionOp = DeclareReductionRef.get();
19838 // It will be analyzed later.
19839 RD.push(RefExpr, ReductionOp);
19840 }
19841 ValueDecl *D = Res.first;
19842 if (!D)
19843 continue;
19844
19845 Expr *TaskgroupDescriptor = nullptr;
19846 QualType Type;
19847 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19848 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
19849 if (ASE) {
19850 Type = ASE->getType().getNonReferenceType();
19851 } else if (OASE) {
19852 QualType BaseType =
19854 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19855 Type = ATy->getElementType();
19856 else
19857 Type = BaseType->getPointeeType();
19858 Type = Type.getNonReferenceType();
19859 } else {
19861 }
19862 auto *VD = dyn_cast<VarDecl>(D);
19863
19864 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19865 // A variable that appears in a private clause must not have an incomplete
19866 // type or a reference type.
19867 if (S.RequireCompleteType(ELoc, D->getType(),
19868 diag::err_omp_reduction_incomplete_type))
19869 continue;
19870 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19871 // A list item that appears in a reduction clause must not be
19872 // const-qualified.
19873 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19874 /*AcceptIfMutable*/ false, ASE || OASE))
19875 continue;
19876
19877 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19878 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19879 // If a list-item is a reference type then it must bind to the same object
19880 // for all threads of the team.
19881 if (!ASE && !OASE) {
19882 if (VD) {
19883 VarDecl *VDDef = VD->getDefinition();
19884 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19885 DSARefChecker Check(Stack);
19886 if (Check.Visit(VDDef->getInit())) {
19887 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19888 << getOpenMPClauseName(ClauseKind) << ERange;
19889 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19890 continue;
19891 }
19892 }
19893 }
19894
19895 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19896 // in a Construct]
19897 // Variables with the predetermined data-sharing attributes may not be
19898 // listed in data-sharing attributes clauses, except for the cases
19899 // listed below. For these exceptions only, listing a predetermined
19900 // variable in a data-sharing attribute clause is allowed and overrides
19901 // the variable's predetermined data-sharing attributes.
19902 // OpenMP [2.14.3.6, Restrictions, p.3]
19903 // Any number of reduction clauses can be specified on the directive,
19904 // but a list item can appear only once in the reduction clauses for that
19905 // directive.
19906 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19907 if (DVar.CKind == OMPC_reduction) {
19908 S.Diag(ELoc, diag::err_omp_once_referenced)
19909 << getOpenMPClauseName(ClauseKind);
19910 if (DVar.RefExpr)
19911 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19912 continue;
19913 }
19914 if (DVar.CKind != OMPC_unknown) {
19915 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19916 << getOpenMPClauseName(DVar.CKind)
19917 << getOpenMPClauseName(OMPC_reduction);
19918 reportOriginalDsa(S, Stack, D, DVar);
19919 continue;
19920 }
19921
19922 // OpenMP [2.14.3.6, Restrictions, p.1]
19923 // A list item that appears in a reduction clause of a worksharing
19924 // construct must be shared in the parallel regions to which any of the
19925 // worksharing regions arising from the worksharing construct bind.
19926 if (isOpenMPWorksharingDirective(CurrDir) &&
19927 !isOpenMPParallelDirective(CurrDir) &&
19928 !isOpenMPTeamsDirective(CurrDir)) {
19929 DVar = Stack->getImplicitDSA(D, true);
19930 if (DVar.CKind != OMPC_shared) {
19931 S.Diag(ELoc, diag::err_omp_required_access)
19932 << getOpenMPClauseName(OMPC_reduction)
19933 << getOpenMPClauseName(OMPC_shared);
19934 reportOriginalDsa(S, Stack, D, DVar);
19935 continue;
19936 }
19937 }
19938 } else {
19939 // Threadprivates cannot be shared between threads, so dignose if the base
19940 // is a threadprivate variable.
19941 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19942 if (DVar.CKind == OMPC_threadprivate) {
19943 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19944 << getOpenMPClauseName(DVar.CKind)
19945 << getOpenMPClauseName(OMPC_reduction);
19946 reportOriginalDsa(S, Stack, D, DVar);
19947 continue;
19948 }
19949 }
19950
19951 // Try to find 'declare reduction' corresponding construct before using
19952 // builtin/overloaded operators.
19953 CXXCastPath BasePath;
19954 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19955 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19956 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19957 if (DeclareReductionRef.isInvalid())
19958 continue;
19959 if (S.CurContext->isDependentContext() &&
19960 (DeclareReductionRef.isUnset() ||
19961 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19962 RD.push(RefExpr, DeclareReductionRef.get());
19963 continue;
19964 }
19965 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19966 // Not allowed reduction identifier is found.
19967 if (S.LangOpts.OpenMP > 52)
19968 S.Diag(ReductionId.getBeginLoc(),
19969 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19970 << Type << ReductionIdRange;
19971 else
19972 S.Diag(ReductionId.getBeginLoc(),
19973 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19974 << Type << ReductionIdRange;
19975 continue;
19976 }
19977
19978 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19979 // The type of a list item that appears in a reduction clause must be valid
19980 // for the reduction-identifier. For a max or min reduction in C, the type
19981 // of the list item must be an allowed arithmetic data type: char, int,
19982 // float, double, or _Bool, possibly modified with long, short, signed, or
19983 // unsigned. For a max or min reduction in C++, the type of the list item
19984 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19985 // double, or bool, possibly modified with long, short, signed, or unsigned.
19986 if (DeclareReductionRef.isUnset()) {
19987 if ((BOK == BO_GT || BOK == BO_LT) &&
19988 !(Type->isScalarType() ||
19989 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19990 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19991 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
19992 if (!ASE && !OASE) {
19993 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19995 S.Diag(D->getLocation(),
19996 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19997 << D;
19998 }
19999 continue;
20000 }
20001 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20002 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20003 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20004 << getOpenMPClauseName(ClauseKind);
20005 if (!ASE && !OASE) {
20006 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20008 S.Diag(D->getLocation(),
20009 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20010 << D;
20011 }
20012 continue;
20013 }
20014 }
20015
20016 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20017 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
20018 D->hasAttrs() ? &D->getAttrs() : nullptr);
20019 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
20020 D->hasAttrs() ? &D->getAttrs() : nullptr);
20021 QualType PrivateTy = Type;
20022
20023 // Try if we can determine constant lengths for all array sections and avoid
20024 // the VLA.
20025 bool ConstantLengthOASE = false;
20026 if (OASE) {
20027 bool SingleElement;
20029 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20030 Context, OASE, SingleElement, ArraySizes);
20031
20032 // If we don't have a single element, we must emit a constant array type.
20033 if (ConstantLengthOASE && !SingleElement) {
20034 for (llvm::APSInt &Size : ArraySizes)
20035 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
20037 /*IndexTypeQuals=*/0);
20038 }
20039 }
20040
20041 if ((OASE && !ConstantLengthOASE) ||
20042 (!OASE && !ASE &&
20044 if (!Context.getTargetInfo().isVLASupported()) {
20045 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
20046 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20047 S.Diag(ELoc, diag::note_vla_unsupported);
20048 continue;
20049 } else {
20050 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20051 S.targetDiag(ELoc, diag::note_vla_unsupported);
20052 }
20053 }
20054 // For arrays/array sections only:
20055 // Create pseudo array type for private copy. The size for this array will
20056 // be generated during codegen.
20057 // For array subscripts or single variables Private Ty is the same as Type
20058 // (type of the variable or single array element).
20059 PrivateTy = Context.getVariableArrayType(
20060 Type,
20061 new (Context)
20062 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20063 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
20064 } else if (!ASE && !OASE &&
20065 Context.getAsArrayType(D->getType().getNonReferenceType())) {
20066 PrivateTy = D->getType().getNonReferenceType();
20067 }
20068 // Private copy.
20069 VarDecl *PrivateVD =
20070 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20071 D->hasAttrs() ? &D->getAttrs() : nullptr,
20072 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20073 // Add initializer for private variable.
20074 Expr *Init = nullptr;
20075 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
20076 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
20077 if (DeclareReductionRef.isUsable()) {
20078 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20079 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
20080 if (DRD->getInitializer()) {
20081 Init = DRDRef;
20082 RHSVD->setInit(DRDRef);
20084 }
20085 } else {
20086 switch (BOK) {
20087 case BO_Add:
20088 case BO_Xor:
20089 case BO_Or:
20090 case BO_LOr:
20091 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20093 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
20094 break;
20095 case BO_Mul:
20096 case BO_LAnd:
20097 if (Type->isScalarType() || Type->isAnyComplexType()) {
20098 // '*' and '&&' reduction ops - initializer is '1'.
20099 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20100 }
20101 break;
20102 case BO_And: {
20103 // '&' reduction op - initializer is '~0'.
20104 QualType OrigType = Type;
20105 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
20106 Type = ComplexTy->getElementType();
20107 if (Type->isRealFloatingType()) {
20108 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20109 Context.getFloatTypeSemantics(Type));
20110 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20111 Type, ELoc);
20112 } else if (Type->isScalarType()) {
20113 uint64_t Size = Context.getTypeSize(Type);
20114 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
20115 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20116 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20117 }
20118 if (Init && OrigType->isAnyComplexType()) {
20119 // Init = 0xFFFF + 0xFFFFi;
20120 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
20121 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
20122 }
20123 Type = OrigType;
20124 break;
20125 }
20126 case BO_LT:
20127 case BO_GT: {
20128 // 'min' reduction op - initializer is 'Largest representable number in
20129 // the reduction list item type'.
20130 // 'max' reduction op - initializer is 'Least representable number in
20131 // the reduction list item type'.
20132 if (Type->isIntegerType() || Type->isPointerType()) {
20133 bool IsSigned = Type->hasSignedIntegerRepresentation();
20134 uint64_t Size = Context.getTypeSize(Type);
20135 QualType IntTy =
20136 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
20137 llvm::APInt InitValue =
20138 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20139 : llvm::APInt::getMinValue(Size)
20140 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20141 : llvm::APInt::getMaxValue(Size);
20142 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20143 if (Type->isPointerType()) {
20144 // Cast to pointer type.
20146 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
20147 if (CastExpr.isInvalid())
20148 continue;
20149 Init = CastExpr.get();
20150 }
20151 } else if (Type->isRealFloatingType()) {
20152 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20153 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
20154 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20155 Type, ELoc);
20156 }
20157 break;
20158 }
20159 case BO_PtrMemD:
20160 case BO_PtrMemI:
20161 case BO_MulAssign:
20162 case BO_Div:
20163 case BO_Rem:
20164 case BO_Sub:
20165 case BO_Shl:
20166 case BO_Shr:
20167 case BO_LE:
20168 case BO_GE:
20169 case BO_EQ:
20170 case BO_NE:
20171 case BO_Cmp:
20172 case BO_AndAssign:
20173 case BO_XorAssign:
20174 case BO_OrAssign:
20175 case BO_Assign:
20176 case BO_AddAssign:
20177 case BO_SubAssign:
20178 case BO_DivAssign:
20179 case BO_RemAssign:
20180 case BO_ShlAssign:
20181 case BO_ShrAssign:
20182 case BO_Comma:
20183 llvm_unreachable("Unexpected reduction operation");
20184 }
20185 }
20186 if (Init && DeclareReductionRef.isUnset()) {
20187 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
20188 // Store initializer for single element in private copy. Will be used
20189 // during codegen.
20190 PrivateVD->setInit(RHSVD->getInit());
20191 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20192 } else if (!Init) {
20193 S.ActOnUninitializedDecl(RHSVD);
20194 // Store initializer for single element in private copy. Will be used
20195 // during codegen.
20196 PrivateVD->setInit(RHSVD->getInit());
20197 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20198 }
20199 if (RHSVD->isInvalidDecl())
20200 continue;
20201 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
20202 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20203 << Type << ReductionIdRange;
20204 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20206 S.Diag(D->getLocation(),
20207 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20208 << D;
20209 continue;
20210 }
20211 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
20212 ExprResult ReductionOp;
20213 if (DeclareReductionRef.isUsable()) {
20214 QualType RedTy = DeclareReductionRef.get()->getType();
20215 QualType PtrRedTy = Context.getPointerType(RedTy);
20216 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
20217 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
20218 if (!BasePath.empty()) {
20219 LHS = S.DefaultLvalueConversion(LHS.get());
20220 RHS = S.DefaultLvalueConversion(RHS.get());
20222 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
20223 LHS.get()->getValueKind(), FPOptionsOverride());
20225 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
20226 RHS.get()->getValueKind(), FPOptionsOverride());
20227 }
20229 QualType Params[] = {PtrRedTy, PtrRedTy};
20230 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20231 auto *OVE = new (Context) OpaqueValueExpr(
20232 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
20233 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
20234 Expr *Args[] = {LHS.get(), RHS.get()};
20235 ReductionOp =
20236 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
20238 } else {
20240 if (Type->isRecordType() && CombBOK != BOK) {
20242 ReductionOp =
20243 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20244 CombBOK, LHSDRE, RHSDRE);
20245 }
20246 if (!ReductionOp.isUsable()) {
20247 ReductionOp =
20248 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
20249 LHSDRE, RHSDRE);
20250 if (ReductionOp.isUsable()) {
20251 if (BOK != BO_LT && BOK != BO_GT) {
20252 ReductionOp =
20253 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20254 BO_Assign, LHSDRE, ReductionOp.get());
20255 } else {
20256 auto *ConditionalOp = new (Context)
20257 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20258 RHSDRE, Type, VK_LValue, OK_Ordinary);
20259 ReductionOp =
20260 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20261 BO_Assign, LHSDRE, ConditionalOp);
20262 }
20263 }
20264 }
20265 if (ReductionOp.isUsable())
20266 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20267 /*DiscardedValue*/ false);
20268 if (!ReductionOp.isUsable())
20269 continue;
20270 }
20271
20272 // Add copy operations for inscan reductions.
20273 // LHS = RHS;
20274 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20275 if (ClauseKind == OMPC_reduction &&
20276 RD.RedModifier == OMPC_REDUCTION_inscan) {
20277 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20278 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20279 RHS.get());
20280 if (!CopyOpRes.isUsable())
20281 continue;
20282 CopyOpRes =
20283 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20284 if (!CopyOpRes.isUsable())
20285 continue;
20286 // For simd directive and simd-based directives in simd mode no need to
20287 // construct temp array, need just a single temp element.
20288 if (Stack->getCurrentDirective() == OMPD_simd ||
20289 (S.getLangOpts().OpenMPSimd &&
20290 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20291 VarDecl *TempArrayVD =
20292 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20293 D->hasAttrs() ? &D->getAttrs() : nullptr);
20294 // Add a constructor to the temp decl.
20295 S.ActOnUninitializedDecl(TempArrayVD);
20296 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20297 } else {
20298 // Build temp array for prefix sum.
20299 auto *Dim = new (S.Context)
20302 PrivateTy, Dim, ArraySizeModifier::Normal,
20303 /*IndexTypeQuals=*/0, {ELoc, ELoc});
20304 VarDecl *TempArrayVD =
20305 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20306 D->hasAttrs() ? &D->getAttrs() : nullptr);
20307 // Add a constructor to the temp decl.
20308 S.ActOnUninitializedDecl(TempArrayVD);
20309 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20310 TempArrayElem =
20311 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20312 auto *Idx = new (S.Context)
20314 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20315 ELoc, Idx, ELoc);
20316 }
20317 }
20318
20319 // OpenMP [2.15.4.6, Restrictions, p.2]
20320 // A list item that appears in an in_reduction clause of a task construct
20321 // must appear in a task_reduction clause of a construct associated with a
20322 // taskgroup region that includes the participating task in its taskgroup
20323 // set. The construct associated with the innermost region that meets this
20324 // condition must specify the same reduction-identifier as the in_reduction
20325 // clause.
20326 if (ClauseKind == OMPC_in_reduction) {
20327 SourceRange ParentSR;
20328 BinaryOperatorKind ParentBOK;
20329 const Expr *ParentReductionOp = nullptr;
20330 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20331 DSAStackTy::DSAVarData ParentBOKDSA =
20332 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20333 ParentBOKTD);
20334 DSAStackTy::DSAVarData ParentReductionOpDSA =
20335 Stack->getTopMostTaskgroupReductionData(
20336 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20337 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20338 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20339 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20340 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20341 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20342 bool EmitError = true;
20343 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20344 llvm::FoldingSetNodeID RedId, ParentRedId;
20345 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20346 DeclareReductionRef.get()->Profile(RedId, Context,
20347 /*Canonical=*/true);
20348 EmitError = RedId != ParentRedId;
20349 }
20350 if (EmitError) {
20351 S.Diag(ReductionId.getBeginLoc(),
20352 diag::err_omp_reduction_identifier_mismatch)
20353 << ReductionIdRange << RefExpr->getSourceRange();
20354 S.Diag(ParentSR.getBegin(),
20355 diag::note_omp_previous_reduction_identifier)
20356 << ParentSR
20357 << (IsParentBOK ? ParentBOKDSA.RefExpr
20358 : ParentReductionOpDSA.RefExpr)
20359 ->getSourceRange();
20360 continue;
20361 }
20362 }
20363 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20364 }
20365
20366 DeclRefExpr *Ref = nullptr;
20367 Expr *VarsExpr = RefExpr->IgnoreParens();
20368 if (!VD && !S.CurContext->isDependentContext()) {
20369 if (ASE || OASE) {
20370 TransformExprToCaptures RebuildToCapture(S, D);
20371 VarsExpr =
20372 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20373 Ref = RebuildToCapture.getCapturedExpr();
20374 } else {
20375 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20376 }
20377 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
20378 RD.ExprCaptures.emplace_back(Ref->getDecl());
20379 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20380 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20381 if (!RefRes.isUsable())
20382 continue;
20383 ExprResult PostUpdateRes =
20384 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20385 RefRes.get());
20386 if (!PostUpdateRes.isUsable())
20387 continue;
20388 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20389 Stack->getCurrentDirective() == OMPD_taskgroup) {
20390 S.Diag(RefExpr->getExprLoc(),
20391 diag::err_omp_reduction_non_addressable_expression)
20392 << RefExpr->getSourceRange();
20393 continue;
20394 }
20395 RD.ExprPostUpdates.emplace_back(
20396 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20397 }
20398 }
20399 }
20400 // All reduction items are still marked as reduction (to do not increase
20401 // code base size).
20402 unsigned Modifier = RD.RedModifier;
20403 // Consider task_reductions as reductions with task modifier. Required for
20404 // correct analysis of in_reduction clauses.
20405 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20406 Modifier = OMPC_REDUCTION_task;
20407 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20408 ASE || OASE);
20409 if (Modifier == OMPC_REDUCTION_task &&
20410 (CurrDir == OMPD_taskgroup ||
20411 ((isOpenMPParallelDirective(CurrDir) ||
20412 isOpenMPWorksharingDirective(CurrDir)) &&
20413 !isOpenMPSimdDirective(CurrDir)))) {
20414 if (DeclareReductionRef.isUsable())
20415 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20416 DeclareReductionRef.get());
20417 else
20418 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20419 }
20420 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20421 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20422 TempArrayElem.get());
20423 }
20424 return RD.Vars.empty();
20425}
20426
20429 SourceLocation StartLoc, SourceLocation LParenLoc,
20430 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20431 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20432 ArrayRef<Expr *> UnresolvedReductions) {
20433 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20434 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20435 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20436 /*Last=*/OMPC_REDUCTION_unknown)
20437 << getOpenMPClauseName(OMPC_reduction);
20438 return nullptr;
20439 }
20440 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20441 // A reduction clause with the inscan reduction-modifier may only appear on a
20442 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20443 // construct, a parallel worksharing-loop construct or a parallel
20444 // worksharing-loop SIMD construct.
20445 if (Modifier == OMPC_REDUCTION_inscan &&
20446 (DSAStack->getCurrentDirective() != OMPD_for &&
20447 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20448 DSAStack->getCurrentDirective() != OMPD_simd &&
20449 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20450 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20451 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20452 return nullptr;
20453 }
20454
20455 ReductionData RD(VarList.size(), Modifier);
20456 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
20457 StartLoc, LParenLoc, ColonLoc, EndLoc,
20458 ReductionIdScopeSpec, ReductionId,
20459 UnresolvedReductions, RD))
20460 return nullptr;
20461
20463 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20464 Modifier, RD.Vars,
20465 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20466 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20467 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20468 buildPreInits(getASTContext(), RD.ExprCaptures),
20469 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20470}
20471
20473 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20474 SourceLocation ColonLoc, SourceLocation EndLoc,
20475 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20476 ArrayRef<Expr *> UnresolvedReductions) {
20477 ReductionData RD(VarList.size());
20478 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
20479 VarList, StartLoc, LParenLoc, ColonLoc,
20480 EndLoc, ReductionIdScopeSpec, ReductionId,
20481 UnresolvedReductions, RD))
20482 return nullptr;
20483
20485 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20486 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20487 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20488 buildPreInits(getASTContext(), RD.ExprCaptures),
20489 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20490}
20491
20493 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20494 SourceLocation ColonLoc, SourceLocation EndLoc,
20495 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20496 ArrayRef<Expr *> UnresolvedReductions) {
20497 ReductionData RD(VarList.size());
20498 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
20499 StartLoc, LParenLoc, ColonLoc, EndLoc,
20500 ReductionIdScopeSpec, ReductionId,
20501 UnresolvedReductions, RD))
20502 return nullptr;
20503
20505 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20506 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20507 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20508 buildPreInits(getASTContext(), RD.ExprCaptures),
20509 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20510}
20511
20513 SourceLocation LinLoc) {
20514 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
20515 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
20516 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
20517 << getLangOpts().CPlusPlus;
20518 return true;
20519 }
20520 return false;
20521}
20522
20524 OpenMPLinearClauseKind LinKind,
20525 QualType Type, bool IsDeclareSimd) {
20526 const auto *VD = dyn_cast_or_null<VarDecl>(D);
20527 // A variable must not have an incomplete type or a reference type.
20529 diag::err_omp_linear_incomplete_type))
20530 return true;
20531 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
20532 !Type->isReferenceType()) {
20533 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
20534 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
20535 return true;
20536 }
20537 Type = Type.getNonReferenceType();
20538
20539 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
20540 // A variable that is privatized must not have a const-qualified type
20541 // unless it is of class type with a mutable member. This restriction does
20542 // not apply to the firstprivate clause, nor to the linear clause on
20543 // declarative directives (like declare simd).
20544 if (!IsDeclareSimd &&
20545 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
20546 return true;
20547
20548 // A list item must be of integral or pointer type.
20549 Type = Type.getUnqualifiedType().getCanonicalType();
20550 const auto *Ty = Type.getTypePtrOrNull();
20551 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
20552 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
20553 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
20554 if (D) {
20555 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20557 Diag(D->getLocation(),
20558 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20559 << D;
20560 }
20561 return true;
20562 }
20563 return false;
20564}
20565
20567 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
20568 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
20569 SourceLocation LinLoc, SourceLocation ColonLoc,
20570 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
20572 SmallVector<Expr *, 8> Privates;
20574 SmallVector<Decl *, 4> ExprCaptures;
20575 SmallVector<Expr *, 4> ExprPostUpdates;
20576 // OpenMP 5.2 [Section 5.4.6, linear clause]
20577 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
20578 // 'ref'
20579 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
20580 getLangOpts().OpenMP >= 52)
20581 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
20582 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
20583 LinKind = OMPC_LINEAR_val;
20584 for (Expr *RefExpr : VarList) {
20585 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20586 SourceLocation ELoc;
20587 SourceRange ERange;
20588 Expr *SimpleRefExpr = RefExpr;
20589 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20590 if (Res.second) {
20591 // It will be analyzed later.
20592 Vars.push_back(RefExpr);
20593 Privates.push_back(nullptr);
20594 Inits.push_back(nullptr);
20595 }
20596 ValueDecl *D = Res.first;
20597 if (!D)
20598 continue;
20599
20600 QualType Type = D->getType();
20601 auto *VD = dyn_cast<VarDecl>(D);
20602
20603 // OpenMP [2.14.3.7, linear clause]
20604 // A list-item cannot appear in more than one linear clause.
20605 // A list-item that appears in a linear clause cannot appear in any
20606 // other data-sharing attribute clause.
20607 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
20608 if (DVar.RefExpr) {
20609 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
20610 << getOpenMPClauseName(OMPC_linear);
20612 continue;
20613 }
20614
20615 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
20616 continue;
20617 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
20618
20619 // Build private copy of original var.
20620 VarDecl *Private =
20621 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
20622 D->hasAttrs() ? &D->getAttrs() : nullptr,
20623 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20624 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
20625 // Build var to save initial value.
20626 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
20627 Expr *InitExpr;
20628 DeclRefExpr *Ref = nullptr;
20629 if (!VD && !SemaRef.CurContext->isDependentContext()) {
20630 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
20631 if (!isOpenMPCapturedDecl(D)) {
20632 ExprCaptures.push_back(Ref->getDecl());
20633 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20635 if (!RefRes.isUsable())
20636 continue;
20637 ExprResult PostUpdateRes =
20638 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
20639 SimpleRefExpr, RefRes.get());
20640 if (!PostUpdateRes.isUsable())
20641 continue;
20642 ExprPostUpdates.push_back(
20643 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
20644 }
20645 }
20646 }
20647 if (LinKind == OMPC_LINEAR_uval)
20648 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
20649 else
20650 InitExpr = VD ? SimpleRefExpr : Ref;
20653 /*DirectInit=*/false);
20654 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
20655
20656 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
20657 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
20658 ? RefExpr->IgnoreParens()
20659 : Ref);
20660 Privates.push_back(PrivateRef);
20661 Inits.push_back(InitRef);
20662 }
20663
20664 if (Vars.empty())
20665 return nullptr;
20666
20667 Expr *StepExpr = Step;
20668 Expr *CalcStepExpr = nullptr;
20669 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
20670 !Step->isInstantiationDependent() &&
20672 SourceLocation StepLoc = Step->getBeginLoc();
20674 if (Val.isInvalid())
20675 return nullptr;
20676 StepExpr = Val.get();
20677
20678 // Build var to save the step value.
20679 VarDecl *SaveVar =
20680 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
20681 ExprResult SaveRef =
20682 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
20683 ExprResult CalcStep = SemaRef.BuildBinOp(
20684 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
20685 CalcStep =
20686 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
20687
20688 // Warn about zero linear step (it would be probably better specified as
20689 // making corresponding variables 'const').
20690 if (std::optional<llvm::APSInt> Result =
20692 if (!Result->isNegative() && !Result->isStrictlyPositive())
20693 Diag(StepLoc, diag::warn_omp_linear_step_zero)
20694 << Vars[0] << (Vars.size() > 1);
20695 } else if (CalcStep.isUsable()) {
20696 // Calculate the step beforehand instead of doing this on each iteration.
20697 // (This is not used if the number of iterations may be kfold-ed).
20698 CalcStepExpr = CalcStep.get();
20699 }
20700 }
20701
20702 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
20703 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
20704 Vars, Privates, Inits, StepExpr, CalcStepExpr,
20705 buildPreInits(getASTContext(), ExprCaptures),
20706 buildPostUpdate(SemaRef, ExprPostUpdates));
20707}
20708
20710 Expr *NumIterations, Sema &SemaRef,
20711 Scope *S, DSAStackTy *Stack) {
20712 // Walk the vars and build update/final expressions for the CodeGen.
20713 SmallVector<Expr *, 8> Updates;
20715 SmallVector<Expr *, 8> UsedExprs;
20716 Expr *Step = Clause.getStep();
20717 Expr *CalcStep = Clause.getCalcStep();
20718 // OpenMP [2.14.3.7, linear clause]
20719 // If linear-step is not specified it is assumed to be 1.
20720 if (!Step)
20721 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
20722 else if (CalcStep)
20723 Step = cast<BinaryOperator>(CalcStep)->getLHS();
20724 bool HasErrors = false;
20725 auto CurInit = Clause.inits().begin();
20726 auto CurPrivate = Clause.privates().begin();
20727 OpenMPLinearClauseKind LinKind = Clause.getModifier();
20728 for (Expr *RefExpr : Clause.varlists()) {
20729 SourceLocation ELoc;
20730 SourceRange ERange;
20731 Expr *SimpleRefExpr = RefExpr;
20732 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20733 ValueDecl *D = Res.first;
20734 if (Res.second || !D) {
20735 Updates.push_back(nullptr);
20736 Finals.push_back(nullptr);
20737 HasErrors = true;
20738 continue;
20739 }
20740 auto &&Info = Stack->isLoopControlVariable(D);
20741 // OpenMP [2.15.11, distribute simd Construct]
20742 // A list item may not appear in a linear clause, unless it is the loop
20743 // iteration variable.
20744 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
20745 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
20746 SemaRef.Diag(ELoc,
20747 diag::err_omp_linear_distribute_var_non_loop_iteration);
20748 Updates.push_back(nullptr);
20749 Finals.push_back(nullptr);
20750 HasErrors = true;
20751 continue;
20752 }
20753 Expr *InitExpr = *CurInit;
20754
20755 // Build privatized reference to the current linear var.
20756 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
20757 Expr *CapturedRef;
20758 if (LinKind == OMPC_LINEAR_uval)
20759 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
20760 else
20761 CapturedRef =
20762 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
20763 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
20764 /*RefersToCapture=*/true);
20765
20766 // Build update: Var = InitExpr + IV * Step
20768 if (!Info.first)
20770 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
20771 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
20772 else
20773 Update = *CurPrivate;
20774 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20775 /*DiscardedValue*/ false);
20776
20777 // Build final: Var = PrivCopy;
20778 ExprResult Final;
20779 if (!Info.first)
20780 Final = SemaRef.BuildBinOp(
20781 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20782 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20783 else
20784 Final = *CurPrivate;
20785 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20786 /*DiscardedValue*/ false);
20787
20788 if (!Update.isUsable() || !Final.isUsable()) {
20789 Updates.push_back(nullptr);
20790 Finals.push_back(nullptr);
20791 UsedExprs.push_back(nullptr);
20792 HasErrors = true;
20793 } else {
20794 Updates.push_back(Update.get());
20795 Finals.push_back(Final.get());
20796 if (!Info.first)
20797 UsedExprs.push_back(SimpleRefExpr);
20798 }
20799 ++CurInit;
20800 ++CurPrivate;
20801 }
20802 if (Expr *S = Clause.getStep())
20803 UsedExprs.push_back(S);
20804 // Fill the remaining part with the nullptr.
20805 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20806 Clause.setUpdates(Updates);
20807 Clause.setFinals(Finals);
20808 Clause.setUsedExprs(UsedExprs);
20809 return HasErrors;
20810}
20811
20813 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20814 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20816 for (Expr *RefExpr : VarList) {
20817 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20818 SourceLocation ELoc;
20819 SourceRange ERange;
20820 Expr *SimpleRefExpr = RefExpr;
20821 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20822 if (Res.second) {
20823 // It will be analyzed later.
20824 Vars.push_back(RefExpr);
20825 }
20826 ValueDecl *D = Res.first;
20827 if (!D)
20828 continue;
20829
20830 QualType QType = D->getType();
20831 auto *VD = dyn_cast<VarDecl>(D);
20832
20833 // OpenMP [2.8.1, simd construct, Restrictions]
20834 // The type of list items appearing in the aligned clause must be
20835 // array, pointer, reference to array, or reference to pointer.
20837 const Type *Ty = QType.getTypePtrOrNull();
20838 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20839 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20840 << QType << getLangOpts().CPlusPlus << ERange;
20841 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20843 Diag(D->getLocation(),
20844 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20845 << D;
20846 continue;
20847 }
20848
20849 // OpenMP [2.8.1, simd construct, Restrictions]
20850 // A list-item cannot appear in more than one aligned clause.
20851 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20852 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20853 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
20854 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20855 << getOpenMPClauseName(OMPC_aligned);
20856 continue;
20857 }
20858
20859 DeclRefExpr *Ref = nullptr;
20860 if (!VD && isOpenMPCapturedDecl(D))
20861 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
20862 Vars.push_back(SemaRef
20863 .DefaultFunctionArrayConversion(
20864 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20865 .get());
20866 }
20867
20868 // OpenMP [2.8.1, simd construct, Description]
20869 // The parameter of the aligned clause, alignment, must be a constant
20870 // positive integer expression.
20871 // If no optional parameter is specified, implementation-defined default
20872 // alignments for SIMD instructions on the target platforms are assumed.
20873 if (Alignment != nullptr) {
20874 ExprResult AlignResult =
20875 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20876 if (AlignResult.isInvalid())
20877 return nullptr;
20878 Alignment = AlignResult.get();
20879 }
20880 if (Vars.empty())
20881 return nullptr;
20882
20883 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
20884 ColonLoc, EndLoc, Vars, Alignment);
20885}
20886
20888 SourceLocation StartLoc,
20889 SourceLocation LParenLoc,
20890 SourceLocation EndLoc) {
20892 SmallVector<Expr *, 8> SrcExprs;
20893 SmallVector<Expr *, 8> DstExprs;
20894 SmallVector<Expr *, 8> AssignmentOps;
20895 for (Expr *RefExpr : VarList) {
20896 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20897 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
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 continue;
20904 }
20905
20906 SourceLocation ELoc = RefExpr->getExprLoc();
20907 // OpenMP [2.1, C/C++]
20908 // A list item is a variable name.
20909 // OpenMP [2.14.4.1, Restrictions, p.1]
20910 // A list item that appears in a copyin clause must be threadprivate.
20911 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20912 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20913 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20914 << 0 << RefExpr->getSourceRange();
20915 continue;
20916 }
20917
20918 Decl *D = DE->getDecl();
20919 auto *VD = cast<VarDecl>(D);
20920
20921 QualType Type = VD->getType();
20923 // It will be analyzed later.
20924 Vars.push_back(DE);
20925 SrcExprs.push_back(nullptr);
20926 DstExprs.push_back(nullptr);
20927 AssignmentOps.push_back(nullptr);
20928 continue;
20929 }
20930
20931 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20932 // A list item that appears in a copyin clause must be threadprivate.
20933 if (!DSAStack->isThreadPrivate(VD)) {
20934 Diag(ELoc, diag::err_omp_required_access)
20935 << getOpenMPClauseName(OMPC_copyin)
20936 << getOpenMPDirectiveName(OMPD_threadprivate);
20937 continue;
20938 }
20939
20940 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20941 // A variable of class type (or array thereof) that appears in a
20942 // copyin clause requires an accessible, unambiguous copy assignment
20943 // operator for the class type.
20944 QualType ElemType =
20946 VarDecl *SrcVD =
20947 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20948 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20949 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20950 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20951 VarDecl *DstVD =
20952 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
20953 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20954 DeclRefExpr *PseudoDstExpr =
20955 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
20956 // For arrays generate assignment operation for single element and replace
20957 // it by the original array element in CodeGen.
20958 ExprResult AssignmentOp =
20959 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
20960 PseudoDstExpr, PseudoSrcExpr);
20961 if (AssignmentOp.isInvalid())
20962 continue;
20963 AssignmentOp =
20964 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20965 /*DiscardedValue*/ false);
20966 if (AssignmentOp.isInvalid())
20967 continue;
20968
20969 DSAStack->addDSA(VD, DE, OMPC_copyin);
20970 Vars.push_back(DE);
20971 SrcExprs.push_back(PseudoSrcExpr);
20972 DstExprs.push_back(PseudoDstExpr);
20973 AssignmentOps.push_back(AssignmentOp.get());
20974 }
20975
20976 if (Vars.empty())
20977 return nullptr;
20978
20979 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20980 Vars, SrcExprs, DstExprs, AssignmentOps);
20981}
20982
20984 SourceLocation StartLoc,
20985 SourceLocation LParenLoc,
20986 SourceLocation EndLoc) {
20988 SmallVector<Expr *, 8> SrcExprs;
20989 SmallVector<Expr *, 8> DstExprs;
20990 SmallVector<Expr *, 8> AssignmentOps;
20991 for (Expr *RefExpr : VarList) {
20992 assert(RefExpr && "NULL expr in OpenMP linear clause.");
20993 SourceLocation ELoc;
20994 SourceRange ERange;
20995 Expr *SimpleRefExpr = RefExpr;
20996 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20997 if (Res.second) {
20998 // It will be analyzed later.
20999 Vars.push_back(RefExpr);
21000 SrcExprs.push_back(nullptr);
21001 DstExprs.push_back(nullptr);
21002 AssignmentOps.push_back(nullptr);
21003 }
21004 ValueDecl *D = Res.first;
21005 if (!D)
21006 continue;
21007
21008 QualType Type = D->getType();
21009 auto *VD = dyn_cast<VarDecl>(D);
21010
21011 // OpenMP [2.14.4.2, Restrictions, p.2]
21012 // A list item that appears in a copyprivate clause may not appear in a
21013 // private or firstprivate clause on the single construct.
21014 if (!VD || !DSAStack->isThreadPrivate(VD)) {
21015 DSAStackTy::DSAVarData DVar =
21016 DSAStack->getTopDSA(D, /*FromParent=*/false);
21017 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21018 DVar.RefExpr) {
21019 Diag(ELoc, diag::err_omp_wrong_dsa)
21020 << getOpenMPClauseName(DVar.CKind)
21021 << getOpenMPClauseName(OMPC_copyprivate);
21023 continue;
21024 }
21025
21026 // OpenMP [2.11.4.2, Restrictions, p.1]
21027 // All list items that appear in a copyprivate clause must be either
21028 // threadprivate or private in the enclosing context.
21029 if (DVar.CKind == OMPC_unknown) {
21030 DVar = DSAStack->getImplicitDSA(D, false);
21031 if (DVar.CKind == OMPC_shared) {
21032 Diag(ELoc, diag::err_omp_required_access)
21033 << getOpenMPClauseName(OMPC_copyprivate)
21034 << "threadprivate or private in the enclosing context";
21036 continue;
21037 }
21038 }
21039 }
21040
21041 // Variably modified types are not supported.
21043 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21044 << getOpenMPClauseName(OMPC_copyprivate) << Type
21045 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
21046 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21048 Diag(D->getLocation(),
21049 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21050 << D;
21051 continue;
21052 }
21053
21054 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21055 // A variable of class type (or array thereof) that appears in a
21056 // copyin clause requires an accessible, unambiguous copy assignment
21057 // operator for the class type.
21059 .getBaseElementType(Type.getNonReferenceType())
21061 VarDecl *SrcVD =
21062 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
21063 D->hasAttrs() ? &D->getAttrs() : nullptr);
21064 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
21065 VarDecl *DstVD =
21066 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
21067 D->hasAttrs() ? &D->getAttrs() : nullptr);
21068 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21069 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21070 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21071 if (AssignmentOp.isInvalid())
21072 continue;
21073 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
21074 /*DiscardedValue*/ false);
21075 if (AssignmentOp.isInvalid())
21076 continue;
21077
21078 // No need to mark vars as copyprivate, they are already threadprivate or
21079 // implicitly private.
21080 assert(VD || isOpenMPCapturedDecl(D));
21081 Vars.push_back(
21082 VD ? RefExpr->IgnoreParens()
21083 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
21084 SrcExprs.push_back(PseudoSrcExpr);
21085 DstExprs.push_back(PseudoDstExpr);
21086 AssignmentOps.push_back(AssignmentOp.get());
21087 }
21088
21089 if (Vars.empty())
21090 return nullptr;
21091
21092 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
21093 EndLoc, Vars, SrcExprs, DstExprs,
21094 AssignmentOps);
21095}
21096
21098 SourceLocation StartLoc,
21099 SourceLocation LParenLoc,
21100 SourceLocation EndLoc) {
21101 if (VarList.empty())
21102 return nullptr;
21103
21104 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21105 VarList);
21106}
21107
21108/// Tries to find omp_depend_t. type.
21109static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
21110 bool Diagnose = true) {
21111 QualType OMPDependT = Stack->getOMPDependT();
21112 if (!OMPDependT.isNull())
21113 return true;
21114 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
21115 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21116 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21117 if (Diagnose)
21118 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
21119 return false;
21120 }
21121 Stack->setOMPDependT(PT.get());
21122 return true;
21123}
21124
21126 SourceLocation StartLoc,
21127 SourceLocation LParenLoc,
21128 SourceLocation EndLoc) {
21129 if (!Depobj)
21130 return nullptr;
21131
21132 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
21133
21134 // OpenMP 5.0, 2.17.10.1 depobj Construct
21135 // depobj is an lvalue expression of type omp_depend_t.
21136 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
21137 !Depobj->isInstantiationDependent() &&
21139 (OMPDependTFound && !getASTContext().typesAreCompatible(
21140 DSAStack->getOMPDependT(), Depobj->getType(),
21141 /*CompareUnqualified=*/true))) {
21142 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21143 << 0 << Depobj->getType() << Depobj->getSourceRange();
21144 }
21145
21146 if (!Depobj->isLValue()) {
21147 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21148 << 1 << Depobj->getSourceRange();
21149 }
21150
21151 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21152 Depobj);
21153}
21154
21155namespace {
21156// Utility struct that gathers the related info for doacross clause.
21157struct DoacrossDataInfoTy {
21158 // The list of expressions.
21160 // The OperatorOffset for doacross loop.
21162 // The depended loop count.
21163 llvm::APSInt TotalDepCount;
21164};
21165} // namespace
21166static DoacrossDataInfoTy
21168 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
21169 SourceLocation EndLoc) {
21170
21173 llvm::APSInt DepCounter(/*BitWidth=*/32);
21174 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21175
21176 if (const Expr *OrderedCountExpr =
21177 Stack->getParentOrderedRegionParam().first) {
21178 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
21179 TotalDepCount.setIsUnsigned(/*Val=*/true);
21180 }
21181
21182 for (Expr *RefExpr : VarList) {
21183 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
21184 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21185 // It will be analyzed later.
21186 Vars.push_back(RefExpr);
21187 continue;
21188 }
21189
21190 SourceLocation ELoc = RefExpr->getExprLoc();
21191 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21192 if (!IsSource) {
21193 if (Stack->getParentOrderedRegionParam().first &&
21194 DepCounter >= TotalDepCount) {
21195 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21196 continue;
21197 }
21198 ++DepCounter;
21199 // OpenMP [2.13.9, Summary]
21200 // depend(dependence-type : vec), where dependence-type is:
21201 // 'sink' and where vec is the iteration vector, which has the form:
21202 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
21203 // where n is the value specified by the ordered clause in the loop
21204 // directive, xi denotes the loop iteration variable of the i-th nested
21205 // loop associated with the loop directive, and di is a constant
21206 // non-negative integer.
21207 if (SemaRef.CurContext->isDependentContext()) {
21208 // It will be analyzed later.
21209 Vars.push_back(RefExpr);
21210 continue;
21211 }
21212 SimpleExpr = SimpleExpr->IgnoreImplicit();
21214 SourceLocation OOLoc;
21215 Expr *LHS = SimpleExpr;
21216 Expr *RHS = nullptr;
21217 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
21218 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
21219 OOLoc = BO->getOperatorLoc();
21220 LHS = BO->getLHS()->IgnoreParenImpCasts();
21221 RHS = BO->getRHS()->IgnoreParenImpCasts();
21222 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
21223 OOK = OCE->getOperator();
21224 OOLoc = OCE->getOperatorLoc();
21225 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21226 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
21227 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
21228 OOK = MCE->getMethodDecl()
21229 ->getNameInfo()
21230 .getName()
21231 .getCXXOverloadedOperator();
21232 OOLoc = MCE->getCallee()->getExprLoc();
21233 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
21234 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21235 }
21236 SourceLocation ELoc;
21237 SourceRange ERange;
21238 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
21239 if (Res.second) {
21240 // It will be analyzed later.
21241 Vars.push_back(RefExpr);
21242 }
21243 ValueDecl *D = Res.first;
21244 if (!D)
21245 continue;
21246
21247 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
21248 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21249 continue;
21250 }
21251 if (RHS) {
21252 ExprResult RHSRes =
21254 RHS, OMPC_depend, /*StrictlyPositive=*/false);
21255 if (RHSRes.isInvalid())
21256 continue;
21257 }
21258 if (!SemaRef.CurContext->isDependentContext() &&
21259 Stack->getParentOrderedRegionParam().first &&
21260 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21261 const ValueDecl *VD =
21262 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21263 if (VD)
21264 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21265 << 1 << VD;
21266 else
21267 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21268 << 0;
21269 continue;
21270 }
21271 OpsOffs.emplace_back(RHS, OOK);
21272 }
21273 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21274 }
21275 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21276 TotalDepCount > VarList.size() &&
21277 Stack->getParentOrderedRegionParam().first &&
21278 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21279 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21280 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21281 }
21282 return {Vars, OpsOffs, TotalDepCount};
21283}
21284
21286 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
21287 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21288 SourceLocation EndLoc) {
21289 OpenMPDependClauseKind DepKind = Data.DepKind;
21290 SourceLocation DepLoc = Data.DepLoc;
21291 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21292 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21293 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21294 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
21295 return nullptr;
21296 }
21297 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21298 DepKind == OMPC_DEPEND_mutexinoutset) {
21299 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21300 return nullptr;
21301 }
21302 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21303 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21304 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21305 DepKind == OMPC_DEPEND_sink ||
21306 ((getLangOpts().OpenMP < 50 ||
21307 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21308 DepKind == OMPC_DEPEND_depobj))) {
21309 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21310 OMPC_DEPEND_outallmemory,
21311 OMPC_DEPEND_inoutallmemory};
21312 if (getLangOpts().OpenMP < 50 ||
21313 DSAStack->getCurrentDirective() == OMPD_depobj)
21314 Except.push_back(OMPC_DEPEND_depobj);
21315 if (getLangOpts().OpenMP < 51)
21316 Except.push_back(OMPC_DEPEND_inoutset);
21317 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
21318 ? "depend modifier(iterator) or "
21319 : "";
21320 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21321 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21322 /*Last=*/OMPC_DEPEND_unknown,
21323 Except)
21324 << getOpenMPClauseName(OMPC_depend);
21325 return nullptr;
21326 }
21327 if (DepModifier &&
21328 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21329 Diag(DepModifier->getExprLoc(),
21330 diag::err_omp_depend_sink_source_with_modifier);
21331 return nullptr;
21332 }
21333 if (DepModifier &&
21334 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21335 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21336
21339 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21340
21341 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21342 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21343 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21344 Vars = VarOffset.Vars;
21345 OpsOffs = VarOffset.OpsOffs;
21346 TotalDepCount = VarOffset.TotalDepCount;
21347 } else {
21348 for (Expr *RefExpr : VarList) {
21349 assert(RefExpr && "NULL expr in OpenMP shared clause.");
21350 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21351 // It will be analyzed later.
21352 Vars.push_back(RefExpr);
21353 continue;
21354 }
21355
21356 SourceLocation ELoc = RefExpr->getExprLoc();
21357 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21358 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21359 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
21360 if (OMPDependTFound)
21361 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
21362 DepKind == OMPC_DEPEND_depobj);
21363 if (DepKind == OMPC_DEPEND_depobj) {
21364 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21365 // List items used in depend clauses with the depobj dependence type
21366 // must be expressions of the omp_depend_t type.
21367 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21368 !RefExpr->isInstantiationDependent() &&
21369 !RefExpr->containsUnexpandedParameterPack() &&
21370 (OMPDependTFound &&
21371 !getASTContext().hasSameUnqualifiedType(
21372 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21373 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21374 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21375 continue;
21376 }
21377 if (!RefExpr->isLValue()) {
21378 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21379 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21380 continue;
21381 }
21382 } else {
21383 // OpenMP 5.0 [2.17.11, Restrictions]
21384 // List items used in depend clauses cannot be zero-length array
21385 // sections.
21386 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21387 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
21388 if (OASE) {
21389 QualType BaseType =
21391 if (BaseType.isNull())
21392 return nullptr;
21393 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21394 ExprTy = ATy->getElementType();
21395 else
21396 ExprTy = BaseType->getPointeeType();
21397 if (BaseType.isNull() || ExprTy.isNull())
21398 return nullptr;
21399 ExprTy = ExprTy.getNonReferenceType();
21400 const Expr *Length = OASE->getLength();
21402 if (Length && !Length->isValueDependent() &&
21403 Length->EvaluateAsInt(Result, getASTContext()) &&
21404 Result.Val.getInt().isZero()) {
21405 Diag(ELoc,
21406 diag::err_omp_depend_zero_length_array_section_not_allowed)
21407 << SimpleExpr->getSourceRange();
21408 continue;
21409 }
21410 }
21411
21412 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21413 // List items used in depend clauses with the in, out, inout,
21414 // inoutset, or mutexinoutset dependence types cannot be
21415 // expressions of the omp_depend_t type.
21416 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21417 !RefExpr->isInstantiationDependent() &&
21418 !RefExpr->containsUnexpandedParameterPack() &&
21419 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21420 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21421 ExprTy.getTypePtr()))) {
21422 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21423 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21424 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21425 << RefExpr->getSourceRange();
21426 continue;
21427 }
21428
21429 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21430 if (ASE && !ASE->getBase()->isTypeDependent() &&
21431 !ASE->getBase()
21432 ->getType()
21433 .getNonReferenceType()
21434 ->isPointerType() &&
21435 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21436 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21437 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21438 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21439 << RefExpr->getSourceRange();
21440 continue;
21441 }
21442
21443 ExprResult Res;
21444 {
21446 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21447 RefExpr->IgnoreParenImpCasts());
21448 }
21449 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
21450 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
21451 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21452 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21453 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21454 << RefExpr->getSourceRange();
21455 continue;
21456 }
21457 }
21458 }
21459 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21460 }
21461 }
21462
21463 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21464 DepKind != OMPC_DEPEND_outallmemory &&
21465 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21466 return nullptr;
21467
21468 auto *C = OMPDependClause::Create(
21469 getASTContext(), StartLoc, LParenLoc, EndLoc,
21470 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21471 TotalDepCount.getZExtValue());
21472 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21473 DSAStack->isParentOrderedRegion())
21474 DSAStack->addDoacrossDependClause(C, OpsOffs);
21475 return C;
21476}
21477
21480 SourceLocation LParenLoc, SourceLocation ModifierLoc,
21481 SourceLocation EndLoc) {
21482 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
21483 "Unexpected device modifier in OpenMP < 50.");
21484
21485 bool ErrorFound = false;
21486 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21487 std::string Values =
21488 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21489 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21490 << Values << getOpenMPClauseName(OMPC_device);
21491 ErrorFound = true;
21492 }
21493
21494 Expr *ValExpr = Device;
21495 Stmt *HelperValStmt = nullptr;
21496
21497 // OpenMP [2.9.1, Restrictions]
21498 // The device expression must evaluate to a non-negative integer value.
21499 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
21500 /*StrictlyPositive=*/false) ||
21501 ErrorFound;
21502 if (ErrorFound)
21503 return nullptr;
21504
21505 // OpenMP 5.0 [2.12.5, Restrictions]
21506 // In case of ancestor device-modifier, a requires directive with
21507 // the reverse_offload clause must be specified.
21508 if (Modifier == OMPC_DEVICE_ancestor) {
21509 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
21511 StartLoc,
21512 diag::err_omp_device_ancestor_without_requires_reverse_offload);
21513 ErrorFound = true;
21514 }
21515 }
21516
21517 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21518 OpenMPDirectiveKind CaptureRegion =
21519 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
21520 if (CaptureRegion != OMPD_unknown &&
21522 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21523 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21524 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21525 HelperValStmt = buildPreInits(getASTContext(), Captures);
21526 }
21527
21528 return new (getASTContext())
21529 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
21530 LParenLoc, ModifierLoc, EndLoc);
21531}
21532
21534 DSAStackTy *Stack, QualType QTy,
21535 bool FullCheck = true) {
21536 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
21537 return false;
21538 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
21539 !QTy.isTriviallyCopyableType(SemaRef.Context))
21540 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
21541 return true;
21542}
21543
21544/// Return true if it can be proven that the provided array expression
21545/// (array section or array subscript) does NOT specify the whole size of the
21546/// array whose base type is \a BaseQTy.
21548 const Expr *E,
21549 QualType BaseQTy) {
21550 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21551
21552 // If this is an array subscript, it refers to the whole size if the size of
21553 // the dimension is constant and equals 1. Also, an array section assumes the
21554 // format of an array subscript if no colon is used.
21555 if (isa<ArraySubscriptExpr>(E) ||
21556 (OASE && OASE->getColonLocFirst().isInvalid())) {
21557 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21558 return ATy->getSExtSize() != 1;
21559 // Size can't be evaluated statically.
21560 return false;
21561 }
21562
21563 assert(OASE && "Expecting array section if not an array subscript.");
21564 const Expr *LowerBound = OASE->getLowerBound();
21565 const Expr *Length = OASE->getLength();
21566
21567 // If there is a lower bound that does not evaluates to zero, we are not
21568 // covering the whole dimension.
21569 if (LowerBound) {
21571 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
21572 return false; // Can't get the integer value as a constant.
21573
21574 llvm::APSInt ConstLowerBound = Result.Val.getInt();
21575 if (ConstLowerBound.getSExtValue())
21576 return true;
21577 }
21578
21579 // If we don't have a length we covering the whole dimension.
21580 if (!Length)
21581 return false;
21582
21583 // If the base is a pointer, we don't have a way to get the size of the
21584 // pointee.
21585 if (BaseQTy->isPointerType())
21586 return false;
21587
21588 // We can only check if the length is the same as the size of the dimension
21589 // if we have a constant array.
21590 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
21591 if (!CATy)
21592 return false;
21593
21595 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21596 return false; // Can't get the integer value as a constant.
21597
21598 llvm::APSInt ConstLength = Result.Val.getInt();
21599 return CATy->getSExtSize() != ConstLength.getSExtValue();
21600}
21601
21602// Return true if it can be proven that the provided array expression (array
21603// section or array subscript) does NOT specify a single element of the array
21604// whose base type is \a BaseQTy.
21606 const Expr *E,
21607 QualType BaseQTy) {
21608 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
21609
21610 // An array subscript always refer to a single element. Also, an array section
21611 // assumes the format of an array subscript if no colon is used.
21612 if (isa<ArraySubscriptExpr>(E) ||
21613 (OASE && OASE->getColonLocFirst().isInvalid()))
21614 return false;
21615
21616 assert(OASE && "Expecting array section if not an array subscript.");
21617 const Expr *Length = OASE->getLength();
21618
21619 // If we don't have a length we have to check if the array has unitary size
21620 // for this dimension. Also, we should always expect a length if the base type
21621 // is pointer.
21622 if (!Length) {
21623 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
21624 return ATy->getSExtSize() != 1;
21625 // We cannot assume anything.
21626 return false;
21627 }
21628
21629 // Check if the length evaluates to 1.
21631 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
21632 return false; // Can't get the integer value as a constant.
21633
21634 llvm::APSInt ConstLength = Result.Val.getInt();
21635 return ConstLength.getSExtValue() != 1;
21636}
21637
21638// The base of elements of list in a map clause have to be either:
21639// - a reference to variable or field.
21640// - a member expression.
21641// - an array expression.
21642//
21643// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
21644// reference to 'r'.
21645//
21646// If we have:
21647//
21648// struct SS {
21649// Bla S;
21650// foo() {
21651// #pragma omp target map (S.Arr[:12]);
21652// }
21653// }
21654//
21655// We want to retrieve the member expression 'this->S';
21656
21657// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
21658// If a list item is an array section, it must specify contiguous storage.
21659//
21660// For this restriction it is sufficient that we make sure only references
21661// to variables or fields and array expressions, and that no array sections
21662// exist except in the rightmost expression (unless they cover the whole
21663// dimension of the array). E.g. these would be invalid:
21664//
21665// r.ArrS[3:5].Arr[6:7]
21666//
21667// r.ArrS[3:5].x
21668//
21669// but these would be valid:
21670// r.ArrS[3].Arr[6:7]
21671//
21672// r.ArrS[3].x
21673namespace {
21674class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
21675 Sema &SemaRef;
21676 OpenMPClauseKind CKind = OMPC_unknown;
21677 OpenMPDirectiveKind DKind = OMPD_unknown;
21679 bool IsNonContiguous = false;
21680 bool NoDiagnose = false;
21681 const Expr *RelevantExpr = nullptr;
21682 bool AllowUnitySizeArraySection = true;
21683 bool AllowWholeSizeArraySection = true;
21684 bool AllowAnotherPtr = true;
21685 SourceLocation ELoc;
21686 SourceRange ERange;
21687
21688 void emitErrorMsg() {
21689 // If nothing else worked, this is not a valid map clause expression.
21690 if (SemaRef.getLangOpts().OpenMP < 50) {
21691 SemaRef.Diag(ELoc,
21692 diag::err_omp_expected_named_var_member_or_array_expression)
21693 << ERange;
21694 } else {
21695 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21696 << getOpenMPClauseName(CKind) << ERange;
21697 }
21698 }
21699
21700public:
21701 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
21702 if (!isa<VarDecl>(DRE->getDecl())) {
21703 emitErrorMsg();
21704 return false;
21705 }
21706 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21707 RelevantExpr = DRE;
21708 // Record the component.
21709 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
21710 return true;
21711 }
21712
21713 bool VisitMemberExpr(MemberExpr *ME) {
21714 Expr *E = ME;
21715 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
21716
21717 if (isa<CXXThisExpr>(BaseE)) {
21718 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21719 // We found a base expression: this->Val.
21720 RelevantExpr = ME;
21721 } else {
21722 E = BaseE;
21723 }
21724
21725 if (!isa<FieldDecl>(ME->getMemberDecl())) {
21726 if (!NoDiagnose) {
21727 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
21728 << ME->getSourceRange();
21729 return false;
21730 }
21731 if (RelevantExpr)
21732 return false;
21733 return Visit(E);
21734 }
21735
21736 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
21737
21738 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
21739 // A bit-field cannot appear in a map clause.
21740 //
21741 if (FD->isBitField()) {
21742 if (!NoDiagnose) {
21743 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
21744 << ME->getSourceRange() << getOpenMPClauseName(CKind);
21745 return false;
21746 }
21747 if (RelevantExpr)
21748 return false;
21749 return Visit(E);
21750 }
21751
21752 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21753 // If the type of a list item is a reference to a type T then the type
21754 // will be considered to be T for all purposes of this clause.
21755 QualType CurType = BaseE->getType().getNonReferenceType();
21756
21757 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
21758 // A list item cannot be a variable that is a member of a structure with
21759 // a union type.
21760 //
21761 if (CurType->isUnionType()) {
21762 if (!NoDiagnose) {
21763 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
21764 << ME->getSourceRange();
21765 return false;
21766 }
21767 return RelevantExpr || Visit(E);
21768 }
21769
21770 // If we got a member expression, we should not expect any array section
21771 // before that:
21772 //
21773 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21774 // If a list item is an element of a structure, only the rightmost symbol
21775 // of the variable reference can be an array section.
21776 //
21777 AllowUnitySizeArraySection = false;
21778 AllowWholeSizeArraySection = false;
21779
21780 // Record the component.
21781 Components.emplace_back(ME, FD, IsNonContiguous);
21782 return RelevantExpr || Visit(E);
21783 }
21784
21785 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21786 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21787
21788 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21789 if (!NoDiagnose) {
21790 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21791 << 0 << AE->getSourceRange();
21792 return false;
21793 }
21794 return RelevantExpr || Visit(E);
21795 }
21796
21797 // If we got an array subscript that express the whole dimension we
21798 // can have any array expressions before. If it only expressing part of
21799 // the dimension, we can only have unitary-size array expressions.
21801 AllowWholeSizeArraySection = false;
21802
21803 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21804 Expr::EvalResult Result;
21805 if (!AE->getIdx()->isValueDependent() &&
21806 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21807 !Result.Val.getInt().isZero()) {
21808 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21809 diag::err_omp_invalid_map_this_expr);
21810 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21811 diag::note_omp_invalid_subscript_on_this_ptr_map);
21812 }
21813 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21814 RelevantExpr = TE;
21815 }
21816
21817 // Record the component - we don't have any declaration associated.
21818 Components.emplace_back(AE, nullptr, IsNonContiguous);
21819
21820 return RelevantExpr || Visit(E);
21821 }
21822
21823 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
21824 // After OMP 5.0 Array section in reduction clause will be implicitly
21825 // mapped
21826 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21827 "Array sections cannot be implicitly mapped.");
21828 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21829 QualType CurType =
21831
21832 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21833 // If the type of a list item is a reference to a type T then the type
21834 // will be considered to be T for all purposes of this clause.
21835 if (CurType->isReferenceType())
21836 CurType = CurType->getPointeeType();
21837
21838 bool IsPointer = CurType->isAnyPointerType();
21839
21840 if (!IsPointer && !CurType->isArrayType()) {
21841 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21842 << 0 << OASE->getSourceRange();
21843 return false;
21844 }
21845
21846 bool NotWhole =
21847 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21848 bool NotUnity =
21849 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21850
21851 if (AllowWholeSizeArraySection) {
21852 // Any array section is currently allowed. Allowing a whole size array
21853 // section implies allowing a unity array section as well.
21854 //
21855 // If this array section refers to the whole dimension we can still
21856 // accept other array sections before this one, except if the base is a
21857 // pointer. Otherwise, only unitary sections are accepted.
21858 if (NotWhole || IsPointer)
21859 AllowWholeSizeArraySection = false;
21860 } else if (DKind == OMPD_target_update &&
21861 SemaRef.getLangOpts().OpenMP >= 50) {
21862 if (IsPointer && !AllowAnotherPtr)
21863 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21864 << /*array of unknown bound */ 1;
21865 else
21866 IsNonContiguous = true;
21867 } else if (AllowUnitySizeArraySection && NotUnity) {
21868 // A unity or whole array section is not allowed and that is not
21869 // compatible with the properties of the current array section.
21870 if (NoDiagnose)
21871 return false;
21872 SemaRef.Diag(ELoc,
21873 diag::err_array_section_does_not_specify_contiguous_storage)
21874 << OASE->getSourceRange();
21875 return false;
21876 }
21877
21878 if (IsPointer)
21879 AllowAnotherPtr = false;
21880
21881 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21882 Expr::EvalResult ResultR;
21883 Expr::EvalResult ResultL;
21884 if (!OASE->getLength()->isValueDependent() &&
21885 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21886 !ResultR.Val.getInt().isOne()) {
21887 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21888 diag::err_omp_invalid_map_this_expr);
21889 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21890 diag::note_omp_invalid_length_on_this_ptr_mapping);
21891 }
21892 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21893 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21894 SemaRef.getASTContext()) &&
21895 !ResultL.Val.getInt().isZero()) {
21896 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21897 diag::err_omp_invalid_map_this_expr);
21898 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21899 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21900 }
21901 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21902 RelevantExpr = TE;
21903 }
21904
21905 // Record the component - we don't have any declaration associated.
21906 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21907 return RelevantExpr || Visit(E);
21908 }
21909 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21910 Expr *Base = E->getBase();
21911
21912 // Record the component - we don't have any declaration associated.
21913 Components.emplace_back(E, nullptr, IsNonContiguous);
21914
21915 return Visit(Base->IgnoreParenImpCasts());
21916 }
21917
21918 bool VisitUnaryOperator(UnaryOperator *UO) {
21919 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21920 UO->getOpcode() != UO_Deref) {
21921 emitErrorMsg();
21922 return false;
21923 }
21924 if (!RelevantExpr) {
21925 // Record the component if haven't found base decl.
21926 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21927 }
21928 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21929 }
21930 bool VisitBinaryOperator(BinaryOperator *BO) {
21931 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21932 emitErrorMsg();
21933 return false;
21934 }
21935
21936 // Pointer arithmetic is the only thing we expect to happen here so after we
21937 // make sure the binary operator is a pointer type, the only thing we need
21938 // to do is to visit the subtree that has the same type as root (so that we
21939 // know the other subtree is just an offset)
21940 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21941 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21942 Components.emplace_back(BO, nullptr, false);
21943 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21944 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21945 "Either LHS or RHS have base decl inside");
21946 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21947 return RelevantExpr || Visit(LE);
21948 return RelevantExpr || Visit(RE);
21949 }
21950 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21951 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21952 RelevantExpr = CTE;
21953 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21954 return true;
21955 }
21956 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21957 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21958 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21959 return true;
21960 }
21961 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21962 Expr *Source = E->getSourceExpr();
21963 if (!Source) {
21964 emitErrorMsg();
21965 return false;
21966 }
21967 return Visit(Source);
21968 }
21969 bool VisitStmt(Stmt *) {
21970 emitErrorMsg();
21971 return false;
21972 }
21973 const Expr *getFoundBase() const { return RelevantExpr; }
21974 explicit MapBaseChecker(
21975 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21977 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21978 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21979 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21980};
21981} // namespace
21982
21983/// Return the expression of the base of the mappable expression or null if it
21984/// cannot be determined and do all the necessary checks to see if the
21985/// expression is valid as a standalone mappable expression. In the process,
21986/// record all the components of the expression.
21988 Sema &SemaRef, Expr *E,
21990 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21991 SourceLocation ELoc = E->getExprLoc();
21992 SourceRange ERange = E->getSourceRange();
21993 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21994 ERange);
21995 if (Checker.Visit(E->IgnoreParens())) {
21996 // Check if the highest dimension array section has length specified
21997 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21998 (CKind == OMPC_to || CKind == OMPC_from)) {
21999 auto CI = CurComponents.rbegin();
22000 auto CE = CurComponents.rend();
22001 for (; CI != CE; ++CI) {
22002 const auto *OASE =
22003 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22004 if (!OASE)
22005 continue;
22006 if (OASE && OASE->getLength())
22007 break;
22008 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
22009 << ERange;
22010 }
22011 }
22012 return Checker.getFoundBase();
22013 }
22014 return nullptr;
22015}
22016
22017// Return true if expression E associated with value VD has conflicts with other
22018// map information.
22020 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22021 bool CurrentRegionOnly,
22023 OpenMPClauseKind CKind) {
22024 assert(VD && E);
22025 SourceLocation ELoc = E->getExprLoc();
22026 SourceRange ERange = E->getSourceRange();
22027
22028 // In order to easily check the conflicts we need to match each component of
22029 // the expression under test with the components of the expressions that are
22030 // already in the stack.
22031
22032 assert(!CurComponents.empty() && "Map clause expression with no components!");
22033 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22034 "Map clause expression with unexpected base!");
22035
22036 // Variables to help detecting enclosing problems in data environment nests.
22037 bool IsEnclosedByDataEnvironmentExpr = false;
22038 const Expr *EnclosingExpr = nullptr;
22039
22040 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22041 VD, CurrentRegionOnly,
22042 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22043 ERange, CKind, &EnclosingExpr,
22045 StackComponents,
22046 OpenMPClauseKind Kind) {
22047 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
22048 return false;
22049 assert(!StackComponents.empty() &&
22050 "Map clause expression with no components!");
22051 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22052 "Map clause expression with unexpected base!");
22053 (void)VD;
22054
22055 // The whole expression in the stack.
22056 const Expr *RE = StackComponents.front().getAssociatedExpression();
22057
22058 // Expressions must start from the same base. Here we detect at which
22059 // point both expressions diverge from each other and see if we can
22060 // detect if the memory referred to both expressions is contiguous and
22061 // do not overlap.
22062 auto CI = CurComponents.rbegin();
22063 auto CE = CurComponents.rend();
22064 auto SI = StackComponents.rbegin();
22065 auto SE = StackComponents.rend();
22066 for (; CI != CE && SI != SE; ++CI, ++SI) {
22067
22068 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
22069 // At most one list item can be an array item derived from a given
22070 // variable in map clauses of the same construct.
22071 if (CurrentRegionOnly &&
22072 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
22073 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
22074 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
22075 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
22076 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
22077 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
22078 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
22079 diag::err_omp_multiple_array_items_in_map_clause)
22080 << CI->getAssociatedExpression()->getSourceRange();
22081 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
22082 diag::note_used_here)
22083 << SI->getAssociatedExpression()->getSourceRange();
22084 return true;
22085 }
22086
22087 // Do both expressions have the same kind?
22088 if (CI->getAssociatedExpression()->getStmtClass() !=
22089 SI->getAssociatedExpression()->getStmtClass())
22090 break;
22091
22092 // Are we dealing with different variables/fields?
22093 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22094 break;
22095 }
22096 // Check if the extra components of the expressions in the enclosing
22097 // data environment are redundant for the current base declaration.
22098 // If they are, the maps completely overlap, which is legal.
22099 for (; SI != SE; ++SI) {
22100 QualType Type;
22101 if (const auto *ASE =
22102 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22103 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22104 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
22105 SI->getAssociatedExpression())) {
22106 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22107 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
22108 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22109 SI->getAssociatedExpression())) {
22110 Type = OASE->getBase()->getType()->getPointeeType();
22111 }
22112 if (Type.isNull() || Type->isAnyPointerType() ||
22114 SemaRef, SI->getAssociatedExpression(), Type))
22115 break;
22116 }
22117
22118 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22119 // List items of map clauses in the same construct must not share
22120 // original storage.
22121 //
22122 // If the expressions are exactly the same or one is a subset of the
22123 // other, it means they are sharing storage.
22124 if (CI == CE && SI == SE) {
22125 if (CurrentRegionOnly) {
22126 if (CKind == OMPC_map) {
22127 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22128 } else {
22129 assert(CKind == OMPC_to || CKind == OMPC_from);
22130 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22131 << ERange;
22132 }
22133 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22134 << RE->getSourceRange();
22135 return true;
22136 }
22137 // If we find the same expression in the enclosing data environment,
22138 // that is legal.
22139 IsEnclosedByDataEnvironmentExpr = true;
22140 return false;
22141 }
22142
22143 QualType DerivedType =
22144 std::prev(CI)->getAssociatedDeclaration()->getType();
22145 SourceLocation DerivedLoc =
22146 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22147
22148 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22149 // If the type of a list item is a reference to a type T then the type
22150 // will be considered to be T for all purposes of this clause.
22151 DerivedType = DerivedType.getNonReferenceType();
22152
22153 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
22154 // A variable for which the type is pointer and an array section
22155 // derived from that variable must not appear as list items of map
22156 // clauses of the same construct.
22157 //
22158 // Also, cover one of the cases in:
22159 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22160 // If any part of the original storage of a list item has corresponding
22161 // storage in the device data environment, all of the original storage
22162 // must have corresponding storage in the device data environment.
22163 //
22164 if (DerivedType->isAnyPointerType()) {
22165 if (CI == CE || SI == SE) {
22166 SemaRef.Diag(
22167 DerivedLoc,
22168 diag::err_omp_pointer_mapped_along_with_derived_section)
22169 << DerivedLoc;
22170 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22171 << RE->getSourceRange();
22172 return true;
22173 }
22174 if (CI->getAssociatedExpression()->getStmtClass() !=
22175 SI->getAssociatedExpression()->getStmtClass() ||
22176 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22177 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22178 assert(CI != CE && SI != SE);
22179 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22180 << DerivedLoc;
22181 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22182 << RE->getSourceRange();
22183 return true;
22184 }
22185 }
22186
22187 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22188 // List items of map clauses in the same construct must not share
22189 // original storage.
22190 //
22191 // An expression is a subset of the other.
22192 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22193 if (CKind == OMPC_map) {
22194 if (CI != CE || SI != SE) {
22195 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
22196 // a pointer.
22197 auto Begin =
22198 CI != CE ? CurComponents.begin() : StackComponents.begin();
22199 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22200 auto It = Begin;
22201 while (It != End && !It->getAssociatedDeclaration())
22202 std::advance(It, 1);
22203 assert(It != End &&
22204 "Expected at least one component with the declaration.");
22205 if (It != Begin && It->getAssociatedDeclaration()
22206 ->getType()
22207 .getCanonicalType()
22208 ->isAnyPointerType()) {
22209 IsEnclosedByDataEnvironmentExpr = false;
22210 EnclosingExpr = nullptr;
22211 return false;
22212 }
22213 }
22214 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22215 } else {
22216 assert(CKind == OMPC_to || CKind == OMPC_from);
22217 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22218 << ERange;
22219 }
22220 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22221 << RE->getSourceRange();
22222 return true;
22223 }
22224
22225 // The current expression uses the same base as other expression in the
22226 // data environment but does not contain it completely.
22227 if (!CurrentRegionOnly && SI != SE)
22228 EnclosingExpr = RE;
22229
22230 // The current expression is a subset of the expression in the data
22231 // environment.
22232 IsEnclosedByDataEnvironmentExpr |=
22233 (!CurrentRegionOnly && CI != CE && SI == SE);
22234
22235 return false;
22236 });
22237
22238 if (CurrentRegionOnly)
22239 return FoundError;
22240
22241 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22242 // If any part of the original storage of a list item has corresponding
22243 // storage in the device data environment, all of the original storage must
22244 // have corresponding storage in the device data environment.
22245 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
22246 // If a list item is an element of a structure, and a different element of
22247 // the structure has a corresponding list item in the device data environment
22248 // prior to a task encountering the construct associated with the map clause,
22249 // then the list item must also have a corresponding list item in the device
22250 // data environment prior to the task encountering the construct.
22251 //
22252 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22253 SemaRef.Diag(ELoc,
22254 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22255 << ERange;
22256 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
22257 << EnclosingExpr->getSourceRange();
22258 return true;
22259 }
22260
22261 return FoundError;
22262}
22263
22264// Look up the user-defined mapper given the mapper name and mapped type, and
22265// build a reference to it.
22267 CXXScopeSpec &MapperIdScopeSpec,
22268 const DeclarationNameInfo &MapperId,
22269 QualType Type,
22270 Expr *UnresolvedMapper) {
22271 if (MapperIdScopeSpec.isInvalid())
22272 return ExprError();
22273 // Get the actual type for the array type.
22274 if (Type->isArrayType()) {
22275 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22277 }
22278 // Find all user-defined mappers with the given MapperId.
22279 SmallVector<UnresolvedSet<8>, 4> Lookups;
22280 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22281 Lookup.suppressDiagnostics();
22282 if (S) {
22283 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22284 /*ObjectType=*/QualType())) {
22285 NamedDecl *D = Lookup.getRepresentativeDecl();
22286 while (S && !S->isDeclScope(D))
22287 S = S->getParent();
22288 if (S)
22289 S = S->getParent();
22290 Lookups.emplace_back();
22291 Lookups.back().append(Lookup.begin(), Lookup.end());
22292 Lookup.clear();
22293 }
22294 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22295 // Extract the user-defined mappers with the given MapperId.
22296 Lookups.push_back(UnresolvedSet<8>());
22297 for (NamedDecl *D : ULE->decls()) {
22298 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22299 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22300 Lookups.back().addDecl(DMD);
22301 }
22302 }
22303 // Defer the lookup for dependent types. The results will be passed through
22304 // UnresolvedMapper on instantiation.
22305 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22308 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
22309 return !D->isInvalidDecl() &&
22310 (D->getType()->isDependentType() ||
22311 D->getType()->isInstantiationDependentType() ||
22312 D->getType()->containsUnexpandedParameterPack());
22313 })) {
22314 UnresolvedSet<8> URS;
22315 for (const UnresolvedSet<8> &Set : Lookups) {
22316 if (Set.empty())
22317 continue;
22318 URS.append(Set.begin(), Set.end());
22319 }
22321 SemaRef.Context, /*NamingClass=*/nullptr,
22322 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22323 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false);
22324 }
22325 SourceLocation Loc = MapperId.getLoc();
22326 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22327 // The type must be of struct, union or class type in C and C++
22329 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22330 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22331 return ExprError();
22332 }
22333 // Perform argument dependent lookup.
22334 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22335 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22336 // Return the first user-defined mapper with the desired type.
22337 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22338 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22339 if (!D->isInvalidDecl() &&
22340 SemaRef.Context.hasSameType(D->getType(), Type))
22341 return D;
22342 return nullptr;
22343 }))
22344 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22345 // Find the first user-defined mapper with a type derived from the desired
22346 // type.
22347 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
22348 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22349 if (!D->isInvalidDecl() &&
22350 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22351 !Type.isMoreQualifiedThan(D->getType()))
22352 return D;
22353 return nullptr;
22354 })) {
22355 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22356 /*DetectVirtual=*/false);
22357 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22358 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22359 VD->getType().getUnqualifiedType()))) {
22360 if (SemaRef.CheckBaseClassAccess(
22361 Loc, VD->getType(), Type, Paths.front(),
22362 /*DiagID=*/0) != Sema::AR_inaccessible) {
22363 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22364 }
22365 }
22366 }
22367 }
22368 // Report error if a mapper is specified, but cannot be found.
22369 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22370 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22371 << Type << MapperId.getName();
22372 return ExprError();
22373 }
22374 return ExprEmpty();
22375}
22376
22377namespace {
22378// Utility struct that gathers all the related lists associated with a mappable
22379// expression.
22380struct MappableVarListInfo {
22381 // The list of expressions.
22382 ArrayRef<Expr *> VarList;
22383 // The list of processed expressions.
22384 SmallVector<Expr *, 16> ProcessedVarList;
22385 // The mappble components for each expression.
22387 // The base declaration of the variable.
22388 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22389 // The reference to the user-defined mapper associated with every expression.
22390 SmallVector<Expr *, 16> UDMapperList;
22391
22392 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22393 // We have a list of components and base declarations for each entry in the
22394 // variable list.
22395 VarComponents.reserve(VarList.size());
22396 VarBaseDeclarations.reserve(VarList.size());
22397 }
22398};
22399} // namespace
22400
22401// Check the validity of the provided variable list for the provided clause kind
22402// \a CKind. In the check process the valid expressions, mappable expression
22403// components, variables, and user-defined mappers are extracted and used to
22404// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
22405// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
22406// and \a MapperId are expected to be valid if the clause kind is 'map'.
22408 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
22409 MappableVarListInfo &MVLI, SourceLocation StartLoc,
22410 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
22411 ArrayRef<Expr *> UnresolvedMappers,
22413 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
22414 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
22415 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
22416 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
22417 "Unexpected clause kind with mappable expressions!");
22418
22419 // If the identifier of user-defined mapper is not specified, it is "default".
22420 // We do not change the actual name in this clause to distinguish whether a
22421 // mapper is specified explicitly, i.e., it is not explicitly specified when
22422 // MapperId.getName() is empty.
22423 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
22424 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
22425 MapperId.setName(DeclNames.getIdentifier(
22426 &SemaRef.getASTContext().Idents.get("default")));
22427 MapperId.setLoc(StartLoc);
22428 }
22429
22430 // Iterators to find the current unresolved mapper expression.
22431 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
22432 bool UpdateUMIt = false;
22433 Expr *UnresolvedMapper = nullptr;
22434
22435 bool HasHoldModifier =
22436 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
22437
22438 // Keep track of the mappable components and base declarations in this clause.
22439 // Each entry in the list is going to have a list of components associated. We
22440 // record each set of the components so that we can build the clause later on.
22441 // In the end we should have the same amount of declarations and component
22442 // lists.
22443
22444 for (Expr *RE : MVLI.VarList) {
22445 assert(RE && "Null expr in omp to/from/map clause");
22446 SourceLocation ELoc = RE->getExprLoc();
22447
22448 // Find the current unresolved mapper expression.
22449 if (UpdateUMIt && UMIt != UMEnd) {
22450 UMIt++;
22451 assert(
22452 UMIt != UMEnd &&
22453 "Expect the size of UnresolvedMappers to match with that of VarList");
22454 }
22455 UpdateUMIt = true;
22456 if (UMIt != UMEnd)
22457 UnresolvedMapper = *UMIt;
22458
22459 const Expr *VE = RE->IgnoreParenLValueCasts();
22460
22461 if (VE->isValueDependent() || VE->isTypeDependent() ||
22464 // Try to find the associated user-defined mapper.
22466 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22467 VE->getType().getCanonicalType(), UnresolvedMapper);
22468 if (ER.isInvalid())
22469 continue;
22470 MVLI.UDMapperList.push_back(ER.get());
22471 // We can only analyze this information once the missing information is
22472 // resolved.
22473 MVLI.ProcessedVarList.push_back(RE);
22474 continue;
22475 }
22476
22477 Expr *SimpleExpr = RE->IgnoreParenCasts();
22478
22479 if (!RE->isLValue()) {
22480 if (SemaRef.getLangOpts().OpenMP < 50) {
22481 SemaRef.Diag(
22482 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
22483 << RE->getSourceRange();
22484 } else {
22485 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22486 << getOpenMPClauseName(CKind) << RE->getSourceRange();
22487 }
22488 continue;
22489 }
22490
22492 ValueDecl *CurDeclaration = nullptr;
22493
22494 // Obtain the array or member expression bases if required. Also, fill the
22495 // components array with all the components identified in the process.
22496 const Expr *BE =
22497 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
22498 DSAS->getCurrentDirective(), NoDiagnose);
22499 if (!BE)
22500 continue;
22501
22502 assert(!CurComponents.empty() &&
22503 "Invalid mappable expression information.");
22504
22505 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
22506 // Add store "this" pointer to class in DSAStackTy for future checking
22507 DSAS->addMappedClassesQualTypes(TE->getType());
22508 // Try to find the associated user-defined mapper.
22510 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22511 VE->getType().getCanonicalType(), UnresolvedMapper);
22512 if (ER.isInvalid())
22513 continue;
22514 MVLI.UDMapperList.push_back(ER.get());
22515 // Skip restriction checking for variable or field declarations
22516 MVLI.ProcessedVarList.push_back(RE);
22517 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22518 MVLI.VarComponents.back().append(CurComponents.begin(),
22519 CurComponents.end());
22520 MVLI.VarBaseDeclarations.push_back(nullptr);
22521 continue;
22522 }
22523
22524 // For the following checks, we rely on the base declaration which is
22525 // expected to be associated with the last component. The declaration is
22526 // expected to be a variable or a field (if 'this' is being mapped).
22527 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
22528 assert(CurDeclaration && "Null decl on map clause.");
22529 assert(
22530 CurDeclaration->isCanonicalDecl() &&
22531 "Expecting components to have associated only canonical declarations.");
22532
22533 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
22534 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
22535
22536 assert((VD || FD) && "Only variables or fields are expected here!");
22537 (void)FD;
22538
22539 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
22540 // threadprivate variables cannot appear in a map clause.
22541 // OpenMP 4.5 [2.10.5, target update Construct]
22542 // threadprivate variables cannot appear in a from clause.
22543 if (VD && DSAS->isThreadPrivate(VD)) {
22544 if (NoDiagnose)
22545 continue;
22546 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22547 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
22548 << getOpenMPClauseName(CKind);
22549 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
22550 continue;
22551 }
22552
22553 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22554 // A list item cannot appear in both a map clause and a data-sharing
22555 // attribute clause on the same construct.
22556
22557 // Check conflicts with other map clause expressions. We check the conflicts
22558 // with the current construct separately from the enclosing data
22559 // environment, because the restrictions are different. We only have to
22560 // check conflicts across regions for the map clauses.
22561 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22562 /*CurrentRegionOnly=*/true, CurComponents, CKind))
22563 break;
22564 if (CKind == OMPC_map &&
22565 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
22566 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
22567 /*CurrentRegionOnly=*/false, CurComponents, CKind))
22568 break;
22569
22570 // OpenMP 4.5 [2.10.5, target update Construct]
22571 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22572 // If the type of a list item is a reference to a type T then the type will
22573 // be considered to be T for all purposes of this clause.
22574 auto I = llvm::find_if(
22575 CurComponents,
22577 return MC.getAssociatedDeclaration();
22578 });
22579 assert(I != CurComponents.end() && "Null decl on map clause.");
22580 (void)I;
22581 QualType Type;
22582 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
22583 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
22584 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
22585 if (ASE) {
22586 Type = ASE->getType().getNonReferenceType();
22587 } else if (OASE) {
22588 QualType BaseType =
22590 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22591 Type = ATy->getElementType();
22592 else
22593 Type = BaseType->getPointeeType();
22594 Type = Type.getNonReferenceType();
22595 } else if (OAShE) {
22596 Type = OAShE->getBase()->getType()->getPointeeType();
22597 } else {
22598 Type = VE->getType();
22599 }
22600
22601 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22602 // A list item in a to or from clause must have a mappable type.
22603 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22604 // A list item must have a mappable type.
22605 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22606 DSAS, Type, /*FullCheck=*/true))
22607 continue;
22608
22609 if (CKind == OMPC_map) {
22610 // target enter data
22611 // OpenMP [2.10.2, Restrictions, p. 99]
22612 // A map-type must be specified in all map clauses and must be either
22613 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22614 // no map type is present.
22615 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22616 if (DKind == OMPD_target_enter_data &&
22617 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22618 SemaRef.getLangOpts().OpenMP >= 52)) {
22619 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22620 << (IsMapTypeImplicit ? 1 : 0)
22621 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22622 << getOpenMPDirectiveName(DKind);
22623 continue;
22624 }
22625
22626 // target exit_data
22627 // OpenMP [2.10.3, Restrictions, p. 102]
22628 // A map-type must be specified in all map clauses and must be either
22629 // from, release, or delete. Starting with OpenMP 5.2 the default map
22630 // type is `from` if no map type is present.
22631 if (DKind == OMPD_target_exit_data &&
22632 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22633 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22634 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22635 << (IsMapTypeImplicit ? 1 : 0)
22636 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22637 << getOpenMPDirectiveName(DKind);
22638 continue;
22639 }
22640
22641 // The 'ompx_hold' modifier is specifically intended to be used on a
22642 // 'target' or 'target data' directive to prevent data from being unmapped
22643 // during the associated statement. It is not permitted on a 'target
22644 // enter data' or 'target exit data' directive, which have no associated
22645 // statement.
22646 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22647 HasHoldModifier) {
22648 SemaRef.Diag(StartLoc,
22649 diag::err_omp_invalid_map_type_modifier_for_directive)
22651 OMPC_MAP_MODIFIER_ompx_hold)
22652 << getOpenMPDirectiveName(DKind);
22653 continue;
22654 }
22655
22656 // target, target data
22657 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22658 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22659 // A map-type in a map clause must be to, from, tofrom or alloc
22660 if ((DKind == OMPD_target_data ||
22662 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22663 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22664 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22665 << (IsMapTypeImplicit ? 1 : 0)
22666 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22667 << getOpenMPDirectiveName(DKind);
22668 continue;
22669 }
22670
22671 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22672 // A list item cannot appear in both a map clause and a data-sharing
22673 // attribute clause on the same construct
22674 //
22675 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22676 // A list item cannot appear in both a map clause and a data-sharing
22677 // attribute clause on the same construct unless the construct is a
22678 // combined construct.
22679 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22681 DKind == OMPD_target)) {
22682 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22683 if (isOpenMPPrivate(DVar.CKind)) {
22684 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22685 << getOpenMPClauseName(DVar.CKind)
22686 << getOpenMPClauseName(OMPC_map)
22687 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
22688 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22689 continue;
22690 }
22691 }
22692 }
22693
22694 // Try to find the associated user-defined mapper.
22696 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22697 Type.getCanonicalType(), UnresolvedMapper);
22698 if (ER.isInvalid())
22699 continue;
22700 MVLI.UDMapperList.push_back(ER.get());
22701
22702 // Save the current expression.
22703 MVLI.ProcessedVarList.push_back(RE);
22704
22705 // Store the components in the stack so that they can be used to check
22706 // against other clauses later on.
22707 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22708 /*WhereFoundClauseKind=*/OMPC_map);
22709
22710 // Save the components and declaration to create the clause. For purposes of
22711 // the clause creation, any component list that has base 'this' uses
22712 // null as base declaration.
22713 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22714 MVLI.VarComponents.back().append(CurComponents.begin(),
22715 CurComponents.end());
22716 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22717 : CurDeclaration);
22718 }
22719}
22720
22722 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22723 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22724 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22725 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22726 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22727 const OMPVarListLocTy &Locs, bool NoDiagnose,
22728 ArrayRef<Expr *> UnresolvedMappers) {
22729 OpenMPMapModifierKind Modifiers[] = {
22734
22735 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22736 BuiltinType::OMPIterator))
22737 Diag(IteratorModifier->getExprLoc(),
22738 diag::err_omp_map_modifier_not_iterator);
22739
22740 // Process map-type-modifiers, flag errors for duplicate modifiers.
22741 unsigned Count = 0;
22742 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22743 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22744 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22745 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22746 continue;
22747 }
22748 assert(Count < NumberOfOMPMapClauseModifiers &&
22749 "Modifiers exceed the allowed number of map type modifiers");
22750 Modifiers[Count] = MapTypeModifiers[I];
22751 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22752 ++Count;
22753 }
22754
22755 MappableVarListInfo MVLI(VarList);
22757 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22758 MapType, Modifiers, IsMapTypeImplicit,
22759 NoDiagnose);
22760
22761 // We need to produce a map clause even if we don't have variables so that
22762 // other diagnostics related with non-existing map clauses are accurate.
22763 return OMPMapClause::Create(
22764 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22765 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22766 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
22767 MapperId, MapType, IsMapTypeImplicit, MapLoc);
22768}
22769
22772 assert(ParsedType.isUsable());
22773
22774 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
22775 if (ReductionType.isNull())
22776 return QualType();
22777
22778 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22779 // A type name in a declare reduction directive cannot be a function type, an
22780 // array type, a reference type, or a type qualified with const, volatile or
22781 // restrict.
22782 if (ReductionType.hasQualifiers()) {
22783 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22784 return QualType();
22785 }
22786
22787 if (ReductionType->isFunctionType()) {
22788 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22789 return QualType();
22790 }
22791 if (ReductionType->isReferenceType()) {
22792 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22793 return QualType();
22794 }
22795 if (ReductionType->isArrayType()) {
22796 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22797 return QualType();
22798 }
22799 return ReductionType;
22800}
22801
22804 Scope *S, DeclContext *DC, DeclarationName Name,
22805 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22806 AccessSpecifier AS, Decl *PrevDeclInScope) {
22808 Decls.reserve(ReductionTypes.size());
22809
22810 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22813 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22814 // A reduction-identifier may not be re-declared in the current scope for the
22815 // same type or for a type that is compatible according to the base language
22816 // rules.
22817 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22818 OMPDeclareReductionDecl *PrevDRD = nullptr;
22819 bool InCompoundScope = true;
22820 if (S != nullptr) {
22821 // Find previous declaration with the same name not referenced in other
22822 // declarations.
22824 InCompoundScope =
22825 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22826 SemaRef.LookupName(Lookup, S);
22827 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22828 /*AllowInlineNamespace=*/false);
22829 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22830 LookupResult::Filter Filter = Lookup.makeFilter();
22831 while (Filter.hasNext()) {
22832 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22833 if (InCompoundScope) {
22834 auto I = UsedAsPrevious.find(PrevDecl);
22835 if (I == UsedAsPrevious.end())
22836 UsedAsPrevious[PrevDecl] = false;
22837 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22838 UsedAsPrevious[D] = true;
22839 }
22840 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22841 PrevDecl->getLocation();
22842 }
22843 Filter.done();
22844 if (InCompoundScope) {
22845 for (const auto &PrevData : UsedAsPrevious) {
22846 if (!PrevData.second) {
22847 PrevDRD = PrevData.first;
22848 break;
22849 }
22850 }
22851 }
22852 } else if (PrevDeclInScope != nullptr) {
22853 auto *PrevDRDInScope = PrevDRD =
22854 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22855 do {
22856 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22857 PrevDRDInScope->getLocation();
22858 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22859 } while (PrevDRDInScope != nullptr);
22860 }
22861 for (const auto &TyData : ReductionTypes) {
22862 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22863 bool Invalid = false;
22864 if (I != PreviousRedeclTypes.end()) {
22865 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22866 << TyData.first;
22867 Diag(I->second, diag::note_previous_definition);
22868 Invalid = true;
22869 }
22870 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22872 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
22873 DC->addDecl(DRD);
22874 DRD->setAccess(AS);
22875 Decls.push_back(DRD);
22876 if (Invalid)
22877 DRD->setInvalidDecl();
22878 else
22879 PrevDRD = DRD;
22880 }
22881
22882 return DeclGroupPtrTy::make(
22883 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
22884}
22885
22887 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22888
22889 // Enter new function scope.
22893
22894 if (S != nullptr)
22895 SemaRef.PushDeclContext(S, DRD);
22896 else
22897 SemaRef.CurContext = DRD;
22898
22901
22902 QualType ReductionType = DRD->getType();
22903 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22904 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22905 // uses semantics of argument handles by value, but it should be passed by
22906 // reference. C lang does not support references, so pass all parameters as
22907 // pointers.
22908 // Create 'T omp_in;' variable.
22909 VarDecl *OmpInParm =
22910 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
22911 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22912 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22913 // uses semantics of argument handles by value, but it should be passed by
22914 // reference. C lang does not support references, so pass all parameters as
22915 // pointers.
22916 // Create 'T omp_out;' variable.
22917 VarDecl *OmpOutParm =
22918 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
22919 if (S != nullptr) {
22920 SemaRef.PushOnScopeChains(OmpInParm, S);
22921 SemaRef.PushOnScopeChains(OmpOutParm, S);
22922 } else {
22923 DRD->addDecl(OmpInParm);
22924 DRD->addDecl(OmpOutParm);
22925 }
22926 Expr *InE =
22927 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
22928 Expr *OutE =
22929 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
22930 DRD->setCombinerData(InE, OutE);
22931}
22932
22934 Expr *Combiner) {
22935 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22938
22941
22942 if (Combiner != nullptr)
22943 DRD->setCombiner(Combiner);
22944 else
22945 DRD->setInvalidDecl();
22946}
22947
22949 Decl *D) {
22950 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22951
22952 // Enter new function scope.
22955
22956 if (S != nullptr)
22957 SemaRef.PushDeclContext(S, DRD);
22958 else
22959 SemaRef.CurContext = DRD;
22960
22963
22964 QualType ReductionType = DRD->getType();
22965 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22966 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22967 // uses semantics of argument handles by value, but it should be passed by
22968 // reference. C lang does not support references, so pass all parameters as
22969 // pointers.
22970 // Create 'T omp_priv;' variable.
22971 VarDecl *OmpPrivParm =
22972 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
22973 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22974 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22975 // uses semantics of argument handles by value, but it should be passed by
22976 // reference. C lang does not support references, so pass all parameters as
22977 // pointers.
22978 // Create 'T omp_orig;' variable.
22979 VarDecl *OmpOrigParm =
22980 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
22981 if (S != nullptr) {
22982 SemaRef.PushOnScopeChains(OmpPrivParm, S);
22983 SemaRef.PushOnScopeChains(OmpOrigParm, S);
22984 } else {
22985 DRD->addDecl(OmpPrivParm);
22986 DRD->addDecl(OmpOrigParm);
22987 }
22988 Expr *OrigE =
22989 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
22990 Expr *PrivE =
22991 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
22992 DRD->setInitializerData(OrigE, PrivE);
22993 return OmpPrivParm;
22994}
22995
22997 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
22998 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23001
23004
23005 if (Initializer != nullptr) {
23006 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
23007 } else if (OmpPrivParm->hasInit()) {
23008 DRD->setInitializer(OmpPrivParm->getInit(),
23009 OmpPrivParm->isDirectInit()
23012 } else {
23013 DRD->setInvalidDecl();
23014 }
23015}
23016
23018 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
23019 for (Decl *D : DeclReductions.get()) {
23020 if (IsValid) {
23021 if (S)
23022 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
23023 /*AddToContext=*/false);
23024 } else {
23025 D->setInvalidDecl();
23026 }
23027 }
23028 return DeclReductions;
23029}
23030
23032 Declarator &D) {
23034 QualType T = TInfo->getType();
23035 if (D.isInvalidType())
23036 return true;
23037
23038 if (getLangOpts().CPlusPlus) {
23039 // Check that there are no default arguments (C++ only).
23041 }
23042
23043 return SemaRef.CreateParsedType(T, TInfo);
23044}
23045
23048 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
23049
23051 assert(!MapperType.isNull() && "Expect valid mapper type");
23052
23053 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23054 // The type must be of struct, union or class type in C and C++
23055 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
23056 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23057 return QualType();
23058 }
23059 return MapperType;
23060}
23061
23063 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
23065 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
23066 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23069 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23070 // A mapper-identifier may not be redeclared in the current scope for the
23071 // same type or for a type that is compatible according to the base language
23072 // rules.
23073 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23074 OMPDeclareMapperDecl *PrevDMD = nullptr;
23075 bool InCompoundScope = true;
23076 if (S != nullptr) {
23077 // Find previous declaration with the same name not referenced in other
23078 // declarations.
23080 InCompoundScope =
23081 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23082 SemaRef.LookupName(Lookup, S);
23083 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23084 /*AllowInlineNamespace=*/false);
23085 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23086 LookupResult::Filter Filter = Lookup.makeFilter();
23087 while (Filter.hasNext()) {
23088 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
23089 if (InCompoundScope) {
23090 auto I = UsedAsPrevious.find(PrevDecl);
23091 if (I == UsedAsPrevious.end())
23092 UsedAsPrevious[PrevDecl] = false;
23093 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
23094 UsedAsPrevious[D] = true;
23095 }
23096 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23097 PrevDecl->getLocation();
23098 }
23099 Filter.done();
23100 if (InCompoundScope) {
23101 for (const auto &PrevData : UsedAsPrevious) {
23102 if (!PrevData.second) {
23103 PrevDMD = PrevData.first;
23104 break;
23105 }
23106 }
23107 }
23108 } else if (PrevDeclInScope) {
23109 auto *PrevDMDInScope = PrevDMD =
23110 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
23111 do {
23112 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23113 PrevDMDInScope->getLocation();
23114 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23115 } while (PrevDMDInScope != nullptr);
23116 }
23117 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
23118 bool Invalid = false;
23119 if (I != PreviousRedeclTypes.end()) {
23120 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23121 << MapperType << Name;
23122 Diag(I->second, diag::note_previous_definition);
23123 Invalid = true;
23124 }
23125 // Build expressions for implicit maps of data members with 'default'
23126 // mappers.
23127 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
23128 Clauses.end());
23129 if (getLangOpts().OpenMP >= 50)
23131 ClausesWithImplicit);
23132 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
23133 MapperType, VN, ClausesWithImplicit,
23134 PrevDMD);
23135 if (S)
23136 SemaRef.PushOnScopeChains(DMD, S);
23137 else
23138 DC->addDecl(DMD);
23139 DMD->setAccess(AS);
23140 if (Invalid)
23141 DMD->setInvalidDecl();
23142
23143 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23144 VD->setDeclContext(DMD);
23145 VD->setLexicalDeclContext(DMD);
23146 DMD->addDecl(VD);
23147 DMD->setMapperVarRef(MapperVarRef);
23148
23150}
23151
23153 Scope *S, QualType MapperType, SourceLocation StartLoc,
23154 DeclarationName VN) {
23155 TypeSourceInfo *TInfo =
23156 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
23157 auto *VD = VarDecl::Create(
23158 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
23159 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
23160 if (S)
23161 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
23162 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
23163 DSAStack->addDeclareMapperVarRef(E);
23164 return E;
23165}
23166
23168 if (DSAStack->getDeclareMapperVarRef())
23169 DSAStack->addIteratorVarDecl(VD);
23170}
23171
23173 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23174 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
23175 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23176 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
23177 return true;
23179 return true;
23180 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
23181 return true;
23182 return false;
23183 }
23184 return true;
23185}
23186
23188 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23189 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
23190}
23191
23193 SourceLocation StartLoc,
23194 SourceLocation LParenLoc,
23195 SourceLocation EndLoc) {
23196 Expr *ValExpr = NumTeams;
23197 Stmt *HelperValStmt = nullptr;
23198
23199 // OpenMP [teams Constrcut, Restrictions]
23200 // The num_teams expression must evaluate to a positive integer value.
23201 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
23202 /*StrictlyPositive=*/true))
23203 return nullptr;
23204
23205 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23207 DKind, OMPC_num_teams, getLangOpts().OpenMP);
23208 if (CaptureRegion != OMPD_unknown &&
23210 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23211 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23212 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23213 HelperValStmt = buildPreInits(getASTContext(), Captures);
23214 }
23215
23216 return new (getASTContext()) OMPNumTeamsClause(
23217 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23218}
23219
23221 SourceLocation StartLoc,
23222 SourceLocation LParenLoc,
23223 SourceLocation EndLoc) {
23224 Expr *ValExpr = ThreadLimit;
23225 Stmt *HelperValStmt = nullptr;
23226
23227 // OpenMP [teams Constrcut, Restrictions]
23228 // The thread_limit expression must evaluate to a positive integer value.
23229 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
23230 /*StrictlyPositive=*/true))
23231 return nullptr;
23232
23233 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23235 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
23236 if (CaptureRegion != OMPD_unknown &&
23238 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23239 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23240 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23241 HelperValStmt = buildPreInits(getASTContext(), Captures);
23242 }
23243
23244 return new (getASTContext()) OMPThreadLimitClause(
23245 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23246}
23247
23249 SourceLocation StartLoc,
23250 SourceLocation LParenLoc,
23251 SourceLocation EndLoc) {
23252 Expr *ValExpr = Priority;
23253 Stmt *HelperValStmt = nullptr;
23254 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23255
23256 // OpenMP [2.9.1, task Constrcut]
23257 // The priority-value is a non-negative numerical scalar expression.
23259 ValExpr, SemaRef, OMPC_priority,
23260 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
23261 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23262 return nullptr;
23263
23264 return new (getASTContext()) OMPPriorityClause(
23265 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23266}
23267
23269 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
23270 SourceLocation StartLoc, SourceLocation LParenLoc,
23271 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23272 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23273 "Unexpected grainsize modifier in OpenMP < 51.");
23274
23275 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
23276 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
23278 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23279 << Values << getOpenMPClauseName(OMPC_grainsize);
23280 return nullptr;
23281 }
23282
23283 Expr *ValExpr = Grainsize;
23284 Stmt *HelperValStmt = nullptr;
23285 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23286
23287 // OpenMP [2.9.2, taskloop Constrcut]
23288 // The parameter of the grainsize clause must be a positive integer
23289 // expression.
23290 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
23291 /*StrictlyPositive=*/true,
23292 /*BuildCapture=*/true,
23293 DSAStack->getCurrentDirective(),
23294 &CaptureRegion, &HelperValStmt))
23295 return nullptr;
23296
23297 return new (getASTContext())
23298 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23299 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23300}
23301
23303 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
23304 SourceLocation StartLoc, SourceLocation LParenLoc,
23305 SourceLocation ModifierLoc, SourceLocation EndLoc) {
23306 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
23307 "Unexpected num_tasks modifier in OpenMP < 51.");
23308
23309 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
23310 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
23312 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
23313 << Values << getOpenMPClauseName(OMPC_num_tasks);
23314 return nullptr;
23315 }
23316
23317 Expr *ValExpr = NumTasks;
23318 Stmt *HelperValStmt = nullptr;
23319 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
23320
23321 // OpenMP [2.9.2, taskloop Constrcut]
23322 // The parameter of the num_tasks clause must be a positive integer
23323 // expression.
23325 ValExpr, SemaRef, OMPC_num_tasks,
23326 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
23327 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
23328 return nullptr;
23329
23330 return new (getASTContext())
23331 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
23332 StartLoc, LParenLoc, ModifierLoc, EndLoc);
23333}
23334
23336 SourceLocation StartLoc,
23337 SourceLocation LParenLoc,
23338 SourceLocation EndLoc) {
23339 // OpenMP [2.13.2, critical construct, Description]
23340 // ... where hint-expression is an integer constant expression that evaluates
23341 // to a valid lock hint.
23342 ExprResult HintExpr =
23343 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
23344 if (HintExpr.isInvalid())
23345 return nullptr;
23346 return new (getASTContext())
23347 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
23348}
23349
23350/// Tries to find omp_event_handle_t type.
23352 DSAStackTy *Stack) {
23353 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
23354 if (!OMPEventHandleT.isNull())
23355 return true;
23356 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
23357 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23358 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23359 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
23360 return false;
23361 }
23362 Stack->setOMPEventHandleT(PT.get());
23363 return true;
23364}
23365
23367 SourceLocation StartLoc,
23368 SourceLocation LParenLoc,
23369 SourceLocation EndLoc) {
23370 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
23371 !Evt->isInstantiationDependent() &&
23374 return nullptr;
23375 // OpenMP 5.0, 2.10.1 task Construct.
23376 // event-handle is a variable of the omp_event_handle_t type.
23377 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
23378 if (!Ref) {
23379 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23380 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23381 return nullptr;
23382 }
23383 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
23384 if (!VD) {
23385 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23386 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
23387 return nullptr;
23388 }
23389 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
23390 VD->getType()) ||
23391 VD->getType().isConstant(getASTContext())) {
23392 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
23393 << "omp_event_handle_t" << 1 << VD->getType()
23394 << Evt->getSourceRange();
23395 return nullptr;
23396 }
23397 // OpenMP 5.0, 2.10.1 task Construct
23398 // [detach clause]... The event-handle will be considered as if it was
23399 // specified on a firstprivate clause.
23400 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
23401 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
23402 DVar.RefExpr) {
23403 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
23404 << getOpenMPClauseName(DVar.CKind)
23405 << getOpenMPClauseName(OMPC_firstprivate);
23407 return nullptr;
23408 }
23409 }
23410
23411 return new (getASTContext())
23412 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
23413}
23414
23416 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
23417 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
23418 SourceLocation EndLoc) {
23419 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
23420 std::string Values;
23421 Values += "'";
23422 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
23423 Values += "'";
23424 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23425 << Values << getOpenMPClauseName(OMPC_dist_schedule);
23426 return nullptr;
23427 }
23428 Expr *ValExpr = ChunkSize;
23429 Stmt *HelperValStmt = nullptr;
23430 if (ChunkSize) {
23431 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
23432 !ChunkSize->isInstantiationDependent() &&
23433 !ChunkSize->containsUnexpandedParameterPack()) {
23434 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
23435 ExprResult Val =
23436 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
23437 if (Val.isInvalid())
23438 return nullptr;
23439
23440 ValExpr = Val.get();
23441
23442 // OpenMP [2.7.1, Restrictions]
23443 // chunk_size must be a loop invariant integer expression with a positive
23444 // value.
23445 if (std::optional<llvm::APSInt> Result =
23447 if (Result->isSigned() && !Result->isStrictlyPositive()) {
23448 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
23449 << "dist_schedule" << ChunkSize->getSourceRange();
23450 return nullptr;
23451 }
23453 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
23454 getLangOpts().OpenMP) != OMPD_unknown &&
23456 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23457 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23458 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23459 HelperValStmt = buildPreInits(getASTContext(), Captures);
23460 }
23461 }
23462 }
23463
23464 return new (getASTContext())
23465 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
23466 Kind, ValExpr, HelperValStmt);
23467}
23468
23471 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
23472 SourceLocation KindLoc, SourceLocation EndLoc) {
23473 if (getLangOpts().OpenMP < 50) {
23474 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
23475 Kind != OMPC_DEFAULTMAP_scalar) {
23476 std::string Value;
23478 Value += "'";
23479 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
23480 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23481 OMPC_DEFAULTMAP_MODIFIER_tofrom);
23482 Loc = MLoc;
23483 } else {
23484 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
23485 OMPC_DEFAULTMAP_scalar);
23486 Loc = KindLoc;
23487 }
23488 Value += "'";
23489 Diag(Loc, diag::err_omp_unexpected_clause_value)
23490 << Value << getOpenMPClauseName(OMPC_defaultmap);
23491 return nullptr;
23492 }
23493 } else {
23494 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
23495 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
23496 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
23497 if (!isDefaultmapKind || !isDefaultmapModifier) {
23498 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
23499 if (getLangOpts().OpenMP == 50) {
23500 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
23501 "'firstprivate', 'none', 'default'";
23502 if (!isDefaultmapKind && isDefaultmapModifier) {
23503 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23504 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23505 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23506 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23507 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23508 } else {
23509 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23510 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23511 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23512 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23513 }
23514 } else {
23515 StringRef ModifierValue =
23516 "'alloc', 'from', 'to', 'tofrom', "
23517 "'firstprivate', 'none', 'default', 'present'";
23518 if (!isDefaultmapKind && isDefaultmapModifier) {
23519 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23520 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23521 } else if (isDefaultmapKind && !isDefaultmapModifier) {
23522 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23523 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23524 } else {
23525 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23526 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
23527 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23528 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
23529 }
23530 }
23531 return nullptr;
23532 }
23533
23534 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23535 // At most one defaultmap clause for each category can appear on the
23536 // directive.
23537 if (DSAStack->checkDefaultmapCategory(Kind)) {
23538 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23539 return nullptr;
23540 }
23541 }
23542 if (Kind == OMPC_DEFAULTMAP_unknown) {
23543 // Variable category is not specified - mark all categories.
23544 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23545 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23546 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23547 } else {
23548 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23549 }
23550
23551 return new (getASTContext())
23552 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23553}
23554
23557 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
23558 if (!CurLexicalContext->isFileContext() &&
23559 !CurLexicalContext->isExternCContext() &&
23560 !CurLexicalContext->isExternCXXContext() &&
23561 !isa<CXXRecordDecl>(CurLexicalContext) &&
23562 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23563 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23564 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23565 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23566 return false;
23567 }
23568
23569 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23570 if (getLangOpts().HIP)
23571 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23572
23573 DeclareTargetNesting.push_back(DTCI);
23574 return true;
23575}
23576
23579 assert(!DeclareTargetNesting.empty() &&
23580 "check isInOpenMPDeclareTargetContext() first!");
23581 return DeclareTargetNesting.pop_back_val();
23582}
23583
23586 for (auto &It : DTCI.ExplicitlyMapped)
23587 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23588}
23589
23591 if (DeclareTargetNesting.empty())
23592 return;
23593 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23594 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23595 << getOpenMPDirectiveName(DTCI.Kind);
23596}
23597
23599 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
23601 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
23602 /*ObjectType=*/QualType(),
23603 /*AllowBuiltinCreation=*/true);
23604
23605 if (Lookup.isAmbiguous())
23606 return nullptr;
23607 Lookup.suppressDiagnostics();
23608
23609 if (!Lookup.isSingleResult()) {
23610 VarOrFuncDeclFilterCCC CCC(SemaRef);
23611 if (TypoCorrection Corrected =
23612 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
23614 SemaRef.diagnoseTypo(Corrected,
23615 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
23616 << Id.getName());
23617 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23618 return nullptr;
23619 }
23620
23621 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23622 return nullptr;
23623 }
23624
23625 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23626 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23627 !isa<FunctionTemplateDecl>(ND)) {
23628 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23629 return nullptr;
23630 }
23631 return ND;
23632}
23633
23635 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
23637 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23638 isa<FunctionTemplateDecl>(ND)) &&
23639 "Expected variable, function or function template.");
23640
23641 if (auto *VD = dyn_cast<VarDecl>(ND)) {
23642 // Only global variables can be marked as declare target.
23643 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23644 !VD->isStaticDataMember()) {
23645 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
23646 << VD->getNameAsString();
23647 return;
23648 }
23649 }
23650 // Diagnose marking after use as it may lead to incorrect diagnosis and
23651 // codegen.
23652 if (getLangOpts().OpenMP >= 50 &&
23653 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23654 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23655
23656 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23657 if (getLangOpts().HIP)
23658 Diag(Loc, diag::warn_hip_omp_target_directives);
23659
23660 // Explicit declare target lists have precedence.
23661 const unsigned Level = -1;
23662
23663 auto *VD = cast<ValueDecl>(ND);
23664 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23665 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23666 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23667 (*ActiveAttr)->getLevel() == Level) {
23668 Diag(Loc, diag::err_omp_device_type_mismatch)
23669 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23670 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23671 (*ActiveAttr)->getDevType());
23672 return;
23673 }
23674 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23675 (*ActiveAttr)->getLevel() == Level) {
23676 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23677 return;
23678 }
23679
23680 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23681 return;
23682
23683 Expr *IndirectE = nullptr;
23684 bool IsIndirect = false;
23685 if (DTCI.Indirect) {
23686 IndirectE = *DTCI.Indirect;
23687 if (!IndirectE)
23688 IsIndirect = true;
23689 }
23690 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23691 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
23692 SourceRange(Loc, Loc));
23693 ND->addAttr(A);
23694 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23695 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23697 if (auto *VD = dyn_cast<VarDecl>(ND);
23698 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23699 VD->hasGlobalStorage())
23701}
23702
23704 Sema &SemaRef, Decl *D) {
23705 if (!D || !isa<VarDecl>(D))
23706 return;
23707 auto *VD = cast<VarDecl>(D);
23708 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23709 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23710 if (SemaRef.LangOpts.OpenMP >= 50 &&
23711 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23712 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23713 VD->hasGlobalStorage()) {
23714 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23715 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23716 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23717 // If a lambda declaration and definition appears between a
23718 // declare target directive and the matching end declare target
23719 // directive, all variables that are captured by the lambda
23720 // expression must also appear in a to clause.
23721 SemaRef.Diag(VD->getLocation(),
23722 diag::err_omp_lambda_capture_in_declare_target_not_to);
23723 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23724 << VD << 0 << SR;
23725 return;
23726 }
23727 }
23728 if (MapTy)
23729 return;
23730 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23731 SemaRef.Diag(SL, diag::note_used_here) << SR;
23732}
23733
23735 Sema &SemaRef, DSAStackTy *Stack,
23736 ValueDecl *VD) {
23737 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23738 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23739 /*FullCheck=*/false);
23740}
23741
23743 SourceLocation IdLoc) {
23744 if (!D || D->isInvalidDecl())
23745 return;
23746 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
23747 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23748 if (auto *VD = dyn_cast<VarDecl>(D)) {
23749 // Only global variables can be marked as declare target.
23750 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23751 !VD->isStaticDataMember())
23752 return;
23753 // 2.10.6: threadprivate variable cannot appear in a declare target
23754 // directive.
23755 if (DSAStack->isThreadPrivate(VD)) {
23756 Diag(SL, diag::err_omp_threadprivate_in_target);
23757 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23758 return;
23759 }
23760 }
23761 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23762 D = FTD->getTemplatedDecl();
23763 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23764 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23765 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23766 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23767 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23768 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23769 return;
23770 }
23771 }
23772 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23773 // Problem if any with var declared with incomplete type will be reported
23774 // as normal, so no need to check it here.
23775 if ((E || !VD->getType()->isIncompleteType()) &&
23777 return;
23778 if (!E && isInOpenMPDeclareTargetContext()) {
23779 // Checking declaration inside declare target region.
23780 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23781 isa<FunctionTemplateDecl>(D)) {
23782 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23783 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23784 unsigned Level = DeclareTargetNesting.size();
23785 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23786 return;
23787 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23788 Expr *IndirectE = nullptr;
23789 bool IsIndirect = false;
23790 if (DTCI.Indirect) {
23791 IndirectE = *DTCI.Indirect;
23792 if (!IndirectE)
23793 IsIndirect = true;
23794 }
23795 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23796 getASTContext(),
23797 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23798 : OMPDeclareTargetDeclAttr::MT_To,
23799 DTCI.DT, IndirectE, IsIndirect, Level,
23800 SourceRange(DTCI.Loc, DTCI.Loc));
23801 D->addAttr(A);
23802 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23803 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23804 }
23805 return;
23806 }
23807 }
23808 if (!E)
23809 return;
23811}
23812
23813/// This class visits every VarDecl that the initializer references and adds
23814/// OMPDeclareTargetDeclAttr to each of them.
23816 : public StmtVisitor<GlobalDeclRefChecker> {
23817 SmallVector<VarDecl *> DeclVector;
23818 Attr *A;
23819
23820public:
23821 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23822 /// OMPDeclareTargetDeclAttr to them.
23824 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23825 VD->addAttr(A);
23826 DeclVector.push_back(VD);
23827 }
23828 }
23829 /// A function that iterates across each of the Expr's children.
23830 void VisitExpr(Expr *Ex) {
23831 for (auto *Child : Ex->children()) {
23832 Visit(Child);
23833 }
23834 }
23835 /// A function that keeps a record of all the Decls that are variables, has
23836 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23837 /// each Decl one at a time and use the inherited 'visit' functions to look
23838 /// for DeclRefExpr.
23840 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23841 DeclVector.push_back(cast<VarDecl>(TD));
23842 while (!DeclVector.empty()) {
23843 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23844 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23845 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23846 if (Expr *Ex = TargetVarDecl->getInit())
23847 Visit(Ex);
23848 }
23849 }
23850 }
23851};
23852
23853/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23854/// duration that are referenced in the initializer expression list of
23855/// variables with static storage duration in declare target directive.
23857 GlobalDeclRefChecker Checker;
23858 if (isa<VarDecl>(TargetDecl))
23859 Checker.declareTargetInitializer(TargetDecl);
23860}
23861
23863 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23864 ArrayRef<SourceLocation> MotionModifiersLoc,
23865 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23866 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23867 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23871
23872 // Process motion-modifiers, flag errors for duplicate modifiers.
23873 unsigned Count = 0;
23874 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23875 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23876 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23877 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23878 continue;
23879 }
23880 assert(Count < NumberOfOMPMotionModifiers &&
23881 "Modifiers exceed the allowed number of motion modifiers");
23882 Modifiers[Count] = MotionModifiers[I];
23883 ModifiersLoc[Count] = MotionModifiersLoc[I];
23884 ++Count;
23885 }
23886
23887 MappableVarListInfo MVLI(VarList);
23889 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23890 if (MVLI.ProcessedVarList.empty())
23891 return nullptr;
23892
23893 return OMPToClause::Create(
23894 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23895 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23896 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23897}
23898
23900 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23901 ArrayRef<SourceLocation> MotionModifiersLoc,
23902 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23903 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23904 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23908
23909 // Process motion-modifiers, flag errors for duplicate modifiers.
23910 unsigned Count = 0;
23911 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23912 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23913 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23914 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23915 continue;
23916 }
23917 assert(Count < NumberOfOMPMotionModifiers &&
23918 "Modifiers exceed the allowed number of motion modifiers");
23919 Modifiers[Count] = MotionModifiers[I];
23920 ModifiersLoc[Count] = MotionModifiersLoc[I];
23921 ++Count;
23922 }
23923
23924 MappableVarListInfo MVLI(VarList);
23925 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23926 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23927 if (MVLI.ProcessedVarList.empty())
23928 return nullptr;
23929
23930 return OMPFromClause::Create(
23931 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23932 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23933 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23934}
23935
23936OMPClause *
23938 const OMPVarListLocTy &Locs) {
23939 MappableVarListInfo MVLI(VarList);
23940 SmallVector<Expr *, 8> PrivateCopies;
23942
23943 for (Expr *RefExpr : VarList) {
23944 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23945 SourceLocation ELoc;
23946 SourceRange ERange;
23947 Expr *SimpleRefExpr = RefExpr;
23948 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23949 if (Res.second) {
23950 // It will be analyzed later.
23951 MVLI.ProcessedVarList.push_back(RefExpr);
23952 PrivateCopies.push_back(nullptr);
23953 Inits.push_back(nullptr);
23954 }
23955 ValueDecl *D = Res.first;
23956 if (!D)
23957 continue;
23958
23959 QualType Type = D->getType();
23960 Type = Type.getNonReferenceType().getUnqualifiedType();
23961
23962 auto *VD = dyn_cast<VarDecl>(D);
23963
23964 // Item should be a pointer or reference to pointer.
23965 if (!Type->isPointerType()) {
23966 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23967 << 0 << RefExpr->getSourceRange();
23968 continue;
23969 }
23970
23971 // Build the private variable and the expression that refers to it.
23972 auto VDPrivate =
23973 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
23974 D->hasAttrs() ? &D->getAttrs() : nullptr,
23975 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23976 if (VDPrivate->isInvalidDecl())
23977 continue;
23978
23979 SemaRef.CurContext->addDecl(VDPrivate);
23980 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23981 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23982
23983 // Add temporary variable to initialize the private copy of the pointer.
23984 VarDecl *VDInit =
23985 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
23986 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23987 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23989 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
23990 /*DirectInit=*/false);
23991
23992 // If required, build a capture to implement the privatization initialized
23993 // with the current list item value.
23994 DeclRefExpr *Ref = nullptr;
23995 if (!VD)
23996 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23997 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23998 PrivateCopies.push_back(VDPrivateRefExpr);
23999 Inits.push_back(VDInitRefExpr);
24000
24001 // We need to add a data sharing attribute for this variable to make sure it
24002 // is correctly captured. A variable that shows up in a use_device_ptr has
24003 // similar properties of a first private variable.
24004 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24005
24006 // Create a mappable component for the list item. List items in this clause
24007 // only need a component.
24008 MVLI.VarBaseDeclarations.push_back(D);
24009 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24010 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24011 /*IsNonContiguous=*/false);
24012 }
24013
24014 if (MVLI.ProcessedVarList.empty())
24015 return nullptr;
24016
24018 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24019 MVLI.VarBaseDeclarations, MVLI.VarComponents);
24020}
24021
24022OMPClause *
24024 const OMPVarListLocTy &Locs) {
24025 MappableVarListInfo MVLI(VarList);
24026
24027 for (Expr *RefExpr : VarList) {
24028 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
24029 SourceLocation ELoc;
24030 SourceRange ERange;
24031 Expr *SimpleRefExpr = RefExpr;
24032 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24033 /*AllowArraySection=*/true);
24034 if (Res.second) {
24035 // It will be analyzed later.
24036 MVLI.ProcessedVarList.push_back(RefExpr);
24037 }
24038 ValueDecl *D = Res.first;
24039 if (!D)
24040 continue;
24041 auto *VD = dyn_cast<VarDecl>(D);
24042
24043 // If required, build a capture to implement the privatization initialized
24044 // with the current list item value.
24045 DeclRefExpr *Ref = nullptr;
24046 if (!VD)
24047 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24048 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24049
24050 // We need to add a data sharing attribute for this variable to make sure it
24051 // is correctly captured. A variable that shows up in a use_device_addr has
24052 // similar properties of a first private variable.
24053 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24054
24055 // Create a mappable component for the list item. List items in this clause
24056 // only need a component.
24057 MVLI.VarBaseDeclarations.push_back(D);
24058 MVLI.VarComponents.emplace_back();
24059 Expr *Component = SimpleRefExpr;
24060 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24061 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24062 Component =
24064 MVLI.VarComponents.back().emplace_back(Component, D,
24065 /*IsNonContiguous=*/false);
24066 }
24067
24068 if (MVLI.ProcessedVarList.empty())
24069 return nullptr;
24070
24072 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24073 MVLI.VarComponents);
24074}
24075
24076OMPClause *
24078 const OMPVarListLocTy &Locs) {
24079 MappableVarListInfo MVLI(VarList);
24080 for (Expr *RefExpr : VarList) {
24081 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
24082 SourceLocation ELoc;
24083 SourceRange ERange;
24084 Expr *SimpleRefExpr = RefExpr;
24085 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24086 if (Res.second) {
24087 // It will be analyzed later.
24088 MVLI.ProcessedVarList.push_back(RefExpr);
24089 }
24090 ValueDecl *D = Res.first;
24091 if (!D)
24092 continue;
24093
24094 QualType Type = D->getType();
24095 // item should be a pointer or array or reference to pointer or array
24096 if (!Type.getNonReferenceType()->isPointerType() &&
24097 !Type.getNonReferenceType()->isArrayType()) {
24098 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24099 << 0 << RefExpr->getSourceRange();
24100 continue;
24101 }
24102
24103 // Check if the declaration in the clause does not show up in any data
24104 // sharing attribute.
24105 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24106 if (isOpenMPPrivate(DVar.CKind)) {
24107 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24108 << getOpenMPClauseName(DVar.CKind)
24109 << getOpenMPClauseName(OMPC_is_device_ptr)
24110 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
24112 continue;
24113 }
24114
24115 const Expr *ConflictExpr;
24116 if (DSAStack->checkMappableExprComponentListsForDecl(
24117 D, /*CurrentRegionOnly=*/true,
24118 [&ConflictExpr](
24120 OpenMPClauseKind) -> bool {
24121 ConflictExpr = R.front().getAssociatedExpression();
24122 return true;
24123 })) {
24124 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24125 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24126 << ConflictExpr->getSourceRange();
24127 continue;
24128 }
24129
24130 // Store the components in the stack so that they can be used to check
24131 // against other clauses later on.
24133 SimpleRefExpr, D, /*IsNonContiguous=*/false);
24134 DSAStack->addMappableExpressionComponents(
24135 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
24136
24137 // Record the expression we've just processed.
24138 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24139
24140 // Create a mappable component for the list item. List items in this clause
24141 // only need a component. We use a null declaration to signal fields in
24142 // 'this'.
24143 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24144 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24145 "Unexpected device pointer expression!");
24146 MVLI.VarBaseDeclarations.push_back(
24147 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24148 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24149 MVLI.VarComponents.back().push_back(MC);
24150 }
24151
24152 if (MVLI.ProcessedVarList.empty())
24153 return nullptr;
24154
24156 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24157 MVLI.VarComponents);
24158}
24159
24160OMPClause *
24162 const OMPVarListLocTy &Locs) {
24163 MappableVarListInfo MVLI(VarList);
24164 for (Expr *RefExpr : VarList) {
24165 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
24166 SourceLocation ELoc;
24167 SourceRange ERange;
24168 Expr *SimpleRefExpr = RefExpr;
24169 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24170 /*AllowArraySection=*/true);
24171 if (Res.second) {
24172 // It will be analyzed later.
24173 MVLI.ProcessedVarList.push_back(RefExpr);
24174 }
24175 ValueDecl *D = Res.first;
24176 if (!D)
24177 continue;
24178
24179 // Check if the declaration in the clause does not show up in any data
24180 // sharing attribute.
24181 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24182 if (isOpenMPPrivate(DVar.CKind)) {
24183 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24184 << getOpenMPClauseName(DVar.CKind)
24185 << getOpenMPClauseName(OMPC_has_device_addr)
24186 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
24188 continue;
24189 }
24190
24191 const Expr *ConflictExpr;
24192 if (DSAStack->checkMappableExprComponentListsForDecl(
24193 D, /*CurrentRegionOnly=*/true,
24194 [&ConflictExpr](
24196 OpenMPClauseKind) -> bool {
24197 ConflictExpr = R.front().getAssociatedExpression();
24198 return true;
24199 })) {
24200 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24201 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24202 << ConflictExpr->getSourceRange();
24203 continue;
24204 }
24205
24206 // Store the components in the stack so that they can be used to check
24207 // against other clauses later on.
24208 Expr *Component = SimpleRefExpr;
24209 auto *VD = dyn_cast<VarDecl>(D);
24210 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
24211 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
24212 Component =
24215 Component, D, /*IsNonContiguous=*/false);
24216 DSAStack->addMappableExpressionComponents(
24217 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
24218
24219 // Record the expression we've just processed.
24220 if (!VD && !SemaRef.CurContext->isDependentContext()) {
24221 DeclRefExpr *Ref =
24222 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24223 assert(Ref && "has_device_addr capture failed");
24224 MVLI.ProcessedVarList.push_back(Ref);
24225 } else
24226 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
24227
24228 // Create a mappable component for the list item. List items in this clause
24229 // only need a component. We use a null declaration to signal fields in
24230 // 'this'.
24231 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24232 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24233 "Unexpected device pointer expression!");
24234 MVLI.VarBaseDeclarations.push_back(
24235 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24236 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24237 MVLI.VarComponents.back().push_back(MC);
24238 }
24239
24240 if (MVLI.ProcessedVarList.empty())
24241 return nullptr;
24242
24244 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24245 MVLI.VarComponents);
24246}
24247
24249 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24250 SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
24251 if (Allocator) {
24252 // OpenMP [2.11.4 allocate Clause, Description]
24253 // allocator is an expression of omp_allocator_handle_t type.
24254 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
24255 return nullptr;
24256
24257 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
24258 if (AllocatorRes.isInvalid())
24259 return nullptr;
24260 AllocatorRes = SemaRef.PerformImplicitConversion(
24261 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
24263 /*AllowExplicit=*/true);
24264 if (AllocatorRes.isInvalid())
24265 return nullptr;
24266 Allocator = AllocatorRes.get();
24267 } else {
24268 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
24269 // allocate clauses that appear on a target construct or on constructs in a
24270 // target region must specify an allocator expression unless a requires
24271 // directive with the dynamic_allocators clause is present in the same
24272 // compilation unit.
24273 if (getLangOpts().OpenMPIsTargetDevice &&
24274 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
24275 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
24276 }
24277 // Analyze and build list of variables.
24279 for (Expr *RefExpr : VarList) {
24280 assert(RefExpr && "NULL expr in OpenMP private clause.");
24281 SourceLocation ELoc;
24282 SourceRange ERange;
24283 Expr *SimpleRefExpr = RefExpr;
24284 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24285 if (Res.second) {
24286 // It will be analyzed later.
24287 Vars.push_back(RefExpr);
24288 }
24289 ValueDecl *D = Res.first;
24290 if (!D)
24291 continue;
24292
24293 auto *VD = dyn_cast<VarDecl>(D);
24294 DeclRefExpr *Ref = nullptr;
24295 if (!VD && !SemaRef.CurContext->isDependentContext())
24296 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
24297 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
24298 ? RefExpr->IgnoreParens()
24299 : Ref);
24300 }
24301
24302 if (Vars.empty())
24303 return nullptr;
24304
24305 if (Allocator)
24306 DSAStack->addInnerAllocatorExpr(Allocator);
24307 return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc,
24308 Allocator, ColonLoc, EndLoc, Vars);
24309}
24310
24312 SourceLocation StartLoc,
24313 SourceLocation LParenLoc,
24314 SourceLocation EndLoc) {
24316 for (Expr *RefExpr : VarList) {
24317 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24318 SourceLocation ELoc;
24319 SourceRange ERange;
24320 Expr *SimpleRefExpr = RefExpr;
24321 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24322 if (Res.second)
24323 // It will be analyzed later.
24324 Vars.push_back(RefExpr);
24325 ValueDecl *D = Res.first;
24326 if (!D)
24327 continue;
24328
24329 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
24330 // A list-item cannot appear in more than one nontemporal clause.
24331 if (const Expr *PrevRef =
24332 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
24333 Diag(ELoc, diag::err_omp_used_in_clause_twice)
24334 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
24335 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
24336 << getOpenMPClauseName(OMPC_nontemporal);
24337 continue;
24338 }
24339
24340 Vars.push_back(RefExpr);
24341 }
24342
24343 if (Vars.empty())
24344 return nullptr;
24345
24346 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
24347 EndLoc, Vars);
24348}
24349
24351 Stmt *AStmt,
24352 SourceLocation StartLoc,
24353 SourceLocation EndLoc) {
24354 if (!AStmt)
24355 return StmtError();
24356
24358
24359 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
24360 AStmt);
24361}
24362
24364 SourceLocation StartLoc,
24365 SourceLocation LParenLoc,
24366 SourceLocation EndLoc) {
24368 for (Expr *RefExpr : VarList) {
24369 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24370 SourceLocation ELoc;
24371 SourceRange ERange;
24372 Expr *SimpleRefExpr = RefExpr;
24373 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24374 /*AllowArraySection=*/true);
24375 if (Res.second)
24376 // It will be analyzed later.
24377 Vars.push_back(RefExpr);
24378 ValueDecl *D = Res.first;
24379 if (!D)
24380 continue;
24381
24382 const DSAStackTy::DSAVarData DVar =
24383 DSAStack->getTopDSA(D, /*FromParent=*/true);
24384 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24385 // A list item that appears in the inclusive or exclusive clause must appear
24386 // in a reduction clause with the inscan modifier on the enclosing
24387 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24388 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
24389 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24390 << RefExpr->getSourceRange();
24391
24392 if (DSAStack->getParentDirective() != OMPD_unknown)
24393 DSAStack->markDeclAsUsedInScanDirective(D);
24394 Vars.push_back(RefExpr);
24395 }
24396
24397 if (Vars.empty())
24398 return nullptr;
24399
24400 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
24401 EndLoc, Vars);
24402}
24403
24405 SourceLocation StartLoc,
24406 SourceLocation LParenLoc,
24407 SourceLocation EndLoc) {
24409 for (Expr *RefExpr : VarList) {
24410 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
24411 SourceLocation ELoc;
24412 SourceRange ERange;
24413 Expr *SimpleRefExpr = RefExpr;
24414 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24415 /*AllowArraySection=*/true);
24416 if (Res.second)
24417 // It will be analyzed later.
24418 Vars.push_back(RefExpr);
24419 ValueDecl *D = Res.first;
24420 if (!D)
24421 continue;
24422
24423 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
24424 DSAStackTy::DSAVarData DVar;
24425 if (ParentDirective != OMPD_unknown)
24426 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
24427 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
24428 // A list item that appears in the inclusive or exclusive clause must appear
24429 // in a reduction clause with the inscan modifier on the enclosing
24430 // worksharing-loop, worksharing-loop SIMD, or simd construct.
24431 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
24432 DVar.Modifier != OMPC_REDUCTION_inscan) {
24433 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
24434 << RefExpr->getSourceRange();
24435 } else {
24436 DSAStack->markDeclAsUsedInScanDirective(D);
24437 }
24438 Vars.push_back(RefExpr);
24439 }
24440
24441 if (Vars.empty())
24442 return nullptr;
24443
24444 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
24445 EndLoc, Vars);
24446}
24447
24448/// Tries to find omp_alloctrait_t type.
24449static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
24450 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
24451 if (!OMPAlloctraitT.isNull())
24452 return true;
24453 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
24454 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
24455 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24456 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
24457 return false;
24458 }
24459 Stack->setOMPAlloctraitT(PT.get());
24460 return true;
24461}
24462
24464 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
24466 ASTContext &Context = getASTContext();
24467 // OpenMP [2.12.5, target Construct]
24468 // allocator is an identifier of omp_allocator_handle_t type.
24469 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
24470 return nullptr;
24471 // OpenMP [2.12.5, target Construct]
24472 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
24473 if (llvm::any_of(
24474 Data,
24475 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
24476 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
24477 return nullptr;
24478 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
24479 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
24480 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
24481 StringRef Allocator =
24482 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
24483 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
24484 PredefinedAllocators.insert(SemaRef.LookupSingleName(
24485 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
24486 }
24487
24489 for (const UsesAllocatorsData &D : Data) {
24490 Expr *AllocatorExpr = nullptr;
24491 // Check allocator expression.
24492 if (D.Allocator->isTypeDependent()) {
24493 AllocatorExpr = D.Allocator;
24494 } else {
24495 // Traits were specified - need to assign new allocator to the specified
24496 // allocator, so it must be an lvalue.
24497 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24498 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24499 bool IsPredefinedAllocator = false;
24500 if (DRE) {
24501 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24502 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
24503 IsPredefinedAllocator =
24504 AllocatorTy !=
24505 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24506 }
24507 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24508 QualType AllocatorExprType = AllocatorExpr->getType();
24509 bool IsTypeCompatible = IsPredefinedAllocator;
24510 IsTypeCompatible = IsTypeCompatible ||
24511 Context.hasSameUnqualifiedType(AllocatorExprType,
24512 OMPAllocatorHandleT);
24513 IsTypeCompatible =
24514 IsTypeCompatible ||
24515 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24516 bool IsNonConstantLValue =
24517 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
24518 if (!DRE || !IsTypeCompatible ||
24519 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24520 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24521 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24522 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24523 continue;
24524 }
24525 // OpenMP [2.12.5, target Construct]
24526 // Predefined allocators appearing in a uses_allocators clause cannot have
24527 // traits specified.
24528 if (IsPredefinedAllocator && D.AllocatorTraits) {
24530 diag::err_omp_predefined_allocator_with_traits)
24532 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24533 << cast<NamedDecl>(DRE->getDecl())->getName()
24534 << D.Allocator->getSourceRange();
24535 continue;
24536 }
24537 // OpenMP [2.12.5, target Construct]
24538 // Non-predefined allocators appearing in a uses_allocators clause must
24539 // have traits specified.
24540 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24542 diag::err_omp_nonpredefined_allocator_without_traits);
24543 continue;
24544 }
24545 // No allocator traits - just convert it to rvalue.
24546 if (!D.AllocatorTraits)
24547 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
24548 DSAStack->addUsesAllocatorsDecl(
24549 DRE->getDecl(),
24550 IsPredefinedAllocator
24551 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24552 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24553 }
24554 Expr *AllocatorTraitsExpr = nullptr;
24555 if (D.AllocatorTraits) {
24557 AllocatorTraitsExpr = D.AllocatorTraits;
24558 } else {
24559 // OpenMP [2.12.5, target Construct]
24560 // Arrays that contain allocator traits that appear in a uses_allocators
24561 // clause must be constant arrays, have constant values and be defined
24562 // in the same scope as the construct in which the clause appears.
24563 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24564 // Check that traits expr is a constant array.
24565 QualType TraitTy;
24566 if (const ArrayType *Ty =
24567 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24568 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24569 TraitTy = ConstArrayTy->getElementType();
24570 if (TraitTy.isNull() ||
24571 !(Context.hasSameUnqualifiedType(TraitTy,
24572 DSAStack->getOMPAlloctraitT()) ||
24573 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24574 /*CompareUnqualified=*/true))) {
24576 diag::err_omp_expected_array_alloctraits)
24577 << AllocatorTraitsExpr->getType();
24578 continue;
24579 }
24580 // Do not map by default allocator traits if it is a standalone
24581 // variable.
24582 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24583 DSAStack->addUsesAllocatorsDecl(
24584 DRE->getDecl(),
24585 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24586 }
24587 }
24588 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24589 NewD.Allocator = AllocatorExpr;
24590 NewD.AllocatorTraits = AllocatorTraitsExpr;
24591 NewD.LParenLoc = D.LParenLoc;
24592 NewD.RParenLoc = D.RParenLoc;
24593 }
24594 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
24595 EndLoc, NewData);
24596}
24597
24599 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24600 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24602 for (Expr *RefExpr : Locators) {
24603 assert(RefExpr && "NULL expr in OpenMP shared clause.");
24604 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24605 // It will be analyzed later.
24606 Vars.push_back(RefExpr);
24607 continue;
24608 }
24609
24610 SourceLocation ELoc = RefExpr->getExprLoc();
24611 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24612
24613 if (!SimpleExpr->isLValue()) {
24614 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24615 << 1 << 0 << RefExpr->getSourceRange();
24616 continue;
24617 }
24618
24619 ExprResult Res;
24620 {
24622 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24623 }
24624 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
24625 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
24626 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24627 << 1 << 0 << RefExpr->getSourceRange();
24628 continue;
24629 }
24630 Vars.push_back(SimpleExpr);
24631 }
24632
24633 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
24634 ColonLoc, EndLoc, Modifier, Vars);
24635}
24636
24638 SourceLocation KindLoc,
24639 SourceLocation StartLoc,
24640 SourceLocation LParenLoc,
24641 SourceLocation EndLoc) {
24642 if (Kind == OMPC_BIND_unknown) {
24643 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24644 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24645 /*Last=*/unsigned(OMPC_BIND_unknown))
24646 << getOpenMPClauseName(OMPC_bind);
24647 return nullptr;
24648 }
24649
24650 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
24651 LParenLoc, EndLoc);
24652}
24653
24655 SourceLocation StartLoc,
24656 SourceLocation LParenLoc,
24657 SourceLocation EndLoc) {
24658 Expr *ValExpr = Size;
24659 Stmt *HelperValStmt = nullptr;
24660
24661 // OpenMP [2.5, Restrictions]
24662 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24663 // value.
24664 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
24665 /*StrictlyPositive=*/false))
24666 return nullptr;
24667
24668 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24670 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
24671 if (CaptureRegion != OMPD_unknown &&
24673 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24674 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24675 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24676 HelperValStmt = buildPreInits(getASTContext(), Captures);
24677 }
24678
24680 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24681}
24682
24685 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24686 SourceLocation LParenLoc, SourceLocation EndLoc) {
24687
24688 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24689 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24690 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24691 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
24692 DepType != OMPC_DOACROSS_source) {
24693 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24694 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
24695 return nullptr;
24696 }
24697
24700 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24701 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24702 SemaRef,
24703 DepType == OMPC_DOACROSS_source ||
24704 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24705 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24706 VarList, DSAStack, EndLoc);
24707 Vars = VarOffset.Vars;
24708 OpsOffs = VarOffset.OpsOffs;
24709 TotalDepCount = VarOffset.TotalDepCount;
24710 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
24711 EndLoc, DepType, DepLoc, ColonLoc, Vars,
24712 TotalDepCount.getZExtValue());
24713 if (DSAStack->isParentOrderedRegion())
24714 DSAStack->addDoacrossDependClause(C, OpsOffs);
24715 return C;
24716}
24717
24719 SourceLocation StartLoc,
24720 SourceLocation LParenLoc,
24721 SourceLocation EndLoc) {
24722 return new (getASTContext())
24723 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24724}
24725
24727 SourceLocation EndLoc) {
24728 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
24729}
24730
24732 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
24733 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
24734 Expr *Stride, SourceLocation RBLoc) {
24735 ASTContext &Context = getASTContext();
24736 if (Base->hasPlaceholderType() &&
24737 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24739 if (Result.isInvalid())
24740 return ExprError();
24741 Base = Result.get();
24742 }
24743 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
24745 if (Result.isInvalid())
24746 return ExprError();
24748 if (Result.isInvalid())
24749 return ExprError();
24750 LowerBound = Result.get();
24751 }
24752 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24754 if (Result.isInvalid())
24755 return ExprError();
24757 if (Result.isInvalid())
24758 return ExprError();
24759 Length = Result.get();
24760 }
24761 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
24763 if (Result.isInvalid())
24764 return ExprError();
24766 if (Result.isInvalid())
24767 return ExprError();
24768 Stride = Result.get();
24769 }
24770
24771 // Build an unanalyzed expression if either operand is type-dependent.
24772 if (Base->isTypeDependent() ||
24773 (LowerBound &&
24774 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
24775 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24776 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
24777 return new (Context) ArraySectionExpr(
24778 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
24779 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24780 }
24781
24782 // Perform default conversions.
24784 QualType ResultTy;
24785 if (OriginalTy->isAnyPointerType()) {
24786 ResultTy = OriginalTy->getPointeeType();
24787 } else if (OriginalTy->isArrayType()) {
24788 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
24789 } else {
24790 return ExprError(
24791 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
24792 << Base->getSourceRange());
24793 }
24794 // C99 6.5.2.1p1
24795 if (LowerBound) {
24796 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
24797 LowerBound);
24798 if (Res.isInvalid())
24799 return ExprError(Diag(LowerBound->getExprLoc(),
24800 diag::err_omp_typecheck_section_not_integer)
24801 << 0 << LowerBound->getSourceRange());
24802 LowerBound = Res.get();
24803
24804 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24805 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24806 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
24807 << 0 << LowerBound->getSourceRange();
24808 }
24809 if (Length) {
24810 auto Res =
24811 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
24812 if (Res.isInvalid())
24813 return ExprError(Diag(Length->getExprLoc(),
24814 diag::err_omp_typecheck_section_not_integer)
24815 << 1 << Length->getSourceRange());
24816 Length = Res.get();
24817
24818 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24819 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24820 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
24821 << 1 << Length->getSourceRange();
24822 }
24823 if (Stride) {
24824 ExprResult Res =
24826 if (Res.isInvalid())
24827 return ExprError(Diag(Stride->getExprLoc(),
24828 diag::err_omp_typecheck_section_not_integer)
24829 << 1 << Stride->getSourceRange());
24830 Stride = Res.get();
24831
24832 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24833 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24834 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
24835 << 1 << Stride->getSourceRange();
24836 }
24837
24838 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
24839 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
24840 // type. Note that functions are not objects, and that (in C99 parlance)
24841 // incomplete types are not object types.
24842 if (ResultTy->isFunctionType()) {
24843 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
24844 << ResultTy << Base->getSourceRange();
24845 return ExprError();
24846 }
24847
24848 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
24849 diag::err_omp_section_incomplete_type, Base))
24850 return ExprError();
24851
24852 if (LowerBound && !OriginalTy->isAnyPointerType()) {
24854 if (LowerBound->EvaluateAsInt(Result, Context)) {
24855 // OpenMP 5.0, [2.1.5 Array Sections]
24856 // The array section must be a subset of the original array.
24857 llvm::APSInt LowerBoundValue = Result.Val.getInt();
24858 if (LowerBoundValue.isNegative()) {
24859 Diag(LowerBound->getExprLoc(),
24860 diag::err_omp_section_not_subset_of_array)
24861 << LowerBound->getSourceRange();
24862 return ExprError();
24863 }
24864 }
24865 }
24866
24867 if (Length) {
24869 if (Length->EvaluateAsInt(Result, Context)) {
24870 // OpenMP 5.0, [2.1.5 Array Sections]
24871 // The length must evaluate to non-negative integers.
24872 llvm::APSInt LengthValue = Result.Val.getInt();
24873 if (LengthValue.isNegative()) {
24874 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
24875 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
24876 << Length->getSourceRange();
24877 return ExprError();
24878 }
24879 }
24880 } else if (ColonLocFirst.isValid() &&
24881 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
24882 !OriginalTy->isVariableArrayType()))) {
24883 // OpenMP 5.0, [2.1.5 Array Sections]
24884 // When the size of the array dimension is not known, the length must be
24885 // specified explicitly.
24886 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
24887 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
24888 return ExprError();
24889 }
24890
24891 if (Stride) {
24893 if (Stride->EvaluateAsInt(Result, Context)) {
24894 // OpenMP 5.0, [2.1.5 Array Sections]
24895 // The stride must evaluate to a positive integer.
24896 llvm::APSInt StrideValue = Result.Val.getInt();
24897 if (!StrideValue.isStrictlyPositive()) {
24898 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
24899 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
24900 << Stride->getSourceRange();
24901 return ExprError();
24902 }
24903 }
24904 }
24905
24906 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24908 if (Result.isInvalid())
24909 return ExprError();
24910 Base = Result.get();
24911 }
24912 return new (Context) ArraySectionExpr(
24913 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
24914 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24915}
24916
24918 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
24919 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
24920 ASTContext &Context = getASTContext();
24921 if (Base->hasPlaceholderType()) {
24923 if (Result.isInvalid())
24924 return ExprError();
24926 if (Result.isInvalid())
24927 return ExprError();
24928 Base = Result.get();
24929 }
24930 QualType BaseTy = Base->getType();
24931 // Delay analysis of the types/expressions if instantiation/specialization is
24932 // required.
24933 if (!BaseTy->isPointerType() && Base->isTypeDependent())
24934 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
24935 LParenLoc, RParenLoc, Dims, Brackets);
24936 if (!BaseTy->isPointerType() ||
24937 (!Base->isTypeDependent() &&
24938 BaseTy->getPointeeType()->isIncompleteType()))
24939 return ExprError(Diag(Base->getExprLoc(),
24940 diag::err_omp_non_pointer_type_array_shaping_base)
24941 << Base->getSourceRange());
24942
24943 SmallVector<Expr *, 4> NewDims;
24944 bool ErrorFound = false;
24945 for (Expr *Dim : Dims) {
24946 if (Dim->hasPlaceholderType()) {
24948 if (Result.isInvalid()) {
24949 ErrorFound = true;
24950 continue;
24951 }
24953 if (Result.isInvalid()) {
24954 ErrorFound = true;
24955 continue;
24956 }
24957 Dim = Result.get();
24958 }
24959 if (!Dim->isTypeDependent()) {
24961 PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
24962 if (Result.isInvalid()) {
24963 ErrorFound = true;
24964 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
24965 << Dim->getSourceRange();
24966 continue;
24967 }
24968 Dim = Result.get();
24969 Expr::EvalResult EvResult;
24970 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
24971 // OpenMP 5.0, [2.1.4 Array Shaping]
24972 // Each si is an integral type expression that must evaluate to a
24973 // positive integer.
24974 llvm::APSInt Value = EvResult.Val.getInt();
24975 if (!Value.isStrictlyPositive()) {
24976 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
24977 << toString(Value, /*Radix=*/10, /*Signed=*/true)
24978 << Dim->getSourceRange();
24979 ErrorFound = true;
24980 continue;
24981 }
24982 }
24983 }
24984 NewDims.push_back(Dim);
24985 }
24986 if (ErrorFound)
24987 return ExprError();
24988 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
24989 LParenLoc, RParenLoc, NewDims, Brackets);
24990}
24991
24993 SourceLocation IteratorKwLoc,
24994 SourceLocation LLoc,
24995 SourceLocation RLoc,
24997 ASTContext &Context = getASTContext();
24999 bool IsCorrect = true;
25000 for (const OMPIteratorData &D : Data) {
25001 TypeSourceInfo *TInfo = nullptr;
25002 SourceLocation StartLoc;
25003 QualType DeclTy;
25004 if (!D.Type.getAsOpaquePtr()) {
25005 // OpenMP 5.0, 2.1.6 Iterators
25006 // In an iterator-specifier, if the iterator-type is not specified then
25007 // the type of that iterator is of int type.
25008 DeclTy = Context.IntTy;
25009 StartLoc = D.DeclIdentLoc;
25010 } else {
25011 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
25012 StartLoc = TInfo->getTypeLoc().getBeginLoc();
25013 }
25014
25015 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25016 DeclTy->containsUnexpandedParameterPack() ||
25017 DeclTy->isInstantiationDependentType();
25018 if (!IsDeclTyDependent) {
25019 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25020 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25021 // The iterator-type must be an integral or pointer type.
25022 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25023 << DeclTy;
25024 IsCorrect = false;
25025 continue;
25026 }
25027 if (DeclTy.isConstant(Context)) {
25028 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25029 // The iterator-type must not be const qualified.
25030 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25031 << DeclTy;
25032 IsCorrect = false;
25033 continue;
25034 }
25035 }
25036
25037 // Iterator declaration.
25038 assert(D.DeclIdent && "Identifier expected.");
25039 // Always try to create iterator declarator to avoid extra error messages
25040 // about unknown declarations use.
25041 auto *VD =
25042 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
25043 D.DeclIdent, DeclTy, TInfo, SC_None);
25044 VD->setImplicit();
25045 if (S) {
25046 // Check for conflicting previous declaration.
25047 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
25049 RedeclarationKind::ForVisibleRedeclaration);
25050 Previous.suppressDiagnostics();
25052
25054 /*ConsiderLinkage=*/false,
25055 /*AllowInlineNamespace=*/false);
25056 if (!Previous.empty()) {
25057 NamedDecl *Old = Previous.getRepresentativeDecl();
25058 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
25059 Diag(Old->getLocation(), diag::note_previous_definition);
25060 } else {
25062 }
25063 } else {
25065 }
25066
25067 /// Act on the iterator variable declaration.
25069
25070 Expr *Begin = D.Range.Begin;
25071 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
25072 ExprResult BeginRes =
25074 Begin = BeginRes.get();
25075 }
25076 Expr *End = D.Range.End;
25077 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
25078 ExprResult EndRes =
25080 End = EndRes.get();
25081 }
25082 Expr *Step = D.Range.Step;
25083 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
25084 if (!Step->getType()->isIntegralType(Context)) {
25085 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
25086 << Step << Step->getSourceRange();
25087 IsCorrect = false;
25088 continue;
25089 }
25090 std::optional<llvm::APSInt> Result =
25091 Step->getIntegerConstantExpr(Context);
25092 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
25093 // If the step expression of a range-specification equals zero, the
25094 // behavior is unspecified.
25095 if (Result && Result->isZero()) {
25096 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
25097 << Step << Step->getSourceRange();
25098 IsCorrect = false;
25099 continue;
25100 }
25101 }
25102 if (!Begin || !End || !IsCorrect) {
25103 IsCorrect = false;
25104 continue;
25105 }
25106 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
25107 IDElem.IteratorDecl = VD;
25108 IDElem.AssignmentLoc = D.AssignLoc;
25109 IDElem.Range.Begin = Begin;
25110 IDElem.Range.End = End;
25111 IDElem.Range.Step = Step;
25112 IDElem.ColonLoc = D.ColonLoc;
25113 IDElem.SecondColonLoc = D.SecColonLoc;
25114 }
25115 if (!IsCorrect) {
25116 // Invalidate all created iterator declarations if error is found.
25117 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25118 if (Decl *ID = D.IteratorDecl)
25119 ID->setInvalidDecl();
25120 }
25121 return ExprError();
25122 }
25125 // Build number of ityeration for each iteration range.
25126 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
25127 // ((Begini-Stepi-1-Endi) / -Stepi);
25129 // (Endi - Begini)
25130 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
25131 D.Range.End, D.Range.Begin);
25132 if (!Res.isUsable()) {
25133 IsCorrect = false;
25134 continue;
25135 }
25136 ExprResult St, St1;
25137 if (D.Range.Step) {
25138 St = D.Range.Step;
25139 // (Endi - Begini) + Stepi
25140 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
25141 St.get());
25142 if (!Res.isUsable()) {
25143 IsCorrect = false;
25144 continue;
25145 }
25146 // (Endi - Begini) + Stepi - 1
25148 D.AssignmentLoc, BO_Sub, Res.get(),
25149 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25150 if (!Res.isUsable()) {
25151 IsCorrect = false;
25152 continue;
25153 }
25154 // ((Endi - Begini) + Stepi - 1) / Stepi
25155 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
25156 St.get());
25157 if (!Res.isUsable()) {
25158 IsCorrect = false;
25159 continue;
25160 }
25161 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
25162 D.Range.Step);
25163 // (Begini - Endi)
25165 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
25166 if (!Res1.isUsable()) {
25167 IsCorrect = false;
25168 continue;
25169 }
25170 // (Begini - Endi) - Stepi
25171 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
25172 St1.get());
25173 if (!Res1.isUsable()) {
25174 IsCorrect = false;
25175 continue;
25176 }
25177 // (Begini - Endi) - Stepi - 1
25179 D.AssignmentLoc, BO_Sub, Res1.get(),
25180 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
25181 if (!Res1.isUsable()) {
25182 IsCorrect = false;
25183 continue;
25184 }
25185 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
25186 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
25187 St1.get());
25188 if (!Res1.isUsable()) {
25189 IsCorrect = false;
25190 continue;
25191 }
25192 // Stepi > 0.
25194 D.AssignmentLoc, BO_GT, D.Range.Step,
25195 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
25196 if (!CmpRes.isUsable()) {
25197 IsCorrect = false;
25198 continue;
25199 }
25200 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
25201 CmpRes.get(), Res.get(), Res1.get());
25202 if (!Res.isUsable()) {
25203 IsCorrect = false;
25204 continue;
25205 }
25206 }
25207 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
25208 if (!Res.isUsable()) {
25209 IsCorrect = false;
25210 continue;
25211 }
25212
25213 // Build counter update.
25214 // Build counter.
25215 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
25216 D.IteratorDecl->getBeginLoc(),
25217 D.IteratorDecl->getBeginLoc(), nullptr,
25218 Res.get()->getType(), nullptr, SC_None);
25219 CounterVD->setImplicit();
25220 ExprResult RefRes =
25221 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
25222 D.IteratorDecl->getBeginLoc());
25223 // Build counter update.
25224 // I = Begini + counter * Stepi;
25225 ExprResult UpdateRes;
25226 if (D.Range.Step) {
25227 UpdateRes = SemaRef.CreateBuiltinBinOp(
25228 D.AssignmentLoc, BO_Mul,
25229 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
25230 } else {
25231 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
25232 }
25233 if (!UpdateRes.isUsable()) {
25234 IsCorrect = false;
25235 continue;
25236 }
25237 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
25238 D.Range.Begin, UpdateRes.get());
25239 if (!UpdateRes.isUsable()) {
25240 IsCorrect = false;
25241 continue;
25242 }
25243 ExprResult VDRes =
25244 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
25245 cast<VarDecl>(D.IteratorDecl)->getType(),
25246 VK_LValue, D.IteratorDecl->getBeginLoc());
25247 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
25248 VDRes.get(), UpdateRes.get());
25249 if (!UpdateRes.isUsable()) {
25250 IsCorrect = false;
25251 continue;
25252 }
25253 UpdateRes =
25254 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
25255 if (!UpdateRes.isUsable()) {
25256 IsCorrect = false;
25257 continue;
25258 }
25259 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
25260 D.AssignmentLoc, UO_PreInc, RefRes.get());
25261 if (!CounterUpdateRes.isUsable()) {
25262 IsCorrect = false;
25263 continue;
25264 }
25265 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
25266 /*DiscardedValue=*/true);
25267 if (!CounterUpdateRes.isUsable()) {
25268 IsCorrect = false;
25269 continue;
25270 }
25271 OMPIteratorHelperData &HD = Helpers.emplace_back();
25272 HD.CounterVD = CounterVD;
25273 HD.Upper = Res.get();
25274 HD.Update = UpdateRes.get();
25275 HD.CounterUpdate = CounterUpdateRes.get();
25276 }
25277 } else {
25278 Helpers.assign(ID.size(), {});
25279 }
25280 if (!IsCorrect) {
25281 // Invalidate all created iterator declarations if error is found.
25282 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
25283 if (Decl *ID = D.IteratorDecl)
25284 ID->setInvalidDecl();
25285 }
25286 return ExprError();
25287 }
25288 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
25289 LLoc, RLoc, ID, Helpers);
25290}
25291
25293 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3285
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:2979
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:48
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.
SourceRange Range
Definition: SemaObjC.cpp:754
SourceLocation Loc
Definition: SemaObjC.cpp:755
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:1204
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2575
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2591
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:1132
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:1591
CanQualType OMPIteratorTy
Definition: ASTContext.h:1132
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:1131
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:2618
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:2341
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:1569
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:5068
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:3518
QualType getElementType() const
Definition: Type.h:3530
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:74
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition: DeclSpec.h:215
SourceLocation getBeginLoc() const
Definition: DeclSpec.h:84
bool isSet() const
Deprecated.
Definition: DeclSpec.h:228
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:213
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:4686
unsigned getNumParams() const
Definition: Decl.h:4728
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5444
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4730
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:3086
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:1348
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1282
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:1716
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:1333
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
Definition: DeclBase.cpp:1352
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1690
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
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition: Expr.h:1452
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Expr.cpp:556
ConstexprSpecKind getConstexprSpecifier() const
Definition: DeclSpec.h:829
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:991
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:1900
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition: DeclSpec.h:2047
SourceLocation getIdentifierLoc() const
Definition: DeclSpec.h:2336
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition: DeclSpec.h:2339
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclSpec.h:2083
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition: DeclSpec.h:2733
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition: DeclSpec.h:2062
bool isInvalidType() const
Definition: DeclSpec.h:2714
const IdentifierInfo * getIdentifier() const
Definition: DeclSpec.h:2330
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:3057
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3148
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3281
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:2706
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2683
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2432
bool isConsteval() const
Definition: Decl.h:2444
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:4656
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:8601
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:675
Represents the results of name lookup.
Definition: Lookup.h:46
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition: Lookup.h:605
DeclClass * getAsSingle() const
Definition: Lookup.h:558
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:749
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition: Lookup.h:568
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:575
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition: Lookup.h:634
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:5149
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:5278
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
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
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:4880
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:2729
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: Type.h:7448
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:3469
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:7359
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:7560
QualType getCanonicalType() const
Definition: Type.h:7411
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7453
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition: Type.h:7531
const Type * getTypePtrOrNull() const
Definition: Type.h:7363
Represents a struct/union/class.
Definition: Decl.h:4168
field_range fields() const
Definition: Decl.h:4374
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5549
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:3380
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:381
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition: Scope.h:305
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition: Scope.h:530
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition: Scope.h:270
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition: Scope.h:523
@ 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:855
Expr * get() const
Definition: Sema.h:5759
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:9449
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:5708
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:451
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
Definition: SemaType.cpp:6350
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:688
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:1585
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
Definition: SemaExpr.cpp:3689
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15428
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:7289
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:7330
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:7332
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:7334
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:3468
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17296
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:20261
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:797
@ AR_inaccessible
Definition: Sema.h:1076
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:2251
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:6326
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:17081
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1422
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:20046
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:848
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4630
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:67
@ AllowFold
Definition: Sema.h:5724
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1523
void CleanupVarDeclMarking()
Definition: SemaExpr.cpp:19525
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:764
ASTContext & getASTContext() const
Definition: Sema.h:517
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15710
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:18817
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:19776
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:17722
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:765
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2208
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:2132
const LangOptions & getLangOpts() const
Definition: Sema.h:510
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...
bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, QualType ObjectType, 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...
Preprocessor & PP
Definition: Sema.h:847
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:6507
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:846
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2366
DeclContext * getCurLexicalContext() const
Definition: Sema.h:692
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3341
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
Definition: SemaStmt.cpp:4541
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:882
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:652
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition: Sema.h:11609
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20416
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2322
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:986
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4645
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4194
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:20849
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:10402
@ TryCapture_ExplicitByVal
Definition: Sema.h:5238
@ AA_Initializing
Definition: Sema.h:5162
@ AA_Converting
Definition: Sema.h:5161
@ AA_Casting
Definition: Sema.h:5164
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:11229
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:8872
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:11584
@ CTK_ErrorRecovery
Definition: Sema.h:7529
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2307
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:8577
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:291
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5211
@ 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:5678
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:79
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:8831
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:820
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:17800
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1330
void PopDeclContext()
Definition: SemaDecl.cpp:1337
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:1607
MemberExpr * BuildMemberExpr(Expr *Base, bool IsArrow, SourceLocation OpLoc, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, ValueDecl *Member, DeclAccessPair FoundDecl, bool HadMultipleCandidates, const DeclarationNameInfo &MemberNameInfo, QualType Ty, ExprValueKind VK, ExprObjectKind OK, const TemplateArgumentListInfo *TemplateArgs=nullptr)
void ActOnUninitializedDecl(Decl *dcl)
Definition: SemaDecl.cpp:14001
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13438
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:15275
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:14739
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:2337
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2706
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:2805
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:415
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:5773
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:6652
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:1561
bool isVLASupported() const
Whether target supports variable-length arrays.
Definition: TargetInfo.h:1572
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition: Decl.h:3390
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7330
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:7341
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:1871
bool isConstantArrayType() const
Definition: Type.h:7682
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:2010
bool isArrayType() const
Definition: Type.h:7678
bool isArithmeticType() const
Definition: Type.cpp:2270
bool isPointerType() const
Definition: Type.h:7612
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:7945
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8193
bool isReferenceType() const
Definition: Type.h:7624
bool isEnumeralType() const
Definition: Type.h:7710
bool isScalarType() const
Definition: Type.h:8004
bool isVariableArrayType() const
Definition: Type.h:7690
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2047
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:695
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2225
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: Type.h:7899
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2661
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:7874
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2653
bool isAnyComplexType() const
Definition: Type.h:7714
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:2175
bool isFunctionProtoType() const
Definition: Type.h:2494
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition: Type.h:8046
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: Type.h:2671
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8179
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition: Type.cpp:2351
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition: Type.h:8143
bool isFunctionType() const
Definition: Type.h:7608
bool isStructureOrClassType() const
Definition: Type.cpp:647
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2255
bool isFloatingType() const
Definition: Type.cpp:2238
bool isAnyPointerType() const
Definition: Type.h:7616
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8126
bool isRecordType() const
Definition: Type.h:7706
bool isUnionType() const
Definition: Type.cpp:661
bool isFunctionNoProtoType() const
Definition: Type.h:2493
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1875
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:5047
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
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition: Specifiers.h:174
unsigned long uint64_t
#define true
Definition: stdbool.h:25
#define false
Definition: stdbool.h:26
#define bool
Definition: stdbool.h:24
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:4735
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.