clang 20.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
16#include "TreeTransform.h"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclCXX.h"
25#include "clang/AST/StmtCXX.h"
34#include "clang/Sema/Lookup.h"
36#include "clang/Sema/Scope.h"
38#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/Sequence.h"
43#include "llvm/ADT/SetVector.h"
44#include "llvm/ADT/SmallSet.h"
45#include "llvm/ADT/StringExtras.h"
46#include "llvm/Frontend/OpenMP/OMPAssume.h"
47#include "llvm/Frontend/OpenMP/OMPConstants.h"
48#include "llvm/IR/Assumptions.h"
49#include <optional>
50
51using namespace clang;
52using namespace llvm::omp;
53
54//===----------------------------------------------------------------------===//
55// Stack of data-sharing attributes for variables
56//===----------------------------------------------------------------------===//
57
59 Sema &SemaRef, Expr *E,
61 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
62
63namespace {
64/// Default data sharing attributes, which can be applied to directive.
65enum DefaultDataSharingAttributes {
66 DSA_unspecified = 0, /// Data sharing attribute not specified.
67 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
68 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
69 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
70 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
71};
72
73/// Stack for tracking declarations used in OpenMP directives and
74/// clauses and their data-sharing attributes.
75class DSAStackTy {
76public:
77 struct DSAVarData {
78 OpenMPDirectiveKind DKind = OMPD_unknown;
79 OpenMPClauseKind CKind = OMPC_unknown;
80 unsigned Modifier = 0;
81 const Expr *RefExpr = nullptr;
82 DeclRefExpr *PrivateCopy = nullptr;
83 SourceLocation ImplicitDSALoc;
84 bool AppliedToPointee = false;
85 DSAVarData() = default;
86 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
87 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
88 SourceLocation ImplicitDSALoc, unsigned Modifier,
89 bool AppliedToPointee)
90 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
91 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
92 AppliedToPointee(AppliedToPointee) {}
93 };
94 using OperatorOffsetTy =
96 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
97 /// Kind of the declaration used in the uses_allocators clauses.
98 enum class UsesAllocatorsDeclKind {
99 /// Predefined allocator
100 PredefinedAllocator,
101 /// User-defined allocator
102 UserDefinedAllocator,
103 /// The declaration that represent allocator trait
104 AllocatorTrait,
105 };
106
107private:
108 struct DSAInfo {
109 OpenMPClauseKind Attributes = OMPC_unknown;
110 unsigned Modifier = 0;
111 /// Pointer to a reference expression and a flag which shows that the
112 /// variable is marked as lastprivate(true) or not (false).
113 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
114 DeclRefExpr *PrivateCopy = nullptr;
115 /// true if the attribute is applied to the pointee, not the variable
116 /// itself.
117 bool AppliedToPointee = false;
118 };
119 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
120 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
121 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
122 using LoopControlVariablesMapTy =
123 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
124 /// Struct that associates a component with the clause kind where they are
125 /// found.
126 struct MappedExprComponentTy {
128 OpenMPClauseKind Kind = OMPC_unknown;
129 };
130 using MappedExprComponentsTy =
131 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
132 using CriticalsWithHintsTy =
133 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
134 struct ReductionData {
135 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
136 SourceRange ReductionRange;
137 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
138 ReductionData() = default;
139 void set(BinaryOperatorKind BO, SourceRange RR) {
140 ReductionRange = RR;
141 ReductionOp = BO;
142 }
143 void set(const Expr *RefExpr, SourceRange RR) {
144 ReductionRange = RR;
145 ReductionOp = RefExpr;
146 }
147 };
148 using DeclReductionMapTy =
149 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
150 struct DefaultmapInfo {
151 OpenMPDefaultmapClauseModifier ImplicitBehavior =
153 SourceLocation SLoc;
154 DefaultmapInfo() = default;
156 : ImplicitBehavior(M), SLoc(Loc) {}
157 };
158
159 struct SharingMapTy {
160 DeclSAMapTy SharingMap;
161 DeclReductionMapTy ReductionMap;
162 UsedRefMapTy AlignedMap;
163 UsedRefMapTy NontemporalMap;
164 MappedExprComponentsTy MappedExprComponents;
165 LoopControlVariablesMapTy LCVMap;
166 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
167 SourceLocation DefaultAttrLoc;
168 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
169 OpenMPDirectiveKind Directive = OMPD_unknown;
170 DeclarationNameInfo DirectiveName;
171 Scope *CurScope = nullptr;
172 DeclContext *Context = nullptr;
173 SourceLocation ConstructLoc;
174 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
175 /// get the data (loop counters etc.) about enclosing loop-based construct.
176 /// This data is required during codegen.
177 DoacrossClauseMapTy DoacrossDepends;
178 /// First argument (Expr *) contains optional argument of the
179 /// 'ordered' clause, the second one is true if the regions has 'ordered'
180 /// clause, false otherwise.
181 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
182 bool RegionHasOrderConcurrent = false;
183 unsigned AssociatedLoops = 1;
184 bool HasMutipleLoops = false;
185 const Decl *PossiblyLoopCounter = nullptr;
186 bool NowaitRegion = false;
187 bool UntiedRegion = false;
188 bool CancelRegion = false;
189 bool LoopStart = false;
190 bool BodyComplete = false;
191 SourceLocation PrevScanLocation;
192 SourceLocation PrevOrderedLocation;
193 SourceLocation InnerTeamsRegionLoc;
194 /// Reference to the taskgroup task_reduction reference expression.
195 Expr *TaskgroupReductionRef = nullptr;
196 llvm::DenseSet<QualType> MappedClassesQualTypes;
197 SmallVector<Expr *, 4> InnerUsedAllocators;
198 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
199 /// List of globals marked as declare target link in this target region
200 /// (isOpenMPTargetExecutionDirective(Directive) == true).
201 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
202 /// List of decls used in inclusive/exclusive clauses of the scan directive.
203 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
204 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
205 UsesAllocatorsDecls;
206 /// Data is required on creating capture fields for implicit
207 /// default first|private clause.
208 struct ImplicitDefaultFDInfoTy {
209 /// Field decl.
210 const FieldDecl *FD = nullptr;
211 /// Nesting stack level
212 size_t StackLevel = 0;
213 /// Capture variable decl.
214 VarDecl *VD = nullptr;
215 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
216 VarDecl *VD)
217 : FD(FD), StackLevel(StackLevel), VD(VD) {}
218 };
219 /// List of captured fields
221 ImplicitDefaultFirstprivateFDs;
222 Expr *DeclareMapperVar = nullptr;
223 SmallVector<VarDecl *, 16> IteratorVarDecls;
224 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
225 Scope *CurScope, SourceLocation Loc)
226 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
227 ConstructLoc(Loc) {}
228 SharingMapTy() = default;
229 };
230
231 using StackTy = SmallVector<SharingMapTy, 4>;
232
233 /// Stack of used declaration and their data-sharing attributes.
234 DeclSAMapTy Threadprivates;
235 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
237 /// true, if check for DSA must be from parent directive, false, if
238 /// from current directive.
239 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
240 Sema &SemaRef;
241 bool ForceCapturing = false;
242 /// true if all the variables in the target executable directives must be
243 /// captured by reference.
244 bool ForceCaptureByReferenceInTargetExecutable = false;
245 CriticalsWithHintsTy Criticals;
246 unsigned IgnoredStackElements = 0;
247
248 /// Iterators over the stack iterate in order from innermost to outermost
249 /// directive.
250 using const_iterator = StackTy::const_reverse_iterator;
251 const_iterator begin() const {
252 return Stack.empty() ? const_iterator()
253 : Stack.back().first.rbegin() + IgnoredStackElements;
254 }
255 const_iterator end() const {
256 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
257 }
258 using iterator = StackTy::reverse_iterator;
259 iterator begin() {
260 return Stack.empty() ? iterator()
261 : Stack.back().first.rbegin() + IgnoredStackElements;
262 }
263 iterator end() {
264 return Stack.empty() ? iterator() : Stack.back().first.rend();
265 }
266
267 // Convenience operations to get at the elements of the stack.
268
269 bool isStackEmpty() const {
270 return Stack.empty() ||
271 Stack.back().second != CurrentNonCapturingFunctionScope ||
272 Stack.back().first.size() <= IgnoredStackElements;
273 }
274 size_t getStackSize() const {
275 return isStackEmpty() ? 0
276 : Stack.back().first.size() - IgnoredStackElements;
277 }
278
279 SharingMapTy *getTopOfStackOrNull() {
280 size_t Size = getStackSize();
281 if (Size == 0)
282 return nullptr;
283 return &Stack.back().first[Size - 1];
284 }
285 const SharingMapTy *getTopOfStackOrNull() const {
286 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
287 }
288 SharingMapTy &getTopOfStack() {
289 assert(!isStackEmpty() && "no current directive");
290 return *getTopOfStackOrNull();
291 }
292 const SharingMapTy &getTopOfStack() const {
293 return const_cast<DSAStackTy &>(*this).getTopOfStack();
294 }
295
296 SharingMapTy *getSecondOnStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size <= 1)
299 return nullptr;
300 return &Stack.back().first[Size - 2];
301 }
302 const SharingMapTy *getSecondOnStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
304 }
305
306 /// Get the stack element at a certain level (previously returned by
307 /// \c getNestingLevel).
308 ///
309 /// Note that nesting levels count from outermost to innermost, and this is
310 /// the reverse of our iteration order where new inner levels are pushed at
311 /// the front of the stack.
312 SharingMapTy &getStackElemAtLevel(unsigned Level) {
313 assert(Level < getStackSize() && "no such stack element");
314 return Stack.back().first[Level];
315 }
316 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
317 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
318 }
319
320 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
321
322 /// Checks if the variable is a local for OpenMP region.
323 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
324
325 /// Vector of previously declared requires directives
327 /// omp_allocator_handle_t type.
328 QualType OMPAllocatorHandleT;
329 /// omp_depend_t type.
330 QualType OMPDependT;
331 /// omp_event_handle_t type.
332 QualType OMPEventHandleT;
333 /// omp_alloctrait_t type.
334 QualType OMPAlloctraitT;
335 /// Expression for the predefined allocators.
336 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
337 nullptr};
338 /// Vector of previously encountered target directives
339 SmallVector<SourceLocation, 2> TargetLocations;
340 SourceLocation AtomicLocation;
341 /// Vector of declare variant construct traits.
343
344public:
345 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
346
347 /// Sets omp_allocator_handle_t type.
348 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
349 /// Gets omp_allocator_handle_t type.
350 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
351 /// Sets omp_alloctrait_t type.
352 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
353 /// Gets omp_alloctrait_t type.
354 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
355 /// Sets the given default allocator.
356 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
357 Expr *Allocator) {
358 OMPPredefinedAllocators[AllocatorKind] = Allocator;
359 }
360 /// Returns the specified default allocator.
361 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
362 return OMPPredefinedAllocators[AllocatorKind];
363 }
364 /// Sets omp_depend_t type.
365 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
366 /// Gets omp_depend_t type.
367 QualType getOMPDependT() const { return OMPDependT; }
368
369 /// Sets omp_event_handle_t type.
370 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
371 /// Gets omp_event_handle_t type.
372 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
373
374 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
375 OpenMPClauseKind getClauseParsingMode() const {
376 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
377 return ClauseKindMode;
378 }
379 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
380
381 bool isBodyComplete() const {
382 const SharingMapTy *Top = getTopOfStackOrNull();
383 return Top && Top->BodyComplete;
384 }
385 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
386
387 bool isForceVarCapturing() const { return ForceCapturing; }
388 void setForceVarCapturing(bool V) { ForceCapturing = V; }
389
390 void setForceCaptureByReferenceInTargetExecutable(bool V) {
391 ForceCaptureByReferenceInTargetExecutable = V;
392 }
393 bool isForceCaptureByReferenceInTargetExecutable() const {
394 return ForceCaptureByReferenceInTargetExecutable;
395 }
396
397 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
398 Scope *CurScope, SourceLocation Loc) {
399 assert(!IgnoredStackElements &&
400 "cannot change stack while ignoring elements");
401 if (Stack.empty() ||
402 Stack.back().second != CurrentNonCapturingFunctionScope)
403 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
404 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
405 Stack.back().first.back().DefaultAttrLoc = Loc;
406 }
407
408 void pop() {
409 assert(!IgnoredStackElements &&
410 "cannot change stack while ignoring elements");
411 assert(!Stack.back().first.empty() &&
412 "Data-sharing attributes stack is empty!");
413 Stack.back().first.pop_back();
414 }
415
416 /// RAII object to temporarily leave the scope of a directive when we want to
417 /// logically operate in its parent.
418 class ParentDirectiveScope {
419 DSAStackTy &Self;
420 bool Active;
421
422 public:
423 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
424 : Self(Self), Active(false) {
425 if (Activate)
426 enable();
427 }
428 ~ParentDirectiveScope() { disable(); }
429 void disable() {
430 if (Active) {
431 --Self.IgnoredStackElements;
432 Active = false;
433 }
434 }
435 void enable() {
436 if (!Active) {
437 ++Self.IgnoredStackElements;
438 Active = true;
439 }
440 }
441 };
442
443 /// Marks that we're started loop parsing.
444 void loopInit() {
445 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
446 "Expected loop-based directive.");
447 getTopOfStack().LoopStart = true;
448 }
449 /// Start capturing of the variables in the loop context.
450 void loopStart() {
451 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
452 "Expected loop-based directive.");
453 getTopOfStack().LoopStart = false;
454 }
455 /// true, if variables are captured, false otherwise.
456 bool isLoopStarted() const {
457 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
458 "Expected loop-based directive.");
459 return !getTopOfStack().LoopStart;
460 }
461 /// Marks (or clears) declaration as possibly loop counter.
462 void resetPossibleLoopCounter(const Decl *D = nullptr) {
463 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
464 }
465 /// Gets the possible loop counter decl.
466 const Decl *getPossiblyLoopCounter() const {
467 return getTopOfStack().PossiblyLoopCounter;
468 }
469 /// Start new OpenMP region stack in new non-capturing function.
470 void pushFunction() {
471 assert(!IgnoredStackElements &&
472 "cannot change stack while ignoring elements");
473 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
474 assert(!isa<CapturingScopeInfo>(CurFnScope));
475 CurrentNonCapturingFunctionScope = CurFnScope;
476 }
477 /// Pop region stack for non-capturing function.
478 void popFunction(const FunctionScopeInfo *OldFSI) {
479 assert(!IgnoredStackElements &&
480 "cannot change stack while ignoring elements");
481 if (!Stack.empty() && Stack.back().second == OldFSI) {
482 assert(Stack.back().first.empty());
483 Stack.pop_back();
484 }
485 CurrentNonCapturingFunctionScope = nullptr;
486 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
487 if (!isa<CapturingScopeInfo>(FSI)) {
488 CurrentNonCapturingFunctionScope = FSI;
489 break;
490 }
491 }
492 }
493
494 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
495 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
496 }
497 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
498 getCriticalWithHint(const DeclarationNameInfo &Name) const {
499 auto I = Criticals.find(Name.getAsString());
500 if (I != Criticals.end())
501 return I->second;
502 return std::make_pair(nullptr, llvm::APSInt());
503 }
504 /// If 'aligned' declaration for given variable \a D was not seen yet,
505 /// add it and return NULL; otherwise return previous occurrence's expression
506 /// for diagnostics.
507 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
508 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
509 /// add it and return NULL; otherwise return previous occurrence's expression
510 /// for diagnostics.
511 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
512
513 /// Register specified variable as loop control variable.
514 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
515 /// Check if the specified variable is a loop control variable for
516 /// current region.
517 /// \return The index of the loop control variable in the list of associated
518 /// for-loops (from outer to inner).
519 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
520 /// Check if the specified variable is a loop control variable for
521 /// parent region.
522 /// \return The index of the loop control variable in the list of associated
523 /// for-loops (from outer to inner).
524 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
525 /// Check if the specified variable is a loop control variable for
526 /// current region.
527 /// \return The index of the loop control variable in the list of associated
528 /// for-loops (from outer to inner).
529 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
530 unsigned Level) const;
531 /// Get the loop control variable for the I-th loop (or nullptr) in
532 /// parent directive.
533 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
534
535 /// Marks the specified decl \p D as used in scan directive.
536 void markDeclAsUsedInScanDirective(ValueDecl *D) {
537 if (SharingMapTy *Stack = getSecondOnStackOrNull())
538 Stack->UsedInScanDirective.insert(D);
539 }
540
541 /// Checks if the specified declaration was used in the inner scan directive.
542 bool isUsedInScanDirective(ValueDecl *D) const {
543 if (const SharingMapTy *Stack = getTopOfStackOrNull())
544 return Stack->UsedInScanDirective.contains(D);
545 return false;
546 }
547
548 /// Adds explicit data sharing attribute to the specified declaration.
549 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
550 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
551 bool AppliedToPointee = false);
552
553 /// Adds additional information for the reduction items with the reduction id
554 /// represented as an operator.
555 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
557 /// Adds additional information for the reduction items with the reduction id
558 /// represented as reduction identifier.
559 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
560 const Expr *ReductionRef);
561 /// Returns the location and reduction operation from the innermost parent
562 /// region for the given \p D.
563 const DSAVarData
564 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
566 Expr *&TaskgroupDescriptor) const;
567 /// Returns the location and reduction operation from the innermost parent
568 /// region for the given \p D.
569 const DSAVarData
570 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
571 const Expr *&ReductionRef,
572 Expr *&TaskgroupDescriptor) const;
573 /// Return reduction reference expression for the current taskgroup or
574 /// parallel/worksharing directives with task reductions.
575 Expr *getTaskgroupReductionRef() const {
576 assert((getTopOfStack().Directive == OMPD_taskgroup ||
577 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
578 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
579 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
580 "taskgroup reference expression requested for non taskgroup or "
581 "parallel/worksharing directive.");
582 return getTopOfStack().TaskgroupReductionRef;
583 }
584 /// Checks if the given \p VD declaration is actually a taskgroup reduction
585 /// descriptor variable at the \p Level of OpenMP regions.
586 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
587 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
588 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
589 ->getDecl() == VD;
590 }
591
592 /// Returns data sharing attributes from top of the stack for the
593 /// specified declaration.
594 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
595 /// Returns data-sharing attributes for the specified declaration.
596 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
599 /// Checks if the specified variables has data-sharing attributes which
600 /// match specified \a CPred predicate in any directive which matches \a DPred
601 /// predicate.
602 const DSAVarData
603 hasDSA(ValueDecl *D,
604 const llvm::function_ref<bool(OpenMPClauseKind, bool,
605 DefaultDataSharingAttributes)>
606 CPred,
607 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
608 bool FromParent) const;
609 /// Checks if the specified variables has data-sharing attributes which
610 /// match specified \a CPred predicate in any innermost directive which
611 /// matches \a DPred predicate.
612 const DSAVarData
613 hasInnermostDSA(ValueDecl *D,
614 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
615 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
616 bool FromParent) const;
617 /// Checks if the specified variables has explicit data-sharing
618 /// attributes which match specified \a CPred predicate at the specified
619 /// OpenMP region.
620 bool
621 hasExplicitDSA(const ValueDecl *D,
622 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
623 unsigned Level, bool NotLastprivate = false) const;
624
625 /// Returns true if the directive at level \Level matches in the
626 /// specified \a DPred predicate.
627 bool hasExplicitDirective(
628 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
629 unsigned Level) const;
630
631 /// Finds a directive which matches specified \a DPred predicate.
632 bool hasDirective(
633 const llvm::function_ref<bool(
635 DPred,
636 bool FromParent) const;
637
638 /// Returns currently analyzed directive.
639 OpenMPDirectiveKind getCurrentDirective() const {
640 const SharingMapTy *Top = getTopOfStackOrNull();
641 return Top ? Top->Directive : OMPD_unknown;
642 }
643 /// Returns directive kind at specified level.
644 OpenMPDirectiveKind getDirective(unsigned Level) const {
645 assert(!isStackEmpty() && "No directive at specified level.");
646 return getStackElemAtLevel(Level).Directive;
647 }
648 /// Returns the capture region at the specified level.
649 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
650 unsigned OpenMPCaptureLevel) const {
652 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
653 return CaptureRegions[OpenMPCaptureLevel];
654 }
655 /// Returns parent directive.
656 OpenMPDirectiveKind getParentDirective() const {
657 const SharingMapTy *Parent = getSecondOnStackOrNull();
658 return Parent ? Parent->Directive : OMPD_unknown;
659 }
660
661 /// Add requires decl to internal vector
662 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
663
664 /// Checks if the defined 'requires' directive has specified type of clause.
665 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
666 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
667 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
668 return isa<ClauseType>(C);
669 });
670 });
671 }
672
673 /// Checks for a duplicate clause amongst previously declared requires
674 /// directives
675 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
676 bool IsDuplicate = false;
677 for (OMPClause *CNew : ClauseList) {
678 for (const OMPRequiresDecl *D : RequiresDecls) {
679 for (const OMPClause *CPrev : D->clauselists()) {
680 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
681 SemaRef.Diag(CNew->getBeginLoc(),
682 diag::err_omp_requires_clause_redeclaration)
683 << getOpenMPClauseName(CNew->getClauseKind());
684 SemaRef.Diag(CPrev->getBeginLoc(),
685 diag::note_omp_requires_previous_clause)
686 << getOpenMPClauseName(CPrev->getClauseKind());
687 IsDuplicate = true;
688 }
689 }
690 }
691 }
692 return IsDuplicate;
693 }
694
695 /// Add location of previously encountered target to internal vector
696 void addTargetDirLocation(SourceLocation LocStart) {
697 TargetLocations.push_back(LocStart);
698 }
699
700 /// Add location for the first encountered atomic directive.
701 void addAtomicDirectiveLoc(SourceLocation Loc) {
702 if (AtomicLocation.isInvalid())
703 AtomicLocation = Loc;
704 }
705
706 /// Returns the location of the first encountered atomic directive in the
707 /// module.
708 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
709
710 // Return previously encountered target region locations.
711 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
712 return TargetLocations;
713 }
714
715 /// Set default data sharing attribute to none.
716 void setDefaultDSANone(SourceLocation Loc) {
717 getTopOfStack().DefaultAttr = DSA_none;
718 getTopOfStack().DefaultAttrLoc = Loc;
719 }
720 /// Set default data sharing attribute to shared.
721 void setDefaultDSAShared(SourceLocation Loc) {
722 getTopOfStack().DefaultAttr = DSA_shared;
723 getTopOfStack().DefaultAttrLoc = Loc;
724 }
725 /// Set default data sharing attribute to private.
726 void setDefaultDSAPrivate(SourceLocation Loc) {
727 getTopOfStack().DefaultAttr = DSA_private;
728 getTopOfStack().DefaultAttrLoc = Loc;
729 }
730 /// Set default data sharing attribute to firstprivate.
731 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
732 getTopOfStack().DefaultAttr = DSA_firstprivate;
733 getTopOfStack().DefaultAttrLoc = Loc;
734 }
735 /// Set default data mapping attribute to Modifier:Kind
736 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
738 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
739 DMI.ImplicitBehavior = M;
740 DMI.SLoc = Loc;
741 }
742 /// Check whether the implicit-behavior has been set in defaultmap
743 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
744 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
745 return getTopOfStack()
746 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
747 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
748 getTopOfStack()
749 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
750 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
751 getTopOfStack()
752 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
753 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
754 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
756 }
757
758 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
759 return ConstructTraits;
760 }
761 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
762 bool ScopeEntry) {
763 if (ScopeEntry)
764 ConstructTraits.append(Traits.begin(), Traits.end());
765 else
766 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
767 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
768 assert(Top == Trait && "Something left a trait on the stack!");
769 (void)Trait;
770 (void)Top;
771 }
772 }
773
774 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
775 return getStackSize() <= Level ? DSA_unspecified
776 : getStackElemAtLevel(Level).DefaultAttr;
777 }
778 DefaultDataSharingAttributes getDefaultDSA() const {
779 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
780 }
781 SourceLocation getDefaultDSALocation() const {
782 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
783 }
785 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
786 return isStackEmpty()
788 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
789 }
791 getDefaultmapModifierAtLevel(unsigned Level,
792 OpenMPDefaultmapClauseKind Kind) const {
793 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
794 }
795 bool isDefaultmapCapturedByRef(unsigned Level,
796 OpenMPDefaultmapClauseKind Kind) const {
798 getDefaultmapModifierAtLevel(Level, Kind);
799 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
800 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
801 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
802 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_present);
805 }
806 return true;
807 }
808 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
810 switch (Kind) {
811 case OMPC_DEFAULTMAP_scalar:
812 case OMPC_DEFAULTMAP_pointer:
813 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
814 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
815 (M == OMPC_DEFAULTMAP_MODIFIER_default);
816 case OMPC_DEFAULTMAP_aggregate:
817 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
818 default:
819 break;
820 }
821 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
822 }
823 bool mustBeFirstprivateAtLevel(unsigned Level,
824 OpenMPDefaultmapClauseKind Kind) const {
826 getDefaultmapModifierAtLevel(Level, Kind);
827 return mustBeFirstprivateBase(M, Kind);
828 }
829 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
830 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
831 return mustBeFirstprivateBase(M, Kind);
832 }
833
834 /// Checks if the specified variable is a threadprivate.
835 bool isThreadPrivate(VarDecl *D) {
836 const DSAVarData DVar = getTopDSA(D, false);
837 return isOpenMPThreadPrivate(DVar.CKind);
838 }
839
840 /// Marks current region as ordered (it has an 'ordered' clause).
841 void setOrderedRegion(bool IsOrdered, const Expr *Param,
842 OMPOrderedClause *Clause) {
843 if (IsOrdered)
844 getTopOfStack().OrderedRegion.emplace(Param, Clause);
845 else
846 getTopOfStack().OrderedRegion.reset();
847 }
848 /// Returns true, if region is ordered (has associated 'ordered' clause),
849 /// false - otherwise.
850 bool isOrderedRegion() const {
851 if (const SharingMapTy *Top = getTopOfStackOrNull())
852 return Top->OrderedRegion.has_value();
853 return false;
854 }
855 /// Returns optional parameter for the ordered region.
856 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
857 if (const SharingMapTy *Top = getTopOfStackOrNull())
858 if (Top->OrderedRegion)
859 return *Top->OrderedRegion;
860 return std::make_pair(nullptr, nullptr);
861 }
862 /// Returns true, if parent region is ordered (has associated
863 /// 'ordered' clause), false - otherwise.
864 bool isParentOrderedRegion() const {
865 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
866 return Parent->OrderedRegion.has_value();
867 return false;
868 }
869 /// Returns optional parameter for the ordered region.
870 std::pair<const Expr *, OMPOrderedClause *>
871 getParentOrderedRegionParam() const {
872 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
873 if (Parent->OrderedRegion)
874 return *Parent->OrderedRegion;
875 return std::make_pair(nullptr, nullptr);
876 }
877 /// Marks current region as having an 'order' clause.
878 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
879 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
880 }
881 /// Returns true, if parent region is order (has associated
882 /// 'order' clause), false - otherwise.
883 bool isParentOrderConcurrent() const {
884 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
885 return Parent->RegionHasOrderConcurrent;
886 return false;
887 }
888 /// Marks current region as nowait (it has a 'nowait' clause).
889 void setNowaitRegion(bool IsNowait = true) {
890 getTopOfStack().NowaitRegion = IsNowait;
891 }
892 /// Returns true, if parent region is nowait (has associated
893 /// 'nowait' clause), false - otherwise.
894 bool isParentNowaitRegion() const {
895 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
896 return Parent->NowaitRegion;
897 return false;
898 }
899 /// Marks current region as untied (it has a 'untied' clause).
900 void setUntiedRegion(bool IsUntied = true) {
901 getTopOfStack().UntiedRegion = IsUntied;
902 }
903 /// Return true if current region is untied.
904 bool isUntiedRegion() const {
905 const SharingMapTy *Top = getTopOfStackOrNull();
906 return Top ? Top->UntiedRegion : false;
907 }
908 /// Marks parent region as cancel region.
909 void setParentCancelRegion(bool Cancel = true) {
910 if (SharingMapTy *Parent = getSecondOnStackOrNull())
911 Parent->CancelRegion |= Cancel;
912 }
913 /// Return true if current region has inner cancel construct.
914 bool isCancelRegion() const {
915 const SharingMapTy *Top = getTopOfStackOrNull();
916 return Top ? Top->CancelRegion : false;
917 }
918
919 /// Mark that parent region already has scan directive.
920 void setParentHasScanDirective(SourceLocation Loc) {
921 if (SharingMapTy *Parent = getSecondOnStackOrNull())
922 Parent->PrevScanLocation = Loc;
923 }
924 /// Return true if current region has inner cancel construct.
925 bool doesParentHasScanDirective() const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevScanLocation.isValid() : false;
928 }
929 /// Return true if current region has inner cancel construct.
930 SourceLocation getParentScanDirectiveLoc() const {
931 const SharingMapTy *Top = getSecondOnStackOrNull();
932 return Top ? Top->PrevScanLocation : SourceLocation();
933 }
934 /// Mark that parent region already has ordered directive.
935 void setParentHasOrderedDirective(SourceLocation Loc) {
936 if (SharingMapTy *Parent = getSecondOnStackOrNull())
937 Parent->PrevOrderedLocation = Loc;
938 }
939 /// Return true if current region has inner ordered construct.
940 bool doesParentHasOrderedDirective() const {
941 const SharingMapTy *Top = getSecondOnStackOrNull();
942 return Top ? Top->PrevOrderedLocation.isValid() : false;
943 }
944 /// Returns the location of the previously specified ordered directive.
945 SourceLocation getParentOrderedDirectiveLoc() const {
946 const SharingMapTy *Top = getSecondOnStackOrNull();
947 return Top ? Top->PrevOrderedLocation : SourceLocation();
948 }
949
950 /// Set collapse value for the region.
951 void setAssociatedLoops(unsigned Val) {
952 getTopOfStack().AssociatedLoops = Val;
953 if (Val > 1)
954 getTopOfStack().HasMutipleLoops = true;
955 }
956 /// Return collapse value for region.
957 unsigned getAssociatedLoops() const {
958 const SharingMapTy *Top = getTopOfStackOrNull();
959 return Top ? Top->AssociatedLoops : 0;
960 }
961 /// Returns true if the construct is associated with multiple loops.
962 bool hasMutipleLoops() const {
963 const SharingMapTy *Top = getTopOfStackOrNull();
964 return Top ? Top->HasMutipleLoops : false;
965 }
966
967 /// Marks current target region as one with closely nested teams
968 /// region.
969 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
970 if (SharingMapTy *Parent = getSecondOnStackOrNull())
971 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
972 }
973 /// Returns true, if current region has closely nested teams region.
974 bool hasInnerTeamsRegion() const {
975 return getInnerTeamsRegionLoc().isValid();
976 }
977 /// Returns location of the nested teams region (if any).
978 SourceLocation getInnerTeamsRegionLoc() const {
979 const SharingMapTy *Top = getTopOfStackOrNull();
980 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
981 }
982
983 Scope *getCurScope() const {
984 const SharingMapTy *Top = getTopOfStackOrNull();
985 return Top ? Top->CurScope : nullptr;
986 }
987 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
988 SourceLocation getConstructLoc() const {
989 const SharingMapTy *Top = getTopOfStackOrNull();
990 return Top ? Top->ConstructLoc : SourceLocation();
991 }
992
993 /// Do the check specified in \a Check to all component lists and return true
994 /// if any issue is found.
995 bool checkMappableExprComponentListsForDecl(
996 const ValueDecl *VD, bool CurrentRegionOnly,
997 const llvm::function_ref<
1000 Check) const {
1001 if (isStackEmpty())
1002 return false;
1003 auto SI = begin();
1004 auto SE = end();
1005
1006 if (SI == SE)
1007 return false;
1008
1009 if (CurrentRegionOnly)
1010 SE = std::next(SI);
1011 else
1012 std::advance(SI, 1);
1013
1014 for (; SI != SE; ++SI) {
1015 auto MI = SI->MappedExprComponents.find(VD);
1016 if (MI != SI->MappedExprComponents.end())
1018 MI->second.Components)
1019 if (Check(L, MI->second.Kind))
1020 return true;
1021 }
1022 return false;
1023 }
1024
1025 /// Do the check specified in \a Check to all component lists at a given level
1026 /// and return true if any issue is found.
1027 bool checkMappableExprComponentListsForDeclAtLevel(
1028 const ValueDecl *VD, unsigned Level,
1029 const llvm::function_ref<
1032 Check) const {
1033 if (getStackSize() <= Level)
1034 return false;
1035
1036 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1037 auto MI = StackElem.MappedExprComponents.find(VD);
1038 if (MI != StackElem.MappedExprComponents.end())
1040 MI->second.Components)
1041 if (Check(L, MI->second.Kind))
1042 return true;
1043 return false;
1044 }
1045
1046 /// Create a new mappable expression component list associated with a given
1047 /// declaration and initialize it with the provided list of components.
1048 void addMappableExpressionComponents(
1049 const ValueDecl *VD,
1051 OpenMPClauseKind WhereFoundClauseKind) {
1052 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1053 // Create new entry and append the new components there.
1054 MEC.Components.resize(MEC.Components.size() + 1);
1055 MEC.Components.back().append(Components.begin(), Components.end());
1056 MEC.Kind = WhereFoundClauseKind;
1057 }
1058
1059 unsigned getNestingLevel() const {
1060 assert(!isStackEmpty());
1061 return getStackSize() - 1;
1062 }
1063 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1064 SharingMapTy *Parent = getSecondOnStackOrNull();
1065 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1066 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1067 }
1068 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1069 getDoacrossDependClauses() const {
1070 const SharingMapTy &StackElem = getTopOfStack();
1071 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1072 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1073 return llvm::make_range(Ref.begin(), Ref.end());
1074 }
1075 return llvm::make_range(StackElem.DoacrossDepends.end(),
1076 StackElem.DoacrossDepends.end());
1077 }
1078
1079 // Store types of classes which have been explicitly mapped
1080 void addMappedClassesQualTypes(QualType QT) {
1081 SharingMapTy &StackElem = getTopOfStack();
1082 StackElem.MappedClassesQualTypes.insert(QT);
1083 }
1084
1085 // Return set of mapped classes types
1086 bool isClassPreviouslyMapped(QualType QT) const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 return StackElem.MappedClassesQualTypes.contains(QT);
1089 }
1090
1091 /// Adds global declare target to the parent target region.
1092 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1093 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1094 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1095 "Expected declare target link global.");
1096 for (auto &Elem : *this) {
1097 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1098 Elem.DeclareTargetLinkVarDecls.push_back(E);
1099 return;
1100 }
1101 }
1102 }
1103
1104 /// Returns the list of globals with declare target link if current directive
1105 /// is target.
1106 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1107 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1108 "Expected target executable directive.");
1109 return getTopOfStack().DeclareTargetLinkVarDecls;
1110 }
1111
1112 /// Adds list of allocators expressions.
1113 void addInnerAllocatorExpr(Expr *E) {
1114 getTopOfStack().InnerUsedAllocators.push_back(E);
1115 }
1116 /// Return list of used allocators.
1117 ArrayRef<Expr *> getInnerAllocators() const {
1118 return getTopOfStack().InnerUsedAllocators;
1119 }
1120 /// Marks the declaration as implicitly firstprivate nin the task-based
1121 /// regions.
1122 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1123 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1124 }
1125 /// Checks if the decl is implicitly firstprivate in the task-based region.
1126 bool isImplicitTaskFirstprivate(Decl *D) const {
1127 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1128 }
1129
1130 /// Marks decl as used in uses_allocators clause as the allocator.
1131 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1132 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1133 }
1134 /// Checks if specified decl is used in uses allocator clause as the
1135 /// allocator.
1136 std::optional<UsesAllocatorsDeclKind>
1137 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1138 const SharingMapTy &StackElem = getTopOfStack();
1139 auto I = StackElem.UsesAllocatorsDecls.find(D);
1140 if (I == StackElem.UsesAllocatorsDecls.end())
1141 return std::nullopt;
1142 return I->getSecond();
1143 }
1144 std::optional<UsesAllocatorsDeclKind>
1145 isUsesAllocatorsDecl(const Decl *D) const {
1146 const SharingMapTy &StackElem = getTopOfStack();
1147 auto I = StackElem.UsesAllocatorsDecls.find(D);
1148 if (I == StackElem.UsesAllocatorsDecls.end())
1149 return std::nullopt;
1150 return I->getSecond();
1151 }
1152
1153 void addDeclareMapperVarRef(Expr *Ref) {
1154 SharingMapTy &StackElem = getTopOfStack();
1155 StackElem.DeclareMapperVar = Ref;
1156 }
1157 const Expr *getDeclareMapperVarRef() const {
1158 const SharingMapTy *Top = getTopOfStackOrNull();
1159 return Top ? Top->DeclareMapperVar : nullptr;
1160 }
1161
1162 /// Add a new iterator variable.
1163 void addIteratorVarDecl(VarDecl *VD) {
1164 SharingMapTy &StackElem = getTopOfStack();
1165 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1166 }
1167 /// Check if variable declaration is an iterator VarDecl.
1168 bool isIteratorVarDecl(const VarDecl *VD) const {
1169 const SharingMapTy *Top = getTopOfStackOrNull();
1170 if (!Top)
1171 return false;
1172
1173 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1174 }
1175 /// get captured field from ImplicitDefaultFirstprivateFDs
1176 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1177 const_iterator I = begin();
1178 const_iterator EndI = end();
1179 size_t StackLevel = getStackSize();
1180 for (; I != EndI; ++I) {
1181 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1182 break;
1183 StackLevel--;
1184 }
1185 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1186 if (I == EndI)
1187 return nullptr;
1188 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1189 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1190 return IFD.VD;
1191 return nullptr;
1192 }
1193 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1194 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1195 const_iterator I = begin();
1196 const_iterator EndI = end();
1197 for (; I != EndI; ++I)
1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1199 break;
1200 if (I == EndI)
1201 return false;
1202 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1203 if (IFD.VD == VD)
1204 return true;
1205 return false;
1206 }
1207 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1208 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1209 iterator I = begin();
1210 const_iterator EndI = end();
1211 size_t StackLevel = getStackSize();
1212 for (; I != EndI; ++I) {
1213 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1214 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1215 break;
1216 }
1217 StackLevel--;
1218 }
1219 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1220 }
1221};
1222
1223bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1224 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1225}
1226
1227bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1228 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1229 DKind == OMPD_unknown;
1230}
1231
1232} // namespace
1233
1234static const Expr *getExprAsWritten(const Expr *E) {
1235 if (const auto *FE = dyn_cast<FullExpr>(E))
1236 E = FE->getSubExpr();
1237
1238 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1239 E = MTE->getSubExpr();
1240
1241 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1242 E = Binder->getSubExpr();
1243
1244 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1245 E = ICE->getSubExprAsWritten();
1246 return E->IgnoreParens();
1247}
1248
1250 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1251}
1252
1253static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1254 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1255 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1256 D = ME->getMemberDecl();
1257
1258 D = cast<ValueDecl>(D->getCanonicalDecl());
1259 return D;
1260}
1261
1263 return const_cast<ValueDecl *>(
1264 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1265}
1266
1267DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1268 ValueDecl *D) const {
1269 D = getCanonicalDecl(D);
1270 auto *VD = dyn_cast<VarDecl>(D);
1271 const auto *FD = dyn_cast<FieldDecl>(D);
1272 DSAVarData DVar;
1273 if (Iter == end()) {
1274 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1275 // in a region but not in construct]
1276 // File-scope or namespace-scope variables referenced in called routines
1277 // in the region are shared unless they appear in a threadprivate
1278 // directive.
1279 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1280 DVar.CKind = OMPC_shared;
1281
1282 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1283 // in a region but not in construct]
1284 // Variables with static storage duration that are declared in called
1285 // routines in the region are shared.
1286 if (VD && VD->hasGlobalStorage())
1287 DVar.CKind = OMPC_shared;
1288
1289 // Non-static data members are shared by default.
1290 if (FD)
1291 DVar.CKind = OMPC_shared;
1292
1293 return DVar;
1294 }
1295
1296 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1297 // in a Construct, C/C++, predetermined, p.1]
1298 // Variables with automatic storage duration that are declared in a scope
1299 // inside the construct are private.
1300 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1301 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1302 DVar.CKind = OMPC_private;
1303 return DVar;
1304 }
1305
1306 DVar.DKind = Iter->Directive;
1307 // Explicitly specified attributes and local variables with predetermined
1308 // attributes.
1309 if (Iter->SharingMap.count(D)) {
1310 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1311 DVar.RefExpr = Data.RefExpr.getPointer();
1312 DVar.PrivateCopy = Data.PrivateCopy;
1313 DVar.CKind = Data.Attributes;
1314 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1315 DVar.Modifier = Data.Modifier;
1316 DVar.AppliedToPointee = Data.AppliedToPointee;
1317 return DVar;
1318 }
1319
1320 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1321 // in a Construct, C/C++, implicitly determined, p.1]
1322 // In a parallel or task construct, the data-sharing attributes of these
1323 // variables are determined by the default clause, if present.
1324 switch (Iter->DefaultAttr) {
1325 case DSA_shared:
1326 DVar.CKind = OMPC_shared;
1327 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1328 return DVar;
1329 case DSA_none:
1330 return DVar;
1331 case DSA_firstprivate:
1332 if (VD && VD->getStorageDuration() == SD_Static &&
1333 VD->getDeclContext()->isFileContext()) {
1334 DVar.CKind = OMPC_unknown;
1335 } else {
1336 DVar.CKind = OMPC_firstprivate;
1337 }
1338 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1339 return DVar;
1340 case DSA_private:
1341 // each variable with static storage duration that is declared
1342 // in a namespace or global scope and referenced in the construct,
1343 // and that does not have a predetermined data-sharing attribute
1344 if (VD && VD->getStorageDuration() == SD_Static &&
1345 VD->getDeclContext()->isFileContext()) {
1346 DVar.CKind = OMPC_unknown;
1347 } else {
1348 DVar.CKind = OMPC_private;
1349 }
1350 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1351 return DVar;
1352 case DSA_unspecified:
1353 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1354 // in a Construct, implicitly determined, p.2]
1355 // In a parallel construct, if no default clause is present, these
1356 // variables are shared.
1357 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1358 if ((isOpenMPParallelDirective(DVar.DKind) &&
1359 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1360 isOpenMPTeamsDirective(DVar.DKind)) {
1361 DVar.CKind = OMPC_shared;
1362 return DVar;
1363 }
1364
1365 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1366 // in a Construct, implicitly determined, p.4]
1367 // In a task construct, if no default clause is present, a variable that in
1368 // the enclosing context is determined to be shared by all implicit tasks
1369 // bound to the current team is shared.
1370 if (isOpenMPTaskingDirective(DVar.DKind)) {
1371 DSAVarData DVarTemp;
1372 const_iterator I = Iter, E = end();
1373 do {
1374 ++I;
1375 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1376 // Referenced in a Construct, implicitly determined, p.6]
1377 // In a task construct, if no default clause is present, a variable
1378 // whose data-sharing attribute is not determined by the rules above is
1379 // firstprivate.
1380 DVarTemp = getDSA(I, D);
1381 if (DVarTemp.CKind != OMPC_shared) {
1382 DVar.RefExpr = nullptr;
1383 DVar.CKind = OMPC_firstprivate;
1384 return DVar;
1385 }
1386 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1387 DVar.CKind =
1388 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : 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.3]
1394 // For constructs other than task, if no default clause is present, these
1395 // variables inherit their data-sharing attributes from the enclosing
1396 // context.
1397 return getDSA(++Iter, D);
1398}
1399
1400const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1401 const Expr *NewDE) {
1402 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1403 D = getCanonicalDecl(D);
1404 SharingMapTy &StackElem = getTopOfStack();
1405 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1406 if (Inserted) {
1407 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1408 return nullptr;
1409 }
1410 assert(It->second && "Unexpected nullptr expr in the aligned map");
1411 return It->second;
1412}
1413
1414const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1415 const Expr *NewDE) {
1416 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1417 D = getCanonicalDecl(D);
1418 SharingMapTy &StackElem = getTopOfStack();
1419 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1420 if (Inserted) {
1421 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1422 return nullptr;
1423 }
1424 assert(It->second && "Unexpected nullptr expr in the aligned map");
1425 return It->second;
1426}
1427
1428void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1429 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1430 D = getCanonicalDecl(D);
1431 SharingMapTy &StackElem = getTopOfStack();
1432 StackElem.LCVMap.try_emplace(
1433 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1434}
1435
1436const DSAStackTy::LCDeclInfo
1437DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1438 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1439 D = getCanonicalDecl(D);
1440 const SharingMapTy &StackElem = getTopOfStack();
1441 auto It = StackElem.LCVMap.find(D);
1442 if (It != StackElem.LCVMap.end())
1443 return It->second;
1444 return {0, nullptr};
1445}
1446
1447const DSAStackTy::LCDeclInfo
1448DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1449 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1450 D = getCanonicalDecl(D);
1451 for (unsigned I = Level + 1; I > 0; --I) {
1452 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1453 auto It = StackElem.LCVMap.find(D);
1454 if (It != StackElem.LCVMap.end())
1455 return It->second;
1456 }
1457 return {0, nullptr};
1458}
1459
1460const DSAStackTy::LCDeclInfo
1461DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1462 const SharingMapTy *Parent = getSecondOnStackOrNull();
1463 assert(Parent && "Data-sharing attributes stack is empty");
1464 D = getCanonicalDecl(D);
1465 auto It = Parent->LCVMap.find(D);
1466 if (It != Parent->LCVMap.end())
1467 return It->second;
1468 return {0, nullptr};
1469}
1470
1471const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1472 const SharingMapTy *Parent = getSecondOnStackOrNull();
1473 assert(Parent && "Data-sharing attributes stack is empty");
1474 if (Parent->LCVMap.size() < I)
1475 return nullptr;
1476 for (const auto &Pair : Parent->LCVMap)
1477 if (Pair.second.first == I)
1478 return Pair.first;
1479 return nullptr;
1480}
1481
1482void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1483 DeclRefExpr *PrivateCopy, unsigned Modifier,
1484 bool AppliedToPointee) {
1485 D = getCanonicalDecl(D);
1486 if (A == OMPC_threadprivate) {
1487 DSAInfo &Data = Threadprivates[D];
1488 Data.Attributes = A;
1489 Data.RefExpr.setPointer(E);
1490 Data.PrivateCopy = nullptr;
1491 Data.Modifier = Modifier;
1492 } else {
1493 DSAInfo &Data = getTopOfStack().SharingMap[D];
1494 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1495 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1496 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1497 (isLoopControlVariable(D).first && A == OMPC_private));
1498 Data.Modifier = Modifier;
1499 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1500 Data.RefExpr.setInt(/*IntVal=*/true);
1501 return;
1502 }
1503 const bool IsLastprivate =
1504 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1505 Data.Attributes = A;
1506 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1507 Data.PrivateCopy = PrivateCopy;
1508 Data.AppliedToPointee = AppliedToPointee;
1509 if (PrivateCopy) {
1510 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1511 Data.Modifier = Modifier;
1512 Data.Attributes = A;
1513 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1514 Data.PrivateCopy = nullptr;
1515 Data.AppliedToPointee = AppliedToPointee;
1516 }
1517 }
1518}
1519
1520/// Build a variable declaration for OpenMP loop iteration variable.
1522 StringRef Name, const AttrVec *Attrs = nullptr,
1523 DeclRefExpr *OrigRef = nullptr) {
1524 DeclContext *DC = SemaRef.CurContext;
1525 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1527 auto *Decl =
1528 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1529 if (Attrs) {
1530 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1531 I != E; ++I)
1532 Decl->addAttr(*I);
1533 }
1534 Decl->setImplicit();
1535 if (OrigRef) {
1536 Decl->addAttr(
1537 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1538 }
1539 return Decl;
1540}
1541
1544 bool RefersToCapture = false) {
1545 D->setReferenced();
1546 D->markUsed(S.Context);
1548 SourceLocation(), D, RefersToCapture, Loc, Ty,
1549 VK_LValue);
1550}
1551
1552void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1553 BinaryOperatorKind BOK) {
1554 D = getCanonicalDecl(D);
1555 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1556 assert(
1557 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1558 "Additional reduction info may be specified only for reduction items.");
1559 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1560 assert(ReductionData.ReductionRange.isInvalid() &&
1561 (getTopOfStack().Directive == OMPD_taskgroup ||
1562 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1563 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1564 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1565 "Additional reduction info may be specified only once for reduction "
1566 "items.");
1567 ReductionData.set(BOK, SR);
1568 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1569 if (!TaskgroupReductionRef) {
1570 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1571 SemaRef.Context.VoidPtrTy, ".task_red.");
1572 TaskgroupReductionRef =
1573 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1574 }
1575}
1576
1577void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1578 const Expr *ReductionRef) {
1579 D = getCanonicalDecl(D);
1580 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1581 assert(
1582 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1583 "Additional reduction info may be specified only for reduction items.");
1584 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1585 assert(ReductionData.ReductionRange.isInvalid() &&
1586 (getTopOfStack().Directive == OMPD_taskgroup ||
1587 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1588 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1589 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1590 "Additional reduction info may be specified only once for reduction "
1591 "items.");
1592 ReductionData.set(ReductionRef, SR);
1593 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1594 if (!TaskgroupReductionRef) {
1595 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1596 SemaRef.Context.VoidPtrTy, ".task_red.");
1597 TaskgroupReductionRef =
1598 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1599 }
1600}
1601
1602const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1603 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1604 Expr *&TaskgroupDescriptor) const {
1605 D = getCanonicalDecl(D);
1606 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1607 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1608 const DSAInfo &Data = I->SharingMap.lookup(D);
1609 if (Data.Attributes != OMPC_reduction ||
1610 Data.Modifier != OMPC_REDUCTION_task)
1611 continue;
1612 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1613 if (!ReductionData.ReductionOp ||
1614 isa<const Expr *>(ReductionData.ReductionOp))
1615 return DSAVarData();
1616 SR = ReductionData.ReductionRange;
1617 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1618 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1619 "expression for the descriptor is not "
1620 "set.");
1621 TaskgroupDescriptor = I->TaskgroupReductionRef;
1622 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1623 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1624 /*AppliedToPointee=*/false);
1625 }
1626 return DSAVarData();
1627}
1628
1629const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1630 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1631 Expr *&TaskgroupDescriptor) const {
1632 D = getCanonicalDecl(D);
1633 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1634 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1635 const DSAInfo &Data = I->SharingMap.lookup(D);
1636 if (Data.Attributes != OMPC_reduction ||
1637 Data.Modifier != OMPC_REDUCTION_task)
1638 continue;
1639 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1640 if (!ReductionData.ReductionOp ||
1641 !isa<const Expr *>(ReductionData.ReductionOp))
1642 return DSAVarData();
1643 SR = ReductionData.ReductionRange;
1644 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1645 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1646 "expression for the descriptor is not "
1647 "set.");
1648 TaskgroupDescriptor = I->TaskgroupReductionRef;
1649 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1650 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1651 /*AppliedToPointee=*/false);
1652 }
1653 return DSAVarData();
1654}
1655
1656bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1657 D = D->getCanonicalDecl();
1658 for (const_iterator E = end(); I != E; ++I) {
1659 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1660 isOpenMPTargetExecutionDirective(I->Directive)) {
1661 if (I->CurScope) {
1662 Scope *TopScope = I->CurScope->getParent();
1663 Scope *CurScope = getCurScope();
1664 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1665 CurScope = CurScope->getParent();
1666 return CurScope != TopScope;
1667 }
1668 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1669 if (I->Context == DC)
1670 return true;
1671 return false;
1672 }
1673 }
1674 return false;
1675}
1676
1678 bool AcceptIfMutable = true,
1679 bool *IsClassType = nullptr) {
1680 ASTContext &Context = SemaRef.getASTContext();
1681 Type = Type.getNonReferenceType().getCanonicalType();
1682 bool IsConstant = Type.isConstant(Context);
1683 Type = Context.getBaseElementType(Type);
1684 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1686 : nullptr;
1687 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1688 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1689 RD = CTD->getTemplatedDecl();
1690 if (IsClassType)
1691 *IsClassType = RD;
1692 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1693 RD->hasDefinition() && RD->hasMutableFields());
1694}
1695
1696static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1698 SourceLocation ELoc,
1699 bool AcceptIfMutable = true,
1700 bool ListItemNotVar = false) {
1701 ASTContext &Context = SemaRef.getASTContext();
1702 bool IsClassType;
1703 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1704 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1705 : IsClassType ? diag::err_omp_const_not_mutable_variable
1706 : diag::err_omp_const_variable;
1707 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1708 if (!ListItemNotVar && D) {
1709 const VarDecl *VD = dyn_cast<VarDecl>(D);
1710 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1712 SemaRef.Diag(D->getLocation(),
1713 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1714 << D;
1715 }
1716 return true;
1717 }
1718 return false;
1719}
1720
1721const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1722 bool FromParent) {
1723 D = getCanonicalDecl(D);
1724 DSAVarData DVar;
1725
1726 auto *VD = dyn_cast<VarDecl>(D);
1727 auto TI = Threadprivates.find(D);
1728 if (TI != Threadprivates.end()) {
1729 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1730 DVar.CKind = OMPC_threadprivate;
1731 DVar.Modifier = TI->getSecond().Modifier;
1732 return DVar;
1733 }
1734 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1735 DVar.RefExpr = buildDeclRefExpr(
1736 SemaRef, VD, D->getType().getNonReferenceType(),
1737 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1738 DVar.CKind = OMPC_threadprivate;
1739 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1740 return DVar;
1741 }
1742 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1743 // in a Construct, C/C++, predetermined, p.1]
1744 // Variables appearing in threadprivate directives are threadprivate.
1745 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1746 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1747 SemaRef.getLangOpts().OpenMPUseTLS &&
1748 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1749 (VD && VD->getStorageClass() == SC_Register &&
1750 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1751 DVar.RefExpr = buildDeclRefExpr(
1752 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1753 DVar.CKind = OMPC_threadprivate;
1754 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1755 return DVar;
1756 }
1757 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1758 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1759 !isLoopControlVariable(D).first) {
1760 const_iterator IterTarget =
1761 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1762 return isOpenMPTargetExecutionDirective(Data.Directive);
1763 });
1764 if (IterTarget != end()) {
1765 const_iterator ParentIterTarget = IterTarget + 1;
1766 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1767 if (isOpenMPLocal(VD, Iter)) {
1768 DVar.RefExpr =
1769 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1770 D->getLocation());
1771 DVar.CKind = OMPC_threadprivate;
1772 return DVar;
1773 }
1774 }
1775 if (!isClauseParsingMode() || IterTarget != begin()) {
1776 auto DSAIter = IterTarget->SharingMap.find(D);
1777 if (DSAIter != IterTarget->SharingMap.end() &&
1778 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1779 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1780 DVar.CKind = OMPC_threadprivate;
1781 return DVar;
1782 }
1783 const_iterator End = end();
1784 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1785 D, std::distance(ParentIterTarget, End),
1786 /*OpenMPCaptureLevel=*/0)) {
1787 DVar.RefExpr =
1788 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1789 IterTarget->ConstructLoc);
1790 DVar.CKind = OMPC_threadprivate;
1791 return DVar;
1792 }
1793 }
1794 }
1795 }
1796
1797 if (isStackEmpty())
1798 // Not in OpenMP execution region and top scope was already checked.
1799 return DVar;
1800
1801 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1802 // in a Construct, C/C++, predetermined, p.4]
1803 // Static data members are shared.
1804 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1805 // in a Construct, C/C++, predetermined, p.7]
1806 // Variables with static storage duration that are declared in a scope
1807 // inside the construct are shared.
1808 if (VD && VD->isStaticDataMember()) {
1809 // Check for explicitly specified attributes.
1810 const_iterator I = begin();
1811 const_iterator EndI = end();
1812 if (FromParent && I != EndI)
1813 ++I;
1814 if (I != EndI) {
1815 auto It = I->SharingMap.find(D);
1816 if (It != I->SharingMap.end()) {
1817 const DSAInfo &Data = It->getSecond();
1818 DVar.RefExpr = Data.RefExpr.getPointer();
1819 DVar.PrivateCopy = Data.PrivateCopy;
1820 DVar.CKind = Data.Attributes;
1821 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1822 DVar.DKind = I->Directive;
1823 DVar.Modifier = Data.Modifier;
1824 DVar.AppliedToPointee = Data.AppliedToPointee;
1825 return DVar;
1826 }
1827 }
1828
1829 DVar.CKind = OMPC_shared;
1830 return DVar;
1831 }
1832
1833 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1834 // The predetermined shared attribute for const-qualified types having no
1835 // mutable members was removed after OpenMP 3.1.
1836 if (SemaRef.LangOpts.OpenMP <= 31) {
1837 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1838 // in a Construct, C/C++, predetermined, p.6]
1839 // Variables with const qualified type having no mutable member are
1840 // shared.
1841 if (isConstNotMutableType(SemaRef, D->getType())) {
1842 // Variables with const-qualified type having no mutable member may be
1843 // listed in a firstprivate clause, even if they are static data members.
1844 DSAVarData DVarTemp = hasInnermostDSA(
1845 D,
1846 [](OpenMPClauseKind C, bool) {
1847 return C == OMPC_firstprivate || C == OMPC_shared;
1848 },
1849 MatchesAlways, FromParent);
1850 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1851 return DVarTemp;
1852
1853 DVar.CKind = OMPC_shared;
1854 return DVar;
1855 }
1856 }
1857
1858 // Explicitly specified attributes and local variables with predetermined
1859 // attributes.
1860 const_iterator I = begin();
1861 const_iterator EndI = end();
1862 if (FromParent && I != EndI)
1863 ++I;
1864 if (I == EndI)
1865 return DVar;
1866 auto It = I->SharingMap.find(D);
1867 if (It != I->SharingMap.end()) {
1868 const DSAInfo &Data = It->getSecond();
1869 DVar.RefExpr = Data.RefExpr.getPointer();
1870 DVar.PrivateCopy = Data.PrivateCopy;
1871 DVar.CKind = Data.Attributes;
1872 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1873 DVar.DKind = I->Directive;
1874 DVar.Modifier = Data.Modifier;
1875 DVar.AppliedToPointee = Data.AppliedToPointee;
1876 }
1877
1878 return DVar;
1879}
1880
1881const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1882 bool FromParent) const {
1883 if (isStackEmpty()) {
1884 const_iterator I;
1885 return getDSA(I, D);
1886 }
1887 D = getCanonicalDecl(D);
1888 const_iterator StartI = begin();
1889 const_iterator EndI = end();
1890 if (FromParent && StartI != EndI)
1891 ++StartI;
1892 return getDSA(StartI, D);
1893}
1894
1895const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1896 unsigned Level) const {
1897 if (getStackSize() <= Level)
1898 return DSAVarData();
1899 D = getCanonicalDecl(D);
1900 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1901 return getDSA(StartI, D);
1902}
1903
1904const DSAStackTy::DSAVarData
1905DSAStackTy::hasDSA(ValueDecl *D,
1906 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1907 DefaultDataSharingAttributes)>
1908 CPred,
1909 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1910 bool FromParent) const {
1911 if (isStackEmpty())
1912 return {};
1913 D = getCanonicalDecl(D);
1914 const_iterator I = begin();
1915 const_iterator EndI = end();
1916 if (FromParent && I != EndI)
1917 ++I;
1918 for (; I != EndI; ++I) {
1919 if (!DPred(I->Directive) &&
1920 !isImplicitOrExplicitTaskingRegion(I->Directive))
1921 continue;
1922 const_iterator NewI = I;
1923 DSAVarData DVar = getDSA(NewI, D);
1924 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1925 return DVar;
1926 }
1927 return {};
1928}
1929
1930const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1931 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1932 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1933 bool FromParent) const {
1934 if (isStackEmpty())
1935 return {};
1936 D = getCanonicalDecl(D);
1937 const_iterator StartI = begin();
1938 const_iterator EndI = end();
1939 if (FromParent && StartI != EndI)
1940 ++StartI;
1941 if (StartI == EndI || !DPred(StartI->Directive))
1942 return {};
1943 const_iterator NewI = StartI;
1944 DSAVarData DVar = getDSA(NewI, D);
1945 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1946 ? DVar
1947 : DSAVarData();
1948}
1949
1950bool DSAStackTy::hasExplicitDSA(
1951 const ValueDecl *D,
1952 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1953 unsigned Level, bool NotLastprivate) const {
1954 if (getStackSize() <= Level)
1955 return false;
1956 D = getCanonicalDecl(D);
1957 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1958 auto I = StackElem.SharingMap.find(D);
1959 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1960 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1961 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1962 return true;
1963 // Check predetermined rules for the loop control variables.
1964 auto LI = StackElem.LCVMap.find(D);
1965 if (LI != StackElem.LCVMap.end())
1966 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1967 return false;
1968}
1969
1970bool DSAStackTy::hasExplicitDirective(
1971 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1972 unsigned Level) const {
1973 if (getStackSize() <= Level)
1974 return false;
1975 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1976 return DPred(StackElem.Directive);
1977}
1978
1979bool DSAStackTy::hasDirective(
1980 const llvm::function_ref<bool(OpenMPDirectiveKind,
1982 DPred,
1983 bool FromParent) const {
1984 // We look only in the enclosing region.
1985 size_t Skip = FromParent ? 2 : 1;
1986 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1987 I != E; ++I) {
1988 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1989 return true;
1990 }
1991 return false;
1992}
1993
1994void SemaOpenMP::InitDataSharingAttributesStack() {
1995 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
1996}
1997
1998#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
1999
2000void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2001
2002void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2003 DSAStack->popFunction(OldFSI);
2004}
2005
2007 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2008 "Expected OpenMP device compilation.");
2010}
2011
2012namespace {
2013/// Status of the function emission on the host/device.
2014enum class FunctionEmissionStatus {
2015 Emitted,
2016 Discarded,
2017 Unknown,
2018};
2019} // anonymous namespace
2020
2023 const FunctionDecl *FD) {
2024 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2025 "Expected OpenMP device compilation.");
2026
2027 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2028 if (FD) {
2030 switch (FES) {
2032 Kind = SemaDiagnosticBuilder::K_Immediate;
2033 break;
2035 // TODO: We should always delay diagnostics here in case a target
2036 // region is in a function we do not emit. However, as the
2037 // current diagnostics are associated with the function containing
2038 // the target region and we do not emit that one, we would miss out
2039 // on diagnostics for the target region itself. We need to anchor
2040 // the diagnostics with the new generated function *or* ensure we
2041 // emit diagnostics associated with the surrounding function.
2043 ? SemaDiagnosticBuilder::K_Deferred
2044 : SemaDiagnosticBuilder::K_Immediate;
2045 break;
2048 Kind = SemaDiagnosticBuilder::K_Nop;
2049 break;
2051 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2052 break;
2053 }
2054 }
2055
2056 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2057}
2058
2061 const FunctionDecl *FD) {
2062 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2063 "Expected OpenMP host compilation.");
2064
2065 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2066 if (FD) {
2068 switch (FES) {
2070 Kind = SemaDiagnosticBuilder::K_Immediate;
2071 break;
2073 Kind = SemaDiagnosticBuilder::K_Deferred;
2074 break;
2078 Kind = SemaDiagnosticBuilder::K_Nop;
2079 break;
2080 }
2081 }
2082
2083 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2084}
2085
2088 if (LO.OpenMP <= 45) {
2090 return OMPC_DEFAULTMAP_scalar;
2091 return OMPC_DEFAULTMAP_aggregate;
2092 }
2094 return OMPC_DEFAULTMAP_pointer;
2096 return OMPC_DEFAULTMAP_scalar;
2097 return OMPC_DEFAULTMAP_aggregate;
2098}
2099
2101 unsigned OpenMPCaptureLevel) const {
2102 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2103
2104 ASTContext &Ctx = getASTContext();
2105 bool IsByRef = true;
2106
2107 // Find the directive that is associated with the provided scope.
2108 D = cast<ValueDecl>(D->getCanonicalDecl());
2109 QualType Ty = D->getType();
2110
2111 bool IsVariableUsedInMapClause = false;
2112 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2113 // This table summarizes how a given variable should be passed to the device
2114 // given its type and the clauses where it appears. This table is based on
2115 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2116 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2117 //
2118 // =========================================================================
2119 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2120 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2121 // =========================================================================
2122 // | scl | | | | - | | bycopy|
2123 // | scl | | - | x | - | - | bycopy|
2124 // | scl | | x | - | - | - | null |
2125 // | scl | x | | | - | | byref |
2126 // | scl | x | - | x | - | - | bycopy|
2127 // | scl | x | x | - | - | - | null |
2128 // | scl | | - | - | - | x | byref |
2129 // | scl | x | - | - | - | x | byref |
2130 //
2131 // | agg | n.a. | | | - | | byref |
2132 // | agg | n.a. | - | x | - | - | byref |
2133 // | agg | n.a. | x | - | - | - | null |
2134 // | agg | n.a. | - | - | - | x | byref |
2135 // | agg | n.a. | - | - | - | x[] | byref |
2136 //
2137 // | ptr | n.a. | | | - | | bycopy|
2138 // | ptr | n.a. | - | x | - | - | bycopy|
2139 // | ptr | n.a. | x | - | - | - | null |
2140 // | ptr | n.a. | - | - | - | x | byref |
2141 // | ptr | n.a. | - | - | - | x[] | bycopy|
2142 // | ptr | n.a. | - | - | x | | bycopy|
2143 // | ptr | n.a. | - | - | x | x | bycopy|
2144 // | ptr | n.a. | - | - | x | x[] | bycopy|
2145 // =========================================================================
2146 // Legend:
2147 // scl - scalar
2148 // ptr - pointer
2149 // agg - aggregate
2150 // x - applies
2151 // - - invalid in this combination
2152 // [] - mapped with an array section
2153 // byref - should be mapped by reference
2154 // byval - should be mapped by value
2155 // null - initialize a local variable to null on the device
2156 //
2157 // Observations:
2158 // - All scalar declarations that show up in a map clause have to be passed
2159 // by reference, because they may have been mapped in the enclosing data
2160 // environment.
2161 // - If the scalar value does not fit the size of uintptr, it has to be
2162 // passed by reference, regardless the result in the table above.
2163 // - For pointers mapped by value that have either an implicit map or an
2164 // array section, the runtime library may pass the NULL value to the
2165 // device instead of the value passed to it by the compiler.
2166
2167 if (Ty->isReferenceType())
2168 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2169
2170 // Locate map clauses and see if the variable being captured is referred to
2171 // in any of those clauses. Here we only care about variables, not fields,
2172 // because fields are part of aggregates.
2173 bool IsVariableAssociatedWithSection = false;
2174
2175 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2176 D, Level,
2177 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2179 MapExprComponents,
2180 OpenMPClauseKind WhereFoundClauseKind) {
2181 // Both map and has_device_addr clauses information influences how a
2182 // variable is captured. E.g. is_device_ptr does not require changing
2183 // the default behavior.
2184 if (WhereFoundClauseKind != OMPC_map &&
2185 WhereFoundClauseKind != OMPC_has_device_addr)
2186 return false;
2187
2188 auto EI = MapExprComponents.rbegin();
2189 auto EE = MapExprComponents.rend();
2190
2191 assert(EI != EE && "Invalid map expression!");
2192
2193 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2194 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2195
2196 ++EI;
2197 if (EI == EE)
2198 return false;
2199 auto Last = std::prev(EE);
2200 const auto *UO =
2201 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2202 if ((UO && UO->getOpcode() == UO_Deref) ||
2203 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2204 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2205 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2206 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2207 IsVariableAssociatedWithSection = true;
2208 // There is nothing more we need to know about this variable.
2209 return true;
2210 }
2211
2212 // Keep looking for more map info.
2213 return false;
2214 });
2215
2216 if (IsVariableUsedInMapClause) {
2217 // If variable is identified in a map clause it is always captured by
2218 // reference except if it is a pointer that is dereferenced somehow.
2219 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2220 } else {
2221 // By default, all the data that has a scalar type is mapped by copy
2222 // (except for reduction variables).
2223 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2224 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2225 !Ty->isAnyPointerType()) ||
2226 !Ty->isScalarType() ||
2227 DSAStack->isDefaultmapCapturedByRef(
2229 DSAStack->hasExplicitDSA(
2230 D,
2231 [](OpenMPClauseKind K, bool AppliedToPointee) {
2232 return K == OMPC_reduction && !AppliedToPointee;
2233 },
2234 Level);
2235 }
2236 }
2237
2238 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2239 IsByRef =
2240 ((IsVariableUsedInMapClause &&
2241 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2242 OMPD_target) ||
2243 !(DSAStack->hasExplicitDSA(
2244 D,
2245 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2246 return K == OMPC_firstprivate ||
2247 (K == OMPC_reduction && AppliedToPointee);
2248 },
2249 Level, /*NotLastprivate=*/true) ||
2250 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2251 // If the variable is artificial and must be captured by value - try to
2252 // capture by value.
2253 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2254 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2255 // If the variable is implicitly firstprivate and scalar - capture by
2256 // copy
2257 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2258 DSAStack->getDefaultDSA() == DSA_private) &&
2259 !DSAStack->hasExplicitDSA(
2260 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2261 Level) &&
2262 !DSAStack->isLoopControlVariable(D, Level).first);
2263 }
2264
2265 // When passing data by copy, we need to make sure it fits the uintptr size
2266 // and alignment, because the runtime library only deals with uintptr types.
2267 // If it does not fit the uintptr size, we need to pass the data by reference
2268 // instead.
2269 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2271 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2272 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2273 IsByRef = true;
2274 }
2275
2276 return IsByRef;
2277}
2278
2279unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2280 assert(getLangOpts().OpenMP);
2281 return DSAStack->getNestingLevel();
2282}
2283
2285 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2286 DSAStack->isUntiedRegion();
2287}
2288
2290 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2291 !DSAStack->isClauseParsingMode()) ||
2292 DSAStack->hasDirective(
2294 SourceLocation) -> bool {
2296 },
2297 false);
2298}
2299
2301 // Only rebuild for Field.
2302 if (!dyn_cast<FieldDecl>(D))
2303 return false;
2304 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2305 D,
2306 [](OpenMPClauseKind C, bool AppliedToPointee,
2307 DefaultDataSharingAttributes DefaultAttr) {
2308 return isOpenMPPrivate(C) && !AppliedToPointee &&
2309 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2310 },
2311 [](OpenMPDirectiveKind) { return true; },
2312 DSAStack->isClauseParsingMode());
2313 if (DVarPrivate.CKind != OMPC_unknown)
2314 return true;
2315 return false;
2316}
2317
2319 Expr *CaptureExpr, bool WithInit,
2320 DeclContext *CurContext,
2321 bool AsExpression);
2322
2324 unsigned StopAt) {
2325 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2326 D = getCanonicalDecl(D);
2327
2328 auto *VD = dyn_cast<VarDecl>(D);
2329 // Do not capture constexpr variables.
2330 if (VD && VD->isConstexpr())
2331 return nullptr;
2332
2333 // If we want to determine whether the variable should be captured from the
2334 // perspective of the current capturing scope, and we've already left all the
2335 // capturing scopes of the top directive on the stack, check from the
2336 // perspective of its parent directive (if any) instead.
2337 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2338 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2339
2340 // If we are attempting to capture a global variable in a directive with
2341 // 'target' we return true so that this global is also mapped to the device.
2342 //
2343 if (VD && !VD->hasLocalStorage() &&
2345 SemaRef.getCurLambda())) {
2347 DSAStackTy::DSAVarData DVarTop =
2348 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2349 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2350 return VD;
2351 // If the declaration is enclosed in a 'declare target' directive,
2352 // then it should not be captured.
2353 //
2354 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2355 return nullptr;
2356 CapturedRegionScopeInfo *CSI = nullptr;
2357 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2358 llvm::reverse(SemaRef.FunctionScopes),
2359 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2360 : 0)) {
2361 if (!isa<CapturingScopeInfo>(FSI))
2362 return nullptr;
2363 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2364 if (RSI->CapRegionKind == CR_OpenMP) {
2365 CSI = RSI;
2366 break;
2367 }
2368 }
2369 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2372 DSAStack->getDirective(CSI->OpenMPLevel));
2373 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2374 return VD;
2375 }
2377 // Try to mark variable as declare target if it is used in capturing
2378 // regions.
2379 if (getLangOpts().OpenMP <= 45 &&
2380 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2382 return nullptr;
2383 }
2384 }
2385
2386 if (CheckScopeInfo) {
2387 bool OpenMPFound = false;
2388 for (unsigned I = StopAt + 1; I > 0; --I) {
2390 if (!isa<CapturingScopeInfo>(FSI))
2391 return nullptr;
2392 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2393 if (RSI->CapRegionKind == CR_OpenMP) {
2394 OpenMPFound = true;
2395 break;
2396 }
2397 }
2398 if (!OpenMPFound)
2399 return nullptr;
2400 }
2401
2402 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2403 (!DSAStack->isClauseParsingMode() ||
2404 DSAStack->getParentDirective() != OMPD_unknown)) {
2405 auto &&Info = DSAStack->isLoopControlVariable(D);
2406 if (Info.first ||
2407 (VD && VD->hasLocalStorage() &&
2408 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2409 (VD && DSAStack->isForceVarCapturing()))
2410 return VD ? VD : Info.second;
2411 DSAStackTy::DSAVarData DVarTop =
2412 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2413 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2414 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2415 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2416 // Threadprivate variables must not be captured.
2417 if (isOpenMPThreadPrivate(DVarTop.CKind))
2418 return nullptr;
2419 // The variable is not private or it is the variable in the directive with
2420 // default(none) clause and not used in any clause.
2421 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2422 D,
2423 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2424 return isOpenMPPrivate(C) && !AppliedToPointee;
2425 },
2426 [](OpenMPDirectiveKind) { return true; },
2427 DSAStack->isClauseParsingMode());
2428 // Global shared must not be captured.
2429 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2430 ((DSAStack->getDefaultDSA() != DSA_none &&
2431 DSAStack->getDefaultDSA() != DSA_private &&
2432 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2433 DVarTop.CKind == OMPC_shared))
2434 return nullptr;
2435 auto *FD = dyn_cast<FieldDecl>(D);
2436 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2437 !DVarPrivate.PrivateCopy) {
2438 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2439 D,
2440 [](OpenMPClauseKind C, bool AppliedToPointee,
2441 DefaultDataSharingAttributes DefaultAttr) {
2442 return isOpenMPPrivate(C) && !AppliedToPointee &&
2443 (DefaultAttr == DSA_firstprivate ||
2444 DefaultAttr == DSA_private);
2445 },
2446 [](OpenMPDirectiveKind) { return true; },
2447 DSAStack->isClauseParsingMode());
2448 if (DVarPrivate.CKind == OMPC_unknown)
2449 return nullptr;
2450
2451 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2452 if (VD)
2453 return VD;
2455 return nullptr;
2458 /*IsImplicit=*/true);
2459 const CXXScopeSpec CS = CXXScopeSpec();
2461 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2464 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2467 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2468 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2469 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2471 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2472 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2473 return VD;
2474 }
2475 if (DVarPrivate.CKind != OMPC_unknown ||
2476 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2477 DSAStack->getDefaultDSA() == DSA_private ||
2478 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2479 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2480 }
2481 return nullptr;
2482}
2483
2484void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2485 unsigned Level) const {
2486 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2487}
2488
2490 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2491 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2492 DSAStack->loopInit();
2493}
2494
2496 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2497 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2498 DSAStack->resetPossibleLoopCounter();
2499 DSAStack->loopStart();
2500 }
2501}
2502
2504 unsigned CapLevel) const {
2505 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2506 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2507 (!DSAStack->isClauseParsingMode() ||
2508 DSAStack->getParentDirective() != OMPD_unknown)) {
2509 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2510 D,
2511 [](OpenMPClauseKind C, bool AppliedToPointee,
2512 DefaultDataSharingAttributes DefaultAttr) {
2513 return isOpenMPPrivate(C) && !AppliedToPointee &&
2514 DefaultAttr == DSA_private;
2515 },
2516 [](OpenMPDirectiveKind) { return true; },
2517 DSAStack->isClauseParsingMode());
2518 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2519 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2520 !DSAStack->isLoopControlVariable(D).first)
2521 return OMPC_private;
2522 }
2523 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2524 bool IsTriviallyCopyable =
2525 D->getType().getNonReferenceType().isTriviallyCopyableType(
2526 getASTContext()) &&
2527 !D->getType()
2528 .getNonReferenceType()
2529 .getCanonicalType()
2530 ->getAsCXXRecordDecl();
2531 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2533 getOpenMPCaptureRegions(CaptureRegions, DKind);
2534 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2535 (IsTriviallyCopyable ||
2536 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2537 if (DSAStack->hasExplicitDSA(
2538 D,
2539 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2540 Level, /*NotLastprivate=*/true))
2541 return OMPC_firstprivate;
2542 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2543 if (DVar.CKind != OMPC_shared &&
2544 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2545 DSAStack->addImplicitTaskFirstprivate(Level, D);
2546 return OMPC_firstprivate;
2547 }
2548 }
2549 }
2550 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2551 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2552 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2553 DSAStack->resetPossibleLoopCounter(D);
2554 DSAStack->loopStart();
2555 return OMPC_private;
2556 }
2557 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2558 DSAStack->isLoopControlVariable(D).first) &&
2559 !DSAStack->hasExplicitDSA(
2560 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2561 Level) &&
2562 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2563 return OMPC_private;
2564 }
2565 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2566 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2567 DSAStack->isForceVarCapturing() &&
2568 !DSAStack->hasExplicitDSA(
2569 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2570 Level))
2571 return OMPC_private;
2572 }
2573 // User-defined allocators are private since they must be defined in the
2574 // context of target region.
2575 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2576 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2577 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2578 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2579 return OMPC_private;
2580 return (DSAStack->hasExplicitDSA(
2581 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2582 Level) ||
2583 (DSAStack->isClauseParsingMode() &&
2584 DSAStack->getClauseParsingMode() == OMPC_private) ||
2585 // Consider taskgroup reduction descriptor variable a private
2586 // to avoid possible capture in the region.
2587 (DSAStack->hasExplicitDirective(
2588 [](OpenMPDirectiveKind K) {
2589 return K == OMPD_taskgroup ||
2590 ((isOpenMPParallelDirective(K) ||
2591 isOpenMPWorksharingDirective(K)) &&
2592 !isOpenMPSimdDirective(K));
2593 },
2594 Level) &&
2595 DSAStack->isTaskgroupReductionRef(D, Level)))
2596 ? OMPC_private
2597 : OMPC_unknown;
2598}
2599
2601 unsigned Level) {
2602 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2603 D = getCanonicalDecl(D);
2604 OpenMPClauseKind OMPC = OMPC_unknown;
2605 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2606 const unsigned NewLevel = I - 1;
2607 if (DSAStack->hasExplicitDSA(
2608 D,
2609 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2610 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2611 OMPC = K;
2612 return true;
2613 }
2614 return false;
2615 },
2616 NewLevel))
2617 break;
2618 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2619 D, NewLevel,
2621 OpenMPClauseKind) { return true; })) {
2622 OMPC = OMPC_map;
2623 break;
2624 }
2625 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2626 NewLevel)) {
2627 OMPC = OMPC_map;
2628 if (DSAStack->mustBeFirstprivateAtLevel(
2630 OMPC = OMPC_firstprivate;
2631 break;
2632 }
2633 }
2634 if (OMPC != OMPC_unknown)
2635 FD->addAttr(
2636 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2637}
2638
2640 unsigned CaptureLevel) const {
2641 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2642 // Return true if the current level is no longer enclosed in a target region.
2643
2645 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2646 const auto *VD = dyn_cast<VarDecl>(D);
2647 return VD && !VD->hasLocalStorage() &&
2648 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2649 Level) &&
2650 Regions[CaptureLevel] != OMPD_task;
2651}
2652
2654 unsigned CaptureLevel) const {
2655 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2656 // Return true if the current level is no longer enclosed in a target region.
2657
2658 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2659 if (!VD->hasLocalStorage()) {
2661 return true;
2662 DSAStackTy::DSAVarData TopDVar =
2663 DSAStack->getTopDSA(D, /*FromParent=*/false);
2664 unsigned NumLevels =
2665 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2666 if (Level == 0)
2667 // non-file scope static variable with default(firstprivate)
2668 // should be global captured.
2669 return (NumLevels == CaptureLevel + 1 &&
2670 (TopDVar.CKind != OMPC_shared ||
2671 DSAStack->getDefaultDSA() == DSA_firstprivate));
2672 do {
2673 --Level;
2674 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2675 if (DVar.CKind != OMPC_shared)
2676 return true;
2677 } while (Level > 0);
2678 }
2679 }
2680 return true;
2681}
2682
2683void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2684
2686 OMPTraitInfo &TI) {
2687 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2688}
2689
2692 "Not in OpenMP declare variant scope!");
2693
2694 OMPDeclareVariantScopes.pop_back();
2695}
2696
2698 const FunctionDecl *Callee,
2700 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2701 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2702 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2703 // Ignore host functions during device analysis.
2704 if (getLangOpts().OpenMPIsTargetDevice &&
2705 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2706 return;
2707 // Ignore nohost functions during host analysis.
2708 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2709 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2710 return;
2711 const FunctionDecl *FD = Callee->getMostRecentDecl();
2712 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2713 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2714 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2715 // Diagnose host function called during device codegen.
2716 StringRef HostDevTy =
2717 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2718 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2719 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2720 diag::note_omp_marked_device_type_here)
2721 << HostDevTy;
2722 return;
2723 }
2724 if (!getLangOpts().OpenMPIsTargetDevice &&
2725 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2726 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2727 // In OpenMP 5.2 or later, if the function has a host variant then allow
2728 // that to be called instead
2729 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2730 for (OMPDeclareVariantAttr *A :
2731 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2732 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2733 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2734 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2735 OMPDeclareTargetDeclAttr::getDeviceType(
2736 VariantFD->getMostRecentDecl());
2737 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2738 return true;
2739 }
2740 return false;
2741 };
2742 if (getLangOpts().OpenMP >= 52 &&
2743 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2744 return;
2745 // Diagnose nohost function called during host codegen.
2746 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2747 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2748 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2749 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2750 diag::note_omp_marked_device_type_here)
2751 << NoHostDevTy;
2752 }
2753}
2754
2756 const DeclarationNameInfo &DirName,
2757 Scope *CurScope, SourceLocation Loc) {
2758 DSAStack->push(DKind, DirName, CurScope, Loc);
2761}
2762
2764 DSAStack->setClauseParsingMode(K);
2765}
2766
2768 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2770}
2771
2772static std::pair<ValueDecl *, bool>
2773getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2774 SourceRange &ERange, bool AllowArraySection = false,
2775 StringRef DiagType = "");
2776
2777/// Check consistency of the reduction clauses.
2778static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2779 ArrayRef<OMPClause *> Clauses) {
2780 bool InscanFound = false;
2781 SourceLocation InscanLoc;
2782 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2783 // A reduction clause without the inscan reduction-modifier may not appear on
2784 // a construct on which a reduction clause with the inscan reduction-modifier
2785 // appears.
2786 for (OMPClause *C : Clauses) {
2787 if (C->getClauseKind() != OMPC_reduction)
2788 continue;
2789 auto *RC = cast<OMPReductionClause>(C);
2790 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2791 InscanFound = true;
2792 InscanLoc = RC->getModifierLoc();
2793 continue;
2794 }
2795 if (RC->getModifier() == OMPC_REDUCTION_task) {
2796 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2797 // A reduction clause with the task reduction-modifier may only appear on
2798 // a parallel construct, a worksharing construct or a combined or
2799 // composite construct for which any of the aforementioned constructs is a
2800 // constituent construct and simd or loop are not constituent constructs.
2801 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2802 if (!(isOpenMPParallelDirective(CurDir) ||
2804 isOpenMPSimdDirective(CurDir))
2805 S.Diag(RC->getModifierLoc(),
2806 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2807 continue;
2808 }
2809 }
2810 if (InscanFound) {
2811 for (OMPClause *C : Clauses) {
2812 if (C->getClauseKind() != OMPC_reduction)
2813 continue;
2814 auto *RC = cast<OMPReductionClause>(C);
2815 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2816 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2817 ? RC->getBeginLoc()
2818 : RC->getModifierLoc(),
2819 diag::err_omp_inscan_reduction_expected);
2820 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2821 continue;
2822 }
2823 for (Expr *Ref : RC->varlist()) {
2824 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2825 SourceLocation ELoc;
2826 SourceRange ERange;
2827 Expr *SimpleRefExpr = Ref;
2828 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2829 /*AllowArraySection=*/true);
2830 ValueDecl *D = Res.first;
2831 if (!D)
2832 continue;
2833 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2834 S.Diag(Ref->getExprLoc(),
2835 diag::err_omp_reduction_not_inclusive_exclusive)
2836 << Ref->getSourceRange();
2837 }
2838 }
2839 }
2840 }
2841}
2842
2843static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2844 ArrayRef<OMPClause *> Clauses);
2845static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2846 bool WithInit);
2847
2848static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2849 const ValueDecl *D,
2850 const DSAStackTy::DSAVarData &DVar,
2851 bool IsLoopIterVar = false);
2852
2854 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2855 // A variable of class type (or array thereof) that appears in a lastprivate
2856 // clause requires an accessible, unambiguous default constructor for the
2857 // class type, unless the list item is also specified in a firstprivate
2858 // clause.
2859
2860 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2861 SmallVector<Expr *, 8> PrivateCopies;
2862 for (Expr *DE : Clause->varlist()) {
2863 if (DE->isValueDependent() || DE->isTypeDependent()) {
2864 PrivateCopies.push_back(nullptr);
2865 continue;
2866 }
2867 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2868 auto *VD = cast<VarDecl>(DRE->getDecl());
2870 const DSAStackTy::DSAVarData DVar =
2871 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2872 if (DVar.CKind != OMPC_lastprivate) {
2873 // The variable is also a firstprivate, so initialization sequence
2874 // for private copy is generated already.
2875 PrivateCopies.push_back(nullptr);
2876 continue;
2877 }
2878 // Generate helper private variable and initialize it with the
2879 // default value. The address of the original variable is replaced
2880 // by the address of the new private variable in CodeGen. This new
2881 // variable is not added to IdResolver, so the code in the OpenMP
2882 // region uses original variable for proper diagnostics.
2883 VarDecl *VDPrivate = buildVarDecl(
2884 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2885 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2887 if (VDPrivate->isInvalidDecl()) {
2888 PrivateCopies.push_back(nullptr);
2889 continue;
2890 }
2891 PrivateCopies.push_back(buildDeclRefExpr(
2892 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2893 }
2894 Clause->setPrivateCopies(PrivateCopies);
2895 };
2896
2897 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2898 // Finalize nontemporal clause by handling private copies, if any.
2899 SmallVector<Expr *, 8> PrivateRefs;
2900 for (Expr *RefExpr : Clause->varlist()) {
2901 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2902 SourceLocation ELoc;
2903 SourceRange ERange;
2904 Expr *SimpleRefExpr = RefExpr;
2905 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2906 if (Res.second)
2907 // It will be analyzed later.
2908 PrivateRefs.push_back(RefExpr);
2909 ValueDecl *D = Res.first;
2910 if (!D)
2911 continue;
2912
2913 const DSAStackTy::DSAVarData DVar =
2914 DSAStack->getTopDSA(D, /*FromParent=*/false);
2915 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2916 : SimpleRefExpr);
2917 }
2918 Clause->setPrivateRefs(PrivateRefs);
2919 };
2920
2921 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
2922 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2923 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2924 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2925 if (!DRE)
2926 continue;
2927 ValueDecl *VD = DRE->getDecl();
2928 if (!VD || !isa<VarDecl>(VD))
2929 continue;
2930 DSAStackTy::DSAVarData DVar =
2931 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2932 // OpenMP [2.12.5, target Construct]
2933 // Memory allocators that appear in a uses_allocators clause cannot
2934 // appear in other data-sharing attribute clauses or data-mapping
2935 // attribute clauses in the same construct.
2936 Expr *MapExpr = nullptr;
2937 if (DVar.RefExpr ||
2938 DSAStack->checkMappableExprComponentListsForDecl(
2939 VD, /*CurrentRegionOnly=*/true,
2940 [VD, &MapExpr](
2942 MapExprComponents,
2944 auto MI = MapExprComponents.rbegin();
2945 auto ME = MapExprComponents.rend();
2946 if (MI != ME &&
2947 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2948 VD->getCanonicalDecl()) {
2949 MapExpr = MI->getAssociatedExpression();
2950 return true;
2951 }
2952 return false;
2953 })) {
2954 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
2955 << D.Allocator->getSourceRange();
2956 if (DVar.RefExpr)
2958 else
2959 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2960 << MapExpr->getSourceRange();
2961 }
2962 }
2963 };
2964
2965 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2966 for (OMPClause *C : D->clauses()) {
2967 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2968 FinalizeLastprivate(Clause);
2969 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2970 FinalizeNontemporal(Clause);
2971 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2972 FinalizeAllocators(Clause);
2973 }
2974 }
2975 // Check allocate clauses.
2976 if (!SemaRef.CurContext->isDependentContext())
2977 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
2978 checkReductionClauses(SemaRef, DSAStack, D->clauses());
2979 }
2980
2981 DSAStack->pop();
2984}
2985
2987 Expr *NumIterations, Sema &SemaRef,
2988 Scope *S, DSAStackTy *Stack);
2989
2990static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
2992 DSAStackTy *Stack) {
2993 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
2994 "loop exprs were not built");
2995
2996 if (SemaRef.CurContext->isDependentContext())
2997 return false;
2998
2999 // Finalize the clauses that need pre-built expressions for CodeGen.
3000 for (OMPClause *C : Clauses) {
3001 auto *LC = dyn_cast<OMPLinearClause>(C);
3002 if (!LC)
3003 continue;
3004 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3005 B.NumIterations, SemaRef,
3006 SemaRef.getCurScope(), Stack))
3007 return true;
3008 }
3009
3010 return false;
3011}
3012
3013namespace {
3014
3015class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3016private:
3017 Sema &SemaRef;
3018
3019public:
3020 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3021 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3022 NamedDecl *ND = Candidate.getCorrectionDecl();
3023 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3024 return VD->hasGlobalStorage() &&
3025 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3026 SemaRef.getCurScope());
3027 }
3028 return false;
3029 }
3030
3031 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3032 return std::make_unique<VarDeclFilterCCC>(*this);
3033 }
3034};
3035
3036class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3037private:
3038 Sema &SemaRef;
3039
3040public:
3041 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3042 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3043 NamedDecl *ND = Candidate.getCorrectionDecl();
3044 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3045 isa<FunctionDecl>(ND))) {
3046 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3047 SemaRef.getCurScope());
3048 }
3049 return false;
3050 }
3051
3052 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3053 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3054 }
3055};
3056
3057} // namespace
3058
3060 CXXScopeSpec &ScopeSpec,
3061 const DeclarationNameInfo &Id,
3062 OpenMPDirectiveKind Kind) {
3063 ASTContext &Context = getASTContext();
3065 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3066 /*ObjectType=*/QualType(),
3067 /*AllowBuiltinCreation=*/true);
3068
3069 if (Lookup.isAmbiguous())
3070 return ExprError();
3071
3072 VarDecl *VD;
3073 if (!Lookup.isSingleResult()) {
3074 VarDeclFilterCCC CCC(SemaRef);
3075 if (TypoCorrection Corrected =
3076 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3079 Corrected,
3080 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3081 : diag::err_omp_expected_var_arg_suggest)
3082 << Id.getName());
3083 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3084 } else {
3085 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3086 : diag::err_omp_expected_var_arg)
3087 << Id.getName();
3088 return ExprError();
3089 }
3090 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3091 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3092 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3093 return ExprError();
3094 }
3095 Lookup.suppressDiagnostics();
3096
3097 // OpenMP [2.9.2, Syntax, C/C++]
3098 // Variables must be file-scope, namespace-scope, or static block-scope.
3099 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3100 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3101 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3102 bool IsDecl =
3104 Diag(VD->getLocation(),
3105 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3106 << VD;
3107 return ExprError();
3108 }
3109
3110 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3111 NamedDecl *ND = CanonicalVD;
3112 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3113 // A threadprivate directive for file-scope variables must appear outside
3114 // any definition or declaration.
3115 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3117 Diag(Id.getLoc(), diag::err_omp_var_scope)
3118 << getOpenMPDirectiveName(Kind) << VD;
3119 bool IsDecl =
3121 Diag(VD->getLocation(),
3122 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3123 << VD;
3124 return ExprError();
3125 }
3126 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3127 // A threadprivate directive for static class member variables must appear
3128 // in the class definition, in the same scope in which the member
3129 // variables are declared.
3130 if (CanonicalVD->isStaticDataMember() &&
3131 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3132 Diag(Id.getLoc(), diag::err_omp_var_scope)
3133 << getOpenMPDirectiveName(Kind) << VD;
3134 bool IsDecl =
3136 Diag(VD->getLocation(),
3137 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3138 << VD;
3139 return ExprError();
3140 }
3141 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3142 // A threadprivate directive for namespace-scope variables must appear
3143 // outside any definition or declaration other than the namespace
3144 // definition itself.
3145 if (CanonicalVD->getDeclContext()->isNamespace() &&
3148 CanonicalVD->getDeclContext()))) {
3149 Diag(Id.getLoc(), diag::err_omp_var_scope)
3150 << getOpenMPDirectiveName(Kind) << VD;
3151 bool IsDecl =
3153 Diag(VD->getLocation(),
3154 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3155 << VD;
3156 return ExprError();
3157 }
3158 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3159 // A threadprivate directive for static block-scope variables must appear
3160 // in the scope of the variable and not in a nested scope.
3161 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3163 Diag(Id.getLoc(), diag::err_omp_var_scope)
3164 << getOpenMPDirectiveName(Kind) << VD;
3165 bool IsDecl =
3167 Diag(VD->getLocation(),
3168 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3169 << VD;
3170 return ExprError();
3171 }
3172
3173 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3174 // A threadprivate directive must lexically precede all references to any
3175 // of the variables in its list.
3176 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3177 !DSAStack->isThreadPrivate(VD)) {
3178 Diag(Id.getLoc(), diag::err_omp_var_used)
3179 << getOpenMPDirectiveName(Kind) << VD;
3180 return ExprError();
3181 }
3182
3183 QualType ExprType = VD->getType().getNonReferenceType();
3185 SourceLocation(), VD,
3186 /*RefersToEnclosingVariableOrCapture=*/false,
3187 Id.getLoc(), ExprType, VK_LValue);
3188}
3189
3192 ArrayRef<Expr *> VarList) {
3196 }
3197 return nullptr;
3198}
3199
3200namespace {
3201class LocalVarRefChecker final
3202 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3203 Sema &SemaRef;
3204
3205public:
3206 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3207 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3208 if (VD->hasLocalStorage()) {
3209 SemaRef.Diag(E->getBeginLoc(),
3210 diag::err_omp_local_var_in_threadprivate_init)
3211 << E->getSourceRange();
3212 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3213 << VD << VD->getSourceRange();
3214 return true;
3215 }
3216 }
3217 return false;
3218 }
3219 bool VisitStmt(const Stmt *S) {
3220 for (const Stmt *Child : S->children()) {
3221 if (Child && Visit(Child))
3222 return true;
3223 }
3224 return false;
3225 }
3226 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3227};
3228} // namespace
3229
3232 ArrayRef<Expr *> VarList) {
3233 ASTContext &Context = getASTContext();
3235 for (Expr *RefExpr : VarList) {
3236 auto *DE = cast<DeclRefExpr>(RefExpr);
3237 auto *VD = cast<VarDecl>(DE->getDecl());
3238 SourceLocation ILoc = DE->getExprLoc();
3239
3240 // Mark variable as used.
3241 VD->setReferenced();
3242 VD->markUsed(Context);
3243
3244 QualType QType = VD->getType();
3245 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3246 // It will be analyzed later.
3247 Vars.push_back(DE);
3248 continue;
3249 }
3250
3251 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3252 // A threadprivate variable must not have an incomplete type.
3254 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3255 continue;
3256 }
3257
3258 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3259 // A threadprivate variable must not have a reference type.
3260 if (VD->getType()->isReferenceType()) {
3261 Diag(ILoc, diag::err_omp_ref_type_arg)
3262 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3263 bool IsDecl =
3265 Diag(VD->getLocation(),
3266 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3267 << VD;
3268 continue;
3269 }
3270
3271 // Check if this is a TLS variable. If TLS is not being supported, produce
3272 // the corresponding diagnostic.
3273 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3274 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3275 getLangOpts().OpenMPUseTLS &&
3276 getASTContext().getTargetInfo().isTLSSupported())) ||
3277 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3278 !VD->isLocalVarDecl())) {
3279 Diag(ILoc, diag::err_omp_var_thread_local)
3280 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3281 bool IsDecl =
3283 Diag(VD->getLocation(),
3284 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3285 << VD;
3286 continue;
3287 }
3288
3289 // Check if initial value of threadprivate variable reference variable with
3290 // local storage (it is not supported by runtime).
3291 if (const Expr *Init = VD->getAnyInitializer()) {
3292 LocalVarRefChecker Checker(SemaRef);
3293 if (Checker.Visit(Init))
3294 continue;
3295 }
3296
3297 Vars.push_back(RefExpr);
3298 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3299 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3300 Context, SourceRange(Loc, Loc)));
3301 if (ASTMutationListener *ML = Context.getASTMutationListener())
3302 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3303 }
3304 OMPThreadPrivateDecl *D = nullptr;
3305 if (!Vars.empty()) {
3307 Loc, Vars);
3309 }
3310 return D;
3311}
3312
3313static OMPAllocateDeclAttr::AllocatorTypeTy
3314getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3315 if (!Allocator)
3316 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3317 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3318 Allocator->isInstantiationDependent() ||
3319 Allocator->containsUnexpandedParameterPack())
3320 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3321 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3322 llvm::FoldingSetNodeID AEId;
3323 const Expr *AE = Allocator->IgnoreParenImpCasts();
3324 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3325 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3326 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3327 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3328 llvm::FoldingSetNodeID DAEId;
3329 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3330 /*Canonical=*/true);
3331 if (AEId == DAEId) {
3332 AllocatorKindRes = AllocatorKind;
3333 break;
3334 }
3335 }
3336 return AllocatorKindRes;
3337}
3338
3340 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3341 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3342 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3343 return false;
3344 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3345 Expr *PrevAllocator = A->getAllocator();
3346 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3347 getAllocatorKind(S, Stack, PrevAllocator);
3348 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3349 if (AllocatorsMatch &&
3350 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3351 Allocator && PrevAllocator) {
3352 const Expr *AE = Allocator->IgnoreParenImpCasts();
3353 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3354 llvm::FoldingSetNodeID AEId, PAEId;
3355 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3356 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3357 AllocatorsMatch = AEId == PAEId;
3358 }
3359 if (!AllocatorsMatch) {
3360 SmallString<256> AllocatorBuffer;
3361 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3362 if (Allocator)
3363 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3364 SmallString<256> PrevAllocatorBuffer;
3365 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3366 if (PrevAllocator)
3367 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3368 S.getPrintingPolicy());
3369
3370 SourceLocation AllocatorLoc =
3371 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3372 SourceRange AllocatorRange =
3373 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3374 SourceLocation PrevAllocatorLoc =
3375 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3376 SourceRange PrevAllocatorRange =
3377 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3378 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3379 << (Allocator ? 1 : 0) << AllocatorStream.str()
3380 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3381 << AllocatorRange;
3382 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3383 << PrevAllocatorRange;
3384 return true;
3385 }
3386 return false;
3387}
3388
3389static void
3391 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3392 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3393 if (VD->hasAttr<OMPAllocateDeclAttr>())
3394 return;
3395 if (Alignment &&
3396 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3397 Alignment->isInstantiationDependent() ||
3398 Alignment->containsUnexpandedParameterPack()))
3399 // Apply later when we have a usable value.
3400 return;
3401 if (Allocator &&
3402 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3403 Allocator->isInstantiationDependent() ||
3404 Allocator->containsUnexpandedParameterPack()))
3405 return;
3406 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3407 Allocator, Alignment, SR);
3408 VD->addAttr(A);
3410 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3411}
3412
3415 DeclContext *Owner) {
3416 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3417 Expr *Alignment = nullptr;
3418 Expr *Allocator = nullptr;
3419 if (Clauses.empty()) {
3420 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3421 // allocate directives that appear in a target region must specify an
3422 // allocator clause unless a requires directive with the dynamic_allocators
3423 // clause is present in the same compilation unit.
3424 if (getLangOpts().OpenMPIsTargetDevice &&
3425 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3426 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3427 } else {
3428 for (const OMPClause *C : Clauses)
3429 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3430 Allocator = AC->getAllocator();
3431 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3432 Alignment = AC->getAlignment();
3433 else
3434 llvm_unreachable("Unexpected clause on allocate directive");
3435 }
3436 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3437 getAllocatorKind(SemaRef, DSAStack, Allocator);
3439 for (Expr *RefExpr : VarList) {
3440 auto *DE = cast<DeclRefExpr>(RefExpr);
3441 auto *VD = cast<VarDecl>(DE->getDecl());
3442
3443 // Check if this is a TLS variable or global register.
3444 if (VD->getTLSKind() != VarDecl::TLS_None ||
3445 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3446 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3447 !VD->isLocalVarDecl()))
3448 continue;
3449
3450 // If the used several times in the allocate directive, the same allocator
3451 // must be used.
3453 AllocatorKind, Allocator))
3454 continue;
3455
3456 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3457 // If a list item has a static storage type, the allocator expression in the
3458 // allocator clause must be a constant expression that evaluates to one of
3459 // the predefined memory allocator values.
3460 if (Allocator && VD->hasGlobalStorage()) {
3461 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3462 Diag(Allocator->getExprLoc(),
3463 diag::err_omp_expected_predefined_allocator)
3464 << Allocator->getSourceRange();
3465 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3467 Diag(VD->getLocation(),
3468 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3469 << VD;
3470 continue;
3471 }
3472 }
3473
3474 Vars.push_back(RefExpr);
3475 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3476 DE->getSourceRange());
3477 }
3478 if (Vars.empty())
3479 return nullptr;
3480 if (!Owner)
3481 Owner = SemaRef.getCurLexicalContext();
3482 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3484 Owner->addDecl(D);
3486}
3487
3490 ArrayRef<OMPClause *> ClauseList) {
3491 OMPRequiresDecl *D = nullptr;
3493 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3494 } else {
3495 D = CheckOMPRequiresDecl(Loc, ClauseList);
3496 if (D) {
3498 DSAStack->addRequiresDecl(D);
3499 }
3500 }
3502}
3503
3505 OpenMPDirectiveKind DKind,
3506 ArrayRef<std::string> Assumptions,
3507 bool SkippedClauses) {
3508 if (!SkippedClauses && Assumptions.empty())
3509 Diag(Loc, diag::err_omp_no_clause_for_directive)
3510 << llvm::omp::getAllAssumeClauseOptions()
3511 << llvm::omp::getOpenMPDirectiveName(DKind);
3512
3513 auto *AA =
3514 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3515 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3516 OMPAssumeScoped.push_back(AA);
3517 return;
3518 }
3519
3520 // Global assumes without assumption clauses are ignored.
3521 if (Assumptions.empty())
3522 return;
3523
3524 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3525 "Unexpected omp assumption directive!");
3526 OMPAssumeGlobal.push_back(AA);
3527
3528 // The OMPAssumeGlobal scope above will take care of new declarations but
3529 // we also want to apply the assumption to existing ones, e.g., to
3530 // declarations in included headers. To this end, we traverse all existing
3531 // declaration contexts and annotate function declarations here.
3532 SmallVector<DeclContext *, 8> DeclContexts;
3533 auto *Ctx = SemaRef.CurContext;
3534 while (Ctx->getLexicalParent())
3535 Ctx = Ctx->getLexicalParent();
3536 DeclContexts.push_back(Ctx);
3537 while (!DeclContexts.empty()) {
3538 DeclContext *DC = DeclContexts.pop_back_val();
3539 for (auto *SubDC : DC->decls()) {
3540 if (SubDC->isInvalidDecl())
3541 continue;
3542 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3543 DeclContexts.push_back(CTD->getTemplatedDecl());
3544 llvm::append_range(DeclContexts, CTD->specializations());
3545 continue;
3546 }
3547 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3548 DeclContexts.push_back(DC);
3549 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3550 F->addAttr(AA);
3551 continue;
3552 }
3553 }
3554 }
3555}
3556
3558 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3559 OMPAssumeScoped.pop_back();
3560}
3561
3563 Stmt *AStmt,
3564 SourceLocation StartLoc,
3565 SourceLocation EndLoc) {
3566 if (!AStmt)
3567 return StmtError();
3568
3569 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3570 AStmt);
3571}
3572
3575 ArrayRef<OMPClause *> ClauseList) {
3576 /// For target specific clauses, the requires directive cannot be
3577 /// specified after the handling of any of the target regions in the
3578 /// current compilation unit.
3579 ArrayRef<SourceLocation> TargetLocations =
3580 DSAStack->getEncounteredTargetLocs();
3581 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3582 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3583 for (const OMPClause *CNew : ClauseList) {
3584 // Check if any of the requires clauses affect target regions.
3585 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3586 isa<OMPUnifiedAddressClause>(CNew) ||
3587 isa<OMPReverseOffloadClause>(CNew) ||
3588 isa<OMPDynamicAllocatorsClause>(CNew)) {
3589 Diag(Loc, diag::err_omp_directive_before_requires)
3590 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3591 for (SourceLocation TargetLoc : TargetLocations) {
3592 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3593 << "target";
3594 }
3595 } else if (!AtomicLoc.isInvalid() &&
3596 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3597 Diag(Loc, diag::err_omp_directive_before_requires)
3598 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3599 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3600 << "atomic";
3601 }
3602 }
3603 }
3604
3605 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3607 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3608 return nullptr;
3609}
3610
3611static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3612 const ValueDecl *D,
3613 const DSAStackTy::DSAVarData &DVar,
3614 bool IsLoopIterVar) {
3615 if (DVar.RefExpr) {
3616 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3617 << getOpenMPClauseName(DVar.CKind);
3618 return;
3619 }
3620 enum {
3621 PDSA_StaticMemberShared,
3622 PDSA_StaticLocalVarShared,
3623 PDSA_LoopIterVarPrivate,
3624 PDSA_LoopIterVarLinear,
3625 PDSA_LoopIterVarLastprivate,
3626 PDSA_ConstVarShared,
3627 PDSA_GlobalVarShared,
3628 PDSA_TaskVarFirstprivate,
3629 PDSA_LocalVarPrivate,
3630 PDSA_Implicit
3631 } Reason = PDSA_Implicit;
3632 bool ReportHint = false;
3633 auto ReportLoc = D->getLocation();
3634 auto *VD = dyn_cast<VarDecl>(D);
3635 if (IsLoopIterVar) {
3636 if (DVar.CKind == OMPC_private)
3637 Reason = PDSA_LoopIterVarPrivate;
3638 else if (DVar.CKind == OMPC_lastprivate)
3639 Reason = PDSA_LoopIterVarLastprivate;
3640 else
3641 Reason = PDSA_LoopIterVarLinear;
3642 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3643 DVar.CKind == OMPC_firstprivate) {
3644 Reason = PDSA_TaskVarFirstprivate;
3645 ReportLoc = DVar.ImplicitDSALoc;
3646 } else if (VD && VD->isStaticLocal())
3647 Reason = PDSA_StaticLocalVarShared;
3648 else if (VD && VD->isStaticDataMember())
3649 Reason = PDSA_StaticMemberShared;
3650 else if (VD && VD->isFileVarDecl())
3651 Reason = PDSA_GlobalVarShared;
3652 else if (D->getType().isConstant(SemaRef.getASTContext()))
3653 Reason = PDSA_ConstVarShared;
3654 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3655 ReportHint = true;
3656 Reason = PDSA_LocalVarPrivate;
3657 }
3658 if (Reason != PDSA_Implicit) {
3659 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3660 << Reason << ReportHint
3661 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3662 } else if (DVar.ImplicitDSALoc.isValid()) {
3663 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3664 << getOpenMPClauseName(DVar.CKind);
3665 }
3666}
3667
3670 bool IsAggregateOrDeclareTarget) {
3672 switch (M) {
3673 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3674 Kind = OMPC_MAP_alloc;
3675 break;
3676 case OMPC_DEFAULTMAP_MODIFIER_to:
3677 Kind = OMPC_MAP_to;
3678 break;
3679 case OMPC_DEFAULTMAP_MODIFIER_from:
3680 Kind = OMPC_MAP_from;
3681 break;
3682 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3683 Kind = OMPC_MAP_tofrom;
3684 break;
3685 case OMPC_DEFAULTMAP_MODIFIER_present:
3686 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3687 // If implicit-behavior is present, each variable referenced in the
3688 // construct in the category specified by variable-category is treated as if
3689 // it had been listed in a map clause with the map-type of alloc and
3690 // map-type-modifier of present.
3691 Kind = OMPC_MAP_alloc;
3692 break;
3693 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3695 llvm_unreachable("Unexpected defaultmap implicit behavior");
3696 case OMPC_DEFAULTMAP_MODIFIER_none:
3697 case OMPC_DEFAULTMAP_MODIFIER_default:
3699 // IsAggregateOrDeclareTarget could be true if:
3700 // 1. the implicit behavior for aggregate is tofrom
3701 // 2. it's a declare target link
3702 if (IsAggregateOrDeclareTarget) {
3703 Kind = OMPC_MAP_tofrom;
3704 break;
3705 }
3706 llvm_unreachable("Unexpected defaultmap implicit behavior");
3707 }
3708 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3709 return Kind;
3710}
3711
3712namespace {
3713struct VariableImplicitInfo {
3714 static const unsigned MapKindNum = OMPC_MAP_unknown;
3715 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3716
3717 llvm::SetVector<Expr *> Privates;
3718 llvm::SetVector<Expr *> Firstprivates;
3719 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3721 MapModifiers[DefaultmapKindNum];
3722};
3723
3724class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3725 DSAStackTy *Stack;
3726 Sema &SemaRef;
3727 OpenMPDirectiveKind DKind = OMPD_unknown;
3728 bool ErrorFound = false;
3729 bool TryCaptureCXXThisMembers = false;
3730 CapturedStmt *CS = nullptr;
3731
3732 VariableImplicitInfo ImpInfo;
3733 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3734 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3735
3736 void VisitSubCaptures(OMPExecutableDirective *S) {
3737 // Check implicitly captured variables.
3738 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3739 return;
3740 if (S->getDirectiveKind() == OMPD_atomic ||
3741 S->getDirectiveKind() == OMPD_critical ||
3742 S->getDirectiveKind() == OMPD_section ||
3743 S->getDirectiveKind() == OMPD_master ||
3744 S->getDirectiveKind() == OMPD_masked ||
3745 S->getDirectiveKind() == OMPD_scope ||
3746 S->getDirectiveKind() == OMPD_assume ||
3747 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3748 Visit(S->getAssociatedStmt());
3749 return;
3750 }
3751 visitSubCaptures(S->getInnermostCapturedStmt());
3752 // Try to capture inner this->member references to generate correct mappings
3753 // and diagnostics.
3754 if (TryCaptureCXXThisMembers ||
3756 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3757 [](const CapturedStmt::Capture &C) {
3758 return C.capturesThis();
3759 }))) {
3760 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3761 TryCaptureCXXThisMembers = true;
3762 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3763 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3764 }
3765 // In tasks firstprivates are not captured anymore, need to analyze them
3766 // explicitly.
3767 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3768 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3769 for (OMPClause *C : S->clauses())
3770 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3771 for (Expr *Ref : FC->varlist())
3772 Visit(Ref);
3773 }
3774 }
3775 }
3776
3777public:
3778 void VisitDeclRefExpr(DeclRefExpr *E) {
3779 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3782 E->isNonOdrUse() == clang::NOUR_Unevaluated)
3783 return;
3784 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3785 // Check the datasharing rules for the expressions in the clauses.
3786 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3787 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3788 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3789 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3790 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3791 Visit(CED->getInit());
3792 return;
3793 }
3794 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3795 // Do not analyze internal variables and do not enclose them into
3796 // implicit clauses.
3797 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3798 return;
3799 VD = VD->getCanonicalDecl();
3800 // Skip internally declared variables.
3801 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3802 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3803 !Stack->isImplicitTaskFirstprivate(VD))
3804 return;
3805 // Skip allocators in uses_allocators clauses.
3806 if (Stack->isUsesAllocatorsDecl(VD))
3807 return;
3808
3809 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3810 // Check if the variable has explicit DSA set and stop analysis if it so.
3811 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3812 return;
3813
3814 // Skip internally declared static variables.
3815 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3816 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3817 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3818 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3819 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3820 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3821 !Stack->isImplicitTaskFirstprivate(VD))
3822 return;
3823
3824 SourceLocation ELoc = E->getExprLoc();
3825 // The default(none) clause requires that each variable that is referenced
3826 // in the construct, and does not have a predetermined data-sharing
3827 // attribute, must have its data-sharing attribute explicitly determined
3828 // by being listed in a data-sharing attribute clause.
3829 if (DVar.CKind == OMPC_unknown &&
3830 (Stack->getDefaultDSA() == DSA_none ||
3831 Stack->getDefaultDSA() == DSA_private ||
3832 Stack->getDefaultDSA() == DSA_firstprivate) &&
3833 isImplicitOrExplicitTaskingRegion(DKind) &&
3834 VarsWithInheritedDSA.count(VD) == 0) {
3835 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3836 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3837 Stack->getDefaultDSA() == DSA_private)) {
3838 DSAStackTy::DSAVarData DVar =
3839 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3840 InheritedDSA = DVar.CKind == OMPC_unknown;
3841 }
3842 if (InheritedDSA)
3843 VarsWithInheritedDSA[VD] = E;
3844 if (Stack->getDefaultDSA() == DSA_none)
3845 return;
3846 }
3847
3848 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3849 // If implicit-behavior is none, each variable referenced in the
3850 // construct that does not have a predetermined data-sharing attribute
3851 // and does not appear in a to or link clause on a declare target
3852 // directive must be listed in a data-mapping attribute clause, a
3853 // data-sharing attribute clause (including a data-sharing attribute
3854 // clause on a combined construct where target. is one of the
3855 // constituent constructs), or an is_device_ptr clause.
3856 OpenMPDefaultmapClauseKind ClauseKind =
3858 if (SemaRef.getLangOpts().OpenMP >= 50) {
3859 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3860 OMPC_DEFAULTMAP_MODIFIER_none;
3861 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3862 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3863 // Only check for data-mapping attribute and is_device_ptr here
3864 // since we have already make sure that the declaration does not
3865 // have a data-sharing attribute above
3866 if (!Stack->checkMappableExprComponentListsForDecl(
3867 VD, /*CurrentRegionOnly=*/true,
3869 MapExprComponents,
3871 auto MI = MapExprComponents.rbegin();
3872 auto ME = MapExprComponents.rend();
3873 return MI != ME && MI->getAssociatedDeclaration() == VD;
3874 })) {
3875 VarsWithInheritedDSA[VD] = E;
3876 return;
3877 }
3878 }
3879 }
3880 if (SemaRef.getLangOpts().OpenMP > 50) {
3881 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3882 OMPC_DEFAULTMAP_MODIFIER_present;
3883 if (IsModifierPresent) {
3884 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
3885 OMPC_MAP_MODIFIER_present)) {
3886 ImpInfo.MapModifiers[ClauseKind].push_back(
3887 OMPC_MAP_MODIFIER_present);
3888 }
3889 }
3890 }
3891
3893 !Stack->isLoopControlVariable(VD).first) {
3894 if (!Stack->checkMappableExprComponentListsForDecl(
3895 VD, /*CurrentRegionOnly=*/true,
3897 StackComponents,
3899 if (SemaRef.LangOpts.OpenMP >= 50)
3900 return !StackComponents.empty();
3901 // Variable is used if it has been marked as an array, array
3902 // section, array shaping or the variable itself.
3903 return StackComponents.size() == 1 ||
3904 llvm::all_of(
3905 llvm::drop_begin(llvm::reverse(StackComponents)),
3906 [](const OMPClauseMappableExprCommon::
3907 MappableComponent &MC) {
3908 return MC.getAssociatedDeclaration() ==
3909 nullptr &&
3910 (isa<ArraySectionExpr>(
3911 MC.getAssociatedExpression()) ||
3912 isa<OMPArrayShapingExpr>(
3913 MC.getAssociatedExpression()) ||
3914 isa<ArraySubscriptExpr>(
3915 MC.getAssociatedExpression()));
3916 });
3917 })) {
3918 bool IsFirstprivate = false;
3919 // By default lambdas are captured as firstprivates.
3920 if (const auto *RD =
3922 IsFirstprivate = RD->isLambda();
3923 IsFirstprivate =
3924 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3925 if (IsFirstprivate) {
3926 ImpInfo.Firstprivates.insert(E);
3927 } else {
3929 Stack->getDefaultmapModifier(ClauseKind);
3931 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3932 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
3933 }
3934 return;
3935 }
3936 }
3937
3938 // OpenMP [2.9.3.6, Restrictions, p.2]
3939 // A list item that appears in a reduction clause of the innermost
3940 // enclosing worksharing or parallel construct may not be accessed in an
3941 // explicit task.
3942 DVar = Stack->hasInnermostDSA(
3943 VD,
3944 [](OpenMPClauseKind C, bool AppliedToPointee) {
3945 return C == OMPC_reduction && !AppliedToPointee;
3946 },
3947 [](OpenMPDirectiveKind K) {
3948 return isOpenMPParallelDirective(K) ||
3950 },
3951 /*FromParent=*/true);
3952 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3953 ErrorFound = true;
3954 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3955 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3956 return;
3957 }
3958
3959 // Define implicit data-sharing attributes for task.
3960 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3961 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3962 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3963 DVar.CKind == OMPC_firstprivate) ||
3964 (Stack->getDefaultDSA() == DSA_private &&
3965 DVar.CKind == OMPC_private)) &&
3966 !DVar.RefExpr)) &&
3967 !Stack->isLoopControlVariable(VD).first) {
3968 if (Stack->getDefaultDSA() == DSA_private)
3969 ImpInfo.Privates.insert(E);
3970 else
3971 ImpInfo.Firstprivates.insert(E);
3972 return;
3973 }
3974
3975 // Store implicitly used globals with declare target link for parent
3976 // target.
3977 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3978 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3979 Stack->addToParentTargetRegionLinkGlobals(E);
3980 return;
3981 }
3982 }
3983 }
3984 void VisitMemberExpr(MemberExpr *E) {
3985 if (E->isTypeDependent() || E->isValueDependent() ||
3987 return;
3988 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3989 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3990 if (!FD)
3991 return;
3992 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3993 // Check if the variable has explicit DSA set and stop analysis if it
3994 // so.
3995 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3996 return;
3997
3999 !Stack->isLoopControlVariable(FD).first &&
4000 !Stack->checkMappableExprComponentListsForDecl(
4001 FD, /*CurrentRegionOnly=*/true,
4003 StackComponents,
4005 return isa<CXXThisExpr>(
4006 cast<MemberExpr>(
4007 StackComponents.back().getAssociatedExpression())
4008 ->getBase()
4009 ->IgnoreParens());
4010 })) {
4011 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4012 // A bit-field cannot appear in a map clause.
4013 //
4014 if (FD->isBitField())
4015 return;
4016
4017 // Check to see if the member expression is referencing a class that
4018 // has already been explicitly mapped
4019 if (Stack->isClassPreviouslyMapped(TE->getType()))
4020 return;
4021
4023 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4024 OpenMPDefaultmapClauseKind ClauseKind =
4027 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4028 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4029 return;
4030 }
4031
4032 SourceLocation ELoc = E->getExprLoc();
4033 // OpenMP [2.9.3.6, Restrictions, p.2]
4034 // A list item that appears in a reduction clause of the innermost
4035 // enclosing worksharing or parallel construct may not be accessed in
4036 // an explicit task.
4037 DVar = Stack->hasInnermostDSA(
4038 FD,
4039 [](OpenMPClauseKind C, bool AppliedToPointee) {
4040 return C == OMPC_reduction && !AppliedToPointee;
4041 },
4042 [](OpenMPDirectiveKind K) {
4043 return isOpenMPParallelDirective(K) ||
4045 },
4046 /*FromParent=*/true);
4047 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4048 ErrorFound = true;
4049 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4050 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4051 return;
4052 }
4053
4054 // Define implicit data-sharing attributes for task.
4055 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4056 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4057 !Stack->isLoopControlVariable(FD).first) {
4058 // Check if there is a captured expression for the current field in the
4059 // region. Do not mark it as firstprivate unless there is no captured
4060 // expression.
4061 // TODO: try to make it firstprivate.
4062 if (DVar.CKind != OMPC_unknown)
4063 ImpInfo.Firstprivates.insert(E);
4064 }
4065 return;
4066 }
4069 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4070 DKind, /*NoDiagnose=*/true))
4071 return;
4072 const auto *VD = cast<ValueDecl>(
4073 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4074 if (!Stack->checkMappableExprComponentListsForDecl(
4075 VD, /*CurrentRegionOnly=*/true,
4076 [&CurComponents](
4078 StackComponents,
4080 auto CCI = CurComponents.rbegin();
4081 auto CCE = CurComponents.rend();
4082 for (const auto &SC : llvm::reverse(StackComponents)) {
4083 // Do both expressions have the same kind?
4084 if (CCI->getAssociatedExpression()->getStmtClass() !=
4085 SC.getAssociatedExpression()->getStmtClass())
4086 if (!((isa<ArraySectionExpr>(
4087 SC.getAssociatedExpression()) ||
4088 isa<OMPArrayShapingExpr>(
4089 SC.getAssociatedExpression())) &&
4090 isa<ArraySubscriptExpr>(
4091 CCI->getAssociatedExpression())))
4092 return false;
4093
4094 const Decl *CCD = CCI->getAssociatedDeclaration();
4095 const Decl *SCD = SC.getAssociatedDeclaration();
4096 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4097 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4098 if (SCD != CCD)
4099 return false;
4100 std::advance(CCI, 1);
4101 if (CCI == CCE)
4102 break;
4103 }
4104 return true;
4105 })) {
4106 Visit(E->getBase());
4107 }
4108 } else if (!TryCaptureCXXThisMembers) {
4109 Visit(E->getBase());
4110 }
4111 }
4112 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4113 for (OMPClause *C : S->clauses()) {
4114 // Skip analysis of arguments of private clauses for task|target
4115 // directives.
4116 if (isa_and_nonnull<OMPPrivateClause>(C))
4117 continue;
4118 // Skip analysis of arguments of implicitly defined firstprivate clause
4119 // for task|target directives.
4120 // Skip analysis of arguments of implicitly defined map clause for target
4121 // directives.
4122 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4123 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4124 for (Stmt *CC : C->children()) {
4125 if (CC)
4126 Visit(CC);
4127 }
4128 }
4129 }
4130 // Check implicitly captured variables.
4131 VisitSubCaptures(S);
4132 }
4133
4134 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4135 // Loop transformation directives do not introduce data sharing
4136 VisitStmt(S);
4137 }
4138
4139 void VisitCallExpr(CallExpr *S) {
4140 for (Stmt *C : S->arguments()) {
4141 if (C) {
4142 // Check implicitly captured variables in the task-based directives to
4143 // check if they must be firstprivatized.
4144 Visit(C);
4145 }
4146 }
4147 if (Expr *Callee = S->getCallee()) {
4148 auto *CI = Callee->IgnoreParenImpCasts();
4149 if (auto *CE = dyn_cast<MemberExpr>(CI))
4150 Visit(CE->getBase());
4151 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4152 Visit(CE);
4153 }
4154 }
4155 void VisitStmt(Stmt *S) {
4156 for (Stmt *C : S->children()) {
4157 if (C) {
4158 // Check implicitly captured variables in the task-based directives to
4159 // check if they must be firstprivatized.
4160 Visit(C);
4161 }
4162 }
4163 }
4164
4165 void visitSubCaptures(CapturedStmt *S) {
4166 for (const CapturedStmt::Capture &Cap : S->captures()) {
4167 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4168 continue;
4169 VarDecl *VD = Cap.getCapturedVar();
4170 // Do not try to map the variable if it or its sub-component was mapped
4171 // already.
4173 Stack->checkMappableExprComponentListsForDecl(
4174 VD, /*CurrentRegionOnly=*/true,
4176 OpenMPClauseKind) { return true; }))
4177 continue;
4179 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4180 Cap.getLocation(), /*RefersToCapture=*/true);
4181 Visit(DRE);
4182 }
4183 }
4184 bool isErrorFound() const { return ErrorFound; }
4185 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4186 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4187 return VarsWithInheritedDSA;
4188 }
4189
4190 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4191 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4192 DKind = S->getCurrentDirective();
4193 // Process declare target link variables for the target directives.
4195 for (DeclRefExpr *E : Stack->getLinkGlobals())
4196 Visit(E);
4197 }
4198 }
4199};
4200} // namespace
4201
4202static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4203 OpenMPDirectiveKind DKind,
4204 bool ScopeEntry) {
4207 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4208 if (isOpenMPTeamsDirective(DKind))
4209 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4210 if (isOpenMPParallelDirective(DKind))
4211 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4213 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4214 if (isOpenMPSimdDirective(DKind))
4215 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4216 Stack->handleConstructTrait(Traits, ScopeEntry);
4217}
4218
4220getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4221 ASTContext &Context = SemaRef.getASTContext();
4222 QualType KmpInt32Ty =
4223 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4224 QualType KmpInt32PtrTy =
4225 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4227 std::make_pair(".global_tid.", KmpInt32PtrTy),
4228 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4229 };
4230 if (LoopBoundSharing) {
4231 QualType KmpSizeTy = Context.getSizeType().withConst();
4232 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4233 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4234 }
4235
4236 // __context with shared vars
4237 Params.push_back(std::make_pair(StringRef(), QualType()));
4238 return Params;
4239}
4240
4243 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4244}
4245
4248 ASTContext &Context = SemaRef.getASTContext();
4249 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4250 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4251 QualType KmpInt32PtrTy =
4252 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4253 QualType Args[] = {VoidPtrTy};
4255 EPI.Variadic = true;
4256 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4258 std::make_pair(".global_tid.", KmpInt32Ty),
4259 std::make_pair(".part_id.", KmpInt32PtrTy),
4260 std::make_pair(".privates.", VoidPtrTy),
4261 std::make_pair(
4262 ".copy_fn.",
4263 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4264 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4265 std::make_pair(StringRef(), QualType()) // __context with shared vars
4266 };
4267 return Params;
4268}
4269
4272 ASTContext &Context = SemaRef.getASTContext();
4274 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4275 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4276 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4277 }
4278 // __context with shared vars
4279 Params.push_back(std::make_pair(StringRef(), QualType()));
4280 return Params;
4281}
4282
4286 std::make_pair(StringRef(), QualType()) // __context with shared vars
4287 };
4288 return Params;
4289}
4290
4293 ASTContext &Context = SemaRef.getASTContext();
4294 QualType KmpInt32Ty =
4295 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4296 QualType KmpUInt64Ty =
4297 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4298 QualType KmpInt64Ty =
4299 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4300 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4301 QualType KmpInt32PtrTy =
4302 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4303 QualType Args[] = {VoidPtrTy};
4305 EPI.Variadic = true;
4306 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4308 std::make_pair(".global_tid.", KmpInt32Ty),
4309 std::make_pair(".part_id.", KmpInt32PtrTy),
4310 std::make_pair(".privates.", VoidPtrTy),
4311 std::make_pair(
4312 ".copy_fn.",
4313 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4314 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4315 std::make_pair(".lb.", KmpUInt64Ty),
4316 std::make_pair(".ub.", KmpUInt64Ty),
4317 std::make_pair(".st.", KmpInt64Ty),
4318 std::make_pair(".liter.", KmpInt32Ty),
4319 std::make_pair(".reductions.", VoidPtrTy),
4320 std::make_pair(StringRef(), QualType()) // __context with shared vars
4321 };
4322 return Params;
4323}
4324
4326 Scope *CurScope, SourceLocation Loc) {
4328 getOpenMPCaptureRegions(Regions, DKind);
4329
4330 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4331
4332 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4333 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4334 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4335 };
4336
4337 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4338 switch (RKind) {
4339 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4340 // are listed here.
4341 case OMPD_parallel:
4343 Loc, CurScope, CR_OpenMP,
4344 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4345 break;
4346 case OMPD_teams:
4347 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4348 getTeamsRegionParams(SemaRef), Level);
4349 break;
4350 case OMPD_task:
4351 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4352 getTaskRegionParams(SemaRef), Level);
4353 // Mark this captured region as inlined, because we don't use outlined
4354 // function directly.
4355 MarkAsInlined(SemaRef.getCurCapturedRegion());
4356 break;
4357 case OMPD_taskloop:
4358 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4359 getTaskloopRegionParams(SemaRef), Level);
4360 // Mark this captured region as inlined, because we don't use outlined
4361 // function directly.
4362 MarkAsInlined(SemaRef.getCurCapturedRegion());
4363 break;
4364 case OMPD_target:
4365 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4366 getTargetRegionParams(SemaRef), Level);
4367 break;
4368 case OMPD_unknown:
4369 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4370 getUnknownRegionParams(SemaRef));
4371 break;
4372 case OMPD_metadirective:
4373 case OMPD_nothing:
4374 default:
4375 llvm_unreachable("Unexpected capture region");
4376 }
4377 }
4378}
4379
4381 Scope *CurScope) {
4382 switch (DKind) {
4383 case OMPD_atomic:
4384 case OMPD_critical:
4385 case OMPD_masked:
4386 case OMPD_master:
4387 case OMPD_section:
4388 case OMPD_tile:
4389 case OMPD_unroll:
4390 case OMPD_reverse:
4391 case OMPD_interchange:
4392 case OMPD_assume:
4393 break;
4394 default:
4395 processCapturedRegions(SemaRef, DKind, CurScope,
4396 DSAStack->getConstructLoc());
4397 break;
4398 }
4399
4400 DSAStack->setContext(SemaRef.CurContext);
4401 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4402}
4403
4404int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4405 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4406}
4407
4410 getOpenMPCaptureRegions(CaptureRegions, DKind);
4411 return CaptureRegions.size();
4412}
4413
4415 Expr *CaptureExpr, bool WithInit,
4416 DeclContext *CurContext,
4417 bool AsExpression) {
4418 assert(CaptureExpr);
4419 ASTContext &C = S.getASTContext();
4420 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4421 QualType Ty = Init->getType();
4422 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4423 if (S.getLangOpts().CPlusPlus) {
4424 Ty = C.getLValueReferenceType(Ty);
4425 } else {
4426 Ty = C.getPointerType(Ty);
4427 ExprResult Res =
4428 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4429 if (!Res.isUsable())
4430 return nullptr;
4431 Init = Res.get();
4432 }
4433 WithInit = true;
4434 }
4435 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4436 CaptureExpr->getBeginLoc());
4437 if (!WithInit)
4438 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4439 CurContext->addHiddenDecl(CED);
4441 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4442 return CED;
4443}
4444
4445static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4446 bool WithInit) {
4448 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4449 CD = cast<OMPCapturedExprDecl>(VD);
4450 else
4451 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4452 S.CurContext,
4453 /*AsExpression=*/false);
4454 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4455 CaptureExpr->getExprLoc());
4456}
4457
4458static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4459 StringRef Name) {
4460 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4461 if (!Ref) {
4463 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4464 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4465 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4466 CaptureExpr->getExprLoc());
4467 }
4468 ExprResult Res = Ref;
4469 if (!S.getLangOpts().CPlusPlus &&
4470 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4471 Ref->getType()->isPointerType()) {
4472 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4473 if (!Res.isUsable())
4474 return ExprError();
4475 }
4476 return S.DefaultLvalueConversion(Res.get());
4477}
4478
4479namespace {
4480// OpenMP directives parsed in this section are represented as a
4481// CapturedStatement with an associated statement. If a syntax error
4482// is detected during the parsing of the associated statement, the
4483// compiler must abort processing and close the CapturedStatement.
4484//
4485// Combined directives such as 'target parallel' have more than one
4486// nested CapturedStatements. This RAII ensures that we unwind out
4487// of all the nested CapturedStatements when an error is found.
4488class CaptureRegionUnwinderRAII {
4489private:
4490 Sema &S;
4491 bool &ErrorFound;
4492 OpenMPDirectiveKind DKind = OMPD_unknown;
4493
4494public:
4495 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4496 OpenMPDirectiveKind DKind)
4497 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4498 ~CaptureRegionUnwinderRAII() {
4499 if (ErrorFound) {
4500 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4501 while (--ThisCaptureLevel >= 0)
4503 }
4504 }
4505};
4506} // namespace
4507
4509 // Capture variables captured by reference in lambdas for target-based
4510 // directives.
4512 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4514 DSAStack->getCurrentDirective()))) {
4515 QualType Type = V->getType();
4516 if (const auto *RD = Type.getCanonicalType()
4517 .getNonReferenceType()
4518 ->getAsCXXRecordDecl()) {
4519 bool SavedForceCaptureByReferenceInTargetExecutable =
4520 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4521 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4522 /*V=*/true);
4523 if (RD->isLambda()) {
4524 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4525 FieldDecl *ThisCapture;
4526 RD->getCaptureFields(Captures, ThisCapture);
4527 for (const LambdaCapture &LC : RD->captures()) {
4528 if (LC.getCaptureKind() == LCK_ByRef) {
4529 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4530 DeclContext *VDC = VD->getDeclContext();
4531 if (!VDC->Encloses(SemaRef.CurContext))
4532 continue;
4533 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4534 } else if (LC.getCaptureKind() == LCK_This) {
4536 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4537 ThisTy, ThisCapture->getType()))
4538 SemaRef.CheckCXXThisCapture(LC.getLocation());
4539 }
4540 }
4541 }
4542 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4543 SavedForceCaptureByReferenceInTargetExecutable);
4544 }
4545 }
4546}
4547
4549 const ArrayRef<OMPClause *> Clauses) {
4550 const OMPOrderedClause *Ordered = nullptr;
4551 const OMPOrderClause *Order = nullptr;
4552
4553 for (const OMPClause *Clause : Clauses) {
4554 if (Clause->getClauseKind() == OMPC_ordered)
4555 Ordered = cast<OMPOrderedClause>(Clause);
4556 else if (Clause->getClauseKind() == OMPC_order) {
4557 Order = cast<OMPOrderClause>(Clause);
4558 if (Order->getKind() != OMPC_ORDER_concurrent)
4559 Order = nullptr;
4560 }
4561 if (Ordered && Order)
4562 break;
4563 }
4564
4565 if (Ordered && Order) {
4566 S.Diag(Order->getKindKwLoc(),
4567 diag::err_omp_simple_clause_incompatible_with_ordered)
4568 << getOpenMPClauseName(OMPC_order)
4569 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4570 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4571 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4572 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4573 return true;
4574 }
4575 return false;
4576}
4577
4579 ArrayRef<OMPClause *> Clauses) {
4581 /*ScopeEntry=*/false);
4582 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4583 return S;
4584
4585 bool ErrorFound = false;
4586 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4587 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4588 if (!S.isUsable()) {
4589 ErrorFound = true;
4590 return StmtError();
4591 }
4592
4594 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4595 OMPOrderedClause *OC = nullptr;
4596 OMPScheduleClause *SC = nullptr;
4599 // This is required for proper codegen.
4600 for (OMPClause *Clause : Clauses) {
4601 if (!getLangOpts().OpenMPSimd &&
4602 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4603 DSAStack->getCurrentDirective() == OMPD_target) &&
4604 Clause->getClauseKind() == OMPC_in_reduction) {
4605 // Capture taskgroup task_reduction descriptors inside the tasking regions
4606 // with the corresponding in_reduction items.
4607 auto *IRC = cast<OMPInReductionClause>(Clause);
4608 for (Expr *E : IRC->taskgroup_descriptors())
4609 if (E)
4611 }
4612 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4613 Clause->getClauseKind() == OMPC_copyprivate ||
4614 (getLangOpts().OpenMPUseTLS &&
4615 getASTContext().getTargetInfo().isTLSSupported() &&
4616 Clause->getClauseKind() == OMPC_copyin)) {
4617 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4618 // Mark all variables in private list clauses as used in inner region.
4619 for (Stmt *VarRef : Clause->children()) {
4620 if (auto *E = cast_or_null<Expr>(VarRef)) {
4622 }
4623 }
4624 DSAStack->setForceVarCapturing(/*V=*/false);
4625 } else if (CaptureRegions.size() > 1 ||
4626 CaptureRegions.back() != OMPD_unknown) {
4627 if (auto *C = OMPClauseWithPreInit::get(Clause))
4628 PICs.push_back(C);
4629 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4630 if (Expr *E = C->getPostUpdateExpr())
4632 }
4633 }
4634 if (Clause->getClauseKind() == OMPC_schedule)
4635 SC = cast<OMPScheduleClause>(Clause);
4636 else if (Clause->getClauseKind() == OMPC_ordered)
4637 OC = cast<OMPOrderedClause>(Clause);
4638 else if (Clause->getClauseKind() == OMPC_linear)
4639 LCs.push_back(cast<OMPLinearClause>(Clause));
4640 }
4641 // Capture allocator expressions if used.
4642 for (Expr *E : DSAStack->getInnerAllocators())
4644 // OpenMP, 2.7.1 Loop Construct, Restrictions
4645 // The nonmonotonic modifier cannot be specified if an ordered clause is
4646 // specified.
4647 if (SC &&
4648 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4650 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4651 OC) {
4652 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4655 diag::err_omp_simple_clause_incompatible_with_ordered)
4656 << getOpenMPClauseName(OMPC_schedule)
4657 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4658 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4659 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4660 ErrorFound = true;
4661 }
4662 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4663 // If an order(concurrent) clause is present, an ordered clause may not appear
4664 // on the same directive.
4665 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4666 ErrorFound = true;
4667 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4668 for (const OMPLinearClause *C : LCs) {
4669 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4670 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4671 }
4672 ErrorFound = true;
4673 }
4674 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4675 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4676 OC->getNumForLoops()) {
4677 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4678 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4679 ErrorFound = true;
4680 }
4681 if (ErrorFound) {
4682 return StmtError();
4683 }
4684 StmtResult SR = S;
4685 unsigned CompletedRegions = 0;
4686 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4687 // Mark all variables in private list clauses as used in inner region.
4688 // Required for proper codegen of combined directives.
4689 // TODO: add processing for other clauses.
4690 if (ThisCaptureRegion != OMPD_unknown) {
4691 for (const clang::OMPClauseWithPreInit *C : PICs) {
4692 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4693 // Find the particular capture region for the clause if the
4694 // directive is a combined one with multiple capture regions.
4695 // If the directive is not a combined one, the capture region
4696 // associated with the clause is OMPD_unknown and is generated
4697 // only once.
4698 if (CaptureRegion == ThisCaptureRegion ||
4699 CaptureRegion == OMPD_unknown) {
4700 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4701 for (Decl *D : DS->decls())
4703 cast<VarDecl>(D));
4704 }
4705 }
4706 }
4707 }
4708 if (ThisCaptureRegion == OMPD_target) {
4709 // Capture allocator traits in the target region. They are used implicitly
4710 // and, thus, are not captured by default.
4711 for (OMPClause *C : Clauses) {
4712 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4713 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4714 ++I) {
4715 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4716 if (Expr *E = D.AllocatorTraits)
4718 }
4719 continue;
4720 }
4721 }
4722 }
4723 if (ThisCaptureRegion == OMPD_parallel) {
4724 // Capture temp arrays for inscan reductions and locals in aligned
4725 // clauses.
4726 for (OMPClause *C : Clauses) {
4727 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4728 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4729 continue;
4730 for (Expr *E : RC->copy_array_temps())
4731 if (E)
4733 }
4734 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4735 for (Expr *E : AC->varlist())
4737 }
4738 }
4739 }
4740 if (++CompletedRegions == CaptureRegions.size())
4741 DSAStack->setBodyComplete();
4743 }
4744 return SR;
4745}
4746
4747static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4748 OpenMPDirectiveKind CancelRegion,
4749 SourceLocation StartLoc) {
4750 // CancelRegion is only needed for cancel and cancellation_point.
4751 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4752 return false;
4753
4754 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4755 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4756 return false;
4757
4758 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4759 << getOpenMPDirectiveName(CancelRegion);
4760 return true;
4761}
4762
4763static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4764 OpenMPDirectiveKind CurrentRegion,
4765 const DeclarationNameInfo &CurrentName,
4766 OpenMPDirectiveKind CancelRegion,
4767 OpenMPBindClauseKind BindKind,
4768 SourceLocation StartLoc) {
4769 if (!Stack->getCurScope())
4770 return false;
4771
4772 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4773 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4774 bool NestingProhibited = false;
4775 bool CloseNesting = true;
4776 bool OrphanSeen = false;
4777 enum {
4778 NoRecommend,
4779 ShouldBeInParallelRegion,
4780 ShouldBeInOrderedRegion,
4781 ShouldBeInTargetRegion,
4782 ShouldBeInTeamsRegion,
4783 ShouldBeInLoopSimdRegion,
4784 } Recommend = NoRecommend;
4785
4788 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4789 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4790
4791 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4792 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4793 CurrentRegion != OMPD_parallel &&
4794 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
4795 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4796 << getOpenMPDirectiveName(CurrentRegion);
4797 return true;
4798 }
4799 if (isOpenMPSimdDirective(ParentRegion) &&
4800 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4801 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4802 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4803 CurrentRegion != OMPD_scan))) {
4804 // OpenMP [2.16, Nesting of Regions]
4805 // OpenMP constructs may not be nested inside a simd region.
4806 // OpenMP [2.8.1,simd Construct, Restrictions]
4807 // An ordered construct with the simd clause is the only OpenMP
4808 // construct that can appear in the simd region.
4809 // Allowing a SIMD construct nested in another SIMD construct is an
4810 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4811 // message.
4812 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4813 // The only OpenMP constructs that can be encountered during execution of
4814 // a simd region are the atomic construct, the loop construct, the simd
4815 // construct and the ordered construct with the simd clause.
4816 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4817 ? diag::err_omp_prohibited_region_simd
4818 : diag::warn_omp_nesting_simd)
4819 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4820 return CurrentRegion != OMPD_simd;
4821 }
4822 if (EnclosingConstruct == OMPD_atomic) {
4823 // OpenMP [2.16, Nesting of Regions]
4824 // OpenMP constructs may not be nested inside an atomic region.
4825 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4826 return true;
4827 }
4828 if (CurrentRegion == OMPD_section) {
4829 // OpenMP [2.7.2, sections Construct, Restrictions]
4830 // Orphaned section directives are prohibited. That is, the section
4831 // directives must appear within the sections construct and must not be
4832 // encountered elsewhere in the sections region.
4833 if (EnclosingConstruct != OMPD_sections) {
4834 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4835 << (ParentRegion != OMPD_unknown)
4836 << getOpenMPDirectiveName(ParentRegion);
4837 return true;
4838 }
4839 return false;
4840 }
4841 // Allow some constructs (except teams and cancellation constructs) to be
4842 // orphaned (they could be used in functions, called from OpenMP regions
4843 // with the required preconditions).
4844 if (ParentRegion == OMPD_unknown &&
4845 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4846 CurrentRegion != OMPD_cancellation_point &&
4847 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4848 return false;
4849 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4850 // for a detailed explanation
4851 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4852 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4853 (isOpenMPWorksharingDirective(ParentRegion) ||
4854 EnclosingConstruct == OMPD_loop)) {
4855 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4856 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4857 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4858 << getOpenMPDirectiveName(CurrentRegion);
4859 return true;
4860 }
4861 if (CurrentRegion == OMPD_cancellation_point ||
4862 CurrentRegion == OMPD_cancel) {
4863 // OpenMP [2.16, Nesting of Regions]
4864 // A cancellation point construct for which construct-type-clause is
4865 // taskgroup must be nested inside a task construct. A cancellation
4866 // point construct for which construct-type-clause is not taskgroup must
4867 // be closely nested inside an OpenMP construct that matches the type
4868 // specified in construct-type-clause.
4869 // A cancel construct for which construct-type-clause is taskgroup must be
4870 // nested inside a task construct. A cancel construct for which
4871 // construct-type-clause is not taskgroup must be closely nested inside an
4872 // OpenMP construct that matches the type specified in
4873 // construct-type-clause.
4874 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4875 if (CancelRegion == OMPD_taskgroup) {
4876 NestingProhibited = EnclosingConstruct != OMPD_task &&
4877 (SemaRef.getLangOpts().OpenMP < 50 ||
4878 EnclosingConstruct != OMPD_taskloop);
4879 } else if (CancelRegion == OMPD_sections) {
4880 NestingProhibited = EnclosingConstruct != OMPD_section &&
4881 EnclosingConstruct != OMPD_sections;
4882 } else {
4883 NestingProhibited = CancelRegion != Leafs.back();
4884 }
4885 OrphanSeen = ParentRegion == OMPD_unknown;
4886 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4887 // OpenMP 5.1 [2.22, Nesting of Regions]
4888 // A masked region may not be closely nested inside a worksharing, loop,
4889 // atomic, task, or taskloop region.
4890 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4891 isOpenMPGenericLoopDirective(ParentRegion) ||
4892 isOpenMPTaskingDirective(ParentRegion);
4893 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4894 // OpenMP [2.16, Nesting of Regions]
4895 // A critical region may not be nested (closely or otherwise) inside a
4896 // critical region with the same name. Note that this restriction is not
4897 // sufficient to prevent deadlock.
4898 SourceLocation PreviousCriticalLoc;
4899 bool DeadLock = Stack->hasDirective(
4900 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4901 const DeclarationNameInfo &DNI,
4903 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4904 PreviousCriticalLoc = Loc;
4905 return true;
4906 }
4907 return false;
4908 },
4909 false /* skip top directive */);
4910 if (DeadLock) {
4911 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4912 << CurrentName.getName();
4913 if (PreviousCriticalLoc.isValid())
4914 SemaRef.Diag(PreviousCriticalLoc,
4915 diag::note_omp_previous_critical_region);
4916 return true;
4917 }
4918 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4919 // OpenMP 5.1 [2.22, Nesting of Regions]
4920 // A scope region may not be closely nested inside a worksharing, loop,
4921 // task, taskloop, critical, ordered, atomic, or masked region.
4922 // OpenMP 5.1 [2.22, Nesting of Regions]
4923 // A barrier region may not be closely nested inside a worksharing, loop,
4924 // task, taskloop, critical, ordered, atomic, or masked region.
4925 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4926 isOpenMPGenericLoopDirective(ParentRegion) ||
4927 isOpenMPTaskingDirective(ParentRegion) ||
4928 llvm::is_contained({OMPD_masked, OMPD_master,
4929 OMPD_critical, OMPD_ordered},
4930 EnclosingConstruct);
4931 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4932 !isOpenMPParallelDirective(CurrentRegion) &&
4933 !isOpenMPTeamsDirective(CurrentRegion)) {
4934 // OpenMP 5.1 [2.22, Nesting of Regions]
4935 // A loop region that binds to a parallel region or a worksharing region
4936 // may not be closely nested inside a worksharing, loop, task, taskloop,
4937 // critical, ordered, atomic, or masked region.
4938 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4939 isOpenMPGenericLoopDirective(ParentRegion) ||
4940 isOpenMPTaskingDirective(ParentRegion) ||
4941 llvm::is_contained({OMPD_masked, OMPD_master,
4942 OMPD_critical, OMPD_ordered},
4943 EnclosingConstruct);
4944 Recommend = ShouldBeInParallelRegion;
4945 } else if (CurrentRegion == OMPD_ordered) {
4946 // OpenMP [2.16, Nesting of Regions]
4947 // An ordered region may not be closely nested inside a critical,
4948 // atomic, or explicit task region.
4949 // An ordered region must be closely nested inside a loop region (or
4950 // parallel loop region) with an ordered clause.
4951 // OpenMP [2.8.1,simd Construct, Restrictions]
4952 // An ordered construct with the simd clause is the only OpenMP construct
4953 // that can appear in the simd region.
4954 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4955 isOpenMPTaskingDirective(ParentRegion) ||
4956 !(isOpenMPSimdDirective(ParentRegion) ||
4957 Stack->isParentOrderedRegion());
4958 Recommend = ShouldBeInOrderedRegion;
4959 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4960 // OpenMP [2.16, Nesting of Regions]
4961 // If specified, a teams construct must be contained within a target
4962 // construct.
4963 NestingProhibited =
4964 (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4965 (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4966 EnclosingConstruct != OMPD_target);
4967 OrphanSeen = ParentRegion == OMPD_unknown;
4968 Recommend = ShouldBeInTargetRegion;
4969 } else if (CurrentRegion == OMPD_scan) {
4970 if (SemaRef.LangOpts.OpenMP >= 50) {
4971 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4972 // simd, or for simd. This has to take into account combined directives.
4973 // In 5.2 this seems to be implied by the fact that the specified
4974 // separated constructs are do, for, and simd.
4975 NestingProhibited = !llvm::is_contained(
4976 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4977 } else {
4978 NestingProhibited = true;
4979 }
4980 OrphanSeen = ParentRegion == OMPD_unknown;
4981 Recommend = ShouldBeInLoopSimdRegion;
4982 }
4983 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
4984 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
4985 EnclosingConstruct == OMPD_teams) {
4986 // OpenMP [5.1, 2.22, Nesting of Regions]
4987 // distribute, distribute simd, distribute parallel worksharing-loop,
4988 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
4989 // including any parallel regions arising from combined constructs,
4990 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
4991 // only OpenMP regions that may be strictly nested inside the teams
4992 // region.
4993 //
4994 // As an extension, we permit atomic within teams as well.
4995 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
4996 !isOpenMPDistributeDirective(CurrentRegion) &&
4997 CurrentRegion != OMPD_loop &&
4998 !(SemaRef.getLangOpts().OpenMPExtensions &&
4999 CurrentRegion == OMPD_atomic);
5000 Recommend = ShouldBeInParallelRegion;
5001 }
5002 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5003 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5004 // If the bind clause is present on the loop construct and binding is
5005 // teams then the corresponding loop region must be strictly nested inside
5006 // a teams region.
5007 NestingProhibited =
5008 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5009 Recommend = ShouldBeInTeamsRegion;
5010 }
5011 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5012 // OpenMP 4.5 [2.17 Nesting of Regions]
5013 // The region associated with the distribute construct must be strictly
5014 // nested inside a teams region
5015 NestingProhibited = EnclosingConstruct != OMPD_teams;
5016 Recommend = ShouldBeInTeamsRegion;
5017 }
5018 if (!NestingProhibited &&
5019 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5020 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5021 // OpenMP 4.5 [2.17 Nesting of Regions]
5022 // If a target, target update, target data, target enter data, or
5023 // target exit data construct is encountered during execution of a
5024 // target region, the behavior is unspecified.
5025 NestingProhibited = Stack->hasDirective(
5026 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5029 OffendingRegion = K;
5030 return true;
5031 }
5032 return false;
5033 },
5034 false /* don't skip top directive */);
5035 CloseNesting = false;
5036 }
5037 if (NestingProhibited) {
5038 if (OrphanSeen) {
5039 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5040 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5041 } else {
5042 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5043 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5044 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5045 }
5046 return true;
5047 }
5048 return false;
5049}
5050
5053 unsigned operator()(argument_type DK) { return unsigned(DK); }
5054};
5056 ArrayRef<OMPClause *> Clauses,
5057 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5058 bool ErrorFound = false;
5059 unsigned NamedModifiersNumber = 0;
5060 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5061 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5062 SmallVector<SourceLocation, 4> NameModifierLoc;
5063 for (const OMPClause *C : Clauses) {
5064 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5065 // At most one if clause without a directive-name-modifier can appear on
5066 // the directive.
5067 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5068 if (FoundNameModifiers[CurNM]) {
5069 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5070 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5071 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5072 ErrorFound = true;
5073 } else if (CurNM != OMPD_unknown) {
5074 NameModifierLoc.push_back(IC->getNameModifierLoc());
5075 ++NamedModifiersNumber;
5076 }
5077 FoundNameModifiers[CurNM] = IC;
5078 if (CurNM == OMPD_unknown)
5079 continue;
5080 // Check if the specified name modifier is allowed for the current
5081 // directive.
5082 // At most one if clause with the particular directive-name-modifier can
5083 // appear on the directive.
5084 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5085 S.Diag(IC->getNameModifierLoc(),
5086 diag::err_omp_wrong_if_directive_name_modifier)
5087 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5088 ErrorFound = true;
5089 }
5090 }
5091 }
5092 // If any if clause on the directive includes a directive-name-modifier then
5093 // all if clauses on the directive must include a directive-name-modifier.
5094 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5095 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5096 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5097 diag::err_omp_no_more_if_clause);
5098 } else {
5099 std::string Values;
5100 std::string Sep(", ");
5101 unsigned AllowedCnt = 0;
5102 unsigned TotalAllowedNum =
5103 AllowedNameModifiers.size() - NamedModifiersNumber;
5104 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5105 ++Cnt) {
5106 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5107 if (!FoundNameModifiers[NM]) {
5108 Values += "'";
5109 Values += getOpenMPDirectiveName(NM);
5110 Values += "'";
5111 if (AllowedCnt + 2 == TotalAllowedNum)
5112 Values += " or ";
5113 else if (AllowedCnt + 1 != TotalAllowedNum)
5114 Values += Sep;
5115 ++AllowedCnt;
5116 }
5117 }
5118 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5119 diag::err_omp_unnamed_if_clause)
5120 << (TotalAllowedNum > 1) << Values;
5121 }
5122 for (SourceLocation Loc : NameModifierLoc) {
5123 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5124 }
5125 ErrorFound = true;
5126 }
5127 return ErrorFound;
5128}
5129
5130static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5131 SourceLocation &ELoc,
5132 SourceRange &ERange,
5133 bool AllowArraySection,
5134 StringRef DiagType) {
5135 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5137 return std::make_pair(nullptr, true);
5138
5139 // OpenMP [3.1, C/C++]
5140 // A list item is a variable name.
5141 // OpenMP [2.9.3.3, Restrictions, p.1]
5142 // A variable that is part of another variable (as an array or
5143 // structure element) cannot appear in a private clause.
5144 RefExpr = RefExpr->IgnoreParens();
5145 enum {
5146 NoArrayExpr = -1,
5147 ArraySubscript = 0,
5148 OMPArraySection = 1
5149 } IsArrayExpr = NoArrayExpr;
5150 if (AllowArraySection) {
5151 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5152 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5153 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5154 Base = TempASE->getBase()->IgnoreParenImpCasts();
5155 RefExpr = Base;
5156 IsArrayExpr = ArraySubscript;
5157 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5158 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5159 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5160 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5161 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5162 Base = TempASE->getBase()->IgnoreParenImpCasts();
5163 RefExpr = Base;
5164 IsArrayExpr = OMPArraySection;
5165 }
5166 }
5167 ELoc = RefExpr->getExprLoc();
5168 ERange = RefExpr->getSourceRange();
5169 RefExpr = RefExpr->IgnoreParenImpCasts();
5170 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5171 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5172 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5173 (S.getCurrentThisType().isNull() || !ME ||
5174 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5175 !isa<FieldDecl>(ME->getMemberDecl()))) {
5176 if (IsArrayExpr != NoArrayExpr) {
5177 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5178 << IsArrayExpr << ERange;
5179 } else if (!DiagType.empty()) {
5180 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5181 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5182 : 0;
5183 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5184 << DiagSelect << DiagType << ERange;
5185 } else {
5186 S.Diag(ELoc,
5187 AllowArraySection
5188 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5189 : diag::err_omp_expected_var_name_member_expr)
5190 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5191 }
5192 return std::make_pair(nullptr, false);
5193 }
5194 return std::make_pair(
5195 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5196}
5197
5198namespace {
5199/// Checks if the allocator is used in uses_allocators clause to be allowed in
5200/// target regions.
5201class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5202 DSAStackTy *S = nullptr;
5203
5204public:
5205 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5206 return S->isUsesAllocatorsDecl(E->getDecl())
5207 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5208 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5209 }
5210 bool VisitStmt(const Stmt *S) {
5211 for (const Stmt *Child : S->children()) {
5212 if (Child && Visit(Child))
5213 return true;
5214 }
5215 return false;
5216 }
5217 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5218};
5219} // namespace
5220
5221static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5222 ArrayRef<OMPClause *> Clauses) {
5223 assert(!S.CurContext->isDependentContext() &&
5224 "Expected non-dependent context.");
5225 auto AllocateRange =
5226 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5227 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5228 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5229 return isOpenMPPrivate(C->getClauseKind());
5230 });
5231 for (OMPClause *Cl : PrivateRange) {
5233 if (Cl->getClauseKind() == OMPC_private) {
5234 auto *PC = cast<OMPPrivateClause>(Cl);
5235 I = PC->private_copies().begin();
5236 It = PC->varlist_begin();
5237 Et = PC->varlist_end();
5238 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5239 auto *PC = cast<OMPFirstprivateClause>(Cl);
5240 I = PC->private_copies().begin();
5241 It = PC->varlist_begin();
5242 Et = PC->varlist_end();
5243 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5244 auto *PC = cast<OMPLastprivateClause>(Cl);
5245 I = PC->private_copies().begin();
5246 It = PC->varlist_begin();
5247 Et = PC->varlist_end();
5248 } else if (Cl->getClauseKind() == OMPC_linear) {
5249 auto *PC = cast<OMPLinearClause>(Cl);
5250 I = PC->privates().begin();
5251 It = PC->varlist_begin();
5252 Et = PC->varlist_end();
5253 } else if (Cl->getClauseKind() == OMPC_reduction) {
5254 auto *PC = cast<OMPReductionClause>(Cl);
5255 I = PC->privates().begin();
5256 It = PC->varlist_begin();
5257 Et = PC->varlist_end();
5258 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5259 auto *PC = cast<OMPTaskReductionClause>(Cl);
5260 I = PC->privates().begin();
5261 It = PC->varlist_begin();
5262 Et = PC->varlist_end();
5263 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5264 auto *PC = cast<OMPInReductionClause>(Cl);
5265 I = PC->privates().begin();
5266 It = PC->varlist_begin();
5267 Et = PC->varlist_end();
5268 } else {
5269 llvm_unreachable("Expected private clause.");
5270 }
5271 for (Expr *E : llvm::make_range(It, Et)) {
5272 if (!*I) {
5273 ++I;
5274 continue;
5275 }
5276 SourceLocation ELoc;
5277 SourceRange ERange;
5278 Expr *SimpleRefExpr = E;
5279 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5280 /*AllowArraySection=*/true);
5281 DeclToCopy.try_emplace(Res.first,
5282 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5283 ++I;
5284 }
5285 }
5286 for (OMPClause *C : AllocateRange) {
5287 auto *AC = cast<OMPAllocateClause>(C);
5288 if (S.getLangOpts().OpenMP >= 50 &&
5289 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5290 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5291 AC->getAllocator()) {
5292 Expr *Allocator = AC->getAllocator();
5293 // OpenMP, 2.12.5 target Construct
5294 // Memory allocators that do not appear in a uses_allocators clause cannot
5295 // appear as an allocator in an allocate clause or be used in the target
5296 // region unless a requires directive with the dynamic_allocators clause
5297 // is present in the same compilation unit.
5298 AllocatorChecker Checker(Stack);
5299 if (Checker.Visit(Allocator))
5300 S.Diag(Allocator->getExprLoc(),
5301 diag::err_omp_allocator_not_in_uses_allocators)
5302 << Allocator->getSourceRange();
5303 }
5304 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5305 getAllocatorKind(S, Stack, AC->getAllocator());
5306 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5307 // For task, taskloop or target directives, allocation requests to memory
5308 // allocators with the trait access set to thread result in unspecified
5309 // behavior.
5310 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5311 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5312 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5313 S.Diag(AC->getAllocator()->getExprLoc(),
5314 diag::warn_omp_allocate_thread_on_task_target_directive)
5315 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5316 }
5317 for (Expr *E : AC->varlist()) {
5318 SourceLocation ELoc;
5319 SourceRange ERange;
5320 Expr *SimpleRefExpr = E;
5321 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5322 ValueDecl *VD = Res.first;
5323 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5324 if (!isOpenMPPrivate(Data.CKind)) {
5325 S.Diag(E->getExprLoc(),
5326 diag::err_omp_expected_private_copy_for_allocate);
5327 continue;
5328 }
5329 VarDecl *PrivateVD = DeclToCopy[VD];
5330 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5331 AllocatorKind, AC->getAllocator()))
5332 continue;
5333 // Placeholder until allocate clause supports align modifier.
5334 Expr *Alignment = nullptr;
5335 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5336 Alignment, E->getSourceRange());
5337 }
5338 }
5339}
5340
5341namespace {
5342/// Rewrite statements and expressions for Sema \p Actions CurContext.
5343///
5344/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5345/// context. DeclRefExpr used inside the new context are changed to refer to the
5346/// captured variable instead.
5347class CaptureVars : public TreeTransform<CaptureVars> {
5348 using BaseTransform = TreeTransform<CaptureVars>;
5349
5350public:
5351 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5352
5353 bool AlwaysRebuild() { return true; }
5354};
5355} // namespace
5356
5357static VarDecl *precomputeExpr(Sema &Actions,
5358 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5359 StringRef Name) {
5360 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5361 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5362 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5363 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5364 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5365 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5366 BodyStmts.push_back(NewDeclStmt);
5367 return NewVar;
5368}
5369
5370/// Create a closure that computes the number of iterations of a loop.
5371///
5372/// \param Actions The Sema object.
5373/// \param LogicalTy Type for the logical iteration number.
5374/// \param Rel Comparison operator of the loop condition.
5375/// \param StartExpr Value of the loop counter at the first iteration.
5376/// \param StopExpr Expression the loop counter is compared against in the loop
5377/// condition. \param StepExpr Amount of increment after each iteration.
5378///
5379/// \return Closure (CapturedStmt) of the distance calculation.
5380static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5382 Expr *StartExpr, Expr *StopExpr,
5383 Expr *StepExpr) {
5384 ASTContext &Ctx = Actions.getASTContext();
5385 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5386
5387 // Captured regions currently don't support return values, we use an
5388 // out-parameter instead. All inputs are implicit captures.
5389 // TODO: Instead of capturing each DeclRefExpr occurring in
5390 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5391 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5392 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5393 {StringRef(), QualType()}};
5394 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5395
5396 Stmt *Body;
5397 {
5398 Sema::CompoundScopeRAII CompoundScope(Actions);
5399 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5400
5401 // Get the LValue expression for the result.
5402 ImplicitParamDecl *DistParam = CS->getParam(0);
5403 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5404 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5405
5406 SmallVector<Stmt *, 4> BodyStmts;
5407
5408 // Capture all referenced variable references.
5409 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5410 // CapturedStmt, we could compute them before and capture the result, to be
5411 // used jointly with the LoopVar function.
5412 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5413 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5414 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5415 auto BuildVarRef = [&](VarDecl *VD) {
5416 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5417 };
5418
5420 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5422 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5423 Expr *Dist;
5424 if (Rel == BO_NE) {
5425 // When using a != comparison, the increment can be +1 or -1. This can be
5426 // dynamic at runtime, so we need to check for the direction.
5427 Expr *IsNegStep = AssertSuccess(
5428 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5429
5430 // Positive increment.
5431 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5432 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5433 ForwardRange = AssertSuccess(
5434 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5435 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5436 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5437
5438 // Negative increment.
5439 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5440 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5441 BackwardRange = AssertSuccess(
5442 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5443 Expr *NegIncAmount = AssertSuccess(
5444 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5445 Expr *BackwardDist = AssertSuccess(
5446 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5447
5448 // Use the appropriate case.
5449 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5450 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5451 } else {
5452 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5453 "Expected one of these relational operators");
5454
5455 // We can derive the direction from any other comparison operator. It is
5456 // non well-formed OpenMP if Step increments/decrements in the other
5457 // directions. Whether at least the first iteration passes the loop
5458 // condition.
5459 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5460 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5461
5462 // Compute the range between first and last counter value.
5463 Expr *Range;
5464 if (Rel == BO_GE || Rel == BO_GT)
5465 Range = AssertSuccess(Actions.BuildBinOp(
5466 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5467 else
5468 Range = AssertSuccess(Actions.BuildBinOp(
5469 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5470
5471 // Ensure unsigned range space.
5472 Range =
5473 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5474
5475 if (Rel == BO_LE || Rel == BO_GE) {
5476 // Add one to the range if the relational operator is inclusive.
5477 Range =
5478 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5479 }
5480
5481 // Divide by the absolute step amount. If the range is not a multiple of
5482 // the step size, rounding-up the effective upper bound ensures that the
5483 // last iteration is included.
5484 // Note that the rounding-up may cause an overflow in a temporary that
5485 // could be avoided, but would have occurred in a C-style for-loop as
5486 // well.
5487 Expr *Divisor = BuildVarRef(NewStep);
5488 if (Rel == BO_GE || Rel == BO_GT)
5489 Divisor =
5490 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5491 Expr *DivisorMinusOne =
5492 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5493 Expr *RangeRoundUp = AssertSuccess(
5494 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5495 Dist = AssertSuccess(
5496 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5497
5498 // If there is not at least one iteration, the range contains garbage. Fix
5499 // to zero in this case.
5500 Dist = AssertSuccess(
5501 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5502 }
5503
5504 // Assign the result to the out-parameter.
5505 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5506 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5507 BodyStmts.push_back(ResultAssign);
5508
5509 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5510 }
5511
5512 return cast<CapturedStmt>(
5513 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5514}
5515
5516/// Create a closure that computes the loop variable from the logical iteration
5517/// number.
5518///
5519/// \param Actions The Sema object.
5520/// \param LoopVarTy Type for the loop variable used for result value.
5521/// \param LogicalTy Type for the logical iteration number.
5522/// \param StartExpr Value of the loop counter at the first iteration.
5523/// \param Step Amount of increment after each iteration.
5524/// \param Deref Whether the loop variable is a dereference of the loop
5525/// counter variable.
5526///
5527/// \return Closure (CapturedStmt) of the loop value calculation.
5528static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5529 QualType LogicalTy,
5530 DeclRefExpr *StartExpr, Expr *Step,
5531 bool Deref) {
5532 ASTContext &Ctx = Actions.getASTContext();
5533
5534 // Pass the result as an out-parameter. Passing as return value would require
5535 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5536 // invoke a copy constructor.
5537 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5538 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5539 {"Logical", LogicalTy},
5540 {StringRef(), QualType()}};
5541 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5542
5543 // Capture the initial iterator which represents the LoopVar value at the
5544 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5545 // it in every iteration, capture it by value before it is modified.
5546 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5547 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5549 (void)Invalid;
5550 assert(!Invalid && "Expecting capture-by-value to work.");
5551
5552 Expr *Body;
5553 {
5554 Sema::CompoundScopeRAII CompoundScope(Actions);
5555 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5556
5557 ImplicitParamDecl *TargetParam = CS->getParam(0);
5558 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5559 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5560 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5561 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5562 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5563
5564 // Capture the Start expression.
5565 CaptureVars Recap(Actions);
5566 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5567 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5568
5570 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5571 // TODO: Explicitly cast to the iterator's difference_type instead of
5572 // relying on implicit conversion.
5573 Expr *Advanced =
5574 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5575
5576 if (Deref) {
5577 // For range-based for-loops convert the loop counter value to a concrete
5578 // loop variable value by dereferencing the iterator.
5579 Advanced =
5580 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5581 }
5582
5583 // Assign the result to the output parameter.
5584 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5585 BO_Assign, TargetRef, Advanced));
5586 }
5587 return cast<CapturedStmt>(
5588 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5589}
5590
5592 ASTContext &Ctx = getASTContext();
5593
5594 // Extract the common elements of ForStmt and CXXForRangeStmt:
5595 // Loop variable, repeat condition, increment
5596 Expr *Cond, *Inc;
5597 VarDecl *LIVDecl, *LUVDecl;
5598 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5599 Stmt *Init = For->getInit();
5600 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5601 // For statement declares loop variable.
5602 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5603 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5604 // For statement reuses variable.
5605 assert(LCAssign->getOpcode() == BO_Assign &&
5606 "init part must be a loop variable assignment");
5607 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5608 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5609 } else
5610 llvm_unreachable("Cannot determine loop variable");
5611 LUVDecl = LIVDecl;
5612
5613 Cond = For->getCond();
5614 Inc = For->getInc();
5615 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5616 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5617 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5618 LUVDecl = RangeFor->getLoopVariable();
5619
5620 Cond = RangeFor->getCond();
5621 Inc = RangeFor->getInc();
5622 } else
5623 llvm_unreachable("unhandled kind of loop");
5624
5625 QualType CounterTy = LIVDecl->getType();
5626 QualType LVTy = LUVDecl->getType();
5627
5628 // Analyze the loop condition.
5629 Expr *LHS, *RHS;
5630 BinaryOperator::Opcode CondRel;
5631 Cond = Cond->IgnoreImplicit();
5632 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5633 LHS = CondBinExpr->getLHS();
5634 RHS = CondBinExpr->getRHS();
5635 CondRel = CondBinExpr->getOpcode();
5636 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5637 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5638 LHS = CondCXXOp->getArg(0);
5639 RHS = CondCXXOp->getArg(1);
5640 switch (CondCXXOp->getOperator()) {
5641 case OO_ExclaimEqual:
5642 CondRel = BO_NE;
5643 break;
5644 case OO_Less:
5645 CondRel = BO_LT;
5646 break;
5647 case OO_LessEqual:
5648 CondRel = BO_LE;
5649 break;
5650 case OO_Greater:
5651 CondRel = BO_GT;
5652 break;
5653 case OO_GreaterEqual:
5654 CondRel = BO_GE;
5655 break;
5656 default:
5657 llvm_unreachable("unexpected iterator operator");
5658 }
5659 } else
5660 llvm_unreachable("unexpected loop condition");
5661
5662 // Normalize such that the loop counter is on the LHS.
5663 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5664 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5665 std::swap(LHS, RHS);
5666 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5667 }
5668 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5669
5670 // Decide the bit width for the logical iteration counter. By default use the
5671 // unsigned ptrdiff_t integer size (for iterators and pointers).
5672 // TODO: For iterators, use iterator::difference_type,
5673 // std::iterator_traits<>::difference_type or decltype(it - end).
5674 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5675 if (CounterTy->isIntegerType()) {
5676 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5677 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5678 }
5679
5680 // Analyze the loop increment.
5681 Expr *Step;
5682 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5683 int Direction;
5684 switch (IncUn->getOpcode()) {
5685 case UO_PreInc:
5686 case UO_PostInc:
5687 Direction = 1;
5688 break;
5689 case UO_PreDec:
5690 case UO_PostDec:
5691 Direction = -1;
5692 break;
5693 default:
5694 llvm_unreachable("unhandled unary increment operator");
5695 }
5697 Ctx,
5698 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5699 LogicalTy, {});
5700 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5701 if (IncBin->getOpcode() == BO_AddAssign) {
5702 Step = IncBin->getRHS();
5703 } else if (IncBin->getOpcode() == BO_SubAssign) {
5704 Step = AssertSuccess(
5705 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5706 } else
5707 llvm_unreachable("unhandled binary increment operator");
5708 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5709 switch (CondCXXOp->getOperator()) {
5710 case OO_PlusPlus:
5712 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5713 break;
5714 case OO_MinusMinus:
5716 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5717 break;
5718 case OO_PlusEqual:
5719 Step = CondCXXOp->getArg(1);
5720 break;
5721 case OO_MinusEqual:
5722 Step = AssertSuccess(
5723 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5724 break;
5725 default:
5726 llvm_unreachable("unhandled overloaded increment operator");
5727 }
5728 } else
5729 llvm_unreachable("unknown increment expression");
5730
5731 CapturedStmt *DistanceFunc =
5732 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5733 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5734 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5735 DeclRefExpr *LVRef =
5736 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5737 nullptr, nullptr, {}, nullptr);
5738 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5739 LoopVarFunc, LVRef);
5740}
5741
5743 // Handle a literal loop.
5744 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5745 return ActOnOpenMPCanonicalLoop(AStmt);
5746
5747 // If not a literal loop, it must be the result of a loop transformation.
5748 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5749 assert(
5751 "Loop transformation directive expected");
5752 return LoopTransform;
5753}
5754
5756 CXXScopeSpec &MapperIdScopeSpec,
5757 const DeclarationNameInfo &MapperId,
5758 QualType Type,
5759 Expr *UnresolvedMapper);
5760
5761/// Perform DFS through the structure/class data members trying to find
5762/// member(s) with user-defined 'default' mapper and generate implicit map
5763/// clauses for such members with the found 'default' mapper.
5764static void
5767 // Check for the default mapper for data members.
5768 if (S.getLangOpts().OpenMP < 50)
5769 return;
5770 SmallVector<OMPClause *, 4> ImplicitMaps;
5771 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5772 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5773 if (!C)
5774 continue;
5775 SmallVector<Expr *, 4> SubExprs;
5776 auto *MI = C->mapperlist_begin();
5777 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5778 ++I, ++MI) {
5779 // Expression is mapped using mapper - skip it.
5780 if (*MI)
5781 continue;
5782 Expr *E = *I;
5783 // Expression is dependent - skip it, build the mapper when it gets
5784 // instantiated.
5785 if (E->isTypeDependent() || E->isValueDependent() ||
5787 continue;
5788 // Array section - need to check for the mapping of the array section
5789 // element.
5790 QualType CanonType = E->getType().getCanonicalType();
5791 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5792 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5793 QualType BaseType =
5795 QualType ElemType;
5796 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5797 ElemType = ATy->getElementType();
5798 else
5799 ElemType = BaseType->getPointeeType();
5800 CanonType = ElemType;
5801 }
5802
5803 // DFS over data members in structures/classes.
5805 1, {CanonType, nullptr});
5806 llvm::DenseMap<const Type *, Expr *> Visited;
5808 1, {nullptr, 1});
5809 while (!Types.empty()) {
5810 QualType BaseType;
5811 FieldDecl *CurFD;
5812 std::tie(BaseType, CurFD) = Types.pop_back_val();
5813 while (ParentChain.back().second == 0)
5814 ParentChain.pop_back();
5815 --ParentChain.back().second;
5816 if (BaseType.isNull())
5817 continue;
5818 // Only structs/classes are allowed to have mappers.
5819 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5820 if (!RD)
5821 continue;
5822 auto It = Visited.find(BaseType.getTypePtr());
5823 if (It == Visited.end()) {
5824 // Try to find the associated user-defined mapper.
5825 CXXScopeSpec MapperIdScopeSpec;
5826 DeclarationNameInfo DefaultMapperId;
5828 &S.Context.Idents.get("default")));
5829 DefaultMapperId.setLoc(E->getExprLoc());
5831 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5832 BaseType, /*UnresolvedMapper=*/nullptr);
5833 if (ER.isInvalid())
5834 continue;
5835 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5836 }
5837 // Found default mapper.
5838 if (It->second) {
5839 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5841 OE->setIsUnique(/*V=*/true);
5842 Expr *BaseExpr = OE;
5843 for (const auto &P : ParentChain) {
5844 if (P.first) {
5845 BaseExpr = S.BuildMemberExpr(
5846 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5848 DeclAccessPair::make(P.first, P.first->getAccess()),
5849 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5850 P.first->getType(), VK_LValue, OK_Ordinary);
5851 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5852 }
5853 }
5854 if (CurFD)
5855 BaseExpr = S.BuildMemberExpr(
5856 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5858 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5859 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5860 CurFD->getType(), VK_LValue, OK_Ordinary);
5861 SubExprs.push_back(BaseExpr);
5862 continue;
5863 }
5864 // Check for the "default" mapper for data members.
5865 bool FirstIter = true;
5866 for (FieldDecl *FD : RD->fields()) {
5867 if (!FD)
5868 continue;
5869 QualType FieldTy = FD->getType();
5870 if (FieldTy.isNull() ||
5871 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5872 continue;
5873 if (FirstIter) {
5874 FirstIter = false;
5875 ParentChain.emplace_back(CurFD, 1);
5876 } else {
5877 ++ParentChain.back().second;
5878 }
5879 Types.emplace_back(FieldTy, FD);
5880 }
5881 }
5882 }
5883 if (SubExprs.empty())
5884 continue;
5885 CXXScopeSpec MapperIdScopeSpec;
5886 DeclarationNameInfo MapperId;
5887 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5888 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
5889 MapperIdScopeSpec, MapperId, C->getMapType(),
5890 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
5891 SubExprs, OMPVarListLocTy()))
5892 Clauses.push_back(NewClause);
5893 }
5894}
5895
5896namespace {
5897/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5898/// call in the associated loop-nest cannot be a 'parallel for'.
5899class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5900 Sema &SemaRef;
5901
5902public:
5903 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5904
5905 // Is there a nested OpenMP loop bind(parallel)
5906 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5907 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5908 if (const auto *C = D->getSingleClause<OMPBindClause>())
5909 if (C->getBindKind() == OMPC_BIND_parallel) {
5910 TeamsLoopCanBeParallelFor = false;
5911 // No need to continue visiting any more
5912 return;
5913 }
5914 }
5915 for (const Stmt *Child : D->children())
5916 if (Child)
5917 Visit(Child);
5918 }
5919
5920 void VisitCallExpr(const CallExpr *C) {
5921 // Function calls inhibit parallel loop translation of 'target teams loop'
5922 // unless the assume-no-nested-parallelism flag has been specified.
5923 // OpenMP API runtime library calls do not inhibit parallel loop
5924 // translation, regardless of the assume-no-nested-parallelism.
5925 bool IsOpenMPAPI = false;
5926 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
5927 if (FD) {
5928 std::string Name = FD->getNameInfo().getAsString();
5929 IsOpenMPAPI = Name.find("omp_") == 0;
5930 }
5931 TeamsLoopCanBeParallelFor =
5932 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5933 if (!TeamsLoopCanBeParallelFor)
5934 return;
5935
5936 for (const Stmt *Child : C->children())
5937 if (Child)
5938 Visit(Child);
5939 }
5940
5941 void VisitCapturedStmt(const CapturedStmt *S) {
5942 if (!S)
5943 return;
5944 Visit(S->getCapturedDecl()->getBody());
5945 }
5946
5947 void VisitStmt(const Stmt *S) {
5948 if (!S)
5949 return;
5950 for (const Stmt *Child : S->children())
5951 if (Child)
5952 Visit(Child);
5953 }
5954 explicit TeamsLoopChecker(Sema &SemaRef)
5955 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5956
5957private:
5958 bool TeamsLoopCanBeParallelFor;
5959};
5960} // namespace
5961
5962static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5963 TeamsLoopChecker Checker(SemaRef);
5964 Checker.Visit(AStmt);
5965 return Checker.teamsLoopCanBeParallelFor();
5966}
5967
5969 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5970 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5971 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5972 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5973
5974 StmtResult Res = StmtError();
5976 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5977
5978 if (const OMPBindClause *BC =
5979 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5980 BindKind = BC->getBindKind();
5981
5982 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
5983 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
5984
5985 // Setting the enclosing teams or parallel construct for the loop
5986 // directive without bind clause.
5987 // [5.0:129:25-28] If the bind clause is not present on the construct and
5988 // the loop construct is closely nested inside a teams or parallel
5989 // construct, the binding region is the corresponding teams or parallel
5990 // region. If none of those conditions hold, the binding region is not
5991 // defined.
5992 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
5993 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
5994 getLeafConstructsOrSelf(ParentDirective);
5995
5996 if (ParentDirective == OMPD_unknown) {
5997 Diag(DSAStack->getDefaultDSALocation(),
5998 diag::err_omp_bind_required_on_loop);
5999 } else if (ParentLeafs.back() == OMPD_parallel) {
6000 BindKind = OMPC_BIND_parallel;
6001 } else if (ParentLeafs.back() == OMPD_teams) {
6002 BindKind = OMPC_BIND_teams;
6003 }
6004
6005 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6006
6007 OMPClause *C =
6010 ClausesWithImplicit.push_back(C);
6011 }
6012
6013 // Diagnose "loop bind(teams)" with "reduction".
6014 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6015 for (OMPClause *C : Clauses) {
6016 if (C->getClauseKind() == OMPC_reduction)
6017 Diag(DSAStack->getDefaultDSALocation(),
6018 diag::err_omp_loop_reduction_clause);
6019 }
6020 }
6021
6022 // First check CancelRegion which is then used in checkNestingOfRegions.
6023 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6024 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6025 BindKind, StartLoc)) {
6026 return StmtError();
6027 }
6028
6029 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6032 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6033
6034 VarsWithInheritedDSAType VarsWithInheritedDSA;
6035 bool ErrorFound = false;
6036 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6037
6038 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6040 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6041
6042 // Check default data sharing attributes for referenced variables.
6043 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6044 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6045 Stmt *S = AStmt;
6046 while (--ThisCaptureLevel >= 0)
6047 S = cast<CapturedStmt>(S)->getCapturedStmt();
6048 DSAChecker.Visit(S);
6050 !isOpenMPTaskingDirective(Kind)) {
6051 // Visit subcaptures to generate implicit clauses for captured vars.
6052 auto *CS = cast<CapturedStmt>(AStmt);
6054 getOpenMPCaptureRegions(CaptureRegions, Kind);
6055 // Ignore outer tasking regions for target directives.
6056 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6057 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6058 DSAChecker.visitSubCaptures(CS);
6059 }
6060 if (DSAChecker.isErrorFound())
6061 return StmtError();
6062 // Generate list of implicitly defined firstprivate variables.
6063 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6064 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6065
6067 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6068 // Get the original location of present modifier from Defaultmap clause.
6069 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6070 for (OMPClause *C : Clauses) {
6071 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6072 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6073 PresentModifierLocs[DMC->getDefaultmapKind()] =
6074 DMC->getDefaultmapModifierLoc();
6075 }
6076
6078 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6080 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6081 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6082 }
6083 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6084 for (OMPClause *C : Clauses) {
6085 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6086 for (Expr *E : IRC->taskgroup_descriptors())
6087 if (E)
6088 ImpInfo.Firstprivates.insert(E);
6089 }
6090 // OpenMP 5.0, 2.10.1 task Construct
6091 // [detach clause]... The event-handle will be considered as if it was
6092 // specified on a firstprivate clause.
6093 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6094 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6095 }
6096 if (!ImpInfo.Firstprivates.empty()) {
6098 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6100 ClausesWithImplicit.push_back(Implicit);
6101 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6102 ImpInfo.Firstprivates.size();
6103 } else {
6104 ErrorFound = true;
6105 }
6106 }
6107 if (!ImpInfo.Privates.empty()) {
6109 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6111 ClausesWithImplicit.push_back(Implicit);
6112 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6113 ImpInfo.Privates.size();
6114 } else {
6115 ErrorFound = true;
6116 }
6117 }
6118 // OpenMP 5.0 [2.19.7]
6119 // If a list item appears in a reduction, lastprivate or linear
6120 // clause on a combined target construct then it is treated as
6121 // if it also appears in a map clause with a map-type of tofrom
6122 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6124 SmallVector<Expr *, 4> ImplicitExprs;
6125 for (OMPClause *C : Clauses) {
6126 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6127 for (Expr *E : RC->varlist())
6128 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6129 ImplicitExprs.emplace_back(E);
6130 }
6131 if (!ImplicitExprs.empty()) {
6132 ArrayRef<Expr *> Exprs = ImplicitExprs;
6133 CXXScopeSpec MapperIdScopeSpec;
6134 DeclarationNameInfo MapperId;
6137 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6138 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6139 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6140 ClausesWithImplicit.emplace_back(Implicit);
6141 }
6142 }
6143 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6144 int ClauseKindCnt = -1;
6145 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6146 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6147 ++ClauseKindCnt;
6148 if (ImplicitMap.empty())
6149 continue;
6150 CXXScopeSpec MapperIdScopeSpec;
6151 DeclarationNameInfo MapperId;
6152 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6154 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6155 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6156 SourceLocation(), SourceLocation(), ImplicitMap,
6157 OMPVarListLocTy())) {
6158 ClausesWithImplicit.emplace_back(Implicit);
6159 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6160 ImplicitMap.size();
6161 } else {
6162 ErrorFound = true;
6163 }
6164 }
6165 }
6166 // Build expressions for implicit maps of data members with 'default'
6167 // mappers.
6168 if (getLangOpts().OpenMP >= 50)
6170 ClausesWithImplicit);
6171 }
6172
6173 switch (Kind) {
6174 case OMPD_parallel:
6175 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6176 EndLoc);
6177 break;
6178 case OMPD_simd:
6179 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6180 VarsWithInheritedDSA);
6181 break;
6182 case OMPD_tile:
6183 Res =
6184 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6185 break;
6186 case OMPD_unroll:
6187 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6188 EndLoc);
6189 break;
6190 case OMPD_reverse:
6191 assert(ClausesWithImplicit.empty() &&
6192 "reverse directive does not support any clauses");
6193 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6194 break;
6195 case OMPD_interchange:
6196 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6197 EndLoc);
6198 break;
6199 case OMPD_for:
6200 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6201 VarsWithInheritedDSA);
6202 break;
6203 case OMPD_for_simd:
6204 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6205 EndLoc, VarsWithInheritedDSA);
6206 break;
6207 case OMPD_sections:
6208 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6209 EndLoc);
6210 break;
6211 case OMPD_section:
6212 assert(ClausesWithImplicit.empty() &&
6213 "No clauses are allowed for 'omp section' directive");
6214 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6215 break;
6216 case OMPD_single:
6217 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6218 EndLoc);
6219 break;
6220 case OMPD_master:
6221 assert(ClausesWithImplicit.empty() &&
6222 "No clauses are allowed for 'omp master' directive");
6223 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6224 break;
6225 case OMPD_masked:
6226 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6227 EndLoc);
6228 break;
6229 case OMPD_critical:
6230 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6231 StartLoc, EndLoc);
6232 break;
6233 case OMPD_parallel_for:
6234 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6235 EndLoc, VarsWithInheritedDSA);
6236 break;
6237 case OMPD_parallel_for_simd:
6239 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6240 break;
6241 case OMPD_scope:
6242 Res =
6243 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6244 break;
6245 case OMPD_parallel_master:
6246 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6247 StartLoc, EndLoc);
6248 break;
6249 case OMPD_parallel_masked:
6250 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6251 StartLoc, EndLoc);
6252 break;
6253 case OMPD_parallel_sections:
6254 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6255 StartLoc, EndLoc);
6256 break;
6257 case OMPD_task:
6258 Res =
6259 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6260 break;
6261 case OMPD_taskyield:
6262 assert(ClausesWithImplicit.empty() &&
6263 "No clauses are allowed for 'omp taskyield' directive");
6264 assert(AStmt == nullptr &&
6265 "No associated statement allowed for 'omp taskyield' directive");
6266 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6267 break;
6268 case OMPD_error:
6269 assert(AStmt == nullptr &&
6270 "No associated statement allowed for 'omp error' directive");
6271 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6272 break;
6273 case OMPD_barrier:
6274 assert(ClausesWithImplicit.empty() &&
6275 "No clauses are allowed for 'omp barrier' directive");
6276 assert(AStmt == nullptr &&
6277 "No associated statement allowed for 'omp barrier' directive");
6278 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6279 break;
6280 case OMPD_taskwait:
6281 assert(AStmt == nullptr &&
6282 "No associated statement allowed for 'omp taskwait' directive");
6283 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6284 break;
6285 case OMPD_taskgroup:
6286 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6287 EndLoc);
6288 break;
6289 case OMPD_flush:
6290 assert(AStmt == nullptr &&
6291 "No associated statement allowed for 'omp flush' directive");
6292 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6293 break;
6294 case OMPD_depobj:
6295 assert(AStmt == nullptr &&
6296 "No associated statement allowed for 'omp depobj' directive");
6297 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6298 break;
6299 case OMPD_scan:
6300 assert(AStmt == nullptr &&
6301 "No associated statement allowed for 'omp scan' directive");
6302 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6303 break;
6304 case OMPD_ordered:
6305 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6306 EndLoc);
6307 break;
6308 case OMPD_atomic:
6309 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6310 EndLoc);
6311 break;
6312 case OMPD_teams:
6313 Res =
6314 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6315 break;
6316 case OMPD_target:
6317 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6318 EndLoc);
6319 break;
6320 case OMPD_target_parallel:
6321 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6322 StartLoc, EndLoc);
6323 break;
6324 case OMPD_target_parallel_for:
6326 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6327 break;
6328 case OMPD_cancellation_point:
6329 assert(ClausesWithImplicit.empty() &&
6330 "No clauses are allowed for 'omp cancellation point' directive");
6331 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6332 "cancellation point' directive");
6333 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6334 break;
6335 case OMPD_cancel:
6336 assert(AStmt == nullptr &&
6337 "No associated statement allowed for 'omp cancel' directive");
6338 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6339 CancelRegion);
6340 break;
6341 case OMPD_target_data:
6342 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6343 EndLoc);
6344 break;
6345 case OMPD_target_enter_data:
6346 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6347 EndLoc, AStmt);
6348 break;
6349 case OMPD_target_exit_data:
6350 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6351 EndLoc, AStmt);
6352 break;
6353 case OMPD_taskloop:
6354 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6355 EndLoc, VarsWithInheritedDSA);
6356 break;
6357 case OMPD_taskloop_simd:
6358 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6359 EndLoc, VarsWithInheritedDSA);
6360 break;
6361 case OMPD_master_taskloop:
6363 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6364 break;
6365 case OMPD_masked_taskloop:
6367 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6368 break;
6369 case OMPD_master_taskloop_simd:
6371 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6372 break;
6373 case OMPD_masked_taskloop_simd:
6375 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6376 break;
6377 case OMPD_parallel_master_taskloop:
6379 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6380 break;
6381 case OMPD_parallel_masked_taskloop:
6383 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6384 break;
6385 case OMPD_parallel_master_taskloop_simd:
6387 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6388 break;
6389 case OMPD_parallel_masked_taskloop_simd:
6391 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6392 break;
6393 case OMPD_distribute:
6394 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6395 EndLoc, VarsWithInheritedDSA);
6396 break;
6397 case OMPD_target_update:
6398 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6399 EndLoc, AStmt);
6400 break;
6401 case OMPD_distribute_parallel_for:
6403 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6404 break;
6405 case OMPD_distribute_parallel_for_simd:
6407 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6408 break;
6409 case OMPD_distribute_simd:
6411 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6412 break;
6413 case OMPD_target_parallel_for_simd:
6415 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6416 break;
6417 case OMPD_target_simd:
6418 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6419 EndLoc, VarsWithInheritedDSA);
6420 break;
6421 case OMPD_teams_distribute:
6423 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6424 break;
6425 case OMPD_teams_distribute_simd:
6427 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6428 break;
6429 case OMPD_teams_distribute_parallel_for_simd:
6431 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6432 break;
6433 case OMPD_teams_distribute_parallel_for:
6435 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6436 break;
6437 case OMPD_target_teams:
6438 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6439 EndLoc);
6440 break;
6441 case OMPD_target_teams_distribute:
6443 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6444 break;
6445 case OMPD_target_teams_distribute_parallel_for:
6447 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6448 break;
6449 case OMPD_target_teams_distribute_parallel_for_simd:
6451 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6452 break;
6453 case OMPD_target_teams_distribute_simd:
6455 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6456 break;
6457 case OMPD_interop:
6458 assert(AStmt == nullptr &&
6459 "No associated statement allowed for 'omp interop' directive");
6460 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6461 break;
6462 case OMPD_dispatch:
6463 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6464 EndLoc);
6465 break;
6466 case OMPD_loop:
6467 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6468 EndLoc, VarsWithInheritedDSA);
6469 break;
6470 case OMPD_teams_loop:
6472 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6473 break;
6474 case OMPD_target_teams_loop:
6476 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6477 break;
6478 case OMPD_parallel_loop:
6480 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6481 break;
6482 case OMPD_target_parallel_loop:
6484 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6485 break;
6486 case OMPD_declare_target:
6487 case OMPD_end_declare_target:
6488 case OMPD_threadprivate:
6489 case OMPD_allocate:
6490 case OMPD_declare_reduction:
6491 case OMPD_declare_mapper:
6492 case OMPD_declare_simd:
6493 case OMPD_requires:
6494 case OMPD_declare_variant:
6495 case OMPD_begin_declare_variant:
6496 case OMPD_end_declare_variant:
6497 llvm_unreachable("OpenMP Directive is not allowed");
6498 case OMPD_unknown:
6499 default:
6500 llvm_unreachable("Unknown OpenMP directive");
6501 }
6502
6503 ErrorFound = Res.isInvalid() || ErrorFound;
6504
6505 // Check variables in the clauses if default(none) or
6506 // default(firstprivate) was specified.
6507 if (DSAStack->getDefaultDSA() == DSA_none ||
6508 DSAStack->getDefaultDSA() == DSA_private ||
6509 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6510 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6511 for (OMPClause *C : Clauses) {
6512 switch (C->getClauseKind()) {
6513 case OMPC_num_threads:
6514 case OMPC_dist_schedule:
6515 // Do not analyze if no parent teams directive.
6516 if (isOpenMPTeamsDirective(Kind))
6517 break;
6518 continue;
6519 case OMPC_if:
6520 if (isOpenMPTeamsDirective(Kind) &&
6521 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6522 break;
6523 if (isOpenMPParallelDirective(Kind) &&
6525 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6526 break;
6527 continue;
6528 case OMPC_schedule:
6529 case OMPC_detach:
6530 break;
6531 case OMPC_grainsize:
6532 case OMPC_num_tasks:
6533 case OMPC_final:
6534 case OMPC_priority:
6535 case OMPC_novariants:
6536 case OMPC_nocontext:
6537 // Do not analyze if no parent parallel directive.
6538 if (isOpenMPParallelDirective(Kind))
6539 break;
6540 continue;
6541 case OMPC_ordered:
6542 case OMPC_device:
6543 case OMPC_num_teams:
6544 case OMPC_thread_limit:
6545 case OMPC_hint:
6546 case OMPC_collapse:
6547 case OMPC_safelen:
6548 case OMPC_simdlen:
6549 case OMPC_sizes:
6550 case OMPC_default:
6551 case OMPC_proc_bind:
6552 case OMPC_private:
6553 case OMPC_firstprivate:
6554 case OMPC_lastprivate:
6555 case OMPC_shared:
6556 case OMPC_reduction:
6557 case OMPC_task_reduction:
6558 case OMPC_in_reduction:
6559 case OMPC_linear:
6560 case OMPC_aligned:
6561 case OMPC_copyin:
6562 case OMPC_copyprivate:
6563 case OMPC_nowait:
6564 case OMPC_untied:
6565 case OMPC_mergeable:
6566 case OMPC_allocate:
6567 case OMPC_read:
6568 case OMPC_write:
6569 case OMPC_update:
6570 case OMPC_capture:
6571 case OMPC_compare:
6572 case OMPC_seq_cst:
6573 case OMPC_acq_rel:
6574 case OMPC_acquire:
6575 case OMPC_release:
6576 case OMPC_relaxed:
6577 case OMPC_depend:
6578 case OMPC_threads:
6579 case OMPC_simd:
6580 case OMPC_map:
6581 case OMPC_nogroup:
6582 case OMPC_defaultmap:
6583 case OMPC_to:
6584 case OMPC_from:
6585 case OMPC_use_device_ptr:
6586 case OMPC_use_device_addr:
6587 case OMPC_is_device_ptr:
6588 case OMPC_has_device_addr:
6589 case OMPC_nontemporal:
6590 case OMPC_order:
6591 case OMPC_destroy:
6592 case OMPC_inclusive:
6593 case OMPC_exclusive:
6594 case OMPC_uses_allocators:
6595 case OMPC_affinity:
6596 case OMPC_bind:
6597 case OMPC_filter:
6598 continue;
6599 case OMPC_allocator:
6600 case OMPC_flush:
6601 case OMPC_depobj:
6602 case OMPC_threadprivate:
6603 case OMPC_uniform:
6604 case OMPC_unknown:
6605 case OMPC_unified_address:
6606 case OMPC_unified_shared_memory:
6607 case OMPC_reverse_offload:
6608 case OMPC_dynamic_allocators:
6609 case OMPC_atomic_default_mem_order:
6610 case OMPC_device_type:
6611 case OMPC_match:
6612 case OMPC_when:
6613 case OMPC_at:
6614 case OMPC_severity:
6615 case OMPC_message:
6616 default:
6617 llvm_unreachable("Unexpected clause");
6618 }
6619 for (Stmt *CC : C->children()) {
6620 if (CC)
6621 DSAChecker.Visit(CC);
6622 }
6623 }
6624 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6625 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6626 }
6627 for (const auto &P : VarsWithInheritedDSA) {
6628 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6629 continue;
6630 ErrorFound = true;
6631 if (DSAStack->getDefaultDSA() == DSA_none ||
6632 DSAStack->getDefaultDSA() == DSA_private ||
6633 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6634 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6635 << P.first << P.second->getSourceRange();
6636 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6637 } else if (getLangOpts().OpenMP >= 50) {
6638 Diag(P.second->getExprLoc(),
6639 diag::err_omp_defaultmap_no_attr_for_variable)
6640 << P.first << P.second->getSourceRange();
6641 Diag(DSAStack->getDefaultDSALocation(),
6642 diag::note_omp_defaultmap_attr_none);
6643 }
6644 }
6645
6646 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6647 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6648 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6649 AllowedNameModifiers.push_back(D);
6650 }
6651 if (!AllowedNameModifiers.empty())
6652 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6653 ErrorFound;
6654
6655 if (ErrorFound)
6656 return StmtError();
6657
6660 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6661 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6662 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6663 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6664 // Register target to DSA Stack.
6665 DSAStack->addTargetDirLocation(StartLoc);
6666 }
6667
6668 return Res;
6669}
6670
6672 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6673 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6674 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6675 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6676 assert(Aligneds.size() == Alignments.size());
6677 assert(Linears.size() == LinModifiers.size());
6678 assert(Linears.size() == Steps.size());
6679 if (!DG || DG.get().isNull())
6680 return DeclGroupPtrTy();
6681
6682 const int SimdId = 0;
6683 if (!DG.get().isSingleDecl()) {
6684 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6685 << SimdId;
6686 return DG;
6687 }
6688 Decl *ADecl = DG.get().getSingleDecl();
6689 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6690 ADecl = FTD->getTemplatedDecl();
6691
6692 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6693 if (!FD) {
6694 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6695 return DeclGroupPtrTy();
6696 }
6697
6698 // OpenMP [2.8.2, declare simd construct, Description]
6699 // The parameter of the simdlen clause must be a constant positive integer
6700 // expression.
6701 ExprResult SL;
6702 if (Simdlen)
6703 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6704 // OpenMP [2.8.2, declare simd construct, Description]
6705 // The special this pointer can be used as if was one of the arguments to the
6706 // function in any of the linear, aligned, or uniform clauses.
6707 // The uniform clause declares one or more arguments to have an invariant
6708 // value for all concurrent invocations of the function in the execution of a
6709 // single SIMD loop.
6710 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6711 const Expr *UniformedLinearThis = nullptr;
6712 for (const Expr *E : Uniforms) {
6713 E = E->IgnoreParenImpCasts();
6714 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6715 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6716 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6717 FD->getParamDecl(PVD->getFunctionScopeIndex())
6718 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6719 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6720 continue;
6721 }
6722 if (isa<CXXThisExpr>(E)) {
6723 UniformedLinearThis = E;
6724 continue;
6725 }
6726 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6727 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6728 }
6729 // OpenMP [2.8.2, declare simd construct, Description]
6730 // The aligned clause declares that the object to which each list item points
6731 // is aligned to the number of bytes expressed in the optional parameter of
6732 // the aligned clause.
6733 // The special this pointer can be used as if was one of the arguments to the
6734 // function in any of the linear, aligned, or uniform clauses.
6735 // The type of list items appearing in the aligned clause must be array,
6736 // pointer, reference to array, or reference to pointer.
6737 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6738 const Expr *AlignedThis = nullptr;
6739 for (const Expr *E : Aligneds) {
6740 E = E->IgnoreParenImpCasts();
6741 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6742 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6743 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6744 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6745 FD->getParamDecl(PVD->getFunctionScopeIndex())
6746 ->getCanonicalDecl() == CanonPVD) {
6747 // OpenMP [2.8.1, simd construct, Restrictions]
6748 // A list-item cannot appear in more than one aligned clause.
6749 if (AlignedArgs.count(CanonPVD) > 0) {
6750 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6751 << 1 << getOpenMPClauseName(OMPC_aligned)
6752 << E->getSourceRange();
6753 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6754 diag::note_omp_explicit_dsa)
6755 << getOpenMPClauseName(OMPC_aligned);
6756 continue;
6757 }
6758 AlignedArgs[CanonPVD] = E;
6759 QualType QTy = PVD->getType()
6760 .getNonReferenceType()
6761 .getUnqualifiedType()
6762 .getCanonicalType();
6763 const Type *Ty = QTy.getTypePtrOrNull();
6764 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6765 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6766 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6767 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6768 }
6769 continue;
6770 }
6771 }
6772 if (isa<CXXThisExpr>(E)) {
6773 if (AlignedThis) {
6774 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6775 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6776 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6777 << getOpenMPClauseName(OMPC_aligned);
6778 }
6779 AlignedThis = E;
6780 continue;
6781 }
6782 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6783 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6784 }
6785 // The optional parameter of the aligned clause, alignment, must be a constant
6786 // positive integer expression. If no optional parameter is specified,
6787 // implementation-defined default alignments for SIMD instructions on the
6788 // target platforms are assumed.
6790 for (Expr *E : Alignments) {
6791 ExprResult Align;
6792 if (E)
6793 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6794 NewAligns.push_back(Align.get());
6795 }
6796 // OpenMP [2.8.2, declare simd construct, Description]
6797 // The linear clause declares one or more list items to be private to a SIMD
6798 // lane and to have a linear relationship with respect to the iteration space
6799 // of a loop.
6800 // The special this pointer can be used as if was one of the arguments to the
6801 // function in any of the linear, aligned, or uniform clauses.
6802 // When a linear-step expression is specified in a linear clause it must be
6803 // either a constant integer expression or an integer-typed parameter that is
6804 // specified in a uniform clause on the directive.
6805 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6806 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6807 auto MI = LinModifiers.begin();
6808 for (const Expr *E : Linears) {
6809 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6810 ++MI;
6811 E = E->IgnoreParenImpCasts();
6812 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6813 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6814 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6815 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6816 FD->getParamDecl(PVD->getFunctionScopeIndex())
6817 ->getCanonicalDecl() == CanonPVD) {
6818 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6819 // A list-item cannot appear in more than one linear clause.
6820 if (LinearArgs.count(CanonPVD) > 0) {
6821 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6822 << getOpenMPClauseName(OMPC_linear)
6823 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6824 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6825 diag::note_omp_explicit_dsa)
6826 << getOpenMPClauseName(OMPC_linear);
6827 continue;
6828 }
6829 // Each argument can appear in at most one uniform or linear clause.
6830 if (UniformedArgs.count(CanonPVD) > 0) {
6831 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6832 << getOpenMPClauseName(OMPC_linear)
6833 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
6834 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6835 diag::note_omp_explicit_dsa)
6836 << getOpenMPClauseName(OMPC_uniform);
6837 continue;
6838 }
6839 LinearArgs[CanonPVD] = E;
6840 if (E->isValueDependent() || E->isTypeDependent() ||
6843 continue;
6844 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6845 PVD->getOriginalType(),
6846 /*IsDeclareSimd=*/true);
6847 continue;
6848 }
6849 }
6850 if (isa<CXXThisExpr>(E)) {
6851 if (UniformedLinearThis) {
6852 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6853 << getOpenMPClauseName(OMPC_linear)
6854 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6855 << E->getSourceRange();
6856 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6857 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6858 : OMPC_linear);
6859 continue;
6860 }
6861 UniformedLinearThis = E;
6862 if (E->isValueDependent() || E->isTypeDependent() ||
6864 continue;
6865 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6866 E->getType(), /*IsDeclareSimd=*/true);
6867 continue;
6868 }
6869 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6870 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6871 }
6872 Expr *Step = nullptr;
6873 Expr *NewStep = nullptr;
6874 SmallVector<Expr *, 4> NewSteps;
6875 for (Expr *E : Steps) {
6876 // Skip the same step expression, it was checked already.
6877 if (Step == E || !E) {
6878 NewSteps.push_back(E ? NewStep : nullptr);
6879 continue;
6880 }
6881 Step = E;
6882 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6883 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6884 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6885 if (UniformedArgs.count(CanonPVD) == 0) {
6886 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6887 << Step->getSourceRange();
6888 } else if (E->isValueDependent() || E->isTypeDependent() ||
6891 CanonPVD->getType()->hasIntegerRepresentation()) {
6892 NewSteps.push_back(Step);
6893 } else {
6894 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6895 << Step->getSourceRange();
6896 }
6897 continue;
6898 }
6899 NewStep = Step;
6900 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6901 !Step->isInstantiationDependent() &&
6903 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6904 .get();
6905 if (NewStep)
6906 NewStep = SemaRef
6908 NewStep, /*FIXME*/ Sema::AllowFold)
6909 .get();
6910 }
6911 NewSteps.push_back(NewStep);
6912 }
6913 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6914 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
6915 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
6916 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
6917 const_cast<Expr **>(Linears.data()), Linears.size(),
6918 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
6919 NewSteps.data(), NewSteps.size(), SR);
6920 ADecl->addAttr(NewAttr);
6921 return DG;
6922}
6923
6925 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6926 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
6927 SourceLocation EndLoc) {
6928 assert(isOpenMPInformationalDirective(Kind) &&
6929 "Unexpected directive category");
6930
6931 StmtResult Res = StmtError();
6932
6933 switch (Kind) {
6934 case OMPD_assume:
6935 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
6936 break;
6937 default:
6938 llvm_unreachable("Unknown OpenMP directive");
6939 }
6940
6941 return Res;
6942}
6943
6944static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6945 QualType NewType) {
6946 assert(NewType->isFunctionProtoType() &&
6947 "Expected function type with prototype.");
6948 assert(FD->getType()->isFunctionNoProtoType() &&
6949 "Expected function with type with no prototype.");
6950 assert(FDWithProto->getType()->isFunctionProtoType() &&
6951 "Expected function with prototype.");
6952 // Synthesize parameters with the same types.
6953 FD->setType(NewType);
6955 for (const ParmVarDecl *P : FDWithProto->parameters()) {
6956 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
6957 SourceLocation(), nullptr, P->getType(),
6958 /*TInfo=*/nullptr, SC_None, nullptr);
6959 Param->setScopeInfo(0, Params.size());
6960 Param->setImplicit();
6961 Params.push_back(Param);
6962 }
6963
6964 FD->setParams(Params);
6965}
6966
6968 if (D->isInvalidDecl())
6969 return;
6970 FunctionDecl *FD = nullptr;
6971 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
6972 FD = UTemplDecl->getTemplatedDecl();
6973 else
6974 FD = cast<FunctionDecl>(D);
6975 assert(FD && "Expected a function declaration!");
6976
6977 // If we are instantiating templates we do *not* apply scoped assumptions but
6978 // only global ones. We apply scoped assumption to the template definition
6979 // though.
6981 for (OMPAssumeAttr *AA : OMPAssumeScoped)
6982 FD->addAttr(AA);
6983 }
6984 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
6985 FD->addAttr(AA);
6986}
6987
6988SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
6989 : TI(&TI), NameSuffix(TI.getMangledName()) {}
6990
6992 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
6994 if (!D.getIdentifier())
6995 return;
6996
6997 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
6998
6999 // Template specialization is an extension, check if we do it.
7000 bool IsTemplated = !TemplateParamLists.empty();
7001 if (IsTemplated &&
7002 !DVScope.TI->isExtensionActive(
7003 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7004 return;
7005
7006 const IdentifierInfo *BaseII = D.getIdentifier();
7007 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7009 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7010 /*ObjectType=*/QualType());
7011
7013 QualType FType = TInfo->getType();
7014
7015 bool IsConstexpr =
7016 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7017 bool IsConsteval =
7018 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7019
7020 for (auto *Candidate : Lookup) {
7021 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7022 FunctionDecl *UDecl = nullptr;
7023 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7024 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7025 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7026 UDecl = FTD->getTemplatedDecl();
7027 } else if (!IsTemplated)
7028 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7029 if (!UDecl)
7030 continue;
7031
7032 // Don't specialize constexpr/consteval functions with
7033 // non-constexpr/consteval functions.
7034 if (UDecl->isConstexpr() && !IsConstexpr)
7035 continue;
7036 if (UDecl->isConsteval() && !IsConsteval)
7037 continue;
7038
7039 QualType UDeclTy = UDecl->getType();
7040 if (!UDeclTy->isDependentType()) {
7042 FType, UDeclTy, /*OfBlockPointer=*/false,
7043 /*Unqualified=*/false, /*AllowCXX=*/true);
7044 if (NewType.isNull())
7045 continue;
7046 }
7047
7048 // Found a base!
7049 Bases.push_back(UDecl);
7050 }
7051
7052 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7053 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7054 // If no base was found we create a declaration that we use as base.
7055 if (Bases.empty() && UseImplicitBase) {
7056 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7057 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7058 BaseD->setImplicit(true);
7059 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7060 Bases.push_back(BaseTemplD->getTemplatedDecl());
7061 else
7062 Bases.push_back(cast<FunctionDecl>(BaseD));
7063 }
7064
7065 std::string MangledName;
7066 MangledName += D.getIdentifier()->getName();
7067 MangledName += getOpenMPVariantManglingSeparatorStr();
7068 MangledName += DVScope.NameSuffix;
7069 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7070
7071 VariantII.setMangledOpenMPVariantName(true);
7072 D.SetIdentifier(&VariantII, D.getBeginLoc());
7073}
7074
7077 // Do not mark function as is used to prevent its emission if this is the
7078 // only place where it is used.
7081
7082 FunctionDecl *FD = nullptr;
7083 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7084 FD = UTemplDecl->getTemplatedDecl();
7085 else
7086 FD = cast<FunctionDecl>(D);
7087 auto *VariantFuncRef = DeclRefExpr::Create(
7089 /*RefersToEnclosingVariableOrCapture=*/false,
7090 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7091
7092 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7093 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7094 getASTContext(), VariantFuncRef, DVScope.TI,
7095 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7096 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7097 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7098 for (FunctionDecl *BaseFD : Bases)
7099 BaseFD->addAttr(OMPDeclareVariantA);
7100}
7101
7103 SourceLocation LParenLoc,
7104 MultiExprArg ArgExprs,
7105 SourceLocation RParenLoc,
7106 Expr *ExecConfig) {
7107 // The common case is a regular call we do not want to specialize at all. Try
7108 // to make that case fast by bailing early.
7109 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7110 if (!CE)
7111 return Call;
7112
7113 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7114 if (!CalleeFnDecl)
7115 return Call;
7116
7117 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7118 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7119 // checking for any calls inside an Order region
7121 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7122 }
7123
7124 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7125 return Call;
7126
7127 ASTContext &Context = getASTContext();
7128 std::function<void(StringRef)> DiagUnknownTrait = [this,
7129 CE](StringRef ISATrait) {
7130 // TODO Track the selector locations in a way that is accessible here to
7131 // improve the diagnostic location.
7132 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7133 << ISATrait;
7134 };
7135 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7137 DSAStack->getConstructTraits());
7138
7139 QualType CalleeFnType = CalleeFnDecl->getType();
7140
7143 while (CalleeFnDecl) {
7144 for (OMPDeclareVariantAttr *A :
7145 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7146 Expr *VariantRef = A->getVariantFuncRef();
7147
7148 VariantMatchInfo VMI;
7149 OMPTraitInfo &TI = A->getTraitInfo();
7150 TI.getAsVariantMatchInfo(Context, VMI);
7151 if (!isVariantApplicableInContext(VMI, OMPCtx,
7152 /*DeviceSetOnly=*/false))
7153 continue;
7154
7155 VMIs.push_back(VMI);
7156 Exprs.push_back(VariantRef);
7157 }
7158
7159 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7160 }
7161
7162 ExprResult NewCall;
7163 do {
7164 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7165 if (BestIdx < 0)
7166 return Call;
7167 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7168 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7169
7170 {
7171 // Try to build a (member) call expression for the current best applicable
7172 // variant expression. We allow this to fail in which case we continue
7173 // with the next best variant expression. The fail case is part of the
7174 // implementation defined behavior in the OpenMP standard when it talks
7175 // about what differences in the function prototypes: "Any differences
7176 // that the specific OpenMP context requires in the prototype of the
7177 // variant from the base function prototype are implementation defined."
7178 // This wording is there to allow the specialized variant to have a
7179 // different type than the base function. This is intended and OK but if
7180 // we cannot create a call the difference is not in the "implementation
7181 // defined range" we allow.
7183
7184 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7185 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7186 BestExpr = MemberExpr::CreateImplicit(
7187 Context, MemberCall->getImplicitObjectArgument(),
7188 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7189 MemberCall->getValueKind(), MemberCall->getObjectKind());
7190 }
7191 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7192 RParenLoc, ExecConfig);
7193 if (NewCall.isUsable()) {
7194 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7195 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7197 CalleeFnType, NewCalleeFnDecl->getType(),
7198 /*OfBlockPointer=*/false,
7199 /*Unqualified=*/false, /*AllowCXX=*/true);
7200 if (!NewType.isNull())
7201 break;
7202 // Don't use the call if the function type was not compatible.
7203 NewCall = nullptr;
7204 }
7205 }
7206 }
7207
7208 VMIs.erase(VMIs.begin() + BestIdx);
7209 Exprs.erase(Exprs.begin() + BestIdx);
7210 } while (!VMIs.empty());
7211
7212 if (!NewCall.isUsable())
7213 return Call;
7214 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7215}
7216
7217std::optional<std::pair<FunctionDecl *, Expr *>>
7219 Expr *VariantRef,
7220 OMPTraitInfo &TI,
7221 unsigned NumAppendArgs,
7222 SourceRange SR) {
7223 ASTContext &Context = getASTContext();
7224 if (!DG || DG.get().isNull())
7225 return std::nullopt;
7226
7227 const int VariantId = 1;
7228 // Must be applied only to single decl.
7229 if (!DG.get().isSingleDecl()) {
7230 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7231 << VariantId << SR;
7232 return std::nullopt;
7233 }
7234 Decl *ADecl = DG.get().getSingleDecl();
7235 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7236 ADecl = FTD->getTemplatedDecl();
7237
7238 // Decl must be a function.
7239 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7240 if (!FD) {
7241 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7242 << VariantId << SR;
7243 return std::nullopt;
7244 }
7245
7246 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7247 // The 'target' attribute needs to be separately checked because it does
7248 // not always signify a multiversion function declaration.
7249 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7250 };
7251 // OpenMP is not compatible with multiversion function attributes.
7252 if (HasMultiVersionAttributes(FD)) {
7253 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7254 << SR;
7255 return std::nullopt;
7256 }
7257
7258 // Allow #pragma omp declare variant only if the function is not used.
7259 if (FD->isUsed(false))
7260 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7261 << FD->getLocation();
7262
7263 // Check if the function was emitted already.
7264 const FunctionDecl *Definition;
7265 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7266 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7267 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7268 << FD->getLocation();
7269
7270 // The VariantRef must point to function.
7271 if (!VariantRef) {
7272 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7273 return std::nullopt;
7274 }
7275
7276 auto ShouldDelayChecks = [](Expr *&E, bool) {
7277 return E && (E->isTypeDependent() || E->isValueDependent() ||
7280 };
7281 // Do not check templates, wait until instantiation.
7282 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7283 TI.anyScoreOrCondition(ShouldDelayChecks))
7284 return std::make_pair(FD, VariantRef);
7285
7286 // Deal with non-constant score and user condition expressions.
7287 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7288 bool IsScore) -> bool {
7290 return false;
7291
7292 if (IsScore) {
7293 // We warn on non-constant scores and pretend they were not present.
7294 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7295 << E;
7296 E = nullptr;
7297 } else {
7298 // We could replace a non-constant user condition with "false" but we
7299 // will soon need to handle these anyway for the dynamic version of
7300 // OpenMP context selectors.
7301 Diag(E->getExprLoc(),
7302 diag::err_omp_declare_variant_user_condition_not_constant)
7303 << E;
7304 }
7305 return true;
7306 };
7307 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7308 return std::nullopt;
7309
7310 QualType AdjustedFnType = FD->getType();
7311 if (NumAppendArgs) {
7312 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7313 if (!PTy) {
7314 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7315 << SR;
7316 return std::nullopt;
7317 }
7318 // Adjust the function type to account for an extra omp_interop_t for each
7319 // specified in the append_args clause.
7320 const TypeDecl *TD = nullptr;
7321 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7324 NamedDecl *ND = Result.getFoundDecl();
7325 TD = dyn_cast_or_null<TypeDecl>(ND);
7326 }
7327 if (!TD) {
7328 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7329 return std::nullopt;
7330 }
7331 QualType InteropType = Context.getTypeDeclType(TD);
7332 if (PTy->isVariadic()) {
7333 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7334 return std::nullopt;
7335 }
7337 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7338 Params.insert(Params.end(), NumAppendArgs, InteropType);
7339 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7340 PTy->getExtProtoInfo());
7341 }
7342
7343 // Convert VariantRef expression to the type of the original function to
7344 // resolve possible conflicts.
7345 ExprResult VariantRefCast = VariantRef;
7346 if (getLangOpts().CPlusPlus) {
7347 QualType FnPtrType;
7348 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7349 if (Method && !Method->isStatic()) {
7350 const Type *ClassType =
7351 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7352 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7353 ExprResult ER;
7354 {
7355 // Build addr_of unary op to correctly handle type checks for member
7356 // functions.
7358 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7359 VariantRef);
7360 }
7361 if (!ER.isUsable()) {
7362 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7363 << VariantId << VariantRef->getSourceRange();
7364 return std::nullopt;
7365 }
7366 VariantRef = ER.get();
7367 } else {
7368 FnPtrType = Context.getPointerType(AdjustedFnType);
7369 }
7370 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7371 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7373 VariantRef, FnPtrType.getUnqualifiedType(),
7374 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7375 /*InOverloadResolution=*/false,
7376 /*CStyle=*/false,
7377 /*AllowObjCWritebackConversion=*/false);
7378 if (ICS.isFailure()) {
7379 Diag(VariantRef->getExprLoc(),
7380 diag::err_omp_declare_variant_incompat_types)
7381 << VariantRef->getType()
7382 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7383 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7384 return std::nullopt;
7385 }
7386 VariantRefCast = SemaRef.PerformImplicitConversion(
7387 VariantRef, FnPtrType.getUnqualifiedType(),
7389 if (!VariantRefCast.isUsable())
7390 return std::nullopt;
7391 }
7392 // Drop previously built artificial addr_of unary op for member functions.
7393 if (Method && !Method->isStatic()) {
7394 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7395 if (auto *UO = dyn_cast<UnaryOperator>(
7396 PossibleAddrOfVariantRef->IgnoreImplicit()))
7397 VariantRefCast = UO->getSubExpr();
7398 }
7399 }
7400
7401 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7402 if (!ER.isUsable() ||
7404 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7405 << VariantId << VariantRef->getSourceRange();
7406 return std::nullopt;
7407 }
7408
7409 // The VariantRef must point to function.
7410 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7411 if (!DRE) {
7412 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7413 << VariantId << VariantRef->getSourceRange();
7414 return std::nullopt;
7415 }
7416 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7417 if (!NewFD) {
7418 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7419 << VariantId << VariantRef->getSourceRange();
7420 return std::nullopt;
7421 }
7422
7423 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7424 Diag(VariantRef->getExprLoc(),
7425 diag::err_omp_declare_variant_same_base_function)
7426 << VariantRef->getSourceRange();
7427 return std::nullopt;
7428 }
7429
7430 // Check if function types are compatible in C.
7431 if (!getLangOpts().CPlusPlus) {
7432 QualType NewType =
7433 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7434 if (NewType.isNull()) {
7435 Diag(VariantRef->getExprLoc(),
7436 diag::err_omp_declare_variant_incompat_types)
7437 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7438 << VariantRef->getSourceRange();
7439 return std::nullopt;
7440 }
7441 if (NewType->isFunctionProtoType()) {
7442 if (FD->getType()->isFunctionNoProtoType())
7443 setPrototype(SemaRef, FD, NewFD, NewType);
7444 else if (NewFD->getType()->isFunctionNoProtoType())
7445 setPrototype(SemaRef, NewFD, FD, NewType);
7446 }
7447 }
7448
7449 // Check if variant function is not marked with declare variant directive.
7450 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7451 Diag(VariantRef->getExprLoc(),
7452 diag::warn_omp_declare_variant_marked_as_declare_variant)
7453 << VariantRef->getSourceRange();
7454 SourceRange SR =
7455 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7456 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7457 return std::nullopt;
7458 }
7459
7460 enum DoesntSupport {
7461 VirtFuncs = 1,
7462 Constructors = 3,
7463 Destructors = 4,
7464 DeletedFuncs = 5,
7465 DefaultedFuncs = 6,
7466 ConstexprFuncs = 7,
7467 ConstevalFuncs = 8,
7468 };
7469 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7470 if (CXXFD->isVirtual()) {
7471 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7472 << VirtFuncs;
7473 return std::nullopt;
7474 }
7475
7476 if (isa<CXXConstructorDecl>(FD)) {
7477 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7478 << Constructors;
7479 return std::nullopt;
7480 }
7481
7482 if (isa<CXXDestructorDecl>(FD)) {
7483 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7484 << Destructors;
7485 return std::nullopt;
7486 }
7487 }
7488
7489 if (FD->isDeleted()) {
7490 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7491 << DeletedFuncs;
7492 return std::nullopt;
7493 }
7494
7495 if (FD->isDefaulted()) {
7496 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7497 << DefaultedFuncs;
7498 return std::nullopt;
7499 }
7500
7501 if (FD->isConstexpr()) {
7502 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7503 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7504 return std::nullopt;
7505 }
7506
7507 // Check general compatibility.
7513 VariantRef->getExprLoc(),
7514 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7515 PartialDiagnosticAt(VariantRef->getExprLoc(),
7516 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7517 << FD->getLocation()),
7518 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7519 /*CLinkageMayDiffer=*/true))
7520 return std::nullopt;
7521 return std::make_pair(FD, cast<Expr>(DRE));
7522}
7523
7525 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7526 ArrayRef<Expr *> AdjustArgsNothing,
7527 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7528 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7529 SourceLocation AppendArgsLoc, SourceRange SR) {
7530
7531 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7532 // An adjust_args clause or append_args clause can only be specified if the
7533 // dispatch selector of the construct selector set appears in the match
7534 // clause.
7535
7536 SmallVector<Expr *, 8> AllAdjustArgs;
7537 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7538 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7539
7540 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7541 VariantMatchInfo VMI;
7543 if (!llvm::is_contained(
7544 VMI.ConstructTraits,
7545 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7546 if (!AllAdjustArgs.empty())
7547 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7548 << getOpenMPClauseName(OMPC_adjust_args);
7549 if (!AppendArgs.empty())
7550 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7551 << getOpenMPClauseName(OMPC_append_args);
7552 return;
7553 }
7554 }
7555
7556 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7557 // Each argument can only appear in a single adjust_args clause for each
7558 // declare variant directive.
7560
7561 for (Expr *E : AllAdjustArgs) {
7562 E = E->IgnoreParenImpCasts();
7563 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7564 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7565 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7566 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7567 FD->getParamDecl(PVD->getFunctionScopeIndex())
7568 ->getCanonicalDecl() == CanonPVD) {
7569 // It's a parameter of the function, check duplicates.
7570 if (!AdjustVars.insert(CanonPVD).second) {
7571 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7572 << PVD;
7573 return;
7574 }
7575 continue;
7576 }
7577 }
7578 }
7579 // Anything that is not a function parameter is an error.
7580 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7581 return;
7582 }
7583
7584 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7585 getASTContext(), VariantRef, &TI,
7586 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7587 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7588 AdjustArgsNeedDevicePtr.size(),
7589 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7590 FD->addAttr(NewAttr);
7591}
7592
7593static CapturedStmt *
7595 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7596 assert(CS && "Captured statement expected");
7597 // 1.2.2 OpenMP Language Terminology
7598 // Structured block - An executable statement with a single entry at the
7599 // top and a single exit at the bottom.
7600 // The point of exit cannot be a branch out of the structured block.
7601 // longjmp() and throw() must not violate the entry/exit criteria.
7602 CS->getCapturedDecl()->setNothrow();
7603
7604 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7605 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7606 CS = cast<CapturedStmt>(CS->getCapturedStmt());
7607 // 1.2.2 OpenMP Language Terminology
7608 // Structured block - An executable statement with a single entry at the
7609 // top and a single exit at the bottom.
7610 // The point of exit cannot be a branch out of the structured block.
7611 // longjmp() and throw() must not violate the entry/exit criteria.
7612 CS->getCapturedDecl()->setNothrow();
7613 }
7615 return CS;
7616}
7617
7620 Stmt *AStmt, SourceLocation StartLoc,
7621 SourceLocation EndLoc) {
7622 if (!AStmt)
7623 return StmtError();
7624
7625 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7626
7628 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7629 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7630}
7631
7632namespace {
7633/// Iteration space of a single for loop.
7634struct LoopIterationSpace final {
7635 /// True if the condition operator is the strict compare operator (<, > or
7636 /// !=).
7637 bool IsStrictCompare = false;
7638 /// Condition of the loop.
7639 Expr *PreCond = nullptr;
7640 /// This expression calculates the number of iterations in the loop.
7641 /// It is always possible to calculate it before starting the loop.
7642 Expr *NumIterations = nullptr;
7643 /// The loop counter variable.
7644 Expr *CounterVar = nullptr;
7645 /// Private loop counter variable.
7646 Expr *PrivateCounterVar = nullptr;
7647 /// This is initializer for the initial value of #CounterVar.
7648 Expr *CounterInit = nullptr;
7649 /// This is step for the #CounterVar used to generate its update:
7650 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7651 Expr *CounterStep = nullptr;
7652 /// Should step be subtracted?
7653 bool Subtract = false;
7654 /// Source range of the loop init.
7655 SourceRange InitSrcRange;
7656 /// Source range of the loop condition.
7657 SourceRange CondSrcRange;
7658 /// Source range of the loop increment.
7659 SourceRange IncSrcRange;
7660 /// Minimum value that can have the loop control variable. Used to support
7661 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7662 /// since only such variables can be used in non-loop invariant expressions.
7663 Expr *MinValue = nullptr;
7664 /// Maximum value that can have the loop control variable. Used to support
7665 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7666 /// since only such variables can be used in non-loop invariant expressions.
7667 Expr *MaxValue = nullptr;
7668 /// true, if the lower bound depends on the outer loop control var.
7669 bool IsNonRectangularLB = false;
7670 /// true, if the upper bound depends on the outer loop control var.
7671 bool IsNonRectangularUB = false;
7672 /// Index of the loop this loop depends on and forms non-rectangular loop
7673 /// nest.
7674 unsigned LoopDependentIdx = 0;
7675 /// Final condition for the non-rectangular loop nest support. It is used to
7676 /// check that the number of iterations for this particular counter must be
7677 /// finished.
7678 Expr *FinalCondition = nullptr;
7679};
7680
7681/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7682/// set are referenced. Used for verifying loop nest structure before
7683/// performing a loop collapse operation.
7684class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7685 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7686 VarDecl *ForbiddenVar = nullptr;
7687 SourceRange ErrLoc;
7688
7689public:
7690 explicit ForSubExprChecker(
7691 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7692 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7693 // We want to visit implicit code, i.e. synthetic initialisation statements
7694 // created during range-for lowering.
7695 ShouldVisitImplicitCode = true;
7696 }
7697
7698 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7699 ValueDecl *VD = E->getDecl();
7700 if (!isa<VarDecl, BindingDecl>(VD))
7701 return true;
7703 if (V->getType()->isReferenceType()) {
7704 VarDecl *VD = V->getDefinition();
7705 if (VD->hasInit()) {
7706 Expr *I = VD->getInit();
7707 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7708 if (!DRE)
7709 return true;
7711 }
7712 }
7713 Decl *Canon = V->getCanonicalDecl();
7714 if (CollapsedLoopVarDecls.contains(Canon)) {
7715 ForbiddenVar = V;
7716 ErrLoc = E->getSourceRange();
7717 return false;
7718 }
7719
7720 return true;
7721 }
7722
7723 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7724 SourceRange getErrRange() const { return ErrLoc; }
7725};
7726
7727/// Helper class for checking canonical form of the OpenMP loops and
7728/// extracting iteration space of each loop in the loop nest, that will be used
7729/// for IR generation.
7730class OpenMPIterationSpaceChecker {
7731 /// Reference to Sema.
7732 Sema &SemaRef;
7733 /// Does the loop associated directive support non-rectangular loops?
7734 bool SupportsNonRectangular;
7735 /// Data-sharing stack.
7736 DSAStackTy &Stack;
7737 /// A location for diagnostics (when there is no some better location).
7738 SourceLocation DefaultLoc;
7739 /// A location for diagnostics (when increment is not compatible).
7740 SourceLocation ConditionLoc;
7741 /// The set of variables declared within the (to be collapsed) loop nest.
7742 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7743 /// A source location for referring to loop init later.
7744 SourceRange InitSrcRange;
7745 /// A source location for referring to condition later.
7746 SourceRange ConditionSrcRange;
7747 /// A source location for referring to increment later.
7748 SourceRange IncrementSrcRange;
7749 /// Loop variable.
7750 ValueDecl *LCDecl = nullptr;
7751 /// Reference to loop variable.
7752 Expr *LCRef = nullptr;
7753 /// Lower bound (initializer for the var).
7754 Expr *LB = nullptr;
7755 /// Upper bound.
7756 Expr *UB = nullptr;
7757 /// Loop step (increment).
7758 Expr *Step = nullptr;
7759 /// This flag is true when condition is one of:
7760 /// Var < UB
7761 /// Var <= UB
7762 /// UB > Var
7763 /// UB >= Var
7764 /// This will have no value when the condition is !=
7765 std::optional<bool> TestIsLessOp;
7766 /// This flag is true when condition is strict ( < or > ).
7767 bool TestIsStrictOp = false;
7768 /// This flag is true when step is subtracted on each iteration.
7769 bool SubtractStep = false;
7770 /// The outer loop counter this loop depends on (if any).
7771 const ValueDecl *DepDecl = nullptr;
7772 /// Contains number of loop (starts from 1) on which loop counter init
7773 /// expression of this loop depends on.
7774 std::optional<unsigned> InitDependOnLC;
7775 /// Contains number of loop (starts from 1) on which loop counter condition
7776 /// expression of this loop depends on.
7777 std::optional<unsigned> CondDependOnLC;
7778 /// Checks if the provide statement depends on the loop counter.
7779 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7780 bool IsInitializer);
7781 /// Original condition required for checking of the exit condition for
7782 /// non-rectangular loop.
7783 Expr *Condition = nullptr;
7784
7785public:
7786 OpenMPIterationSpaceChecker(
7787 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
7788 SourceLocation DefaultLoc,
7789 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7790 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7791 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7792 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7793 /// Check init-expr for canonical loop form and save loop counter
7794 /// variable - #Var and its initialization value - #LB.
7795 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7796 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7797 /// for less/greater and for strict/non-strict comparison.
7798 bool checkAndSetCond(Expr *S);
7799 /// Check incr-expr for canonical loop form and return true if it
7800 /// does not conform, otherwise save loop step (#Step).
7801 bool checkAndSetInc(Expr *S);
7802 /// Return the loop counter variable.
7803 ValueDecl *getLoopDecl() const { return LCDecl; }
7804 /// Return the reference expression to loop counter variable.
7805 Expr *getLoopDeclRefExpr() const { return LCRef; }
7806 /// Source range of the loop init.
7807 SourceRange getInitSrcRange() const { return InitSrcRange; }
7808 /// Source range of the loop condition.
7809 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7810 /// Source range of the loop increment.
7811 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7812 /// True if the step should be subtracted.
7813 bool shouldSubtractStep() const { return SubtractStep; }
7814 /// True, if the compare operator is strict (<, > or !=).
7815 bool isStrictTestOp() const { return TestIsStrictOp; }
7816 /// Build the expression to calculate the number of iterations.
7817 Expr *buildNumIterations(
7818 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7819 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7820 /// Build the precondition expression for the loops.
7821 Expr *
7822 buildPreCond(Scope *S, Expr *Cond,
7823 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7824 /// Build reference expression to the counter be used for codegen.
7825 DeclRefExpr *
7826 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7827 DSAStackTy &DSA) const;
7828 /// Build reference expression to the private counter be used for
7829 /// codegen.
7830 Expr *buildPrivateCounterVar() const;
7831 /// Build initialization of the counter be used for codegen.
7832 Expr *buildCounterInit() const;
7833 /// Build step of the counter be used for codegen.
7834 Expr *buildCounterStep() const;
7835 /// Build loop data with counter value for depend clauses in ordered
7836 /// directives.
7837 Expr *
7838 buildOrderedLoopData(Scope *S, Expr *Counter,
7839 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7840 SourceLocation Loc, Expr *Inc = nullptr,
7841 OverloadedOperatorKind OOK = OO_Amp);
7842 /// Builds the minimum value for the loop counter.
7843 std::pair<Expr *, Expr *> buildMinMaxValues(
7844 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7845 /// Builds final condition for the non-rectangular loops.
7846 Expr *buildFinalCondition(Scope *S) const;
7847 /// Return true if any expression is dependent.
7848 bool dependent() const;
7849 /// Returns true if the initializer forms non-rectangular loop.
7850 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7851 /// Returns true if the condition forms non-rectangular loop.
7852 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7853 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7854 unsigned getLoopDependentIdx() const {
7855 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7856 }
7857
7858private:
7859 /// Check the right-hand side of an assignment in the increment
7860 /// expression.
7861 bool checkAndSetIncRHS(Expr *RHS);
7862 /// Helper to set loop counter variable and its initializer.
7863 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7864 bool EmitDiags);
7865 /// Helper to set upper bound.
7866 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7868 /// Helper to set loop increment.
7869 bool setStep(Expr *NewStep, bool Subtract);
7870};
7871
7872bool OpenMPIterationSpaceChecker::dependent() const {
7873 if (!LCDecl) {
7874 assert(!LB && !UB && !Step);
7875 return false;
7876 }
7877 return LCDecl->getType()->isDependentType() ||
7878 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7879 (Step && Step->isValueDependent());
7880}
7881
7882bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7883 Expr *NewLCRefExpr,
7884 Expr *NewLB, bool EmitDiags) {
7885 // State consistency checking to ensure correct usage.
7886 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7887 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7888 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7889 return true;
7890 LCDecl = getCanonicalDecl(NewLCDecl);
7891 LCRef = NewLCRefExpr;
7892 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7893 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7894 if ((Ctor->isCopyOrMoveConstructor() ||
7895 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7896 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7897 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7898 LB = NewLB;
7899 if (EmitDiags)
7900 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7901 return false;
7902}
7903
7904bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7905 bool StrictOp, SourceRange SR,
7906 SourceLocation SL) {
7907 // State consistency checking to ensure correct usage.
7908 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7909 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7910 if (!NewUB || NewUB->containsErrors())
7911 return true;
7912 UB = NewUB;
7913 if (LessOp)
7914 TestIsLessOp = LessOp;
7915 TestIsStrictOp = StrictOp;
7916 ConditionSrcRange = SR;
7917 ConditionLoc = SL;
7918 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7919 return false;
7920}
7921
7922bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7923 // State consistency checking to ensure correct usage.
7924 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7925 if (!NewStep || NewStep->containsErrors())
7926 return true;
7927 if (!NewStep->isValueDependent()) {
7928 // Check that the step is integer expression.
7929 SourceLocation StepLoc = NewStep->getBeginLoc();
7931 StepLoc, getExprAsWritten(NewStep));
7932 if (Val.isInvalid())
7933 return true;
7934 NewStep = Val.get();
7935
7936 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7937 // If test-expr is of form var relational-op b and relational-op is < or
7938 // <= then incr-expr must cause var to increase on each iteration of the
7939 // loop. If test-expr is of form var relational-op b and relational-op is
7940 // > or >= then incr-expr must cause var to decrease on each iteration of
7941 // the loop.
7942 // If test-expr is of form b relational-op var and relational-op is < or
7943 // <= then incr-expr must cause var to decrease on each iteration of the
7944 // loop. If test-expr is of form b relational-op var and relational-op is
7945 // > or >= then incr-expr must cause var to increase on each iteration of
7946 // the loop.
7947 std::optional<llvm::APSInt> Result =
7948 NewStep->getIntegerConstantExpr(SemaRef.Context);
7949 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7950 bool IsConstNeg =
7951 Result && Result->isSigned() && (Subtract != Result->isNegative());
7952 bool IsConstPos =
7953 Result && Result->isSigned() && (Subtract == Result->isNegative());
7954 bool IsConstZero = Result && !Result->getBoolValue();
7955
7956 // != with increment is treated as <; != with decrement is treated as >
7957 if (!TestIsLessOp)
7958 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7959 if (UB && (IsConstZero ||
7960 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7961 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7962 SemaRef.Diag(NewStep->getExprLoc(),
7963 diag::err_omp_loop_incr_not_compatible)
7964 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7965 SemaRef.Diag(ConditionLoc,
7966 diag::note_omp_loop_cond_requires_compatible_incr)
7967 << *TestIsLessOp << ConditionSrcRange;
7968 return true;
7969 }
7970 if (*TestIsLessOp == Subtract) {
7971 NewStep =
7972 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
7973 .get();
7974 Subtract = !Subtract;
7975 }
7976 }
7977
7978 Step = NewStep;
7979 SubtractStep = Subtract;
7980 return false;
7981}
7982
7983namespace {
7984/// Checker for the non-rectangular loops. Checks if the initializer or
7985/// condition expression references loop counter variable.
7986class LoopCounterRefChecker final
7987 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
7988 Sema &SemaRef;
7989 DSAStackTy &Stack;
7990 const ValueDecl *CurLCDecl = nullptr;
7991 const ValueDecl *DepDecl = nullptr;
7992 const ValueDecl *PrevDepDecl = nullptr;
7993 bool IsInitializer = true;
7994 bool SupportsNonRectangular;
7995 unsigned BaseLoopId = 0;
7996 bool checkDecl(const Expr *E, const ValueDecl *VD) {
7997 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
7998 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7999 << (IsInitializer ? 0 : 1);
8000 return false;
8001 }
8002 const auto &&Data = Stack.isLoopControlVariable(VD);
8003 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8004 // The type of the loop iterator on which we depend may not have a random
8005 // access iterator type.
8006 if (Data.first && VD->getType()->isRecordType()) {
8007 SmallString<128> Name;
8008 llvm::raw_svector_ostream OS(Name);
8009 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8010 /*Qualified=*/true);
8011 SemaRef.Diag(E->getExprLoc(),
8012 diag::err_omp_wrong_dependency_iterator_type)
8013 << OS.str();
8014 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8015 return false;
8016 }
8017 if (Data.first && !SupportsNonRectangular) {
8018 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8019 return false;
8020 }
8021 if (Data.first &&
8022 (DepDecl || (PrevDepDecl &&
8023 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8024 if (!DepDecl && PrevDepDecl)
8025 DepDecl = PrevDepDecl;
8026 SmallString<128> Name;
8027 llvm::raw_svector_ostream OS(Name);
8028 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8029 /*Qualified=*/true);
8030 SemaRef.Diag(E->getExprLoc(),
8031 diag::err_omp_invariant_or_linear_dependency)
8032 << OS.str();
8033 return false;
8034 }
8035 if (Data.first) {
8036 DepDecl = VD;
8037 BaseLoopId = Data.first;
8038 }
8039 return Data.first;
8040 }
8041
8042public:
8043 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8044 const ValueDecl *VD = E->getDecl();
8045 if (isa<VarDecl>(VD))
8046 return checkDecl(E, VD);
8047 return false;
8048 }
8049 bool VisitMemberExpr(const MemberExpr *E) {
8050 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8051 const ValueDecl *VD = E->getMemberDecl();
8052 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8053 return checkDecl(E, VD);
8054 }
8055 return false;
8056 }
8057 bool VisitStmt(const Stmt *S) {
8058 bool Res = false;
8059 for (const Stmt *Child : S->children())
8060 Res = (Child && Visit(Child)) || Res;
8061 return Res;
8062 }
8063 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8064 const ValueDecl *CurLCDecl, bool IsInitializer,
8065 const ValueDecl *PrevDepDecl = nullptr,
8066 bool SupportsNonRectangular = true)
8067 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8068 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8069 SupportsNonRectangular(SupportsNonRectangular) {}
8070 unsigned getBaseLoopId() const {
8071 assert(CurLCDecl && "Expected loop dependency.");
8072 return BaseLoopId;
8073 }
8074 const ValueDecl *getDepDecl() const {
8075 assert(CurLCDecl && "Expected loop dependency.");
8076 return DepDecl;
8077 }
8078};
8079} // namespace
8080
8081std::optional<unsigned>
8082OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8083 bool IsInitializer) {
8084 // Check for the non-rectangular loops.
8085 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8086 DepDecl, SupportsNonRectangular);
8087 if (LoopStmtChecker.Visit(S)) {
8088 DepDecl = LoopStmtChecker.getDepDecl();
8089 return LoopStmtChecker.getBaseLoopId();
8090 }
8091 return std::nullopt;
8092}
8093
8094bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8095 // Check init-expr for canonical loop form and save loop counter
8096 // variable - #Var and its initialization value - #LB.
8097 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8098 // var = lb
8099 // integer-type var = lb
8100 // random-access-iterator-type var = lb
8101 // pointer-type var = lb
8102 //
8103 if (!S) {
8104 if (EmitDiags) {
8105 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8106 }
8107 return true;
8108 }
8109 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8110 if (!ExprTemp->cleanupsHaveSideEffects())
8111 S = ExprTemp->getSubExpr();
8112
8113 if (!CollapsedLoopVarDecls.empty()) {
8114 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8115 if (!FSEC.TraverseStmt(S)) {
8116 SourceRange Range = FSEC.getErrRange();
8117 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8118 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8119 return true;
8120 }
8121 }
8122
8123 InitSrcRange = S->getSourceRange();
8124 if (Expr *E = dyn_cast<Expr>(S))
8125 S = E->IgnoreParens();
8126 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8127 if (BO->getOpcode() == BO_Assign) {
8128 Expr *LHS = BO->getLHS()->IgnoreParens();
8129 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8130 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8131 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8132 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8133 EmitDiags);
8134 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8135 }
8136 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8137 if (ME->isArrow() &&
8138 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8139 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8140 EmitDiags);
8141 }
8142 }
8143 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8144 if (DS->isSingleDecl()) {
8145 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8146 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8147 // Accept non-canonical init form here but emit ext. warning.
8148 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8149 SemaRef.Diag(S->getBeginLoc(),
8150 diag::ext_omp_loop_not_canonical_init)
8151 << S->getSourceRange();
8152 return setLCDeclAndLB(
8153 Var,
8154 buildDeclRefExpr(SemaRef, Var,
8155 Var->getType().getNonReferenceType(),
8156 DS->getBeginLoc()),
8157 Var->getInit(), EmitDiags);
8158 }
8159 }
8160 }
8161 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8162 if (CE->getOperator() == OO_Equal) {
8163 Expr *LHS = CE->getArg(0);
8164 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8165 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8166 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8167 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8168 EmitDiags);
8169 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8170 }
8171 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8172 if (ME->isArrow() &&
8173 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8174 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8175 EmitDiags);
8176 }
8177 }
8178 }
8179
8180 if (dependent() || SemaRef.CurContext->isDependentContext())
8181 return false;
8182 if (EmitDiags) {
8183 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8184 << S->getSourceRange();
8185 }
8186 return true;
8187}
8188
8189/// Ignore parenthesizes, implicit casts, copy constructor and return the
8190/// variable (which may be the loop variable) if possible.
8191static const ValueDecl *getInitLCDecl(const Expr *E) {
8192 if (!E)
8193 return nullptr;
8194 E = getExprAsWritten(E);
8195 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8196 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8197 if ((Ctor->isCopyOrMoveConstructor() ||
8198 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8199 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8200 E = CE->getArg(0)->IgnoreParenImpCasts();
8201 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8202 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8203 return getCanonicalDecl(VD);
8204 }
8205 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8206 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8207 return getCanonicalDecl(ME->getMemberDecl());
8208 return nullptr;
8209}
8210
8211bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8212 // Check test-expr for canonical form, save upper-bound UB, flags for
8213 // less/greater and for strict/non-strict comparison.
8214 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8215 // var relational-op b
8216 // b relational-op var
8217 //
8218 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8219 if (!S) {
8220 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8221 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8222 return true;
8223 }
8224 Condition = S;
8225 S = getExprAsWritten(S);
8226
8227 if (!CollapsedLoopVarDecls.empty()) {
8228 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8229 if (!FSEC.TraverseStmt(S)) {
8230 SourceRange Range = FSEC.getErrRange();
8231 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8232 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8233 return true;
8234 }
8235 }
8236
8237 SourceLocation CondLoc = S->getBeginLoc();
8238 auto &&CheckAndSetCond =
8239 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8240 const Expr *RHS, SourceRange SR,
8241 SourceLocation OpLoc) -> std::optional<bool> {
8242 if (BinaryOperator::isRelationalOp(Opcode)) {
8243 if (getInitLCDecl(LHS) == LCDecl)
8244 return setUB(const_cast<Expr *>(RHS),
8245 (Opcode == BO_LT || Opcode == BO_LE),
8246 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8247 if (getInitLCDecl(RHS) == LCDecl)
8248 return setUB(const_cast<Expr *>(LHS),
8249 (Opcode == BO_GT || Opcode == BO_GE),
8250 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8251 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8252 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8253 /*LessOp=*/std::nullopt,
8254 /*StrictOp=*/true, SR, OpLoc);
8255 }
8256 return std::nullopt;
8257 };
8258 std::optional<bool> Res;
8259 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8260 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8261 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8262 RBO->getOperatorLoc());
8263 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8264 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8265 BO->getSourceRange(), BO->getOperatorLoc());
8266 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8267 if (CE->getNumArgs() == 2) {
8268 Res = CheckAndSetCond(
8269 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8270 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8271 }
8272 }
8273 if (Res)
8274 return *Res;
8275 if (dependent() || SemaRef.CurContext->isDependentContext())
8276 return false;
8277 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8278 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8279 return true;
8280}
8281
8282bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8283 // RHS of canonical loop form increment can be:
8284 // var + incr
8285 // incr + var
8286 // var - incr
8287 //
8288 RHS = RHS->IgnoreParenImpCasts();
8289 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8290 if (BO->isAdditiveOp()) {
8291 bool IsAdd = BO->getOpcode() == BO_Add;
8292 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8293 return setStep(BO->getRHS(), !IsAdd);
8294 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8295 return setStep(BO->getLHS(), /*Subtract=*/false);
8296 }
8297 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8298 bool IsAdd = CE->getOperator() == OO_Plus;
8299 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8300 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8301 return setStep(CE->getArg(1), !IsAdd);
8302 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8303 return setStep(CE->getArg(0), /*Subtract=*/false);
8304 }
8305 }
8306 if (dependent() || SemaRef.CurContext->isDependentContext())
8307 return false;
8308 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8309 << RHS->getSourceRange() << LCDecl;
8310 return true;
8311}
8312
8313bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8314 // Check incr-expr for canonical loop form and return true if it
8315 // does not conform.
8316 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8317 // ++var
8318 // var++
8319 // --var
8320 // var--
8321 // var += incr
8322 // var -= incr
8323 // var = var + incr
8324 // var = incr + var
8325 // var = var - incr
8326 //
8327 if (!S) {
8328 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8329 return true;
8330 }
8331 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8332 if (!ExprTemp->cleanupsHaveSideEffects())
8333 S = ExprTemp->getSubExpr();
8334
8335 if (!CollapsedLoopVarDecls.empty()) {
8336 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8337 if (!FSEC.TraverseStmt(S)) {
8338 SourceRange Range = FSEC.getErrRange();
8339 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8340 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8341 return true;
8342 }
8343 }
8344
8345 IncrementSrcRange = S->getSourceRange();
8346 S = S->IgnoreParens();
8347 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8348 if (UO->isIncrementDecrementOp() &&
8349 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8350 return setStep(SemaRef
8351 .ActOnIntegerConstant(UO->getBeginLoc(),
8352 (UO->isDecrementOp() ? -1 : 1))
8353 .get(),
8354 /*Subtract=*/false);
8355 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8356 switch (BO->getOpcode()) {
8357 case BO_AddAssign:
8358 case BO_SubAssign:
8359 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8360 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8361 break;
8362 case BO_Assign:
8363 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8364 return checkAndSetIncRHS(BO->getRHS());
8365 break;
8366 default:
8367 break;
8368 }
8369 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8370 switch (CE->getOperator()) {
8371 case OO_PlusPlus:
8372 case OO_MinusMinus:
8373 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8374 return setStep(SemaRef
8375 .ActOnIntegerConstant(
8376 CE->getBeginLoc(),
8377 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8378 .get(),
8379 /*Subtract=*/false);
8380 break;
8381 case OO_PlusEqual:
8382 case OO_MinusEqual:
8383 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8384 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8385 break;
8386 case OO_Equal:
8387 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8388 return checkAndSetIncRHS(CE->getArg(1));
8389 break;
8390 default:
8391 break;
8392 }
8393 }
8394 if (dependent() || SemaRef.CurContext->isDependentContext())
8395 return false;
8396 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8397 << S->getSourceRange() << LCDecl;
8398 return true;
8399}
8400
8401static ExprResult
8402tryBuildCapture(Sema &SemaRef, Expr *Capture,
8403 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8404 StringRef Name = ".capture_expr.") {
8405 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8406 return Capture;
8407 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8408 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8409 Capture->getType(),
8411 /*AllowExplicit=*/true);
8412 auto I = Captures.find(Capture);
8413 if (I != Captures.end())
8414 return buildCapture(SemaRef, Capture, I->second, Name);
8415 DeclRefExpr *Ref = nullptr;
8416 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8417 Captures[Capture] = Ref;
8418 return Res;
8419}
8420
8421/// Calculate number of iterations, transforming to unsigned, if number of
8422/// iterations may be larger than the original type.
8423static Expr *
8424calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8425 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8426 bool TestIsStrictOp, bool RoundToStep,
8427 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8428 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8429 if (!NewStep.isUsable())
8430 return nullptr;
8431 llvm::APSInt LRes, SRes;
8432 bool IsLowerConst = false, IsStepConst = false;
8433 if (std::optional<llvm::APSInt> Res =
8434 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8435 LRes = *Res;
8436 IsLowerConst = true;
8437 }
8438 if (std::optional<llvm::APSInt> Res =
8439 Step->getIntegerConstantExpr(SemaRef.Context)) {
8440 SRes = *Res;
8441 IsStepConst = true;
8442 }
8443 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8444 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8445 (TestIsStrictOp && LRes.isStrictlyPositive()));
8446 bool NeedToReorganize = false;
8447 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8448 if (!NoNeedToConvert && IsLowerConst &&
8449 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8450 NoNeedToConvert = true;
8451 if (RoundToStep) {
8452 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8453 ? LRes.getBitWidth()
8454 : SRes.getBitWidth();
8455 LRes = LRes.extend(BW + 1);
8456 LRes.setIsSigned(true);
8457 SRes = SRes.extend(BW + 1);
8458 SRes.setIsSigned(true);
8459 LRes -= SRes;
8460 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8461 LRes = LRes.trunc(BW);
8462 }
8463 if (TestIsStrictOp) {
8464 unsigned BW = LRes.getBitWidth();
8465 LRes = LRes.extend(BW + 1);
8466 LRes.setIsSigned(true);
8467 ++LRes;
8468 NoNeedToConvert =
8469 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8470 // truncate to the original bitwidth.
8471 LRes = LRes.trunc(BW);
8472 }
8473 NeedToReorganize = NoNeedToConvert;
8474 }
8475 llvm::APSInt URes;
8476 bool IsUpperConst = false;
8477 if (std::optional<llvm::APSInt> Res =
8478 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8479 URes = *Res;
8480 IsUpperConst = true;
8481 }
8482 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8483 (!RoundToStep || IsStepConst)) {
8484 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8485 : URes.getBitWidth();
8486 LRes = LRes.extend(BW + 1);
8487 LRes.setIsSigned(true);
8488 URes = URes.extend(BW + 1);
8489 URes.setIsSigned(true);
8490 URes -= LRes;
8491 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8492 NeedToReorganize = NoNeedToConvert;
8493 }
8494 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8495 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8496 // unsigned.
8497 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8498 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8499 QualType LowerTy = Lower->getType();
8500 QualType UpperTy = Upper->getType();
8501 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8502 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8503 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8504 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8506 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8507 Upper =
8508 SemaRef
8510 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8512 .get();
8513 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8514 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8515 }
8516 }
8517 if (!Lower || !Upper || NewStep.isInvalid())
8518 return nullptr;
8519
8520 ExprResult Diff;
8521 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8522 // 1]).
8523 if (NeedToReorganize) {
8524 Diff = Lower;
8525
8526 if (RoundToStep) {
8527 // Lower - Step
8528 Diff =
8529 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8530 if (!Diff.isUsable())
8531 return nullptr;
8532 }
8533
8534 // Lower - Step [+ 1]
8535 if (TestIsStrictOp)
8536 Diff = SemaRef.BuildBinOp(
8537 S, DefaultLoc, BO_Add, Diff.get(),
8538 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8539 if (!Diff.isUsable())
8540 return nullptr;
8541
8542 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8543 if (!Diff.isUsable())
8544 return nullptr;
8545
8546 // Upper - (Lower - Step [+ 1]).
8547 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8548 if (!Diff.isUsable())
8549 return nullptr;
8550 } else {
8551 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8552
8553 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8554 // BuildBinOp already emitted error, this one is to point user to upper
8555 // and lower bound, and to tell what is passed to 'operator-'.
8556 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8557 << Upper->getSourceRange() << Lower->getSourceRange();
8558 return nullptr;
8559 }
8560
8561 if (!Diff.isUsable())
8562 return nullptr;
8563
8564 // Upper - Lower [- 1]
8565 if (TestIsStrictOp)
8566 Diff = SemaRef.BuildBinOp(
8567 S, DefaultLoc, BO_Sub, Diff.get(),
8568 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8569 if (!Diff.isUsable())
8570 return nullptr;
8571
8572 if (RoundToStep) {
8573 // Upper - Lower [- 1] + Step
8574 Diff =
8575 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8576 if (!Diff.isUsable())
8577 return nullptr;
8578 }
8579 }
8580
8581 // Parentheses (for dumping/debugging purposes only).
8582 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8583 if (!Diff.isUsable())
8584 return nullptr;
8585
8586 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8587 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8588 if (!Diff.isUsable())
8589 return nullptr;
8590
8591 return Diff.get();
8592}
8593
8594/// Build the expression to calculate the number of iterations.
8595Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8596 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8597 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8598 QualType VarType = LCDecl->getType().getNonReferenceType();
8599 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8600 !SemaRef.getLangOpts().CPlusPlus)
8601 return nullptr;
8602 Expr *LBVal = LB;
8603 Expr *UBVal = UB;
8604 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8605 // max(LB(MinVal), LB(MaxVal)))
8606 if (InitDependOnLC) {
8607 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8608 if (!IS.MinValue || !IS.MaxValue)
8609 return nullptr;
8610 // OuterVar = Min
8611 ExprResult MinValue =
8612 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8613 if (!MinValue.isUsable())
8614 return nullptr;
8615
8616 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8617 IS.CounterVar, MinValue.get());
8618 if (!LBMinVal.isUsable())
8619 return nullptr;
8620 // OuterVar = Min, LBVal
8621 LBMinVal =
8622 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8623 if (!LBMinVal.isUsable())
8624 return nullptr;
8625 // (OuterVar = Min, LBVal)
8626 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8627 if (!LBMinVal.isUsable())
8628 return nullptr;
8629
8630 // OuterVar = Max
8631 ExprResult MaxValue =
8632 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8633 if (!MaxValue.isUsable())
8634 return nullptr;
8635
8636 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8637 IS.CounterVar, MaxValue.get());
8638 if (!LBMaxVal.isUsable())
8639 return nullptr;
8640 // OuterVar = Max, LBVal
8641 LBMaxVal =
8642 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8643 if (!LBMaxVal.isUsable())
8644 return nullptr;
8645 // (OuterVar = Max, LBVal)
8646 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8647 if (!LBMaxVal.isUsable())
8648 return nullptr;
8649
8650 Expr *LBMin =
8651 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8652 Expr *LBMax =
8653 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8654 if (!LBMin || !LBMax)
8655 return nullptr;
8656 // LB(MinVal) < LB(MaxVal)
8657 ExprResult MinLessMaxRes =
8658 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8659 if (!MinLessMaxRes.isUsable())
8660 return nullptr;
8661 Expr *MinLessMax =
8662 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8663 .get();
8664 if (!MinLessMax)
8665 return nullptr;
8666 if (*TestIsLessOp) {
8667 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8668 // LB(MaxVal))
8669 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8670 MinLessMax, LBMin, LBMax);
8671 if (!MinLB.isUsable())
8672 return nullptr;
8673 LBVal = MinLB.get();
8674 } else {
8675 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8676 // LB(MaxVal))
8677 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8678 MinLessMax, LBMax, LBMin);
8679 if (!MaxLB.isUsable())
8680 return nullptr;
8681 LBVal = MaxLB.get();
8682 }
8683 // OuterVar = LB
8684 LBMinVal =
8685 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8686 if (!LBMinVal.isUsable())
8687 return nullptr;
8688 LBVal = LBMinVal.get();
8689 }
8690 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8691 // min(UB(MinVal), UB(MaxVal))
8692 if (CondDependOnLC) {
8693 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8694 if (!IS.MinValue || !IS.MaxValue)
8695 return nullptr;
8696 // OuterVar = Min
8697 ExprResult MinValue =
8698 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8699 if (!MinValue.isUsable())
8700 return nullptr;
8701
8702 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8703 IS.CounterVar, MinValue.get());
8704 if (!UBMinVal.isUsable())
8705 return nullptr;
8706 // OuterVar = Min, UBVal
8707 UBMinVal =
8708 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8709 if (!UBMinVal.isUsable())
8710 return nullptr;
8711 // (OuterVar = Min, UBVal)
8712 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8713 if (!UBMinVal.isUsable())
8714 return nullptr;
8715
8716 // OuterVar = Max
8717 ExprResult MaxValue =
8718 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8719 if (!MaxValue.isUsable())
8720 return nullptr;
8721
8722 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8723 IS.CounterVar, MaxValue.get());
8724 if (!UBMaxVal.isUsable())
8725 return nullptr;
8726 // OuterVar = Max, UBVal
8727 UBMaxVal =
8728 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8729 if (!UBMaxVal.isUsable())
8730 return nullptr;
8731 // (OuterVar = Max, UBVal)
8732 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8733 if (!UBMaxVal.isUsable())
8734 return nullptr;
8735
8736 Expr *UBMin =
8737 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8738 Expr *UBMax =
8739 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8740 if (!UBMin || !UBMax)
8741 return nullptr;
8742 // UB(MinVal) > UB(MaxVal)
8743 ExprResult MinGreaterMaxRes =
8744 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8745 if (!MinGreaterMaxRes.isUsable())
8746 return nullptr;
8747 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8748 Captures, ".min_greater_max")
8749 .get();
8750 if (!MinGreaterMax)
8751 return nullptr;
8752 if (*TestIsLessOp) {
8753 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8754 // UB(MaxVal))
8755 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8756 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8757 if (!MaxUB.isUsable())
8758 return nullptr;
8759 UBVal = MaxUB.get();
8760 } else {
8761 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8762 // UB(MaxVal))
8763 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8764 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8765 if (!MinUB.isUsable())
8766 return nullptr;
8767 UBVal = MinUB.get();
8768 }
8769 }
8770 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8771 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8772 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8773 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8774 if (!Upper || !Lower)
8775 return nullptr;
8776
8777 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8778 Step, VarType, TestIsStrictOp,
8779 /*RoundToStep=*/true, Captures);
8780 if (!Diff.isUsable())
8781 return nullptr;
8782
8783 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8784 QualType Type = Diff.get()->getType();
8785 ASTContext &C = SemaRef.Context;
8786 bool UseVarType = VarType->hasIntegerRepresentation() &&
8787 C.getTypeSize(Type) > C.getTypeSize(VarType);
8788 if (!Type->isIntegerType() || UseVarType) {
8789 unsigned NewSize =
8790 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8791 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8793 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8794 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8795 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
8797 /*AllowExplicit=*/true);
8798 if (!Diff.isUsable())
8799 return nullptr;
8800 }
8801 }
8802 if (LimitedType) {
8803 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8804 if (NewSize != C.getTypeSize(Type)) {
8805 if (NewSize < C.getTypeSize(Type)) {
8806 assert(NewSize == 64 && "incorrect loop var size");
8807 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8808 << InitSrcRange << ConditionSrcRange;
8809 }
8810 QualType NewType = C.getIntTypeForBitwidth(
8812 C.getTypeSize(Type) < NewSize);
8813 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8814 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8816 /*AllowExplicit=*/true);
8817 if (!Diff.isUsable())
8818 return nullptr;
8819 }
8820 }
8821 }
8822
8823 return Diff.get();
8824}
8825
8826std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8827 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8828 // Do not build for iterators, they cannot be used in non-rectangular loop
8829 // nests.
8830 if (LCDecl->getType()->isRecordType())
8831 return std::make_pair(nullptr, nullptr);
8832 // If we subtract, the min is in the condition, otherwise the min is in the
8833 // init value.
8834 Expr *MinExpr = nullptr;
8835 Expr *MaxExpr = nullptr;
8836 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8837 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8838 bool LBNonRect =
8839 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8840 bool UBNonRect =
8841 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8842 Expr *Lower =
8843 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8844 Expr *Upper =
8845 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8846 if (!Upper || !Lower)
8847 return std::make_pair(nullptr, nullptr);
8848
8849 if (*TestIsLessOp)
8850 MinExpr = Lower;
8851 else
8852 MaxExpr = Upper;
8853
8854 // Build minimum/maximum value based on number of iterations.
8855 QualType VarType = LCDecl->getType().getNonReferenceType();
8856
8857 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8858 Step, VarType, TestIsStrictOp,
8859 /*RoundToStep=*/false, Captures);
8860 if (!Diff.isUsable())
8861 return std::make_pair(nullptr, nullptr);
8862
8863 // ((Upper - Lower [- 1]) / Step) * Step
8864 // Parentheses (for dumping/debugging purposes only).
8865 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8866 if (!Diff.isUsable())
8867 return std::make_pair(nullptr, nullptr);
8868
8869 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8870 if (!NewStep.isUsable())
8871 return std::make_pair(nullptr, nullptr);
8872 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8873 if (!Diff.isUsable())
8874 return std::make_pair(nullptr, nullptr);
8875
8876 // Parentheses (for dumping/debugging purposes only).
8877 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8878 if (!Diff.isUsable())
8879 return std::make_pair(nullptr, nullptr);
8880
8881 // Convert to the ptrdiff_t, if original type is pointer.
8882 if (VarType->isAnyPointerType() &&
8883 !SemaRef.Context.hasSameType(
8884 Diff.get()->getType(),
8886 Diff = SemaRef.PerformImplicitConversion(
8887 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8888 AssignmentAction::Converting, /*AllowExplicit=*/true);
8889 }
8890 if (!Diff.isUsable())
8891 return std::make_pair(nullptr, nullptr);
8892
8893 if (*TestIsLessOp) {
8894 // MinExpr = Lower;
8895 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8896 Diff = SemaRef.BuildBinOp(
8897 S, DefaultLoc, BO_Add,
8898 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8899 Diff.get());
8900 if (!Diff.isUsable())
8901 return std::make_pair(nullptr, nullptr);
8902 } else {
8903 // MaxExpr = Upper;
8904 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8905 Diff = SemaRef.BuildBinOp(
8906 S, DefaultLoc, BO_Sub,
8907 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8908 Diff.get());
8909 if (!Diff.isUsable())
8910 return std::make_pair(nullptr, nullptr);
8911 }
8912
8913 // Convert to the original type.
8914 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8915 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8917 /*AllowExplicit=*/true);
8918 if (!Diff.isUsable())
8919 return std::make_pair(nullptr, nullptr);
8920
8921 Sema::TentativeAnalysisScope Trap(SemaRef);
8922 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8923 if (!Diff.isUsable())
8924 return std::make_pair(nullptr, nullptr);
8925
8926 if (*TestIsLessOp)
8927 MaxExpr = Diff.get();
8928 else
8929 MinExpr = Diff.get();
8930
8931 return std::make_pair(MinExpr, MaxExpr);
8932}
8933
8934Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8935 if (InitDependOnLC || CondDependOnLC)
8936 return Condition;
8937 return nullptr;
8938}
8939
8940Expr *OpenMPIterationSpaceChecker::buildPreCond(
8941 Scope *S, Expr *Cond,
8942 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8943 // Do not build a precondition when the condition/initialization is dependent
8944 // to prevent pessimistic early loop exit.
8945 // TODO: this can be improved by calculating min/max values but not sure that
8946 // it will be very effective.
8947 if (CondDependOnLC || InitDependOnLC)
8948 return SemaRef
8950 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8951 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
8952 /*AllowExplicit=*/true)
8953 .get();
8954
8955 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8956 Sema::TentativeAnalysisScope Trap(SemaRef);
8957
8958 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8959 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8960 if (!NewLB.isUsable() || !NewUB.isUsable())
8961 return nullptr;
8962
8963 ExprResult CondExpr =
8964 SemaRef.BuildBinOp(S, DefaultLoc,
8965 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8966 : (TestIsStrictOp ? BO_GT : BO_GE),
8967 NewLB.get(), NewUB.get());
8968 if (CondExpr.isUsable()) {
8969 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8970 SemaRef.Context.BoolTy))
8971 CondExpr = SemaRef.PerformImplicitConversion(
8972 CondExpr.get(), SemaRef.Context.BoolTy,
8973 /*Action=*/AssignmentAction::Casting,
8974 /*AllowExplicit=*/true);
8975 }
8976
8977 // Otherwise use original loop condition and evaluate it in runtime.
8978 return CondExpr.isUsable() ? CondExpr.get() : Cond;
8979}
8980
8981/// Build reference expression to the counter be used for codegen.
8982DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8983 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8984 DSAStackTy &DSA) const {
8985 auto *VD = dyn_cast<VarDecl>(LCDecl);
8986 if (!VD) {
8987 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
8989 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
8990 const DSAStackTy::DSAVarData Data =
8991 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
8992 // If the loop control decl is explicitly marked as private, do not mark it
8993 // as captured again.
8994 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
8995 Captures.insert(std::make_pair(LCRef, Ref));
8996 return Ref;
8997 }
8998 return cast<DeclRefExpr>(LCRef);
8999}
9000
9001Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9002 if (LCDecl && !LCDecl->isInvalidDecl()) {
9004 VarDecl *PrivateVar = buildVarDecl(
9005 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9006 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9007 isa<VarDecl>(LCDecl)
9008 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9009 : nullptr);
9010 if (PrivateVar->isInvalidDecl())
9011 return nullptr;
9012 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9013 }
9014 return nullptr;
9015}
9016
9017/// Build initialization of the counter to be used for codegen.
9018Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9019
9020/// Build step of the counter be used for codegen.
9021Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9022
9023Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9024 Scope *S, Expr *Counter,
9025 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9026 Expr *Inc, OverloadedOperatorKind OOK) {
9027 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9028 if (!Cnt)
9029 return nullptr;
9030 if (Inc) {
9031 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9032 "Expected only + or - operations for depend clauses.");
9033 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9034 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9035 if (!Cnt)
9036 return nullptr;
9037 }
9038 QualType VarType = LCDecl->getType().getNonReferenceType();
9039 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9040 !SemaRef.getLangOpts().CPlusPlus)
9041 return nullptr;
9042 // Upper - Lower
9043 Expr *Upper =
9044 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9045 Expr *Lower =
9046 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9047 if (!Upper || !Lower)
9048 return nullptr;
9049
9050 ExprResult Diff = calculateNumIters(
9051 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9052 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9053 if (!Diff.isUsable())
9054 return nullptr;
9055
9056 return Diff.get();
9057}
9058} // namespace
9059
9061 Stmt *Init) {
9062 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9063 assert(Init && "Expected loop in canonical form.");
9064 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9065 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9066 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9067 return;
9068
9069 DSAStack->loopStart();
9071 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9072 *DSAStack, ForLoc, EmptyDeclSet);
9073 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9074 if (ValueDecl *D = ISC.getLoopDecl()) {
9075 auto *VD = dyn_cast<VarDecl>(D);
9076 DeclRefExpr *PrivateRef = nullptr;
9077 if (!VD) {
9079 VD = Private;
9080 } else {
9081 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9082 /*WithInit=*/false);
9083 VD = cast<VarDecl>(PrivateRef->getDecl());
9084 }
9085 }
9086 DSAStack->addLoopControlVariable(D, VD);
9087 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9088 if (LD != D->getCanonicalDecl()) {
9089 DSAStack->resetPossibleLoopCounter();
9090 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9092 SemaRef, const_cast<VarDecl *>(Var),
9093 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9094 /*RefersToCapture=*/true));
9095 }
9096 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9097 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9098 // associated for-loop of a simd construct with just one associated
9099 // for-loop may be listed in a linear clause with a constant-linear-step
9100 // that is the increment of the associated for-loop. The loop iteration
9101 // variable(s) in the associated for-loop(s) of a for or parallel for
9102 // construct may be listed in a private or lastprivate clause.
9103 DSAStackTy::DSAVarData DVar =
9104 DSAStack->getTopDSA(D, /*FromParent=*/false);
9105 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9106 // is declared in the loop and it is predetermined as a private.
9107 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9108 OpenMPClauseKind PredeterminedCKind =
9110 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9111 : OMPC_private;
9112 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9113 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9114 };
9115 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9116 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9117 (getLangOpts().OpenMP <= 45 ||
9118 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9120 IsOpenMPTaskloopDirective(DKind) ||
9122 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9123 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9124 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9125 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9126 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9127 << getOpenMPClauseName(PredeterminedCKind);
9128 if (DVar.RefExpr == nullptr)
9129 DVar.CKind = PredeterminedCKind;
9130 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9131 } else if (LoopDeclRefExpr) {
9132 // Make the loop iteration variable private (for worksharing
9133 // constructs), linear (for simd directives with the only one
9134 // associated loop) or lastprivate (for simd directives with several
9135 // collapsed or ordered loops).
9136 if (DVar.CKind == OMPC_unknown)
9137 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9138 }
9139 }
9140 }
9141 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9142}
9143
9144namespace {
9145// Utility for OpenMP doacross clause kind
9146class OMPDoacrossKind {
9147public:
9148 bool isSource(const OMPDoacrossClause *C) {
9149 return C->getDependenceType() == OMPC_DOACROSS_source ||
9150 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9151 }
9152 bool isSink(const OMPDoacrossClause *C) {
9153 return C->getDependenceType() == OMPC_DOACROSS_sink;
9154 }
9155 bool isSinkIter(const OMPDoacrossClause *C) {
9156 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9157 }
9158};
9159} // namespace
9160/// Called on a for stmt to check and extract its iteration space
9161/// for further processing (such as collapsing).
9163 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9164 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9165 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9166 Expr *OrderedLoopCountExpr,
9167 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9169 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9170 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9171 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9172 // OpenMP [2.9.1, Canonical Loop Form]
9173 // for (init-expr; test-expr; incr-expr) structured-block
9174 // for (range-decl: range-expr) structured-block
9175 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9176 S = CanonLoop->getLoopStmt();
9177 auto *For = dyn_cast_or_null<ForStmt>(S);
9178 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9179 // Ranged for is supported only in OpenMP 5.0.
9180 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9181 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9182 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9183 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9184 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9185 if (TotalNestedLoopCount > 1) {
9186 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9187 SemaRef.Diag(DSA.getConstructLoc(),
9188 diag::note_omp_collapse_ordered_expr)
9189 << 2 << CollapseLoopCountExpr->getSourceRange()
9190 << OrderedLoopCountExpr->getSourceRange();
9191 else if (CollapseLoopCountExpr)
9192 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9193 diag::note_omp_collapse_ordered_expr)
9194 << 0 << CollapseLoopCountExpr->getSourceRange();
9195 else if (OrderedLoopCountExpr)
9196 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9197 diag::note_omp_collapse_ordered_expr)
9198 << 1 << OrderedLoopCountExpr->getSourceRange();
9199 }
9200 return true;
9201 }
9202 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9203 "No loop body.");
9204 // Postpone analysis in dependent contexts for ranged for loops.
9205 if (CXXFor && SemaRef.CurContext->isDependentContext())
9206 return false;
9207
9208 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9209 For ? For->getForLoc() : CXXFor->getForLoc(),
9210 CollapsedLoopVarDecls);
9211
9212 // Check init.
9213 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9214 if (ISC.checkAndSetInit(Init))
9215 return true;
9216
9217 bool HasErrors = false;
9218
9219 // Check loop variable's type.
9220 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9221 // OpenMP [2.6, Canonical Loop Form]
9222 // Var is one of the following:
9223 // A variable of signed or unsigned integer type.
9224 // For C++, a variable of a random access iterator type.
9225 // For C, a variable of a pointer type.
9226 QualType VarType = LCDecl->getType().getNonReferenceType();
9227 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9228 !VarType->isPointerType() &&
9229 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9230 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9231 << SemaRef.getLangOpts().CPlusPlus;
9232 HasErrors = true;
9233 }
9234
9235 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9236 // a Construct
9237 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9238 // parallel for construct is (are) private.
9239 // The loop iteration variable in the associated for-loop of a simd
9240 // construct with just one associated for-loop is linear with a
9241 // constant-linear-step that is the increment of the associated for-loop.
9242 // Exclude loop var from the list of variables with implicitly defined data
9243 // sharing attributes.
9244 VarsWithImplicitDSA.erase(LCDecl);
9245
9246 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9247
9248 // Check test-expr.
9249 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9250
9251 // Check incr-expr.
9252 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9253 }
9254
9255 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9256 return HasErrors;
9257
9258 // Build the loop's iteration space representation.
9259 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9260 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9261 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9262 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9268 Captures);
9269 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9270 ISC.buildCounterVar(Captures, DSA);
9271 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9272 ISC.buildPrivateCounterVar();
9273 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9274 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9275 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9276 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9277 ISC.getConditionSrcRange();
9278 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9279 ISC.getIncrementSrcRange();
9280 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9281 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9282 ISC.isStrictTestOp();
9283 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9284 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9285 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9286 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9287 ISC.buildFinalCondition(DSA.getCurScope());
9288 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9289 ISC.doesInitDependOnLC();
9290 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9291 ISC.doesCondDependOnLC();
9292 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9293 ISC.getLoopDependentIdx();
9294
9295 HasErrors |=
9296 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9297 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9298 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9299 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9300 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9301 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9302 if (!HasErrors && DSA.isOrderedRegion()) {
9303 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9304 if (CurrentNestedLoopCount <
9305 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9306 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9307 CurrentNestedLoopCount,
9308 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9309 DSA.getOrderedRegionParam().second->setLoopCounter(
9310 CurrentNestedLoopCount,
9311 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9312 }
9313 }
9314 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9315 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9316 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9317 unsigned NumLoops =
9318 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9319 if (CurrentNestedLoopCount >= NumLoops) {
9320 // Erroneous case - clause has some problems.
9321 continue;
9322 }
9323 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9324 Pair.second.size() <= CurrentNestedLoopCount) {
9325 // Erroneous case - clause has some problems.
9326 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9327 continue;
9328 }
9329 OMPDoacrossKind ODK;
9330 if (DoacrossC && ODK.isSink(DoacrossC) &&
9331 Pair.second.size() <= CurrentNestedLoopCount) {
9332 // Erroneous case - clause has some problems.
9333 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9334 continue;
9335 }
9336 Expr *CntValue;
9337 SourceLocation DepLoc =
9338 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9339 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9340 (DoacrossC && ODK.isSource(DoacrossC)))
9341 CntValue = ISC.buildOrderedLoopData(
9342 DSA.getCurScope(),
9343 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9344 DepLoc);
9345 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9346 Expr *Cnt = SemaRef
9348 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9349 .get();
9350 if (!Cnt)
9351 continue;
9352 // build CounterVar - 1
9353 Expr *Inc =
9354 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9355 .get();
9356 CntValue = ISC.buildOrderedLoopData(
9357 DSA.getCurScope(),
9358 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9359 DepLoc, Inc, clang::OO_Minus);
9360 } else
9361 CntValue = ISC.buildOrderedLoopData(
9362 DSA.getCurScope(),
9363 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9364 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9365 Pair.second[CurrentNestedLoopCount].second);
9366 if (DependC)
9367 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9368 else
9369 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9370 }
9371 }
9372
9373 return HasErrors;
9374}
9375
9376/// Build 'VarRef = Start.
9377static ExprResult
9379 ExprResult Start, bool IsNonRectangularLB,
9380 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9381 // Build 'VarRef = Start.
9382 ExprResult NewStart = IsNonRectangularLB
9383 ? Start.get()
9384 : tryBuildCapture(SemaRef, Start.get(), Captures);
9385 if (!NewStart.isUsable())
9386 return ExprError();
9387 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9388 VarRef.get()->getType())) {
9389 NewStart = SemaRef.PerformImplicitConversion(
9390 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9391 /*AllowExplicit=*/true);
9392 if (!NewStart.isUsable())
9393 return ExprError();
9394 }
9395
9397 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9398 return Init;
9399}
9400
9401/// Build 'VarRef = Start + Iter * Step'.
9403 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9404 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9405 bool IsNonRectangularLB,
9406 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9407 // Add parentheses (for debugging purposes only).
9408 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9409 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9410 !Step.isUsable())
9411 return ExprError();
9412
9413 ExprResult NewStep = Step;
9414 if (Captures)
9415 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9416 if (NewStep.isInvalid())
9417 return ExprError();
9419 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9420 if (!Update.isUsable())
9421 return ExprError();
9422
9423 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9424 // 'VarRef = Start (+|-) Iter * Step'.
9425 if (!Start.isUsable())
9426 return ExprError();
9427 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9428 if (!NewStart.isUsable())
9429 return ExprError();
9430 if (Captures && !IsNonRectangularLB)
9431 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9432 if (NewStart.isInvalid())
9433 return ExprError();
9434
9435 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9436 ExprResult SavedUpdate = Update;
9437 ExprResult UpdateVal;
9438 if (VarRef.get()->getType()->isOverloadableType() ||
9439 NewStart.get()->getType()->isOverloadableType() ||
9440 Update.get()->getType()->isOverloadableType()) {
9441 Sema::TentativeAnalysisScope Trap(SemaRef);
9442
9443 Update =
9444 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9445 if (Update.isUsable()) {
9446 UpdateVal =
9447 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9448 VarRef.get(), SavedUpdate.get());
9449 if (UpdateVal.isUsable()) {
9450 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9451 UpdateVal.get());
9452 }
9453 }
9454 }
9455
9456 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9457 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9458 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9459 NewStart.get(), SavedUpdate.get());
9460 if (!Update.isUsable())
9461 return ExprError();
9462
9463 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9464 VarRef.get()->getType())) {
9466 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9467 /*AllowExplicit=*/true);
9468 if (!Update.isUsable())
9469 return ExprError();
9470 }
9471
9472 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9473 }
9474 return Update;
9475}
9476
9477/// Convert integer expression \a E to make it have at least \a Bits
9478/// bits.
9479static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9480 if (E == nullptr)
9481 return ExprError();
9482 ASTContext &C = SemaRef.Context;
9483 QualType OldType = E->getType();
9484 unsigned HasBits = C.getTypeSize(OldType);
9485 if (HasBits >= Bits)
9486 return ExprResult(E);
9487 // OK to convert to signed, because new type has more bits than old.
9488 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9489 return SemaRef.PerformImplicitConversion(
9490 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9491}
9492
9493/// Check if the given expression \a E is a constant integer that fits
9494/// into \a Bits bits.
9495static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9496 if (E == nullptr)
9497 return false;
9498 if (std::optional<llvm::APSInt> Result =
9500 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9501 return false;
9502}
9503
9504/// Build preinits statement for the given declarations.
9506 MutableArrayRef<Decl *> PreInits) {
9507 if (!PreInits.empty()) {
9508 return new (Context) DeclStmt(
9509 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9511 }
9512 return nullptr;
9513}
9514
9515/// Append the \p Item or the content of a CompoundStmt to the list \p
9516/// TargetList.
9517///
9518/// A CompoundStmt is used as container in case multiple statements need to be
9519/// stored in lieu of using an explicit list. Flattening is necessary because
9520/// contained DeclStmts need to be visible after the execution of the list. Used
9521/// for OpenMP pre-init declarations/statements.
9523 Stmt *Item) {
9524 // nullptr represents an empty list.
9525 if (!Item)
9526 return;
9527
9528 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9529 llvm::append_range(TargetList, CS->body());
9530 else
9531 TargetList.push_back(Item);
9532}
9533
9534/// Build preinits statement for the given declarations.
9535static Stmt *
9537 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9538 if (!Captures.empty()) {
9539 SmallVector<Decl *, 16> PreInits;
9540 for (const auto &Pair : Captures)
9541 PreInits.push_back(Pair.second->getDecl());
9542 return buildPreInits(Context, PreInits);
9543 }
9544 return nullptr;
9545}
9546
9547/// Build pre-init statement for the given statements.
9548static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9549 if (PreInits.empty())
9550 return nullptr;
9551
9552 SmallVector<Stmt *> Stmts;
9553 for (Stmt *S : PreInits)
9554 appendFlattenedStmtList(Stmts, S);
9555 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9556}
9557
9558/// Build postupdate expression for the given list of postupdates expressions.
9559static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9560 Expr *PostUpdate = nullptr;
9561 if (!PostUpdates.empty()) {
9562 for (Expr *E : PostUpdates) {
9563 Expr *ConvE = S.BuildCStyleCastExpr(
9564 E->getExprLoc(),
9566 E->getExprLoc(), E)
9567 .get();
9568 PostUpdate = PostUpdate
9569 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9570 PostUpdate, ConvE)
9571 .get()
9572 : ConvE;
9573 }
9574 }
9575 return PostUpdate;
9576}
9577
9578/// Look for variables declared in the body parts of a for-loop nest. Used
9579/// for verifying loop nest structure before performing a loop collapse
9580/// operation.
9582 int NestingDepth = 0;
9583 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9584
9585public:
9586 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9587 : VarDecls(VD) {}
9588
9589 bool VisitForStmt(ForStmt *F) override {
9590 ++NestingDepth;
9591 TraverseStmt(F->getBody());
9592 --NestingDepth;
9593 return false;
9594 }
9595
9597 ++NestingDepth;
9598 TraverseStmt(RF->getBody());
9599 --NestingDepth;
9600 return false;
9601 }
9602
9603 bool VisitVarDecl(VarDecl *D) override {
9604 Decl *C = D->getCanonicalDecl();
9605 if (NestingDepth > 0)
9606 VarDecls.insert(C);
9607 return true;
9608 }
9609};
9610
9611/// Called on a for stmt to check itself and nested loops (if any).
9612/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9613/// number of collapsed loops otherwise.
9614static unsigned
9615checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9616 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9617 DSAStackTy &DSA,
9618 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9620 unsigned NestedLoopCount = 1;
9621 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9623 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9624
9625 if (CollapseLoopCountExpr) {
9626 // Found 'collapse' clause - calculate collapse number.
9628 if (!CollapseLoopCountExpr->isValueDependent() &&
9629 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9630 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9631
9632 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9633 FVDF.TraverseStmt(AStmt);
9634 } else {
9635 Built.clear(/*Size=*/1);
9636 return 1;
9637 }
9638 }
9639 unsigned OrderedLoopCount = 1;
9640 if (OrderedLoopCountExpr) {
9641 // Found 'ordered' clause - calculate collapse number.
9642 Expr::EvalResult EVResult;
9643 if (!OrderedLoopCountExpr->isValueDependent() &&
9644 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9645 SemaRef.getASTContext())) {
9646 llvm::APSInt Result = EVResult.Val.getInt();
9647 if (Result.getLimitedValue() < NestedLoopCount) {
9648 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9649 diag::err_omp_wrong_ordered_loop_count)
9650 << OrderedLoopCountExpr->getSourceRange();
9651 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9652 diag::note_collapse_loop_count)
9653 << CollapseLoopCountExpr->getSourceRange();
9654 }
9655 OrderedLoopCount = Result.getLimitedValue();
9656 } else {
9657 Built.clear(/*Size=*/1);
9658 return 1;
9659 }
9660 }
9661 // This is helper routine for loop directives (e.g., 'for', 'simd',
9662 // 'for simd', etc.).
9663 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9664 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9665 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9668 SupportsNonPerfectlyNested, NumLoops,
9669 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9670 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9671 &IterSpaces, &Captures,
9672 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9674 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9675 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9676 VarsWithImplicitDSA, IterSpaces, Captures,
9677 CollapsedLoopVarDecls))
9678 return true;
9679 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9680 IterSpaces[Cnt].CounterVar) {
9681 // Handle initialization of captured loop iterator variables.
9682 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9683 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9684 Captures[DRE] = DRE;
9685 }
9686 }
9687 return false;
9688 },
9689 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9690 Stmt *DependentPreInits = Transform->getPreInits();
9691 if (!DependentPreInits)
9692 return;
9693
9694 // Search for pre-init declared variables that need to be captured
9695 // to be referenceable inside the directive.
9696 SmallVector<Stmt *> Constituents;
9697 appendFlattenedStmtList(Constituents, DependentPreInits);
9698 for (Stmt *S : Constituents) {
9699 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9700 for (Decl *C : DC->decls()) {
9701 auto *D = cast<VarDecl>(C);
9703 SemaRef, D, D->getType().getNonReferenceType(),
9704 Transform->getBeginLoc());
9705 Captures[Ref] = Ref;
9706 }
9707 }
9708 }
9709 }))
9710 return 0;
9711
9712 Built.clear(/*size=*/NestedLoopCount);
9713
9714 if (SemaRef.CurContext->isDependentContext())
9715 return NestedLoopCount;
9716
9717 // An example of what is generated for the following code:
9718 //
9719 // #pragma omp simd collapse(2) ordered(2)
9720 // for (i = 0; i < NI; ++i)
9721 // for (k = 0; k < NK; ++k)
9722 // for (j = J0; j < NJ; j+=2) {
9723 // <loop body>
9724 // }
9725 //
9726 // We generate the code below.
9727 // Note: the loop body may be outlined in CodeGen.
9728 // Note: some counters may be C++ classes, operator- is used to find number of
9729 // iterations and operator+= to calculate counter value.
9730 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9731 // or i64 is currently supported).
9732 //
9733 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9734 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9735 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9736 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9737 // // similar updates for vars in clauses (e.g. 'linear')
9738 // <loop body (using local i and j)>
9739 // }
9740 // i = NI; // assign final values of counters
9741 // j = NJ;
9742 //
9743
9744 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9745 // the iteration counts of the collapsed for loops.
9746 // Precondition tests if there is at least one iteration (all conditions are
9747 // true).
9748 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9749 Expr *N0 = IterSpaces[0].NumIterations;
9750 ExprResult LastIteration32 = widenIterationCount(
9751 /*Bits=*/32,
9752 SemaRef
9753 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9755 /*AllowExplicit=*/true)
9756 .get(),
9757 SemaRef);
9758 ExprResult LastIteration64 = widenIterationCount(
9759 /*Bits=*/64,
9760 SemaRef
9761 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9763 /*AllowExplicit=*/true)
9764 .get(),
9765 SemaRef);
9766
9767 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9768 return NestedLoopCount;
9769
9770 ASTContext &C = SemaRef.Context;
9771 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9772
9773 Scope *CurScope = DSA.getCurScope();
9774 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9775 if (PreCond.isUsable()) {
9776 PreCond =
9777 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9778 PreCond.get(), IterSpaces[Cnt].PreCond);
9779 }
9780 Expr *N = IterSpaces[Cnt].NumIterations;
9782 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9783 if (LastIteration32.isUsable())
9784 LastIteration32 = SemaRef.BuildBinOp(
9785 CurScope, Loc, BO_Mul, LastIteration32.get(),
9786 SemaRef
9789 /*AllowExplicit=*/true)
9790 .get());
9791 if (LastIteration64.isUsable())
9792 LastIteration64 = SemaRef.BuildBinOp(
9793 CurScope, Loc, BO_Mul, LastIteration64.get(),
9794 SemaRef
9797 /*AllowExplicit=*/true)
9798 .get());
9799 }
9800
9801 // Choose either the 32-bit or 64-bit version.
9802 ExprResult LastIteration = LastIteration64;
9803 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9804 (LastIteration32.isUsable() &&
9805 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9806 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9807 fitsInto(
9808 /*Bits=*/32,
9809 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9810 LastIteration64.get(), SemaRef))))
9811 LastIteration = LastIteration32;
9812 QualType VType = LastIteration.get()->getType();
9813 QualType RealVType = VType;
9814 QualType StrideVType = VType;
9815 if (isOpenMPTaskLoopDirective(DKind)) {
9816 VType =
9817 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9818 StrideVType =
9819 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9820 }
9821
9822 if (!LastIteration.isUsable())
9823 return 0;
9824
9825 // Save the number of iterations.
9826 ExprResult NumIterations = LastIteration;
9827 {
9828 LastIteration = SemaRef.BuildBinOp(
9829 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9830 LastIteration.get(),
9831 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9832 if (!LastIteration.isUsable())
9833 return 0;
9834 }
9835
9836 // Calculate the last iteration number beforehand instead of doing this on
9837 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9838 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9839 ExprResult CalcLastIteration;
9840 if (!IsConstant) {
9841 ExprResult SaveRef =
9842 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9843 LastIteration = SaveRef;
9844
9845 // Prepare SaveRef + 1.
9846 NumIterations = SemaRef.BuildBinOp(
9847 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9848 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9849 if (!NumIterations.isUsable())
9850 return 0;
9851 }
9852
9853 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9854
9855 // Build variables passed into runtime, necessary for worksharing directives.
9856 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9861 // Lower bound variable, initialized with zero.
9862 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9863 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9864 SemaRef.AddInitializerToDecl(LBDecl,
9865 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9866 /*DirectInit=*/false);
9867
9868 // Upper bound variable, initialized with last iteration number.
9869 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9870 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9871 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9872 /*DirectInit=*/false);
9873
9874 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9875 // This will be used to implement clause 'lastprivate'.
9876 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9877 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9878 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9879 SemaRef.AddInitializerToDecl(ILDecl,
9880 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9881 /*DirectInit=*/false);
9882
9883 // Stride variable returned by runtime (we initialize it to 1 by default).
9884 VarDecl *STDecl =
9885 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9886 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9887 SemaRef.AddInitializerToDecl(STDecl,
9888 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9889 /*DirectInit=*/false);
9890
9891 // Build expression: UB = min(UB, LastIteration)
9892 // It is necessary for CodeGen of directives with static scheduling.
9893 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9894 UB.get(), LastIteration.get());
9895 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9896 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9897 LastIteration.get(), UB.get());
9898 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9899 CondOp.get());
9900 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
9901
9902 // If we have a combined directive that combines 'distribute', 'for' or
9903 // 'simd' we need to be able to access the bounds of the schedule of the
9904 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9905 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9907 // Lower bound variable, initialized with zero.
9908 VarDecl *CombLBDecl =
9909 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9910 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9911 SemaRef.AddInitializerToDecl(
9912 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9913 /*DirectInit=*/false);
9914
9915 // Upper bound variable, initialized with last iteration number.
9916 VarDecl *CombUBDecl =
9917 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9918 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9919 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9920 /*DirectInit=*/false);
9921
9922 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9923 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9924 ExprResult CombCondOp =
9925 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9926 LastIteration.get(), CombUB.get());
9927 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9928 CombCondOp.get());
9929 CombEUB =
9930 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
9931
9932 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9933 // We expect to have at least 2 more parameters than the 'parallel'
9934 // directive does - the lower and upper bounds of the previous schedule.
9935 assert(CD->getNumParams() >= 4 &&
9936 "Unexpected number of parameters in loop combined directive");
9937
9938 // Set the proper type for the bounds given what we learned from the
9939 // enclosed loops.
9940 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9941 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9942
9943 // Previous lower and upper bounds are obtained from the region
9944 // parameters.
9945 PrevLB =
9946 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9947 PrevUB =
9948 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9949 }
9950 }
9951
9952 // Build the iteration variable and its initialization before loop.
9953 ExprResult IV;
9954 ExprResult Init, CombInit;
9955 {
9956 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9957 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9958 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9963 ? LB.get()
9964 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9965 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9966 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
9967
9969 Expr *CombRHS =
9974 ? CombLB.get()
9975 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9976 CombInit =
9977 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9978 CombInit =
9979 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
9980 }
9981 }
9982
9983 bool UseStrictCompare =
9984 RealVType->hasUnsignedIntegerRepresentation() &&
9985 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9986 return LIS.IsStrictCompare;
9987 });
9988 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9989 // unsigned IV)) for worksharing loops.
9990 SourceLocation CondLoc = AStmt->getBeginLoc();
9991 Expr *BoundUB = UB.get();
9992 if (UseStrictCompare) {
9993 BoundUB =
9994 SemaRef
9995 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9996 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9997 .get();
9998 BoundUB =
9999 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10000 }
10001 ExprResult Cond =
10006 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10007 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10008 BoundUB)
10009 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10010 NumIterations.get());
10011 ExprResult CombDistCond;
10013 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10014 NumIterations.get());
10015 }
10016
10017 ExprResult CombCond;
10019 Expr *BoundCombUB = CombUB.get();
10020 if (UseStrictCompare) {
10021 BoundCombUB =
10022 SemaRef
10023 .BuildBinOp(
10024 CurScope, CondLoc, BO_Add, BoundCombUB,
10025 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10026 .get();
10027 BoundCombUB =
10028 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10029 .get();
10030 }
10031 CombCond =
10032 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10033 IV.get(), BoundCombUB);
10034 }
10035 // Loop increment (IV = IV + 1)
10036 SourceLocation IncLoc = AStmt->getBeginLoc();
10037 ExprResult Inc =
10038 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10039 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10040 if (!Inc.isUsable())
10041 return 0;
10042 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10043 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10044 if (!Inc.isUsable())
10045 return 0;
10046
10047 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10048 // Used for directives with static scheduling.
10049 // In combined construct, add combined version that use CombLB and CombUB
10050 // base variables for the update
10051 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10056 // LB + ST
10057 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10058 if (!NextLB.isUsable())
10059 return 0;
10060 // LB = LB + ST
10061 NextLB =
10062 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10063 NextLB =
10064 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10065 if (!NextLB.isUsable())
10066 return 0;
10067 // UB + ST
10068 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10069 if (!NextUB.isUsable())
10070 return 0;
10071 // UB = UB + ST
10072 NextUB =
10073 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10074 NextUB =
10075 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10076 if (!NextUB.isUsable())
10077 return 0;
10079 CombNextLB =
10080 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10081 if (!NextLB.isUsable())
10082 return 0;
10083 // LB = LB + ST
10084 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10085 CombNextLB.get());
10086 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10087 /*DiscardedValue=*/false);
10088 if (!CombNextLB.isUsable())
10089 return 0;
10090 // UB + ST
10091 CombNextUB =
10092 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10093 if (!CombNextUB.isUsable())
10094 return 0;
10095 // UB = UB + ST
10096 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10097 CombNextUB.get());
10098 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10099 /*DiscardedValue=*/false);
10100 if (!CombNextUB.isUsable())
10101 return 0;
10102 }
10103 }
10104
10105 // Create increment expression for distribute loop when combined in a same
10106 // directive with for as IV = IV + ST; ensure upper bound expression based
10107 // on PrevUB instead of NumIterations - used to implement 'for' when found
10108 // in combination with 'distribute', like in 'distribute parallel for'
10109 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10110 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10112 DistCond = SemaRef.BuildBinOp(
10113 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10114 assert(DistCond.isUsable() && "distribute cond expr was not built");
10115
10116 DistInc =
10117 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10118 assert(DistInc.isUsable() && "distribute inc expr was not built");
10119 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10120 DistInc.get());
10121 DistInc =
10122 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10123 assert(DistInc.isUsable() && "distribute inc expr was not built");
10124
10125 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10126 // construct
10127 ExprResult NewPrevUB = PrevUB;
10128 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10129 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10130 PrevUB.get()->getType())) {
10131 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10132 DistEUBLoc,
10134 DistEUBLoc, NewPrevUB.get());
10135 if (!NewPrevUB.isUsable())
10136 return 0;
10137 }
10138 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10139 UB.get(), NewPrevUB.get());
10140 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10141 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10142 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10143 CondOp.get());
10144 PrevEUB =
10145 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10146
10147 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10148 // parallel for is in combination with a distribute directive with
10149 // schedule(static, 1)
10150 Expr *BoundPrevUB = PrevUB.get();
10151 if (UseStrictCompare) {
10152 BoundPrevUB =
10153 SemaRef
10154 .BuildBinOp(
10155 CurScope, CondLoc, BO_Add, BoundPrevUB,
10156 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10157 .get();
10158 BoundPrevUB =
10159 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10160 .get();
10161 }
10162 ParForInDistCond =
10163 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10164 IV.get(), BoundPrevUB);
10165 }
10166
10167 // Build updates and final values of the loop counters.
10168 bool HasErrors = false;
10169 Built.Counters.resize(NestedLoopCount);
10170 Built.Inits.resize(NestedLoopCount);
10171 Built.Updates.resize(NestedLoopCount);
10172 Built.Finals.resize(NestedLoopCount);
10173 Built.DependentCounters.resize(NestedLoopCount);
10174 Built.DependentInits.resize(NestedLoopCount);
10175 Built.FinalsConditions.resize(NestedLoopCount);
10176 {
10177 // We implement the following algorithm for obtaining the
10178 // original loop iteration variable values based on the
10179 // value of the collapsed loop iteration variable IV.
10180 //
10181 // Let n+1 be the number of collapsed loops in the nest.
10182 // Iteration variables (I0, I1, .... In)
10183 // Iteration counts (N0, N1, ... Nn)
10184 //
10185 // Acc = IV;
10186 //
10187 // To compute Ik for loop k, 0 <= k <= n, generate:
10188 // Prod = N(k+1) * N(k+2) * ... * Nn;
10189 // Ik = Acc / Prod;
10190 // Acc -= Ik * Prod;
10191 //
10192 ExprResult Acc = IV;
10193 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10194 LoopIterationSpace &IS = IterSpaces[Cnt];
10195 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10197
10198 // Compute prod
10199 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10200 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10201 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10202 IterSpaces[K].NumIterations);
10203
10204 // Iter = Acc / Prod
10205 // If there is at least one more inner loop to avoid
10206 // multiplication by 1.
10207 if (Cnt + 1 < NestedLoopCount)
10208 Iter =
10209 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10210 else
10211 Iter = Acc;
10212 if (!Iter.isUsable()) {
10213 HasErrors = true;
10214 break;
10215 }
10216
10217 // Update Acc:
10218 // Acc -= Iter * Prod
10219 // Check if there is at least one more inner loop to avoid
10220 // multiplication by 1.
10221 if (Cnt + 1 < NestedLoopCount)
10222 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10223 Prod.get());
10224 else
10225 Prod = Iter;
10226 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10227
10228 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10229 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10230 DeclRefExpr *CounterVar = buildDeclRefExpr(
10231 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10232 /*RefersToCapture=*/true);
10234 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10235 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10236 if (!Init.isUsable()) {
10237 HasErrors = true;
10238 break;
10239 }
10241 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10242 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10243 if (!Update.isUsable()) {
10244 HasErrors = true;
10245 break;
10246 }
10247
10248 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10249 ExprResult Final =
10250 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10251 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10252 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10253 if (!Final.isUsable()) {
10254 HasErrors = true;
10255 break;
10256 }
10257
10258 if (!Update.isUsable() || !Final.isUsable()) {
10259 HasErrors = true;
10260 break;
10261 }
10262 // Save results
10263 Built.Counters[Cnt] = IS.CounterVar;
10264 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10265 Built.Inits[Cnt] = Init.get();
10266 Built.Updates[Cnt] = Update.get();
10267 Built.Finals[Cnt] = Final.get();
10268 Built.DependentCounters[Cnt] = nullptr;
10269 Built.DependentInits[Cnt] = nullptr;
10270 Built.FinalsConditions[Cnt] = nullptr;
10271 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10272 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10273 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10274 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10275 }
10276 }
10277 }
10278
10279 if (HasErrors)
10280 return 0;
10281
10282 // Save results
10283 Built.IterationVarRef = IV.get();
10284 Built.LastIteration = LastIteration.get();
10285 Built.NumIterations = NumIterations.get();
10286 Built.CalcLastIteration = SemaRef
10287 .ActOnFinishFullExpr(CalcLastIteration.get(),
10288 /*DiscardedValue=*/false)
10289 .get();
10290 Built.PreCond = PreCond.get();
10291 Built.PreInits = buildPreInits(C, Captures);
10292 Built.Cond = Cond.get();
10293 Built.Init = Init.get();
10294 Built.Inc = Inc.get();
10295 Built.LB = LB.get();
10296 Built.UB = UB.get();
10297 Built.IL = IL.get();
10298 Built.ST = ST.get();
10299 Built.EUB = EUB.get();
10300 Built.NLB = NextLB.get();
10301 Built.NUB = NextUB.get();
10302 Built.PrevLB = PrevLB.get();
10303 Built.PrevUB = PrevUB.get();
10304 Built.DistInc = DistInc.get();
10305 Built.PrevEUB = PrevEUB.get();
10306 Built.DistCombinedFields.LB = CombLB.get();
10307 Built.DistCombinedFields.UB = CombUB.get();
10308 Built.DistCombinedFields.EUB = CombEUB.get();
10309 Built.DistCombinedFields.Init = CombInit.get();
10310 Built.DistCombinedFields.Cond = CombCond.get();
10311 Built.DistCombinedFields.NLB = CombNextLB.get();
10312 Built.DistCombinedFields.NUB = CombNextUB.get();
10313 Built.DistCombinedFields.DistCond = CombDistCond.get();
10314 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10315
10316 return NestedLoopCount;
10317}
10318
10320 auto CollapseClauses =
10321 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10322 if (CollapseClauses.begin() != CollapseClauses.end())
10323 return (*CollapseClauses.begin())->getNumForLoops();
10324 return nullptr;
10325}
10326
10328 auto OrderedClauses =
10329 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10330 if (OrderedClauses.begin() != OrderedClauses.end())
10331 return (*OrderedClauses.begin())->getNumForLoops();
10332 return nullptr;
10333}
10334
10336 const ArrayRef<OMPClause *> Clauses) {
10337 const OMPSafelenClause *Safelen = nullptr;
10338 const OMPSimdlenClause *Simdlen = nullptr;
10339
10340 for (const OMPClause *Clause : Clauses) {
10341 if (Clause->getClauseKind() == OMPC_safelen)
10342 Safelen = cast<OMPSafelenClause>(Clause);
10343 else if (Clause->getClauseKind() == OMPC_simdlen)
10344 Simdlen = cast<OMPSimdlenClause>(Clause);
10345 if (Safelen && Simdlen)
10346 break;
10347 }
10348
10349 if (Simdlen && Safelen) {
10350 const Expr *SimdlenLength = Simdlen->getSimdlen();
10351 const Expr *SafelenLength = Safelen->getSafelen();
10352 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10353 SimdlenLength->isInstantiationDependent() ||
10354 SimdlenLength->containsUnexpandedParameterPack())
10355 return false;
10356 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10357 SafelenLength->isInstantiationDependent() ||
10358 SafelenLength->containsUnexpandedParameterPack())
10359 return false;
10360 Expr::EvalResult SimdlenResult, SafelenResult;
10361 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10362 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10363 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10364 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10365 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10366 // If both simdlen and safelen clauses are specified, the value of the
10367 // simdlen parameter must be less than or equal to the value of the safelen
10368 // parameter.
10369 if (SimdlenRes > SafelenRes) {
10370 S.Diag(SimdlenLength->getExprLoc(),
10371 diag::err_omp_wrong_simdlen_safelen_values)
10372 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10373 return true;
10374 }
10375 }
10376 return false;
10377}
10378
10380 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10381 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10382 if (!AStmt)
10383 return StmtError();
10384
10385 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10386
10387 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10389 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10390 // define the nested loops number.
10391 unsigned NestedLoopCount = checkOpenMPLoop(
10392 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10393 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10394 if (NestedLoopCount == 0)
10395 return StmtError();
10396
10397 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10398 return StmtError();
10399
10401 return StmtError();
10402
10403 auto *SimdDirective = OMPSimdDirective::Create(
10404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10405 return SimdDirective;
10406}
10407
10409 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10410 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10411 if (!AStmt)
10412 return StmtError();
10413
10414 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10416 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10417 // define the nested loops number.
10418 unsigned NestedLoopCount = checkOpenMPLoop(
10419 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10420 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10421 if (NestedLoopCount == 0)
10422 return StmtError();
10423
10424 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10425 return StmtError();
10426
10427 auto *ForDirective = OMPForDirective::Create(
10428 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10429 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10430 return ForDirective;
10431}
10432
10434 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10435 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10436 if (!AStmt)
10437 return StmtError();
10438
10439 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10440
10441 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10443 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10444 // define the nested loops number.
10445 unsigned NestedLoopCount =
10446 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10447 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10448 VarsWithImplicitDSA, B);
10449 if (NestedLoopCount == 0)
10450 return StmtError();
10451
10452 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10453 return StmtError();
10454
10456 return StmtError();
10457
10458 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10459 NestedLoopCount, Clauses, AStmt, B);
10460}
10461
10463 Stmt *AStmt, DSAStackTy *Stack) {
10464 if (!AStmt)
10465 return true;
10466
10467 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10468 auto BaseStmt = AStmt;
10469 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10470 BaseStmt = CS->getCapturedStmt();
10471 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10472 auto S = C->children();
10473 if (S.begin() == S.end())
10474 return true;
10475 // All associated statements must be '#pragma omp section' except for
10476 // the first one.
10477 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10478 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10479 if (SectionStmt)
10480 SemaRef.Diag(SectionStmt->getBeginLoc(),
10481 diag::err_omp_sections_substmt_not_section)
10482 << getOpenMPDirectiveName(DKind);
10483 return true;
10484 }
10485 cast<OMPSectionDirective>(SectionStmt)
10486 ->setHasCancel(Stack->isCancelRegion());
10487 }
10488 } else {
10489 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10490 << getOpenMPDirectiveName(DKind);
10491 return true;
10492 }
10493 return false;
10494}
10495
10498 Stmt *AStmt, SourceLocation StartLoc,
10499 SourceLocation EndLoc) {
10500 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10501 return StmtError();
10502
10504
10506 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10507 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10508}
10509
10511 SourceLocation StartLoc,
10512 SourceLocation EndLoc) {
10513 if (!AStmt)
10514 return StmtError();
10515
10517 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10518
10519 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10520 DSAStack->isCancelRegion());
10521}
10522
10525 if (auto *CE = dyn_cast<CallExpr>(E))
10526 if (CE->getDirectCallee())
10527 return E;
10528 return nullptr;
10529}
10530
10533 Stmt *AStmt, SourceLocation StartLoc,
10534 SourceLocation EndLoc) {
10535 if (!AStmt)
10536 return StmtError();
10537
10538 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10539
10540 // 5.1 OpenMP
10541 // expression-stmt : an expression statement with one of the following forms:
10542 // expression = target-call ( [expression-list] );
10543 // target-call ( [expression-list] );
10544
10545 SourceLocation TargetCallLoc;
10546
10548 Expr *TargetCall = nullptr;
10549
10550 auto *E = dyn_cast<Expr>(S);
10551 if (!E) {
10552 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10553 return StmtError();
10554 }
10555
10557
10558 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10559 if (BO->getOpcode() == BO_Assign)
10560 TargetCall = getDirectCallExpr(BO->getRHS());
10561 } else {
10562 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10563 if (COCE->getOperator() == OO_Equal)
10564 TargetCall = getDirectCallExpr(COCE->getArg(1));
10565 if (!TargetCall)
10566 TargetCall = getDirectCallExpr(E);
10567 }
10568 if (!TargetCall) {
10569 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10570 return StmtError();
10571 }
10572 TargetCallLoc = TargetCall->getExprLoc();
10573 }
10574
10576
10577 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10578 Clauses, AStmt, TargetCallLoc);
10579}
10580
10583 DSAStackTy *Stack) {
10584 bool ErrorFound = false;
10585 for (OMPClause *C : Clauses) {
10586 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10587 for (Expr *RefExpr : LPC->varlist()) {
10588 SourceLocation ELoc;
10589 SourceRange ERange;
10590 Expr *SimpleRefExpr = RefExpr;
10591 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10592 if (ValueDecl *D = Res.first) {
10593 auto &&Info = Stack->isLoopControlVariable(D);
10594 if (!Info.first) {
10595 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10596 << getOpenMPDirectiveName(K);
10597 ErrorFound = true;
10598 }
10599 }
10600 }
10601 }
10602 }
10603 return ErrorFound;
10604}
10605
10607 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10608 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10609 if (!AStmt)
10610 return StmtError();
10611
10612 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10613 // A list item may not appear in a lastprivate clause unless it is the
10614 // loop iteration variable of a loop that is associated with the construct.
10615 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10616 return StmtError();
10617
10618 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10619
10621 // In presence of clause 'collapse', it will define the nested loops number.
10622 unsigned NestedLoopCount = checkOpenMPLoop(
10623 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10624 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10625 if (NestedLoopCount == 0)
10626 return StmtError();
10627
10628 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10629 "omp loop exprs were not built");
10630
10631 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10632 NestedLoopCount, Clauses, AStmt, B);
10633}
10634
10636 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10637 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10638 if (!AStmt)
10639 return StmtError();
10640
10641 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10642 // A list item may not appear in a lastprivate clause unless it is the
10643 // loop iteration variable of a loop that is associated with the construct.
10644 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10645 return StmtError();
10646
10647 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10648
10650 // In presence of clause 'collapse', it will define the nested loops number.
10651 unsigned NestedLoopCount =
10652 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10653 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10654 VarsWithImplicitDSA, B);
10655 if (NestedLoopCount == 0)
10656 return StmtError();
10657
10658 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10659 "omp loop exprs were not built");
10660
10661 DSAStack->setParentTeamsRegionLoc(StartLoc);
10662
10664 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10665}
10666
10668 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10669 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10670 if (!AStmt)
10671 return StmtError();
10672
10673 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10674 // A list item may not appear in a lastprivate clause unless it is the
10675 // loop iteration variable of a loop that is associated with the construct.
10676 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10677 DSAStack))
10678 return StmtError();
10679
10680 CapturedStmt *CS =
10681 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10682
10684 // In presence of clause 'collapse', it will define the nested loops number.
10685 unsigned NestedLoopCount =
10686 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10687 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10688 VarsWithImplicitDSA, B);
10689 if (NestedLoopCount == 0)
10690 return StmtError();
10691
10692 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10693 "omp loop exprs were not built");
10694
10696 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10698}
10699
10701 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10702 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10703 if (!AStmt)
10704 return StmtError();
10705
10706 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10707 // A list item may not appear in a lastprivate clause unless it is the
10708 // loop iteration variable of a loop that is associated with the construct.
10709 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10710 DSAStack))
10711 return StmtError();
10712
10713 CapturedStmt *CS =
10714 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10715
10717 // In presence of clause 'collapse', it will define the nested loops number.
10718 unsigned NestedLoopCount =
10719 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10720 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10721 VarsWithImplicitDSA, B);
10722 if (NestedLoopCount == 0)
10723 return StmtError();
10724
10725 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10726 "omp loop exprs were not built");
10727
10729 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10730}
10731
10733 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10734 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10735 if (!AStmt)
10736 return StmtError();
10737
10738 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10739 // A list item may not appear in a lastprivate clause unless it is the
10740 // loop iteration variable of a loop that is associated with the construct.
10741 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10742 DSAStack))
10743 return StmtError();
10744
10745 CapturedStmt *CS =
10746 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
10747
10749 // In presence of clause 'collapse', it will define the nested loops number.
10750 unsigned NestedLoopCount =
10751 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10752 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10753 VarsWithImplicitDSA, B);
10754 if (NestedLoopCount == 0)
10755 return StmtError();
10756
10757 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10758 "omp loop exprs were not built");
10759
10761 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10762}
10763
10765 Stmt *AStmt,
10766 SourceLocation StartLoc,
10767 SourceLocation EndLoc) {
10768 if (!AStmt)
10769 return StmtError();
10770
10771 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10772
10774
10775 // OpenMP [2.7.3, single Construct, Restrictions]
10776 // The copyprivate clause must not be used with the nowait clause.
10777 const OMPClause *Nowait = nullptr;
10778 const OMPClause *Copyprivate = nullptr;
10779 for (const OMPClause *Clause : Clauses) {
10780 if (Clause->getClauseKind() == OMPC_nowait)
10781 Nowait = Clause;
10782 else if (Clause->getClauseKind() == OMPC_copyprivate)
10783 Copyprivate = Clause;
10784 if (Copyprivate && Nowait) {
10785 Diag(Copyprivate->getBeginLoc(),
10786 diag::err_omp_single_copyprivate_with_nowait);
10787 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10788 return StmtError();
10789 }
10790 }
10791
10792 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10793 AStmt);
10794}
10795
10797 SourceLocation StartLoc,
10798 SourceLocation EndLoc) {
10799 if (!AStmt)
10800 return StmtError();
10801
10803
10804 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
10805}
10806
10808 Stmt *AStmt,
10809 SourceLocation StartLoc,
10810 SourceLocation EndLoc) {
10811 if (!AStmt)
10812 return StmtError();
10813
10815
10816 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10817 AStmt);
10818}
10819
10821 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10822 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10823 if (!AStmt)
10824 return StmtError();
10825
10826 bool ErrorFound = false;
10827 llvm::APSInt Hint;
10828 SourceLocation HintLoc;
10829 bool DependentHint = false;
10830 for (const OMPClause *C : Clauses) {
10831 if (C->getClauseKind() == OMPC_hint) {
10832 if (!DirName.getName()) {
10833 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10834 ErrorFound = true;
10835 }
10836 Expr *E = cast<OMPHintClause>(C)->getHint();
10837 if (E->isTypeDependent() || E->isValueDependent() ||
10839 DependentHint = true;
10840 } else {
10842 HintLoc = C->getBeginLoc();
10843 }
10844 }
10845 }
10846 if (ErrorFound)
10847 return StmtError();
10848 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10849 if (Pair.first && DirName.getName() && !DependentHint) {
10850 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10851 Diag(StartLoc, diag::err_omp_critical_with_hint);
10852 if (HintLoc.isValid())
10853 Diag(HintLoc, diag::note_omp_critical_hint_here)
10854 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10855 else
10856 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10857 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10858 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10859 << 1
10860 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10861 /*Radix=*/10, /*Signed=*/false);
10862 } else {
10863 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10864 }
10865 }
10866 }
10867
10869
10870 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
10871 EndLoc, Clauses, AStmt);
10872 if (!Pair.first && DirName.getName() && !DependentHint)
10873 DSAStack->addCriticalWithHint(Dir, Hint);
10874 return Dir;
10875}
10876
10878 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10879 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10880 if (!AStmt)
10881 return StmtError();
10882
10883 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10884
10886 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10887 // define the nested loops number.
10888 unsigned NestedLoopCount =
10889 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10890 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10891 VarsWithImplicitDSA, B);
10892 if (NestedLoopCount == 0)
10893 return StmtError();
10894
10895 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10896 return StmtError();
10897
10899 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10900 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10901}
10902
10904 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10905 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10906 if (!AStmt)
10907 return StmtError();
10908
10909 CapturedStmt *CS =
10910 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10911
10913 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10914 // define the nested loops number.
10915 unsigned NestedLoopCount =
10916 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10917 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10918 VarsWithImplicitDSA, B);
10919 if (NestedLoopCount == 0)
10920 return StmtError();
10921
10922 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10923 return StmtError();
10924
10926 return StmtError();
10927
10929 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10930}
10931
10933 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10934 SourceLocation EndLoc) {
10935 if (!AStmt)
10936 return StmtError();
10937
10938 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
10939
10941 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10942 DSAStack->getTaskgroupReductionRef());
10943}
10944
10946 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10947 SourceLocation EndLoc) {
10948 if (!AStmt)
10949 return StmtError();
10950
10951 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
10952
10954 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10955 DSAStack->getTaskgroupReductionRef());
10956}
10957
10959 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10960 SourceLocation EndLoc) {
10961 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
10962 return StmtError();
10963
10965
10967 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10968 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10969}
10970
10971/// Find and diagnose mutually exclusive clause kinds.
10973 Sema &S, ArrayRef<OMPClause *> Clauses,
10974 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
10975 const OMPClause *PrevClause = nullptr;
10976 bool ErrorFound = false;
10977 for (const OMPClause *C : Clauses) {
10978 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
10979 if (!PrevClause) {
10980 PrevClause = C;
10981 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
10982 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10983 << getOpenMPClauseName(C->getClauseKind())
10984 << getOpenMPClauseName(PrevClause->getClauseKind());
10985 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
10986 << getOpenMPClauseName(PrevClause->getClauseKind());
10987 ErrorFound = true;
10988 }
10989 }
10990 }
10991 return ErrorFound;
10992}
10993
10995 Stmt *AStmt,
10996 SourceLocation StartLoc,
10997 SourceLocation EndLoc) {
10998 if (!AStmt)
10999 return StmtError();
11000
11001 // OpenMP 5.0, 2.10.1 task Construct
11002 // If a detach clause appears on the directive, then a mergeable clause cannot
11003 // appear on the same directive.
11005 {OMPC_detach, OMPC_mergeable}))
11006 return StmtError();
11007
11008 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11009
11010 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11011 AStmt, DSAStack->isCancelRegion());
11012}
11013
11015 SourceLocation EndLoc) {
11016 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11017}
11018
11020 SourceLocation EndLoc) {
11021 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11022}
11023
11025 SourceLocation StartLoc,
11026 SourceLocation EndLoc,
11027 bool InExContext) {
11028 const OMPAtClause *AtC =
11029 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11030
11031 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11032 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11033 return StmtError();
11034 }
11035
11036 const OMPSeverityClause *SeverityC =
11037 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11038 const OMPMessageClause *MessageC =
11039 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11040 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11041
11042 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11043 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11044 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11045 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11046 else
11047 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11048 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11049 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11050 return StmtError();
11051 }
11052 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11053}
11054
11057 SourceLocation StartLoc,
11058 SourceLocation EndLoc) {
11059 const OMPNowaitClause *NowaitC =
11060 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11061 bool HasDependC =
11062 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11063 .empty();
11064 if (NowaitC && !HasDependC) {
11065 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11066 return StmtError();
11067 }
11068
11069 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11070 Clauses);
11071}
11072
11075 Stmt *AStmt, SourceLocation StartLoc,
11076 SourceLocation EndLoc) {
11077 if (!AStmt)
11078 return StmtError();
11079
11080 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11081
11083
11084 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11085 Clauses, AStmt,
11086 DSAStack->getTaskgroupReductionRef());
11087}
11088
11090 SourceLocation StartLoc,
11091 SourceLocation EndLoc) {
11092 OMPFlushClause *FC = nullptr;
11093 OMPClause *OrderClause = nullptr;
11094 for (OMPClause *C : Clauses) {
11095 if (C->getClauseKind() == OMPC_flush)
11096 FC = cast<OMPFlushClause>(C);
11097 else
11098 OrderClause = C;
11099 }
11100 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11101 SourceLocation MemOrderLoc;
11102 for (const OMPClause *C : Clauses) {
11103 if (C->getClauseKind() == OMPC_acq_rel ||
11104 C->getClauseKind() == OMPC_acquire ||
11105 C->getClauseKind() == OMPC_release ||
11106 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11107 if (MemOrderKind != OMPC_unknown) {
11108 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11109 << getOpenMPDirectiveName(OMPD_flush) << 1
11110 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11111 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11112 << getOpenMPClauseName(MemOrderKind);
11113 } else {
11114 MemOrderKind = C->getClauseKind();
11115 MemOrderLoc = C->getBeginLoc();
11116 }
11117 }
11118 }
11119 if (FC && OrderClause) {
11120 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11121 << getOpenMPClauseName(OrderClause->getClauseKind());
11122 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11123 << getOpenMPClauseName(OrderClause->getClauseKind());
11124 return StmtError();
11125 }
11126 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11127}
11128
11130 SourceLocation StartLoc,
11131 SourceLocation EndLoc) {
11132 if (Clauses.empty()) {
11133 Diag(StartLoc, diag::err_omp_depobj_expected);
11134 return StmtError();
11135 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11136 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11137 return StmtError();
11138 }
11139 // Only depobj expression and another single clause is allowed.
11140 if (Clauses.size() > 2) {
11141 Diag(Clauses[2]->getBeginLoc(),
11142 diag::err_omp_depobj_single_clause_expected);
11143 return StmtError();
11144 } else if (Clauses.size() < 1) {
11145 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11146 return StmtError();
11147 }
11148 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11149}
11150
11152 SourceLocation StartLoc,
11153 SourceLocation EndLoc) {
11154 // Check that exactly one clause is specified.
11155 if (Clauses.size() != 1) {
11156 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11157 diag::err_omp_scan_single_clause_expected);
11158 return StmtError();
11159 }
11160 // Check that scan directive is used in the scope of the OpenMP loop body.
11161 if (Scope *S = DSAStack->getCurScope()) {
11162 Scope *ParentS = S->getParent();
11163 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11164 !ParentS->getBreakParent()->isOpenMPLoopScope())
11165 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11166 << getOpenMPDirectiveName(OMPD_scan) << 5);
11167 }
11168 // Check that only one instance of scan directives is used in the same outer
11169 // region.
11170 if (DSAStack->doesParentHasScanDirective()) {
11171 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11172 Diag(DSAStack->getParentScanDirectiveLoc(),
11173 diag::note_omp_previous_directive)
11174 << "scan";
11175 return StmtError();
11176 }
11177 DSAStack->setParentHasScanDirective(StartLoc);
11178 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11179}
11180
11183 Stmt *AStmt, SourceLocation StartLoc,
11184 SourceLocation EndLoc) {
11185 const OMPClause *DependFound = nullptr;
11186 const OMPClause *DependSourceClause = nullptr;
11187 const OMPClause *DependSinkClause = nullptr;
11188 const OMPClause *DoacrossFound = nullptr;
11189 const OMPClause *DoacrossSourceClause = nullptr;
11190 const OMPClause *DoacrossSinkClause = nullptr;
11191 bool ErrorFound = false;
11192 const OMPThreadsClause *TC = nullptr;
11193 const OMPSIMDClause *SC = nullptr;
11194 for (const OMPClause *C : Clauses) {
11195 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11196 auto DC = dyn_cast<OMPDependClause>(C);
11197 if (DC || DOC) {
11198 DependFound = DC ? C : nullptr;
11199 DoacrossFound = DOC ? C : nullptr;
11200 OMPDoacrossKind ODK;
11201 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11202 (DOC && (ODK.isSource(DOC)))) {
11203 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11204 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11205 << getOpenMPDirectiveName(OMPD_ordered)
11206 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11207 ErrorFound = true;
11208 } else {
11209 if (DC)
11210 DependSourceClause = C;
11211 else
11212 DoacrossSourceClause = C;
11213 }
11214 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11215 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11216 << (DC ? "depend" : "doacross") << 0;
11217 ErrorFound = true;
11218 }
11219 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11220 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11221 if (DependSourceClause || DoacrossSourceClause) {
11222 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11223 << (DC ? "depend" : "doacross") << 1;
11224 ErrorFound = true;
11225 }
11226 if (DC)
11227 DependSinkClause = C;
11228 else
11229 DoacrossSinkClause = C;
11230 }
11231 } else if (C->getClauseKind() == OMPC_threads) {
11232 TC = cast<OMPThreadsClause>(C);
11233 } else if (C->getClauseKind() == OMPC_simd) {
11234 SC = cast<OMPSIMDClause>(C);
11235 }
11236 }
11237 if (!ErrorFound && !SC &&
11238 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11239 // OpenMP [2.8.1,simd Construct, Restrictions]
11240 // An ordered construct with the simd clause is the only OpenMP construct
11241 // that can appear in the simd region.
11242 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11243 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11244 ErrorFound = true;
11245 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11247 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11248 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11249 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11250 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11251 ErrorFound = true;
11252 } else if ((DependFound || DoacrossFound) &&
11253 !DSAStack->getParentOrderedRegionParam().first) {
11255 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11256 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11257 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11258 ErrorFound = true;
11259 } else if (TC || Clauses.empty()) {
11260 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11261 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11262 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11263 << (TC != nullptr);
11264 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11265 ErrorFound = true;
11266 }
11267 }
11268 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11269 return StmtError();
11270
11271 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11272 // During execution of an iteration of a worksharing-loop or a loop nest
11273 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11274 // must not execute more than one ordered region corresponding to an ordered
11275 // construct without a depend clause.
11276 if (!DependFound && !DoacrossFound) {
11277 if (DSAStack->doesParentHasOrderedDirective()) {
11278 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11279 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11280 diag::note_omp_previous_directive)
11281 << "ordered";
11282 return StmtError();
11283 }
11284 DSAStack->setParentHasOrderedDirective(StartLoc);
11285 }
11286
11287 if (AStmt) {
11288 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11289
11291 }
11292
11293 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11294 AStmt);
11295}
11296
11297namespace {
11298/// Helper class for checking expression in 'omp atomic [update]'
11299/// construct.
11300class OpenMPAtomicUpdateChecker {
11301 /// Error results for atomic update expressions.
11302 enum ExprAnalysisErrorCode {
11303 /// A statement is not an expression statement.
11304 NotAnExpression,
11305 /// Expression is not builtin binary or unary operation.
11306 NotABinaryOrUnaryExpression,
11307 /// Unary operation is not post-/pre- increment/decrement operation.
11308 NotAnUnaryIncDecExpression,
11309 /// An expression is not of scalar type.
11310 NotAScalarType,
11311 /// A binary operation is not an assignment operation.
11312 NotAnAssignmentOp,
11313 /// RHS part of the binary operation is not a binary expression.
11314 NotABinaryExpression,
11315 /// RHS part is not additive/multiplicative/shift/bitwise binary
11316 /// expression.
11317 NotABinaryOperator,
11318 /// RHS binary operation does not have reference to the updated LHS
11319 /// part.
11320 NotAnUpdateExpression,
11321 /// An expression contains semantical error not related to
11322 /// 'omp atomic [update]'
11323 NotAValidExpression,
11324 /// No errors is found.
11325 NoError
11326 };
11327 /// Reference to Sema.
11328 Sema &SemaRef;
11329 /// A location for note diagnostics (when error is found).
11330 SourceLocation NoteLoc;
11331 /// 'x' lvalue part of the source atomic expression.
11332 Expr *X;
11333 /// 'expr' rvalue part of the source atomic expression.
11334 Expr *E;
11335 /// Helper expression of the form
11336 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11337 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11338 Expr *UpdateExpr;
11339 /// Is 'x' a LHS in a RHS part of full update expression. It is
11340 /// important for non-associative operations.
11341 bool IsXLHSInRHSPart;
11343 SourceLocation OpLoc;
11344 /// true if the source expression is a postfix unary operation, false
11345 /// if it is a prefix unary operation.
11346 bool IsPostfixUpdate;
11347
11348public:
11349 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11350 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11351 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11352 /// Check specified statement that it is suitable for 'atomic update'
11353 /// constructs and extract 'x', 'expr' and Operation from the original
11354 /// expression. If DiagId and NoteId == 0, then only check is performed
11355 /// without error notification.
11356 /// \param DiagId Diagnostic which should be emitted if error is found.
11357 /// \param NoteId Diagnostic note for the main error message.
11358 /// \return true if statement is not an update expression, false otherwise.
11359 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11360 /// Return the 'x' lvalue part of the source atomic expression.
11361 Expr *getX() const { return X; }
11362 /// Return the 'expr' rvalue part of the source atomic expression.
11363 Expr *getExpr() const { return E; }
11364 /// Return the update expression used in calculation of the updated
11365 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11366 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11367 Expr *getUpdateExpr() const { return UpdateExpr; }
11368 /// Return true if 'x' is LHS in RHS part of full update expression,
11369 /// false otherwise.
11370 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11371
11372 /// true if the source expression is a postfix unary operation, false
11373 /// if it is a prefix unary operation.
11374 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11375
11376private:
11377 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11378 unsigned NoteId = 0);
11379};
11380
11381bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11382 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11383 ExprAnalysisErrorCode ErrorFound = NoError;
11384 SourceLocation ErrorLoc, NoteLoc;
11385 SourceRange ErrorRange, NoteRange;
11386 // Allowed constructs are:
11387 // x = x binop expr;
11388 // x = expr binop x;
11389 if (AtomicBinOp->getOpcode() == BO_Assign) {
11390 X = AtomicBinOp->getLHS();
11391 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11392 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11393 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11394 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11395 AtomicInnerBinOp->isBitwiseOp()) {
11396 Op = AtomicInnerBinOp->getOpcode();
11397 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11398 Expr *LHS = AtomicInnerBinOp->getLHS();
11399 Expr *RHS = AtomicInnerBinOp->getRHS();
11400 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11401 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11402 /*Canonical=*/true);
11403 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11404 /*Canonical=*/true);
11405 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11406 /*Canonical=*/true);
11407 if (XId == LHSId) {
11408 E = RHS;
11409 IsXLHSInRHSPart = true;
11410 } else if (XId == RHSId) {
11411 E = LHS;
11412 IsXLHSInRHSPart = false;
11413 } else {
11414 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11415 ErrorRange = AtomicInnerBinOp->getSourceRange();
11416 NoteLoc = X->getExprLoc();
11417 NoteRange = X->getSourceRange();
11418 ErrorFound = NotAnUpdateExpression;
11419 }
11420 } else {
11421 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11422 ErrorRange = AtomicInnerBinOp->getSourceRange();
11423 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11424 NoteRange = SourceRange(NoteLoc, NoteLoc);
11425 ErrorFound = NotABinaryOperator;
11426 }
11427 } else {
11428 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11429 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11430 ErrorFound = NotABinaryExpression;
11431 }
11432 } else {
11433 ErrorLoc = AtomicBinOp->getExprLoc();
11434 ErrorRange = AtomicBinOp->getSourceRange();
11435 NoteLoc = AtomicBinOp->getOperatorLoc();
11436 NoteRange = SourceRange(NoteLoc, NoteLoc);
11437 ErrorFound = NotAnAssignmentOp;
11438 }
11439 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11440 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11441 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11442 return true;
11443 }
11444 if (SemaRef.CurContext->isDependentContext())
11445 E = X = UpdateExpr = nullptr;
11446 return ErrorFound != NoError;
11447}
11448
11449bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11450 unsigned NoteId) {
11451 ExprAnalysisErrorCode ErrorFound = NoError;
11452 SourceLocation ErrorLoc, NoteLoc;
11453 SourceRange ErrorRange, NoteRange;
11454 // Allowed constructs are:
11455 // x++;
11456 // x--;
11457 // ++x;
11458 // --x;
11459 // x binop= expr;
11460 // x = x binop expr;
11461 // x = expr binop x;
11462 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11463 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11464 if (AtomicBody->getType()->isScalarType() ||
11465 AtomicBody->isInstantiationDependent()) {
11466 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11467 AtomicBody->IgnoreParenImpCasts())) {
11468 // Check for Compound Assignment Operation
11470 AtomicCompAssignOp->getOpcode());
11471 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11472 E = AtomicCompAssignOp->getRHS();
11473 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11474 IsXLHSInRHSPart = true;
11475 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11476 AtomicBody->IgnoreParenImpCasts())) {
11477 // Check for Binary Operation
11478 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11479 return true;
11480 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11481 AtomicBody->IgnoreParenImpCasts())) {
11482 // Check for Unary Operation
11483 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11484 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11485 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11486 OpLoc = AtomicUnaryOp->getOperatorLoc();
11487 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11488 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11489 IsXLHSInRHSPart = true;
11490 } else {
11491 ErrorFound = NotAnUnaryIncDecExpression;
11492 ErrorLoc = AtomicUnaryOp->getExprLoc();
11493 ErrorRange = AtomicUnaryOp->getSourceRange();
11494 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11495 NoteRange = SourceRange(NoteLoc, NoteLoc);
11496 }
11497 } else if (!AtomicBody->isInstantiationDependent()) {
11498 ErrorFound = NotABinaryOrUnaryExpression;
11499 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11500 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11501 } else if (AtomicBody->containsErrors()) {
11502 ErrorFound = NotAValidExpression;
11503 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11504 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11505 }
11506 } else {
11507 ErrorFound = NotAScalarType;
11508 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11509 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11510 }
11511 } else {
11512 ErrorFound = NotAnExpression;
11513 NoteLoc = ErrorLoc = S->getBeginLoc();
11514 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11515 }
11516 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11517 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11518 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11519 return true;
11520 }
11521 if (SemaRef.CurContext->isDependentContext())
11522 E = X = UpdateExpr = nullptr;
11523 if (ErrorFound == NoError && E && X) {
11524 // Build an update expression of form 'OpaqueValueExpr(x) binop
11525 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11526 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11527 auto *OVEX = new (SemaRef.getASTContext())
11528 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11529 auto *OVEExpr = new (SemaRef.getASTContext())
11532 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11533 IsXLHSInRHSPart ? OVEExpr : OVEX);
11534 if (Update.isInvalid())
11535 return true;
11536 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11538 if (Update.isInvalid())
11539 return true;
11540 UpdateExpr = Update.get();
11541 }
11542 return ErrorFound != NoError;
11543}
11544
11545/// Get the node id of the fixed point of an expression \a S.
11546llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11547 llvm::FoldingSetNodeID Id;
11548 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11549 return Id;
11550}
11551
11552/// Check if two expressions are same.
11553bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11554 const Expr *RHS) {
11555 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11556}
11557
11558class OpenMPAtomicCompareChecker {
11559public:
11560 /// All kinds of errors that can occur in `atomic compare`
11561 enum ErrorTy {
11562 /// Empty compound statement.
11563 NoStmt = 0,
11564 /// More than one statement in a compound statement.
11565 MoreThanOneStmt,
11566 /// Not an assignment binary operator.
11567 NotAnAssignment,
11568 /// Not a conditional operator.
11569 NotCondOp,
11570 /// Wrong false expr. According to the spec, 'x' should be at the false
11571 /// expression of a conditional expression.
11572 WrongFalseExpr,
11573 /// The condition of a conditional expression is not a binary operator.
11574 NotABinaryOp,
11575 /// Invalid binary operator (not <, >, or ==).
11576 InvalidBinaryOp,
11577 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11578 InvalidComparison,
11579 /// X is not a lvalue.
11580 XNotLValue,
11581 /// Not a scalar.
11582 NotScalar,
11583 /// Not an integer.
11584 NotInteger,
11585 /// 'else' statement is not expected.
11586 UnexpectedElse,
11587 /// Not an equality operator.
11588 NotEQ,
11589 /// Invalid assignment (not v == x).
11590 InvalidAssignment,
11591 /// Not if statement
11592 NotIfStmt,
11593 /// More than two statements in a compound statement.
11594 MoreThanTwoStmts,
11595 /// Not a compound statement.
11596 NotCompoundStmt,
11597 /// No else statement.
11598 NoElse,
11599 /// Not 'if (r)'.
11600 InvalidCondition,
11601 /// No error.
11602 NoError,
11603 };
11604
11605 struct ErrorInfoTy {
11606 ErrorTy Error;
11607 SourceLocation ErrorLoc;
11608 SourceRange ErrorRange;
11609 SourceLocation NoteLoc;
11610 SourceRange NoteRange;
11611 };
11612
11613 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11614
11615 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11616 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11617
11618 Expr *getX() const { return X; }
11619 Expr *getE() const { return E; }
11620 Expr *getD() const { return D; }
11621 Expr *getCond() const { return C; }
11622 bool isXBinopExpr() const { return IsXBinopExpr; }
11623
11624protected:
11625 /// Reference to ASTContext
11626 ASTContext &ContextRef;
11627 /// 'x' lvalue part of the source atomic expression.
11628 Expr *X = nullptr;
11629 /// 'expr' or 'e' rvalue part of the source atomic expression.
11630 Expr *E = nullptr;
11631 /// 'd' rvalue part of the source atomic expression.
11632 Expr *D = nullptr;
11633 /// 'cond' part of the source atomic expression. It is in one of the following
11634 /// forms:
11635 /// expr ordop x
11636 /// x ordop expr
11637 /// x == e
11638 /// e == x
11639 Expr *C = nullptr;
11640 /// True if the cond expr is in the form of 'x ordop expr'.
11641 bool IsXBinopExpr = true;
11642
11643 /// Check if it is a valid conditional update statement (cond-update-stmt).
11644 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11645
11646 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11647 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11648
11649 /// Check if all captured values have right type.
11650 bool checkType(ErrorInfoTy &ErrorInfo) const;
11651
11652 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11653 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11655 return true;
11656
11657 if (ShouldBeLValue && !E->isLValue()) {
11658 ErrorInfo.Error = ErrorTy::XNotLValue;
11659 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11660 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11661 return false;
11662 }
11663
11664 QualType QTy = E->getType();
11665 if (!QTy->isScalarType()) {
11666 ErrorInfo.Error = ErrorTy::NotScalar;
11667 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11668 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11669 return false;
11670 }
11671 if (ShouldBeInteger && !QTy->isIntegerType()) {
11672 ErrorInfo.Error = ErrorTy::NotInteger;
11673 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11674 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11675 return false;
11676 }
11677
11678 return true;
11679 }
11680};
11681
11682bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11683 ErrorInfoTy &ErrorInfo) {
11684 auto *Then = S->getThen();
11685 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11686 if (CS->body_empty()) {
11687 ErrorInfo.Error = ErrorTy::NoStmt;
11688 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11689 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11690 return false;
11691 }
11692 if (CS->size() > 1) {
11693 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11694 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11695 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11696 return false;
11697 }
11698 Then = CS->body_front();
11699 }
11700
11701 auto *BO = dyn_cast<BinaryOperator>(Then);
11702 if (!BO) {
11703 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11704 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11705 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11706 return false;
11707 }
11708 if (BO->getOpcode() != BO_Assign) {
11709 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11710 ErrorInfo.ErrorLoc = BO->getExprLoc();
11711 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11712 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11713 return false;
11714 }
11715
11716 X = BO->getLHS();
11717
11718 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11719 if (!Cond) {
11720 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11721 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11722 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11723 return false;
11724 }
11725
11726 switch (Cond->getOpcode()) {
11727 case BO_EQ: {
11728 C = Cond;
11729 D = BO->getRHS();
11730 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11731 E = Cond->getRHS();
11732 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11733 E = Cond->getLHS();
11734 } else {
11735 ErrorInfo.Error = ErrorTy::InvalidComparison;
11736 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11737 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11738 return false;
11739 }
11740 break;
11741 }
11742 case BO_LT:
11743 case BO_GT: {
11744 E = BO->getRHS();
11745 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11746 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11747 C = Cond;
11748 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11749 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11750 C = Cond;
11751 IsXBinopExpr = false;
11752 } else {
11753 ErrorInfo.Error = ErrorTy::InvalidComparison;
11754 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11755 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11756 return false;
11757 }
11758 break;
11759 }
11760 default:
11761 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11762 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11763 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11764 return false;
11765 }
11766
11767 if (S->getElse()) {
11768 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11769 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11770 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11771 return false;
11772 }
11773
11774 return true;
11775}
11776
11777bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11778 ErrorInfoTy &ErrorInfo) {
11779 auto *BO = dyn_cast<BinaryOperator>(S);
11780 if (!BO) {
11781 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11782 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11783 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11784 return false;
11785 }
11786 if (BO->getOpcode() != BO_Assign) {
11787 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11788 ErrorInfo.ErrorLoc = BO->getExprLoc();
11789 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11790 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11791 return false;
11792 }
11793
11794 X = BO->getLHS();
11795
11796 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11797 if (!CO) {
11798 ErrorInfo.Error = ErrorTy::NotCondOp;
11799 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11800 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11801 return false;
11802 }
11803
11804 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11805 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11806 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11807 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11808 CO->getFalseExpr()->getSourceRange();
11809 return false;
11810 }
11811
11812 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11813 if (!Cond) {
11814 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11815 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11816 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11817 CO->getCond()->getSourceRange();
11818 return false;
11819 }
11820
11821 switch (Cond->getOpcode()) {
11822 case BO_EQ: {
11823 C = Cond;
11824 D = CO->getTrueExpr();
11825 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11826 E = Cond->getRHS();
11827 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11828 E = Cond->getLHS();
11829 } else {
11830 ErrorInfo.Error = ErrorTy::InvalidComparison;
11831 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11832 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11833 return false;
11834 }
11835 break;
11836 }
11837 case BO_LT:
11838 case BO_GT: {
11839 E = CO->getTrueExpr();
11840 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11841 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11842 C = Cond;
11843 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11844 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11845 C = Cond;
11846 IsXBinopExpr = false;
11847 } else {
11848 ErrorInfo.Error = ErrorTy::InvalidComparison;
11849 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11850 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11851 return false;
11852 }
11853 break;
11854 }
11855 default:
11856 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11857 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11858 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11859 return false;
11860 }
11861
11862 return true;
11863}
11864
11865bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11866 // 'x' and 'e' cannot be nullptr
11867 assert(X && E && "X and E cannot be nullptr");
11868
11869 if (!CheckValue(X, ErrorInfo, true))
11870 return false;
11871
11872 if (!CheckValue(E, ErrorInfo, false))
11873 return false;
11874
11875 if (D && !CheckValue(D, ErrorInfo, false))
11876 return false;
11877
11878 return true;
11879}
11880
11881bool OpenMPAtomicCompareChecker::checkStmt(
11882 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11883 auto *CS = dyn_cast<CompoundStmt>(S);
11884 if (CS) {
11885 if (CS->body_empty()) {
11886 ErrorInfo.Error = ErrorTy::NoStmt;
11887 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11888 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11889 return false;
11890 }
11891
11892 if (CS->size() != 1) {
11893 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11894 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11895 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11896 return false;
11897 }
11898 S = CS->body_front();
11899 }
11900
11901 auto Res = false;
11902
11903 if (auto *IS = dyn_cast<IfStmt>(S)) {
11904 // Check if the statement is in one of the following forms
11905 // (cond-update-stmt):
11906 // if (expr ordop x) { x = expr; }
11907 // if (x ordop expr) { x = expr; }
11908 // if (x == e) { x = d; }
11909 Res = checkCondUpdateStmt(IS, ErrorInfo);
11910 } else {
11911 // Check if the statement is in one of the following forms (cond-expr-stmt):
11912 // x = expr ordop x ? expr : x;
11913 // x = x ordop expr ? expr : x;
11914 // x = x == e ? d : x;
11915 Res = checkCondExprStmt(S, ErrorInfo);
11916 }
11917
11918 if (!Res)
11919 return false;
11920
11921 return checkType(ErrorInfo);
11922}
11923
11924class OpenMPAtomicCompareCaptureChecker final
11925 : public OpenMPAtomicCompareChecker {
11926public:
11927 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11928
11929 Expr *getV() const { return V; }
11930 Expr *getR() const { return R; }
11931 bool isFailOnly() const { return IsFailOnly; }
11932 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11933
11934 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11935 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11936
11937private:
11938 bool checkType(ErrorInfoTy &ErrorInfo);
11939
11940 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11941 // form of 'conditional-update-capture-atomic' structured block on the v5.2
11942 // spec p.p. 82:
11943 // (1) { v = x; cond-update-stmt }
11944 // (2) { cond-update-stmt v = x; }
11945 // (3) if(x == e) { x = d; } else { v = x; }
11946 // (4) { r = x == e; if(r) { x = d; } }
11947 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11948
11949 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11950 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11951
11952 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11953 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11954 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
11955
11956 /// 'v' lvalue part of the source atomic expression.
11957 Expr *V = nullptr;
11958 /// 'r' lvalue part of the source atomic expression.
11959 Expr *R = nullptr;
11960 /// If 'v' is only updated when the comparison fails.
11961 bool IsFailOnly = false;
11962 /// If original value of 'x' must be stored in 'v', not an updated one.
11963 bool IsPostfixUpdate = false;
11964};
11965
11966bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11967 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11968 return false;
11969
11970 if (V && !CheckValue(V, ErrorInfo, true))
11971 return false;
11972
11973 if (R && !CheckValue(R, ErrorInfo, true, true))
11974 return false;
11975
11976 return true;
11977}
11978
11979bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
11980 ErrorInfoTy &ErrorInfo) {
11981 IsFailOnly = true;
11982
11983 auto *Then = S->getThen();
11984 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11985 if (CS->body_empty()) {
11986 ErrorInfo.Error = ErrorTy::NoStmt;
11987 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11988 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11989 return false;
11990 }
11991 if (CS->size() > 1) {
11992 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11993 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11994 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11995 return false;
11996 }
11997 Then = CS->body_front();
11998 }
11999
12000 auto *BO = dyn_cast<BinaryOperator>(Then);
12001 if (!BO) {
12002 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12003 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12004 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12005 return false;
12006 }
12007 if (BO->getOpcode() != BO_Assign) {
12008 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12009 ErrorInfo.ErrorLoc = BO->getExprLoc();
12010 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12011 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12012 return false;
12013 }
12014
12015 X = BO->getLHS();
12016 D = BO->getRHS();
12017
12018 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12019 if (!Cond) {
12020 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12021 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12022 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12023 return false;
12024 }
12025 if (Cond->getOpcode() != BO_EQ) {
12026 ErrorInfo.Error = ErrorTy::NotEQ;
12027 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12028 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12029 return false;
12030 }
12031
12032 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12033 E = Cond->getRHS();
12034 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12035 E = Cond->getLHS();
12036 } else {
12037 ErrorInfo.Error = ErrorTy::InvalidComparison;
12038 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12039 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12040 return false;
12041 }
12042
12043 C = Cond;
12044
12045 if (!S->getElse()) {
12046 ErrorInfo.Error = ErrorTy::NoElse;
12047 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12048 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12049 return false;
12050 }
12051
12052 auto *Else = S->getElse();
12053 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12054 if (CS->body_empty()) {
12055 ErrorInfo.Error = ErrorTy::NoStmt;
12056 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12058 return false;
12059 }
12060 if (CS->size() > 1) {
12061 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12062 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12064 return false;
12065 }
12066 Else = CS->body_front();
12067 }
12068
12069 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12070 if (!ElseBO) {
12071 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12072 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12073 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12074 return false;
12075 }
12076 if (ElseBO->getOpcode() != BO_Assign) {
12077 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12078 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12079 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12080 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12081 return false;
12082 }
12083
12084 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12085 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12088 ElseBO->getRHS()->getSourceRange();
12089 return false;
12090 }
12091
12092 V = ElseBO->getLHS();
12093
12094 return checkType(ErrorInfo);
12095}
12096
12097bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12098 ErrorInfoTy &ErrorInfo) {
12099 // We don't check here as they should be already done before call this
12100 // function.
12101 auto *CS = cast<CompoundStmt>(S);
12102 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12103 auto *S1 = cast<BinaryOperator>(CS->body_front());
12104 auto *S2 = cast<IfStmt>(CS->body_back());
12105 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12106
12107 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12108 ErrorInfo.Error = ErrorTy::InvalidCondition;
12109 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12110 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12111 return false;
12112 }
12113
12114 R = S1->getLHS();
12115
12116 auto *Then = S2->getThen();
12117 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12118 if (ThenCS->body_empty()) {
12119 ErrorInfo.Error = ErrorTy::NoStmt;
12120 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12121 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12122 return false;
12123 }
12124 if (ThenCS->size() > 1) {
12125 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12126 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12127 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12128 return false;
12129 }
12130 Then = ThenCS->body_front();
12131 }
12132
12133 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12134 if (!ThenBO) {
12135 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12136 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12137 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12138 return false;
12139 }
12140 if (ThenBO->getOpcode() != BO_Assign) {
12141 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12142 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12143 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12144 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12145 return false;
12146 }
12147
12148 X = ThenBO->getLHS();
12149 D = ThenBO->getRHS();
12150
12151 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12152 if (BO->getOpcode() != BO_EQ) {
12153 ErrorInfo.Error = ErrorTy::NotEQ;
12154 ErrorInfo.ErrorLoc = BO->getExprLoc();
12155 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12156 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12157 return false;
12158 }
12159
12160 C = BO;
12161
12162 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12163 E = BO->getRHS();
12164 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12165 E = BO->getLHS();
12166 } else {
12167 ErrorInfo.Error = ErrorTy::InvalidComparison;
12168 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12169 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12170 return false;
12171 }
12172
12173 if (S2->getElse()) {
12174 IsFailOnly = true;
12175
12176 auto *Else = S2->getElse();
12177 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12178 if (ElseCS->body_empty()) {
12179 ErrorInfo.Error = ErrorTy::NoStmt;
12180 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12181 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12182 return false;
12183 }
12184 if (ElseCS->size() > 1) {
12185 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12186 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12187 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12188 return false;
12189 }
12190 Else = ElseCS->body_front();
12191 }
12192
12193 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12194 if (!ElseBO) {
12195 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12196 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12197 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12198 return false;
12199 }
12200 if (ElseBO->getOpcode() != BO_Assign) {
12201 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12202 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12203 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12204 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12205 return false;
12206 }
12207 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12208 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12209 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12210 ErrorInfo.NoteLoc = X->getExprLoc();
12211 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12212 ErrorInfo.NoteRange = X->getSourceRange();
12213 return false;
12214 }
12215
12216 V = ElseBO->getLHS();
12217 }
12218
12219 return checkType(ErrorInfo);
12220}
12221
12222bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12223 ErrorInfoTy &ErrorInfo) {
12224 // if(x == e) { x = d; } else { v = x; }
12225 if (auto *IS = dyn_cast<IfStmt>(S))
12226 return checkForm3(IS, ErrorInfo);
12227
12228 auto *CS = dyn_cast<CompoundStmt>(S);
12229 if (!CS) {
12230 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12231 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12232 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12233 return false;
12234 }
12235 if (CS->body_empty()) {
12236 ErrorInfo.Error = ErrorTy::NoStmt;
12237 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12238 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12239 return false;
12240 }
12241
12242 // { if(x == e) { x = d; } else { v = x; } }
12243 if (CS->size() == 1) {
12244 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12245 if (!IS) {
12246 ErrorInfo.Error = ErrorTy::NotIfStmt;
12247 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12248 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12249 CS->body_front()->getSourceRange();
12250 return false;
12251 }
12252
12253 return checkForm3(IS, ErrorInfo);
12254 } else if (CS->size() == 2) {
12255 auto *S1 = CS->body_front();
12256 auto *S2 = CS->body_back();
12257
12258 Stmt *UpdateStmt = nullptr;
12259 Stmt *CondUpdateStmt = nullptr;
12260 Stmt *CondExprStmt = nullptr;
12261
12262 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12263 // It could be one of the following cases:
12264 // { v = x; cond-update-stmt }
12265 // { v = x; cond-expr-stmt }
12266 // { cond-expr-stmt; v = x; }
12267 // form 45
12268 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12269 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12270 // check if form 45
12271 if (isa<IfStmt>(S2))
12272 return checkForm45(CS, ErrorInfo);
12273 // { cond-expr-stmt; v = x; }
12274 CondExprStmt = S1;
12275 UpdateStmt = S2;
12276 } else {
12277 IsPostfixUpdate = true;
12278 UpdateStmt = S1;
12279 if (isa<IfStmt>(S2)) {
12280 // { v = x; cond-update-stmt }
12281 CondUpdateStmt = S2;
12282 } else {
12283 // { v = x; cond-expr-stmt }
12284 CondExprStmt = S2;
12285 }
12286 }
12287 } else {
12288 // { cond-update-stmt v = x; }
12289 UpdateStmt = S2;
12290 CondUpdateStmt = S1;
12291 }
12292
12293 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12294 auto *IS = dyn_cast<IfStmt>(CUS);
12295 if (!IS) {
12296 ErrorInfo.Error = ErrorTy::NotIfStmt;
12297 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12298 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12299 return false;
12300 }
12301
12302 return checkCondUpdateStmt(IS, ErrorInfo);
12303 };
12304
12305 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12306 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12307 auto *BO = dyn_cast<BinaryOperator>(US);
12308 if (!BO) {
12309 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12310 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12311 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12312 return false;
12313 }
12314 if (BO->getOpcode() != BO_Assign) {
12315 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12316 ErrorInfo.ErrorLoc = BO->getExprLoc();
12317 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12318 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12319 return false;
12320 }
12321 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12322 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12323 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12324 ErrorInfo.NoteLoc = this->X->getExprLoc();
12325 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12326 ErrorInfo.NoteRange = this->X->getSourceRange();
12327 return false;
12328 }
12329
12330 this->V = BO->getLHS();
12331
12332 return true;
12333 };
12334
12335 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12336 return false;
12337 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12338 return false;
12339 if (!CheckUpdateStmt(UpdateStmt))
12340 return false;
12341 } else {
12342 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12343 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12344 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12345 return false;
12346 }
12347
12348 return checkType(ErrorInfo);
12349}
12350} // namespace
12351
12353 Stmt *AStmt,
12354 SourceLocation StartLoc,
12355 SourceLocation EndLoc) {
12356 ASTContext &Context = getASTContext();
12357 // Register location of the first atomic directive.
12358 DSAStack->addAtomicDirectiveLoc(StartLoc);
12359 if (!AStmt)
12360 return StmtError();
12361
12362 // 1.2.2 OpenMP Language Terminology
12363 // Structured block - An executable statement with a single entry at the
12364 // top and a single exit at the bottom.
12365 // The point of exit cannot be a branch out of the structured block.
12366 // longjmp() and throw() must not violate the entry/exit criteria.
12367 OpenMPClauseKind AtomicKind = OMPC_unknown;
12368 SourceLocation AtomicKindLoc;
12369 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12370 SourceLocation MemOrderLoc;
12371 bool MutexClauseEncountered = false;
12372 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12373 for (const OMPClause *C : Clauses) {
12374 switch (C->getClauseKind()) {
12375 case OMPC_read:
12376 case OMPC_write:
12377 case OMPC_update:
12378 MutexClauseEncountered = true;
12379 [[fallthrough]];
12380 case OMPC_capture:
12381 case OMPC_compare: {
12382 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12383 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12384 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12385 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12386 << getOpenMPClauseName(AtomicKind);
12387 } else {
12388 AtomicKind = C->getClauseKind();
12389 AtomicKindLoc = C->getBeginLoc();
12390 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12391 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12392 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12393 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12394 << getOpenMPClauseName(AtomicKind);
12395 }
12396 }
12397 break;
12398 }
12399 case OMPC_weak:
12400 case OMPC_fail: {
12401 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12402 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12403 << getOpenMPClauseName(C->getClauseKind())
12404 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12405 return StmtError();
12406 }
12407 break;
12408 }
12409 case OMPC_seq_cst:
12410 case OMPC_acq_rel:
12411 case OMPC_acquire:
12412 case OMPC_release:
12413 case OMPC_relaxed: {
12414 if (MemOrderKind != OMPC_unknown) {
12415 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12416 << getOpenMPDirectiveName(OMPD_atomic) << 0
12417 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12418 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12419 << getOpenMPClauseName(MemOrderKind);
12420 } else {
12421 MemOrderKind = C->getClauseKind();
12422 MemOrderLoc = C->getBeginLoc();
12423 }
12424 break;
12425 }
12426 // The following clauses are allowed, but we don't need to do anything here.
12427 case OMPC_hint:
12428 break;
12429 default:
12430 llvm_unreachable("unknown clause is encountered");
12431 }
12432 }
12433 bool IsCompareCapture = false;
12434 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12435 EncounteredAtomicKinds.contains(OMPC_capture)) {
12436 IsCompareCapture = true;
12437 AtomicKind = OMPC_compare;
12438 }
12439 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12440 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12441 // release.
12442 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12443 // acquire.
12444 // If atomic-clause is update or not present then memory-order-clause must not
12445 // be acq_rel or acquire.
12446 if ((AtomicKind == OMPC_read &&
12447 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12448 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12449 AtomicKind == OMPC_unknown) &&
12450 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12451 SourceLocation Loc = AtomicKindLoc;
12452 if (AtomicKind == OMPC_unknown)
12453 Loc = StartLoc;
12454 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12455 << getOpenMPClauseName(AtomicKind)
12456 << (AtomicKind == OMPC_unknown ? 1 : 0)
12457 << getOpenMPClauseName(MemOrderKind);
12458 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12459 << getOpenMPClauseName(MemOrderKind);
12460 }
12461
12462 Stmt *Body = AStmt;
12463 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12464 Body = EWC->getSubExpr();
12465
12466 Expr *X = nullptr;
12467 Expr *V = nullptr;
12468 Expr *E = nullptr;
12469 Expr *UE = nullptr;
12470 Expr *D = nullptr;
12471 Expr *CE = nullptr;
12472 Expr *R = nullptr;
12473 bool IsXLHSInRHSPart = false;
12474 bool IsPostfixUpdate = false;
12475 bool IsFailOnly = false;
12476 // OpenMP [2.12.6, atomic Construct]
12477 // In the next expressions:
12478 // * x and v (as applicable) are both l-value expressions with scalar type.
12479 // * During the execution of an atomic region, multiple syntactic
12480 // occurrences of x must designate the same storage location.
12481 // * Neither of v and expr (as applicable) may access the storage location
12482 // designated by x.
12483 // * Neither of x and expr (as applicable) may access the storage location
12484 // designated by v.
12485 // * expr is an expression with scalar type.
12486 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12487 // * binop, binop=, ++, and -- are not overloaded operators.
12488 // * The expression x binop expr must be numerically equivalent to x binop
12489 // (expr). This requirement is satisfied if the operators in expr have
12490 // precedence greater than binop, or by using parentheses around expr or
12491 // subexpressions of expr.
12492 // * The expression expr binop x must be numerically equivalent to (expr)
12493 // binop x. This requirement is satisfied if the operators in expr have
12494 // precedence equal to or greater than binop, or by using parentheses around
12495 // expr or subexpressions of expr.
12496 // * For forms that allow multiple occurrences of x, the number of times
12497 // that x is evaluated is unspecified.
12498 if (AtomicKind == OMPC_read) {
12499 enum {
12500 NotAnExpression,
12501 NotAnAssignmentOp,
12502 NotAScalarType,
12503 NotAnLValue,
12504 NoError
12505 } ErrorFound = NoError;
12506 SourceLocation ErrorLoc, NoteLoc;
12507 SourceRange ErrorRange, NoteRange;
12508 // If clause is read:
12509 // v = x;
12510 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12511 const auto *AtomicBinOp =
12512 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12513 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12514 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12515 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12516 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12517 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12518 if (!X->isLValue() || !V->isLValue()) {
12519 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12520 ErrorFound = NotAnLValue;
12521 ErrorLoc = AtomicBinOp->getExprLoc();
12522 ErrorRange = AtomicBinOp->getSourceRange();
12523 NoteLoc = NotLValueExpr->getExprLoc();
12524 NoteRange = NotLValueExpr->getSourceRange();
12525 }
12526 } else if (!X->isInstantiationDependent() ||
12527 !V->isInstantiationDependent()) {
12528 const Expr *NotScalarExpr =
12529 (X->isInstantiationDependent() || X->getType()->isScalarType())
12530 ? V
12531 : X;
12532 ErrorFound = NotAScalarType;
12533 ErrorLoc = AtomicBinOp->getExprLoc();
12534 ErrorRange = AtomicBinOp->getSourceRange();
12535 NoteLoc = NotScalarExpr->getExprLoc();
12536 NoteRange = NotScalarExpr->getSourceRange();
12537 }
12538 } else if (!AtomicBody->isInstantiationDependent()) {
12539 ErrorFound = NotAnAssignmentOp;
12540 ErrorLoc = AtomicBody->getExprLoc();
12541 ErrorRange = AtomicBody->getSourceRange();
12542 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12543 : AtomicBody->getExprLoc();
12544 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12545 : AtomicBody->getSourceRange();
12546 }
12547 } else {
12548 ErrorFound = NotAnExpression;
12549 NoteLoc = ErrorLoc = Body->getBeginLoc();
12550 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12551 }
12552 if (ErrorFound != NoError) {
12553 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12554 << ErrorRange;
12555 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12556 << ErrorFound << NoteRange;
12557 return StmtError();
12558 }
12560 V = X = nullptr;
12561 } else if (AtomicKind == OMPC_write) {
12562 enum {
12563 NotAnExpression,
12564 NotAnAssignmentOp,
12565 NotAScalarType,
12566 NotAnLValue,
12567 NoError
12568 } ErrorFound = NoError;
12569 SourceLocation ErrorLoc, NoteLoc;
12570 SourceRange ErrorRange, NoteRange;
12571 // If clause is write:
12572 // x = expr;
12573 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12574 const auto *AtomicBinOp =
12575 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12576 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12577 X = AtomicBinOp->getLHS();
12578 E = AtomicBinOp->getRHS();
12579 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12581 if (!X->isLValue()) {
12582 ErrorFound = NotAnLValue;
12583 ErrorLoc = AtomicBinOp->getExprLoc();
12584 ErrorRange = AtomicBinOp->getSourceRange();
12585 NoteLoc = X->getExprLoc();
12586 NoteRange = X->getSourceRange();
12587 }
12588 } else if (!X->isInstantiationDependent() ||
12590 const Expr *NotScalarExpr =
12591 (X->isInstantiationDependent() || X->getType()->isScalarType())
12592 ? E
12593 : X;
12594 ErrorFound = NotAScalarType;
12595 ErrorLoc = AtomicBinOp->getExprLoc();
12596 ErrorRange = AtomicBinOp->getSourceRange();
12597 NoteLoc = NotScalarExpr->getExprLoc();
12598 NoteRange = NotScalarExpr->getSourceRange();
12599 }
12600 } else if (!AtomicBody->isInstantiationDependent()) {
12601 ErrorFound = NotAnAssignmentOp;
12602 ErrorLoc = AtomicBody->getExprLoc();
12603 ErrorRange = AtomicBody->getSourceRange();
12604 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12605 : AtomicBody->getExprLoc();
12606 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12607 : AtomicBody->getSourceRange();
12608 }
12609 } else {
12610 ErrorFound = NotAnExpression;
12611 NoteLoc = ErrorLoc = Body->getBeginLoc();
12612 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12613 }
12614 if (ErrorFound != NoError) {
12615 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12616 << ErrorRange;
12617 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12618 << ErrorFound << NoteRange;
12619 return StmtError();
12620 }
12622 E = X = nullptr;
12623 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12624 // If clause is update:
12625 // x++;
12626 // x--;
12627 // ++x;
12628 // --x;
12629 // x binop= expr;
12630 // x = x binop expr;
12631 // x = expr binop x;
12632 OpenMPAtomicUpdateChecker Checker(SemaRef);
12633 if (Checker.checkStatement(
12634 Body,
12635 (AtomicKind == OMPC_update)
12636 ? diag::err_omp_atomic_update_not_expression_statement
12637 : diag::err_omp_atomic_not_expression_statement,
12638 diag::note_omp_atomic_update))
12639 return StmtError();
12641 E = Checker.getExpr();
12642 X = Checker.getX();
12643 UE = Checker.getUpdateExpr();
12644 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12645 }
12646 } else if (AtomicKind == OMPC_capture) {
12647 enum {
12648 NotAnAssignmentOp,
12649 NotACompoundStatement,
12650 NotTwoSubstatements,
12651 NotASpecificExpression,
12652 NoError
12653 } ErrorFound = NoError;
12654 SourceLocation ErrorLoc, NoteLoc;
12655 SourceRange ErrorRange, NoteRange;
12656 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12657 // If clause is a capture:
12658 // v = x++;
12659 // v = x--;
12660 // v = ++x;
12661 // v = --x;
12662 // v = x binop= expr;
12663 // v = x = x binop expr;
12664 // v = x = expr binop x;
12665 const auto *AtomicBinOp =
12666 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12667 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12668 V = AtomicBinOp->getLHS();
12669 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12670 OpenMPAtomicUpdateChecker Checker(SemaRef);
12671 if (Checker.checkStatement(
12672 Body, diag::err_omp_atomic_capture_not_expression_statement,
12673 diag::note_omp_atomic_update))
12674 return StmtError();
12675 E = Checker.getExpr();
12676 X = Checker.getX();
12677 UE = Checker.getUpdateExpr();
12678 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12679 IsPostfixUpdate = Checker.isPostfixUpdate();
12680 } else if (!AtomicBody->isInstantiationDependent()) {
12681 ErrorLoc = AtomicBody->getExprLoc();
12682 ErrorRange = AtomicBody->getSourceRange();
12683 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12684 : AtomicBody->getExprLoc();
12685 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12686 : AtomicBody->getSourceRange();
12687 ErrorFound = NotAnAssignmentOp;
12688 }
12689 if (ErrorFound != NoError) {
12690 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12691 << ErrorRange;
12692 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12693 return StmtError();
12694 }
12696 UE = V = E = X = nullptr;
12697 } else {
12698 // If clause is a capture:
12699 // { v = x; x = expr; }
12700 // { v = x; x++; }
12701 // { v = x; x--; }
12702 // { v = x; ++x; }
12703 // { v = x; --x; }
12704 // { v = x; x binop= expr; }
12705 // { v = x; x = x binop expr; }
12706 // { v = x; x = expr binop x; }
12707 // { x++; v = x; }
12708 // { x--; v = x; }
12709 // { ++x; v = x; }
12710 // { --x; v = x; }
12711 // { x binop= expr; v = x; }
12712 // { x = x binop expr; v = x; }
12713 // { x = expr binop x; v = x; }
12714 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12715 // Check that this is { expr1; expr2; }
12716 if (CS->size() == 2) {
12717 Stmt *First = CS->body_front();
12718 Stmt *Second = CS->body_back();
12719 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12720 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12721 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12722 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12723 // Need to find what subexpression is 'v' and what is 'x'.
12724 OpenMPAtomicUpdateChecker Checker(SemaRef);
12725 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12726 BinaryOperator *BinOp = nullptr;
12727 if (IsUpdateExprFound) {
12728 BinOp = dyn_cast<BinaryOperator>(First);
12729 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12730 }
12731 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12732 // { v = x; x++; }
12733 // { v = x; x--; }
12734 // { v = x; ++x; }
12735 // { v = x; --x; }
12736 // { v = x; x binop= expr; }
12737 // { v = x; x = x binop expr; }
12738 // { v = x; x = expr binop x; }
12739 // Check that the first expression has form v = x.
12740 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12741 llvm::FoldingSetNodeID XId, PossibleXId;
12742 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12743 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12744 IsUpdateExprFound = XId == PossibleXId;
12745 if (IsUpdateExprFound) {
12746 V = BinOp->getLHS();
12747 X = Checker.getX();
12748 E = Checker.getExpr();
12749 UE = Checker.getUpdateExpr();
12750 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12751 IsPostfixUpdate = true;
12752 }
12753 }
12754 if (!IsUpdateExprFound) {
12755 IsUpdateExprFound = !Checker.checkStatement(First);
12756 BinOp = nullptr;
12757 if (IsUpdateExprFound) {
12758 BinOp = dyn_cast<BinaryOperator>(Second);
12759 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12760 }
12761 if (IsUpdateExprFound &&
12763 // { x++; v = x; }
12764 // { x--; v = x; }
12765 // { ++x; v = x; }
12766 // { --x; v = x; }
12767 // { x binop= expr; v = x; }
12768 // { x = x binop expr; v = x; }
12769 // { x = expr binop x; v = x; }
12770 // Check that the second expression has form v = x.
12771 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12772 llvm::FoldingSetNodeID XId, PossibleXId;
12773 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12774 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12775 IsUpdateExprFound = XId == PossibleXId;
12776 if (IsUpdateExprFound) {
12777 V = BinOp->getLHS();
12778 X = Checker.getX();
12779 E = Checker.getExpr();
12780 UE = Checker.getUpdateExpr();
12781 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12782 IsPostfixUpdate = false;
12783 }
12784 }
12785 }
12786 if (!IsUpdateExprFound) {
12787 // { v = x; x = expr; }
12788 auto *FirstExpr = dyn_cast<Expr>(First);
12789 auto *SecondExpr = dyn_cast<Expr>(Second);
12790 if (!FirstExpr || !SecondExpr ||
12791 !(FirstExpr->isInstantiationDependent() ||
12792 SecondExpr->isInstantiationDependent())) {
12793 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12794 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12795 ErrorFound = NotAnAssignmentOp;
12796 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12797 : First->getBeginLoc();
12798 NoteRange = ErrorRange = FirstBinOp
12799 ? FirstBinOp->getSourceRange()
12800 : SourceRange(ErrorLoc, ErrorLoc);
12801 } else {
12802 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12803 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12804 ErrorFound = NotAnAssignmentOp;
12805 NoteLoc = ErrorLoc = SecondBinOp
12806 ? SecondBinOp->getOperatorLoc()
12807 : Second->getBeginLoc();
12808 NoteRange = ErrorRange =
12809 SecondBinOp ? SecondBinOp->getSourceRange()
12810 : SourceRange(ErrorLoc, ErrorLoc);
12811 } else {
12812 Expr *PossibleXRHSInFirst =
12813 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12814 Expr *PossibleXLHSInSecond =
12815 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12816 llvm::FoldingSetNodeID X1Id, X2Id;
12817 PossibleXRHSInFirst->Profile(X1Id, Context,
12818 /*Canonical=*/true);
12819 PossibleXLHSInSecond->Profile(X2Id, Context,
12820 /*Canonical=*/true);
12821 IsUpdateExprFound = X1Id == X2Id;
12822 if (IsUpdateExprFound) {
12823 V = FirstBinOp->getLHS();
12824 X = SecondBinOp->getLHS();
12825 E = SecondBinOp->getRHS();
12826 UE = nullptr;
12827 IsXLHSInRHSPart = false;
12828 IsPostfixUpdate = true;
12829 } else {
12830 ErrorFound = NotASpecificExpression;
12831 ErrorLoc = FirstBinOp->getExprLoc();
12832 ErrorRange = FirstBinOp->getSourceRange();
12833 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12834 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12835 }
12836 }
12837 }
12838 }
12839 }
12840 } else {
12841 NoteLoc = ErrorLoc = Body->getBeginLoc();
12842 NoteRange = ErrorRange =
12843 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12844 ErrorFound = NotTwoSubstatements;
12845 }
12846 } else {
12847 NoteLoc = ErrorLoc = Body->getBeginLoc();
12848 NoteRange = ErrorRange =
12849 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12850 ErrorFound = NotACompoundStatement;
12851 }
12852 }
12853 if (ErrorFound != NoError) {
12854 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12855 << ErrorRange;
12856 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12857 return StmtError();
12858 }
12860 UE = V = E = X = nullptr;
12861 } else if (AtomicKind == OMPC_compare) {
12862 if (IsCompareCapture) {
12863 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12864 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12865 if (!Checker.checkStmt(Body, ErrorInfo)) {
12866 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12867 << ErrorInfo.ErrorRange;
12868 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12869 << ErrorInfo.Error << ErrorInfo.NoteRange;
12870 return StmtError();
12871 }
12872 X = Checker.getX();
12873 E = Checker.getE();
12874 D = Checker.getD();
12875 CE = Checker.getCond();
12876 V = Checker.getV();
12877 R = Checker.getR();
12878 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12879 IsXLHSInRHSPart = Checker.isXBinopExpr();
12880 IsFailOnly = Checker.isFailOnly();
12881 IsPostfixUpdate = Checker.isPostfixUpdate();
12882 } else {
12883 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12884 OpenMPAtomicCompareChecker Checker(SemaRef);
12885 if (!Checker.checkStmt(Body, ErrorInfo)) {
12886 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12887 << ErrorInfo.ErrorRange;
12888 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12889 << ErrorInfo.Error << ErrorInfo.NoteRange;
12890 return StmtError();
12891 }
12892 X = Checker.getX();
12893 E = Checker.getE();
12894 D = Checker.getD();
12895 CE = Checker.getCond();
12896 // The weak clause may only appear if the resulting atomic operation is
12897 // an atomic conditional update for which the comparison tests for
12898 // equality. It was not possible to do this check in
12899 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12900 // could not be performed (Clauses are not available).
12901 auto *It = find_if(Clauses, [](OMPClause *C) {
12902 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12903 });
12904 if (It != Clauses.end()) {
12905 auto *Cond = dyn_cast<BinaryOperator>(CE);
12906 if (Cond->getOpcode() != BO_EQ) {
12907 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12908 ErrorInfo.ErrorLoc = Cond->getExprLoc();
12909 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12910 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12911
12912 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12913 << ErrorInfo.ErrorRange;
12914 return StmtError();
12915 }
12916 }
12917 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12918 IsXLHSInRHSPart = Checker.isXBinopExpr();
12919 }
12920 }
12921
12923
12925 Context, StartLoc, EndLoc, Clauses, AStmt,
12926 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12927}
12928
12930 Stmt *AStmt,
12931 SourceLocation StartLoc,
12932 SourceLocation EndLoc) {
12933 if (!AStmt)
12934 return StmtError();
12935
12936 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
12937
12938 // OpenMP [2.16, Nesting of Regions]
12939 // If specified, a teams construct must be contained within a target
12940 // construct. That target construct must contain no statements or directives
12941 // outside of the teams construct.
12942 if (DSAStack->hasInnerTeamsRegion()) {
12943 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12944 bool OMPTeamsFound = true;
12945 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12946 auto I = CS->body_begin();
12947 while (I != CS->body_end()) {
12948 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12949 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12950 if (!IsTeams || I != CS->body_begin()) {
12951 OMPTeamsFound = false;
12952 if (IsTeams && I != CS->body_begin()) {
12953 // This is the two teams case. Since the InnerTeamsRegionLoc will
12954 // point to this second one reset the iterator to the other teams.
12955 --I;
12956 }
12957 break;
12958 }
12959 ++I;
12960 }
12961 assert(I != CS->body_end() && "Not found statement");
12962 S = *I;
12963 } else {
12964 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12965 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12966 }
12967 if (!OMPTeamsFound) {
12968 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12969 Diag(DSAStack->getInnerTeamsRegionLoc(),
12970 diag::note_omp_nested_teams_construct_here);
12971 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12972 << isa<OMPExecutableDirective>(S);
12973 return StmtError();
12974 }
12975 }
12976
12977 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12978 AStmt);
12979}
12980
12982 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12983 SourceLocation EndLoc) {
12984 if (!AStmt)
12985 return StmtError();
12986
12987 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
12988
12990 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12991 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12992}
12993
12995 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12996 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12997 if (!AStmt)
12998 return StmtError();
12999
13000 CapturedStmt *CS =
13001 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13002
13004 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13005 // define the nested loops number.
13006 unsigned NestedLoopCount =
13007 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13008 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13009 VarsWithImplicitDSA, B);
13010 if (NestedLoopCount == 0)
13011 return StmtError();
13012
13013 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13014 return StmtError();
13015
13017 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13018 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13019}
13020
13021/// Check for existence of a map clause in the list of clauses.
13023 const OpenMPClauseKind K) {
13024 return llvm::any_of(
13025 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13026}
13027
13028template <typename... Params>
13030 const Params... ClauseTypes) {
13031 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13032}
13033
13034/// Check if the variables in the mapping clause are externally visible.
13036 for (const OMPClause *C : Clauses) {
13037 if (auto *TC = dyn_cast<OMPToClause>(C))
13038 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13039 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13040 (VD->isExternallyVisible() &&
13041 VD->getVisibility() != HiddenVisibility);
13042 });
13043 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13044 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13045 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13046 (VD->isExternallyVisible() &&
13047 VD->getVisibility() != HiddenVisibility);
13048 });
13049 }
13050
13051 return true;
13052}
13053
13056 Stmt *AStmt, SourceLocation StartLoc,
13057 SourceLocation EndLoc) {
13058 if (!AStmt)
13059 return StmtError();
13060
13061 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13062
13063 // OpenMP [2.12.2, target data Construct, Restrictions]
13064 // At least one map, use_device_addr or use_device_ptr clause must appear on
13065 // the directive.
13066 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13067 (getLangOpts().OpenMP < 50 ||
13068 !hasClauses(Clauses, OMPC_use_device_addr))) {
13069 StringRef Expected;
13070 if (getLangOpts().OpenMP < 50)
13071 Expected = "'map' or 'use_device_ptr'";
13072 else
13073 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13074 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13075 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13076 return StmtError();
13077 }
13078
13080
13081 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13082 Clauses, AStmt);
13083}
13084
13086 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13087 SourceLocation EndLoc, Stmt *AStmt) {
13088 if (!AStmt)
13089 return StmtError();
13090
13091 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13092
13093 // OpenMP [2.10.2, Restrictions, p. 99]
13094 // At least one map clause must appear on the directive.
13095 if (!hasClauses(Clauses, OMPC_map)) {
13096 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13097 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13098 return StmtError();
13099 }
13100
13101 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13102 Clauses, AStmt);
13103}
13104
13106 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13107 SourceLocation EndLoc, Stmt *AStmt) {
13108 if (!AStmt)
13109 return StmtError();
13110
13111 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13112
13113 // OpenMP [2.10.3, Restrictions, p. 102]
13114 // At least one map clause must appear on the directive.
13115 if (!hasClauses(Clauses, OMPC_map)) {
13116 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13117 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13118 return StmtError();
13119 }
13120
13121 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13122 Clauses, AStmt);
13123}
13124
13126 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13127 SourceLocation EndLoc, Stmt *AStmt) {
13128 if (!AStmt)
13129 return StmtError();
13130
13131 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13132
13133 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13134 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13135 return StmtError();
13136 }
13137
13138 if (!isClauseMappable(Clauses)) {
13139 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13140 return StmtError();
13141 }
13142
13143 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13144 Clauses, AStmt);
13145}
13146
13147/// This checks whether a \p ClauseType clause \p C has at most \p Max
13148/// expression. If not, a diag of number \p Diag will be emitted.
13149template <typename ClauseType>
13150static bool checkNumExprsInClause(SemaBase &SemaRef,
13151 ArrayRef<OMPClause *> Clauses,
13152 unsigned MaxNum, unsigned Diag) {
13153 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13154 if (ClauseItr == Clauses.end())
13155 return true;
13156 const auto *C = cast<ClauseType>(*ClauseItr);
13157 auto VarList = C->getVarRefs();
13158 if (VarList.size() > MaxNum) {
13159 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13160 << getOpenMPClauseName(C->getClauseKind());
13161 return false;
13162 }
13163 return true;
13164}
13165
13167 Stmt *AStmt,
13168 SourceLocation StartLoc,
13169 SourceLocation EndLoc) {
13170 if (!AStmt)
13171 return StmtError();
13172
13173 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13174 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13175 !checkNumExprsInClause<OMPThreadLimitClause>(
13176 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13177 return StmtError();
13178
13179 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13180 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13181 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13182
13183 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13184
13185 DSAStack->setParentTeamsRegionLoc(StartLoc);
13186
13187 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13188 AStmt);
13189}
13190
13192 SourceLocation StartLoc, SourceLocation EndLoc,
13193 OpenMPDirectiveKind CancelRegion) {
13194 if (DSAStack->isParentNowaitRegion()) {
13195 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13196 return StmtError();
13197 }
13198 if (DSAStack->isParentOrderedRegion()) {
13199 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13200 return StmtError();
13201 }
13203 EndLoc, CancelRegion);
13204}
13205
13207 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13208 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13209 if (DSAStack->isParentNowaitRegion()) {
13210 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13211 return StmtError();
13212 }
13213 if (DSAStack->isParentOrderedRegion()) {
13214 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13215 return StmtError();
13216 }
13217 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13218 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13219 CancelRegion);
13220}
13221
13223 ArrayRef<OMPClause *> Clauses) {
13224 const OMPClause *ReductionClause = nullptr;
13225 const OMPClause *NogroupClause = nullptr;
13226 for (const OMPClause *C : Clauses) {
13227 if (C->getClauseKind() == OMPC_reduction) {
13228 ReductionClause = C;
13229 if (NogroupClause)
13230 break;
13231 continue;
13232 }
13233 if (C->getClauseKind() == OMPC_nogroup) {
13234 NogroupClause = C;
13235 if (ReductionClause)
13236 break;
13237 continue;
13238 }
13239 }
13240 if (ReductionClause && NogroupClause) {
13241 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13242 << SourceRange(NogroupClause->getBeginLoc(),
13243 NogroupClause->getEndLoc());
13244 return true;
13245 }
13246 return false;
13247}
13248
13250 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13251 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13252 if (!AStmt)
13253 return StmtError();
13254
13255 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13257 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13258 // define the nested loops number.
13259 unsigned NestedLoopCount =
13260 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13261 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13262 *DSAStack, VarsWithImplicitDSA, B);
13263 if (NestedLoopCount == 0)
13264 return StmtError();
13265
13266 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13267 "omp for loop exprs were not built");
13268
13269 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13270 // The grainsize clause and num_tasks clause are mutually exclusive and may
13271 // not appear on the same taskloop directive.
13273 {OMPC_grainsize, OMPC_num_tasks}))
13274 return StmtError();
13275 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13276 // If a reduction clause is present on the taskloop directive, the nogroup
13277 // clause must not be specified.
13279 return StmtError();
13280
13282 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13283 NestedLoopCount, Clauses, AStmt, B,
13284 DSAStack->isCancelRegion());
13285}
13286
13288 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13289 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13290 if (!AStmt)
13291 return StmtError();
13292
13293 CapturedStmt *CS =
13294 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13295
13296 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13298 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13299 // define the nested loops number.
13300 unsigned NestedLoopCount =
13301 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13302 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13303 VarsWithImplicitDSA, B);
13304 if (NestedLoopCount == 0)
13305 return StmtError();
13306
13307 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13308 return StmtError();
13309
13310 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13311 // The grainsize clause and num_tasks clause are mutually exclusive and may
13312 // not appear on the same taskloop directive.
13314 {OMPC_grainsize, OMPC_num_tasks}))
13315 return StmtError();
13316 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13317 // If a reduction clause is present on the taskloop directive, the nogroup
13318 // clause must not be specified.
13320 return StmtError();
13322 return StmtError();
13323
13324 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13325 NestedLoopCount, Clauses, AStmt, B);
13326}
13327
13329 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13330 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13331 if (!AStmt)
13332 return StmtError();
13333
13334 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13336 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13337 // define the nested loops number.
13338 unsigned NestedLoopCount =
13339 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13340 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13341 *DSAStack, VarsWithImplicitDSA, B);
13342 if (NestedLoopCount == 0)
13343 return StmtError();
13344
13345 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13346 "omp for loop exprs were not built");
13347
13348 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13349 // The grainsize clause and num_tasks clause are mutually exclusive and may
13350 // not appear on the same taskloop directive.
13352 {OMPC_grainsize, OMPC_num_tasks}))
13353 return StmtError();
13354 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13355 // If a reduction clause is present on the taskloop directive, the nogroup
13356 // clause must not be specified.
13358 return StmtError();
13359
13361 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13362 NestedLoopCount, Clauses, AStmt, B,
13363 DSAStack->isCancelRegion());
13364}
13365
13367 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13368 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13369 if (!AStmt)
13370 return StmtError();
13371
13372 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13374 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13375 // define the nested loops number.
13376 unsigned NestedLoopCount =
13377 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13378 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13379 *DSAStack, VarsWithImplicitDSA, B);
13380 if (NestedLoopCount == 0)
13381 return StmtError();
13382
13383 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13384 "omp for loop exprs were not built");
13385
13386 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13387 // The grainsize clause and num_tasks clause are mutually exclusive and may
13388 // not appear on the same taskloop directive.
13390 {OMPC_grainsize, OMPC_num_tasks}))
13391 return StmtError();
13392 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13393 // If a reduction clause is present on the taskloop directive, the nogroup
13394 // clause must not be specified.
13396 return StmtError();
13397
13399 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13400 NestedLoopCount, Clauses, AStmt, B,
13401 DSAStack->isCancelRegion());
13402}
13403
13405 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13406 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13407 if (!AStmt)
13408 return StmtError();
13409
13410 CapturedStmt *CS =
13411 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13412
13413 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13415 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13416 // define the nested loops number.
13417 unsigned NestedLoopCount =
13418 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13419 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13420 VarsWithImplicitDSA, B);
13421 if (NestedLoopCount == 0)
13422 return StmtError();
13423
13424 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13425 return StmtError();
13426
13427 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13428 // The grainsize clause and num_tasks clause are mutually exclusive and may
13429 // not appear on the same taskloop directive.
13431 {OMPC_grainsize, OMPC_num_tasks}))
13432 return StmtError();
13433 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13434 // If a reduction clause is present on the taskloop directive, the nogroup
13435 // clause must not be specified.
13437 return StmtError();
13439 return StmtError();
13440
13442 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13443}
13444
13446 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13447 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13448 if (!AStmt)
13449 return StmtError();
13450
13451 CapturedStmt *CS =
13452 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13453
13454 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13456 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13457 // define the nested loops number.
13458 unsigned NestedLoopCount =
13459 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13460 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13461 VarsWithImplicitDSA, B);
13462 if (NestedLoopCount == 0)
13463 return StmtError();
13464
13465 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13466 return StmtError();
13467
13468 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13469 // The grainsize clause and num_tasks clause are mutually exclusive and may
13470 // not appear on the same taskloop directive.
13472 {OMPC_grainsize, OMPC_num_tasks}))
13473 return StmtError();
13474 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13475 // If a reduction clause is present on the taskloop directive, the nogroup
13476 // clause must not be specified.
13478 return StmtError();
13480 return StmtError();
13481
13483 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13484}
13485
13487 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13488 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13489 if (!AStmt)
13490 return StmtError();
13491
13492 CapturedStmt *CS =
13493 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13494
13496 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13497 // define the nested loops number.
13498 unsigned NestedLoopCount = checkOpenMPLoop(
13499 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13500 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13501 VarsWithImplicitDSA, B);
13502 if (NestedLoopCount == 0)
13503 return StmtError();
13504
13505 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13506 "omp for loop exprs were not built");
13507
13508 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13509 // The grainsize clause and num_tasks clause are mutually exclusive and may
13510 // not appear on the same taskloop directive.
13512 {OMPC_grainsize, OMPC_num_tasks}))
13513 return StmtError();
13514 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13515 // If a reduction clause is present on the taskloop directive, the nogroup
13516 // clause must not be specified.
13518 return StmtError();
13519
13521 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13522 DSAStack->isCancelRegion());
13523}
13524
13526 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13527 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13528 if (!AStmt)
13529 return StmtError();
13530
13531 CapturedStmt *CS =
13532 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13533
13535 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13536 // define the nested loops number.
13537 unsigned NestedLoopCount = checkOpenMPLoop(
13538 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13539 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13540 VarsWithImplicitDSA, B);
13541 if (NestedLoopCount == 0)
13542 return StmtError();
13543
13544 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13545 "omp for loop exprs were not built");
13546
13547 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13548 // The grainsize clause and num_tasks clause are mutually exclusive and may
13549 // not appear on the same taskloop directive.
13551 {OMPC_grainsize, OMPC_num_tasks}))
13552 return StmtError();
13553 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13554 // If a reduction clause is present on the taskloop directive, the nogroup
13555 // clause must not be specified.
13557 return StmtError();
13558
13560 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13561 DSAStack->isCancelRegion());
13562}
13563
13565 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13566 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13567 if (!AStmt)
13568 return StmtError();
13569
13571 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13572
13574 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13575 // define the nested loops number.
13576 unsigned NestedLoopCount = checkOpenMPLoop(
13577 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13578 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13579 VarsWithImplicitDSA, B);
13580 if (NestedLoopCount == 0)
13581 return StmtError();
13582
13583 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13584 return StmtError();
13585
13586 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13587 // The grainsize clause and num_tasks clause are mutually exclusive and may
13588 // not appear on the same taskloop directive.
13590 {OMPC_grainsize, OMPC_num_tasks}))
13591 return StmtError();
13592 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13593 // If a reduction clause is present on the taskloop directive, the nogroup
13594 // clause must not be specified.
13596 return StmtError();
13598 return StmtError();
13599
13601 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13602}
13603
13605 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13606 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13607 if (!AStmt)
13608 return StmtError();
13609
13611 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13612
13614 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13615 // define the nested loops number.
13616 unsigned NestedLoopCount = checkOpenMPLoop(
13617 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13618 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13619 VarsWithImplicitDSA, B);
13620 if (NestedLoopCount == 0)
13621 return StmtError();
13622
13623 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13624 return StmtError();
13625
13626 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13627 // The grainsize clause and num_tasks clause are mutually exclusive and may
13628 // not appear on the same taskloop directive.
13630 {OMPC_grainsize, OMPC_num_tasks}))
13631 return StmtError();
13632 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13633 // If a reduction clause is present on the taskloop directive, the nogroup
13634 // clause must not be specified.
13636 return StmtError();
13638 return StmtError();
13639
13641 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13642}
13643
13645 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13646 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13647 if (!AStmt)
13648 return StmtError();
13649
13650 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13652 // In presence of clause 'collapse' with number of loops, it will
13653 // define the nested loops number.
13654 unsigned NestedLoopCount =
13655 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13656 nullptr /*ordered not a clause on distribute*/, AStmt,
13657 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13658 if (NestedLoopCount == 0)
13659 return StmtError();
13660
13661 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13662 "omp for loop exprs were not built");
13663
13665 auto *DistributeDirective = OMPDistributeDirective::Create(
13666 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13667 return DistributeDirective;
13668}
13669
13671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13673 if (!AStmt)
13674 return StmtError();
13675
13676 CapturedStmt *CS =
13677 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13678
13680 // In presence of clause 'collapse' with number of loops, it will
13681 // define the nested loops number.
13682 unsigned NestedLoopCount = checkOpenMPLoop(
13683 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13684 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13685 VarsWithImplicitDSA, B);
13686 if (NestedLoopCount == 0)
13687 return StmtError();
13688
13689 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13690 "omp for loop exprs were not built");
13691
13693 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13694 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13695}
13696
13698 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13699 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13700 if (!AStmt)
13701 return StmtError();
13702
13704 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13705
13707 // In presence of clause 'collapse' with number of loops, it will
13708 // define the nested loops number.
13709 unsigned NestedLoopCount = checkOpenMPLoop(
13710 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13711 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13712 VarsWithImplicitDSA, B);
13713 if (NestedLoopCount == 0)
13714 return StmtError();
13715
13716 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13717 return StmtError();
13718
13720 return StmtError();
13721
13723 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13724}
13725
13727 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13728 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13729 if (!AStmt)
13730 return StmtError();
13731
13732 CapturedStmt *CS =
13733 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
13734
13736 // In presence of clause 'collapse' with number of loops, it will
13737 // define the nested loops number.
13738 unsigned NestedLoopCount =
13739 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13740 nullptr /*ordered not a clause on distribute*/, CS,
13741 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13742 if (NestedLoopCount == 0)
13743 return StmtError();
13744
13745 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13746 return StmtError();
13747
13749 return StmtError();
13750
13751 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13752 NestedLoopCount, Clauses, AStmt, B);
13753}
13754
13756 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13757 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13758 if (!AStmt)
13759 return StmtError();
13760
13761 CapturedStmt *CS =
13762 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13763
13765 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13766 // define the nested loops number.
13767 unsigned NestedLoopCount = checkOpenMPLoop(
13768 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13769 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13770 VarsWithImplicitDSA, B);
13771 if (NestedLoopCount == 0)
13772 return StmtError();
13773
13774 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13775 return StmtError();
13776
13778 return StmtError();
13779
13781 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13782}
13783
13785 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13786 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13787 if (!AStmt)
13788 return StmtError();
13789
13790 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13791
13793 // In presence of clause 'collapse' with number of loops, it will define the
13794 // nested loops number.
13795 unsigned NestedLoopCount =
13796 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13797 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13800 return StmtError();
13801
13802 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13803 return StmtError();
13804
13806 return StmtError();
13807
13808 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13809 NestedLoopCount, Clauses, AStmt, B);
13810}
13811
13813 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13814 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13815 if (!AStmt)
13816 return StmtError();
13817
13818 CapturedStmt *CS =
13819 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13820
13822 // In presence of clause 'collapse' with number of loops, it will
13823 // define the nested loops number.
13824 unsigned NestedLoopCount =
13825 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13826 nullptr /*ordered not a clause on distribute*/, CS,
13827 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13828 if (NestedLoopCount == 0)
13829 return StmtError();
13830
13831 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13832 "omp teams distribute loop exprs were not built");
13833
13834 DSAStack->setParentTeamsRegionLoc(StartLoc);
13835
13837 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13838}
13839
13841 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13842 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13843 if (!AStmt)
13844 return StmtError();
13845
13846 CapturedStmt *CS =
13847 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13848
13850 // In presence of clause 'collapse' with number of loops, it will
13851 // define the nested loops number.
13852 unsigned NestedLoopCount = checkOpenMPLoop(
13853 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13854 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13855 VarsWithImplicitDSA, B);
13856 if (NestedLoopCount == 0)
13857 return StmtError();
13858
13859 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13860 return StmtError();
13861
13863 return StmtError();
13864
13865 DSAStack->setParentTeamsRegionLoc(StartLoc);
13866
13868 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13869}
13870
13872 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13873 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13874 if (!AStmt)
13875 return StmtError();
13876
13878 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13879
13881 // In presence of clause 'collapse' with number of loops, it will
13882 // define the nested loops number.
13883 unsigned NestedLoopCount = checkOpenMPLoop(
13884 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13885 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13886 VarsWithImplicitDSA, B);
13887 if (NestedLoopCount == 0)
13888 return StmtError();
13889
13890 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13891 return StmtError();
13892
13894 return StmtError();
13895
13896 DSAStack->setParentTeamsRegionLoc(StartLoc);
13897
13899 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13900}
13901
13903 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13904 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13905 if (!AStmt)
13906 return StmtError();
13907
13909 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13910
13912 // In presence of clause 'collapse' with number of loops, it will
13913 // define the nested loops number.
13914 unsigned NestedLoopCount = checkOpenMPLoop(
13915 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13916 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13917 VarsWithImplicitDSA, B);
13918
13919 if (NestedLoopCount == 0)
13920 return StmtError();
13921
13922 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13923 "omp for loop exprs were not built");
13924
13925 DSAStack->setParentTeamsRegionLoc(StartLoc);
13926
13928 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13929 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13930}
13931
13933 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13934 SourceLocation EndLoc) {
13935 if (!AStmt)
13936 return StmtError();
13937
13938 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
13939
13940 const OMPClause *BareClause = nullptr;
13941 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
13942 hasClauses(Clauses, OMPC_thread_limit);
13943 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
13944 BareClause = C;
13945 return C->getClauseKind() == OMPC_ompx_bare;
13946 });
13947
13948 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13949 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
13950 return StmtError();
13951 }
13952
13953 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
13954 unsigned DiagNo = HasBareClause
13955 ? diag::err_ompx_more_than_three_expr_not_allowed
13956 : diag::err_omp_multi_expr_not_allowed;
13957 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
13958 ClauseMaxNumExprs, DiagNo) ||
13959 !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses,
13960 ClauseMaxNumExprs, DiagNo))
13961 return StmtError();
13962
13963 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
13964 Clauses, AStmt);
13965}
13966
13968 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13969 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13970 if (!AStmt)
13971 return StmtError();
13972
13973 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13974 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13975 !checkNumExprsInClause<OMPThreadLimitClause>(
13976 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13977 return StmtError();
13978
13979 CapturedStmt *CS =
13980 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
13981
13983 // In presence of clause 'collapse' with number of loops, it will
13984 // define the nested loops number.
13985 unsigned NestedLoopCount = checkOpenMPLoop(
13986 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
13987 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13988 VarsWithImplicitDSA, B);
13989 if (NestedLoopCount == 0)
13990 return StmtError();
13991
13992 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13993 "omp target teams distribute loop exprs were not built");
13994
13996 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13997}
13998
14000 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14001 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14002 if (!AStmt)
14003 return StmtError();
14004
14005 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14006 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14007 !checkNumExprsInClause<OMPThreadLimitClause>(
14008 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14009 return StmtError();
14010
14012 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14013
14015 // In presence of clause 'collapse' with number of loops, it will
14016 // define the nested loops number.
14017 unsigned NestedLoopCount = checkOpenMPLoop(
14018 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14019 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14020 VarsWithImplicitDSA, B);
14021 if (NestedLoopCount == 0)
14022 return StmtError();
14023
14024 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14025 return StmtError();
14026
14028 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14029 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14030}
14031
14033 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14034 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14035 if (!AStmt)
14036 return StmtError();
14037
14038 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14039 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14040 !checkNumExprsInClause<OMPThreadLimitClause>(
14041 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14042 return StmtError();
14043
14045 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14046
14048 // In presence of clause 'collapse' with number of loops, it will
14049 // define the nested loops number.
14050 unsigned NestedLoopCount =
14051 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14052 getCollapseNumberExpr(Clauses),
14053 nullptr /*ordered not a clause on distribute*/, CS,
14054 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14055 if (NestedLoopCount == 0)
14056 return StmtError();
14057
14058 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14059 return StmtError();
14060
14062 return StmtError();
14063
14065 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14066}
14067
14069 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14070 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14071 if (!AStmt)
14072 return StmtError();
14073
14074 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14075 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14076 !checkNumExprsInClause<OMPThreadLimitClause>(
14077 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14078 return StmtError();
14079
14081 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14082
14084 // In presence of clause 'collapse' with number of loops, it will
14085 // define the nested loops number.
14086 unsigned NestedLoopCount = checkOpenMPLoop(
14087 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14088 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14089 VarsWithImplicitDSA, B);
14090 if (NestedLoopCount == 0)
14091 return StmtError();
14092
14093 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14094 return StmtError();
14095
14097 return StmtError();
14098
14100 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14101}
14102
14103bool SemaOpenMP::checkTransformableLoopNest(
14104 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14106 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14107 OriginalInits.emplace_back();
14109 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14110 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14111 Stmt *CurStmt) {
14112 VarsWithInheritedDSAType TmpDSA;
14113 unsigned SingleNumLoops =
14114 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14115 TmpDSA, LoopHelpers[Cnt]);
14116 if (SingleNumLoops == 0)
14117 return true;
14118 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14119 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14120 OriginalInits.back().push_back(For->getInit());
14121 Body = For->getBody();
14122 } else {
14123 assert(isa<CXXForRangeStmt>(CurStmt) &&
14124 "Expected canonical for or range-based for loops.");
14125 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14126 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14127 Body = CXXFor->getBody();
14128 }
14129 OriginalInits.emplace_back();
14130 return false;
14131 },
14132 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14133 Stmt *DependentPreInits;
14134 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14135 DependentPreInits = Dir->getPreInits();
14136 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14137 DependentPreInits = Dir->getPreInits();
14138 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14139 DependentPreInits = Dir->getPreInits();
14140 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14141 DependentPreInits = Dir->getPreInits();
14142 else
14143 llvm_unreachable("Unhandled loop transformation");
14144
14145 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
14146 });
14147 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14148 OriginalInits.pop_back();
14149 return Result;
14150}
14151
14152/// Add preinit statements that need to be propageted from the selected loop.
14153static void addLoopPreInits(ASTContext &Context,
14155 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14156 SmallVectorImpl<Stmt *> &PreInits) {
14157
14158 // For range-based for-statements, ensure that their syntactic sugar is
14159 // executed by adding them as pre-init statements.
14160 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14161 Stmt *RangeInit = CXXRangeFor->getInit();
14162 if (RangeInit)
14163 PreInits.push_back(RangeInit);
14164
14165 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14166 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14167 RangeStmt->getBeginLoc(),
14168 RangeStmt->getEndLoc()));
14169
14170 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14171 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14172 RangeEnd->getBeginLoc(),
14173 RangeEnd->getEndLoc()));
14174 }
14175
14176 llvm::append_range(PreInits, OriginalInit);
14177
14178 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14179 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14180 PreInits.push_back(new (Context) DeclStmt(
14181 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14182 }
14183
14184 // Gather declarations for the data members used as counters.
14185 for (Expr *CounterRef : LoopHelper.Counters) {
14186 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14187 if (isa<OMPCapturedExprDecl>(CounterDecl))
14188 PreInits.push_back(new (Context) DeclStmt(
14189 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14190 }
14191}
14192
14193/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14194/// loop of a construct.
14195static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14196 size_t NumLoops = LoopStmts.size();
14198 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14199 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14200 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14201 LoopStmts[Cnt] = CurStmt;
14202 return false;
14203 });
14204 assert(!is_contained(LoopStmts, nullptr) &&
14205 "Expecting a loop statement for each affected loop");
14206}
14207
14209 Stmt *AStmt,
14210 SourceLocation StartLoc,
14211 SourceLocation EndLoc) {
14212 ASTContext &Context = getASTContext();
14213 Scope *CurScope = SemaRef.getCurScope();
14214
14215 const auto *SizesClause =
14216 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14217 if (!SizesClause ||
14218 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14219 return StmtError();
14220 unsigned NumLoops = SizesClause->getNumSizes();
14221
14222 // Empty statement should only be possible if there already was an error.
14223 if (!AStmt)
14224 return StmtError();
14225
14226 // Verify and diagnose loop nest.
14228 Stmt *Body = nullptr;
14229 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14230 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14231 OriginalInits))
14232 return StmtError();
14233
14234 // Delay tiling to when template is completely instantiated.
14236 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14237 NumLoops, AStmt, nullptr, nullptr);
14238
14239 assert(LoopHelpers.size() == NumLoops &&
14240 "Expecting loop iteration space dimensionality to match number of "
14241 "affected loops");
14242 assert(OriginalInits.size() == NumLoops &&
14243 "Expecting loop iteration space dimensionality to match number of "
14244 "affected loops");
14245
14246 // Collect all affected loop statements.
14247 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14248 collectLoopStmts(AStmt, LoopStmts);
14249
14250 SmallVector<Stmt *, 4> PreInits;
14251 CaptureVars CopyTransformer(SemaRef);
14252
14253 // Create iteration variables for the generated loops.
14254 SmallVector<VarDecl *, 4> FloorIndVars;
14255 SmallVector<VarDecl *, 4> TileIndVars;
14256 FloorIndVars.resize(NumLoops);
14257 TileIndVars.resize(NumLoops);
14258 for (unsigned I = 0; I < NumLoops; ++I) {
14259 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14260
14261 assert(LoopHelper.Counters.size() == 1 &&
14262 "Expect single-dimensional loop iteration space");
14263 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14264 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14265 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14266 QualType CntTy = IterVarRef->getType();
14267
14268 // Iteration variable for the floor (i.e. outer) loop.
14269 {
14270 std::string FloorCntName =
14271 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14272 VarDecl *FloorCntDecl =
14273 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14274 FloorIndVars[I] = FloorCntDecl;
14275 }
14276
14277 // Iteration variable for the tile (i.e. inner) loop.
14278 {
14279 std::string TileCntName =
14280 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14281
14282 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14283 // used by the expressions to derive the original iteration variable's
14284 // value from the logical iteration number.
14285 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14286 TileCntDecl->setDeclName(
14287 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14288 TileIndVars[I] = TileCntDecl;
14289 }
14290
14291 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14292 PreInits);
14293 }
14294
14295 // Once the original iteration values are set, append the innermost body.
14296 Stmt *Inner = Body;
14297
14298 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14299 SizesClause, CurScope](int I) -> Expr * {
14300 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14301 if (isa<ConstantExpr>(DimTileSizeExpr))
14302 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14303
14304 // When the tile size is not a constant but a variable, it is possible to
14305 // pass non-positive numbers. For instance:
14306 // \code{c}
14307 // int a = 0;
14308 // #pragma omp tile sizes(a)
14309 // for (int i = 0; i < 42; ++i)
14310 // body(i);
14311 // \endcode
14312 // Although there is no meaningful interpretation of the tile size, the body
14313 // should still be executed 42 times to avoid surprises. To preserve the
14314 // invariant that every loop iteration is executed exactly once and not
14315 // cause an infinite loop, apply a minimum tile size of one.
14316 // Build expr:
14317 // \code{c}
14318 // (TS <= 0) ? 1 : TS
14319 // \endcode
14320 QualType DimTy = DimTileSizeExpr->getType();
14321 uint64_t DimWidth = Context.getTypeSize(DimTy);
14323 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14324 IntegerLiteral *One =
14325 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14327 CurScope, {}, BO_LE,
14328 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14329 Expr *MinOne = new (Context) ConditionalOperator(
14330 Cond, {}, One, {},
14331 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14333 return MinOne;
14334 };
14335
14336 // Create tile loops from the inside to the outside.
14337 for (int I = NumLoops - 1; I >= 0; --I) {
14338 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14339 Expr *NumIterations = LoopHelper.NumIterations;
14340 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14341 QualType IVTy = NumIterations->getType();
14342 Stmt *LoopStmt = LoopStmts[I];
14343
14344 // Commonly used variables. One of the constraints of an AST is that every
14345 // node object must appear at most once, hence we define lamdas that create
14346 // a new AST node at every use.
14347 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14348 OrigCntVar]() {
14349 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14350 OrigCntVar->getExprLoc());
14351 };
14352 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14353 OrigCntVar]() {
14354 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14355 OrigCntVar->getExprLoc());
14356 };
14357
14358 // For init-statement: auto .tile.iv = .floor.iv
14360 TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(),
14361 /*DirectInit=*/false);
14362 Decl *CounterDecl = TileIndVars[I];
14363 StmtResult InitStmt = new (Context)
14364 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14365 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14366 if (!InitStmt.isUsable())
14367 return StmtError();
14368
14369 // For cond-expression:
14370 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14371 ExprResult EndOfTile =
14372 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14373 MakeFloorIVRef(), MakeDimTileSize(I));
14374 if (!EndOfTile.isUsable())
14375 return StmtError();
14376 ExprResult IsPartialTile =
14377 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14378 NumIterations, EndOfTile.get());
14379 if (!IsPartialTile.isUsable())
14380 return StmtError();
14381 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14382 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14383 IsPartialTile.get(), NumIterations, EndOfTile.get());
14384 if (!MinTileAndIterSpace.isUsable())
14385 return StmtError();
14386 ExprResult CondExpr =
14387 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14388 MakeTileIVRef(), MinTileAndIterSpace.get());
14389 if (!CondExpr.isUsable())
14390 return StmtError();
14391
14392 // For incr-statement: ++.tile.iv
14393 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14394 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14395 if (!IncrStmt.isUsable())
14396 return StmtError();
14397
14398 // Statements to set the original iteration variable's value from the
14399 // logical iteration number.
14400 // Generated for loop is:
14401 // \code
14402 // Original_for_init;
14403 // for (auto .tile.iv = .floor.iv;
14404 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14405 // ++.tile.iv) {
14406 // Original_Body;
14407 // Original_counter_update;
14408 // }
14409 // \endcode
14410 // FIXME: If the innermost body is an loop itself, inserting these
14411 // statements stops it being recognized as a perfectly nested loop (e.g.
14412 // for applying tiling again). If this is the case, sink the expressions
14413 // further into the inner loop.
14414 SmallVector<Stmt *, 4> BodyParts;
14415 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14416 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14417 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14418 BodyParts.push_back(Inner);
14419 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14420 Inner->getBeginLoc(), Inner->getEndLoc());
14421 Inner = new (Context)
14422 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14423 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14424 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14425 }
14426
14427 // Create floor loops from the inside to the outside.
14428 for (int I = NumLoops - 1; I >= 0; --I) {
14429 auto &LoopHelper = LoopHelpers[I];
14430 Expr *NumIterations = LoopHelper.NumIterations;
14431 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14432 QualType IVTy = NumIterations->getType();
14433
14434 // Commonly used variables. One of the constraints of an AST is that every
14435 // node object must appear at most once, hence we define lamdas that create
14436 // a new AST node at every use.
14437 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14438 OrigCntVar]() {
14439 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14440 OrigCntVar->getExprLoc());
14441 };
14442
14443 // For init-statement: auto .floor.iv = 0
14445 FloorIndVars[I],
14446 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14447 /*DirectInit=*/false);
14448 Decl *CounterDecl = FloorIndVars[I];
14449 StmtResult InitStmt = new (Context)
14450 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14451 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14452 if (!InitStmt.isUsable())
14453 return StmtError();
14454
14455 // For cond-expression: .floor.iv < NumIterations
14456 ExprResult CondExpr =
14457 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14458 MakeFloorIVRef(), NumIterations);
14459 if (!CondExpr.isUsable())
14460 return StmtError();
14461
14462 // For incr-statement: .floor.iv += DimTileSize
14463 ExprResult IncrStmt =
14464 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14465 MakeFloorIVRef(), MakeDimTileSize(I));
14466 if (!IncrStmt.isUsable())
14467 return StmtError();
14468
14469 Inner = new (Context)
14470 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14471 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14472 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14473 }
14474
14475 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14476 AStmt, Inner,
14477 buildPreInits(Context, PreInits));
14478}
14479
14481 Stmt *AStmt,
14482 SourceLocation StartLoc,
14483 SourceLocation EndLoc) {
14484 ASTContext &Context = getASTContext();
14485 Scope *CurScope = SemaRef.getCurScope();
14486 // Empty statement should only be possible if there already was an error.
14487 if (!AStmt)
14488 return StmtError();
14489
14491 {OMPC_partial, OMPC_full}))
14492 return StmtError();
14493
14494 const OMPFullClause *FullClause =
14495 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14496 const OMPPartialClause *PartialClause =
14497 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14498 assert(!(FullClause && PartialClause) &&
14499 "mutual exclusivity must have been checked before");
14500
14501 constexpr unsigned NumLoops = 1;
14502 Stmt *Body = nullptr;
14504 NumLoops);
14505 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14506 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14507 Body, OriginalInits))
14508 return StmtError();
14509
14510 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14511
14512 // Delay unrolling to when template is completely instantiated.
14514 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14515 NumGeneratedLoops, nullptr, nullptr);
14516
14517 assert(LoopHelpers.size() == NumLoops &&
14518 "Expecting a single-dimensional loop iteration space");
14519 assert(OriginalInits.size() == NumLoops &&
14520 "Expecting a single-dimensional loop iteration space");
14521 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14522
14523 if (FullClause) {
14525 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14526 /*SuppressExprDiags=*/true)
14527 .isUsable()) {
14528 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14529 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14530 << "#pragma omp unroll full";
14531 return StmtError();
14532 }
14533 }
14534
14535 // The generated loop may only be passed to other loop-associated directive
14536 // when a partial clause is specified. Without the requirement it is
14537 // sufficient to generate loop unroll metadata at code-generation.
14538 if (NumGeneratedLoops == 0)
14539 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14540 NumGeneratedLoops, nullptr, nullptr);
14541
14542 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14543 // associated with another loop directive.
14544 //
14545 // The canonical loop analysis return by checkTransformableLoopNest assumes
14546 // the following structure to be the same loop without transformations or
14547 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14548 // LoopHelper.Counters;
14549 // for (; IV < LoopHelper.NumIterations; ++IV) {
14550 // LoopHelper.Updates;
14551 // Body;
14552 // }
14553 // \endcode
14554 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14555 // and referenced by LoopHelper.IterationVarRef.
14556 //
14557 // The unrolling directive transforms this into the following loop:
14558 // \code
14559 // OriginalInits; \
14560 // LoopHelper.PreInits; > NewPreInits
14561 // LoopHelper.Counters; /
14562 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14563 // #pragma clang loop unroll_count(Factor)
14564 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14565 // {
14566 // LoopHelper.Updates;
14567 // Body;
14568 // }
14569 // }
14570 // \endcode
14571 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14572 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14573 // references it. If the partially unrolled loop is associated with another
14574 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14575 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14576 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14577 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14578 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14579 // property of the OMPLoopBasedDirective instead of statements in
14580 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14581 // of a canonical loop nest where these PreInits are emitted before the
14582 // outermost directive.
14583
14584 // Find the loop statement.
14585 Stmt *LoopStmt = nullptr;
14586 collectLoopStmts(AStmt, {LoopStmt});
14587
14588 // Determine the PreInit declarations.
14589 SmallVector<Stmt *, 4> PreInits;
14590 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14591
14592 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14593 QualType IVTy = IterationVarRef->getType();
14594 assert(LoopHelper.Counters.size() == 1 &&
14595 "Expecting a single-dimensional loop iteration space");
14596 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14597
14598 // Determine the unroll factor.
14599 uint64_t Factor;
14600 SourceLocation FactorLoc;
14601 if (Expr *FactorVal = PartialClause->getFactor()) {
14602 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14603 FactorLoc = FactorVal->getExprLoc();
14604 } else {
14605 // TODO: Use a better profitability model.
14606 Factor = 2;
14607 }
14608 assert(Factor > 0 && "Expected positive unroll factor");
14609 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14611 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14612 IVTy, FactorLoc);
14613 };
14614
14615 // Iteration variable SourceLocations.
14616 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14617 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14618 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14619
14620 // Internal variable names.
14621 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14622 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14623 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14624 std::string InnerTripCountName =
14625 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
14626
14627 // Create the iteration variable for the unrolled loop.
14628 VarDecl *OuterIVDecl =
14629 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
14630 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14631 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
14632 };
14633
14634 // Iteration variable for the inner loop: Reuse the iteration variable created
14635 // by checkOpenMPLoop.
14636 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14637 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
14638 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14639 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
14640 };
14641
14642 // Make a copy of the NumIterations expression for each use: By the AST
14643 // constraints, every expression object in a DeclContext must be unique.
14644 CaptureVars CopyTransformer(SemaRef);
14645 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14646 return AssertSuccess(
14647 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14648 };
14649
14650 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
14651 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
14652 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
14653 /*DirectInit=*/false);
14654 StmtResult InnerInit = new (Context)
14655 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14656 if (!InnerInit.isUsable())
14657 return StmtError();
14658
14659 // Inner For cond-expression:
14660 // \code
14661 // .unroll_inner.iv < .unrolled.iv + Factor &&
14662 // .unroll_inner.iv < NumIterations
14663 // \endcode
14664 // This conjunction of two conditions allows ScalarEvolution to derive the
14665 // maximum trip count of the inner loop.
14666 ExprResult EndOfTile =
14667 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14668 MakeOuterRef(), MakeFactorExpr());
14669 if (!EndOfTile.isUsable())
14670 return StmtError();
14671 ExprResult InnerCond1 =
14672 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14673 MakeInnerRef(), EndOfTile.get());
14674 if (!InnerCond1.isUsable())
14675 return StmtError();
14676 ExprResult InnerCond2 =
14677 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14678 MakeInnerRef(), MakeNumIterations());
14679 if (!InnerCond2.isUsable())
14680 return StmtError();
14681 ExprResult InnerCond =
14682 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
14683 InnerCond1.get(), InnerCond2.get());
14684 if (!InnerCond.isUsable())
14685 return StmtError();
14686
14687 // Inner For incr-statement: ++.unroll_inner.iv
14688 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
14689 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
14690 if (!InnerIncr.isUsable())
14691 return StmtError();
14692
14693 // Inner For statement.
14694 SmallVector<Stmt *> InnerBodyStmts;
14695 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14696 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14697 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14698 InnerBodyStmts.push_back(Body);
14699 CompoundStmt *InnerBody =
14701 Body->getBeginLoc(), Body->getEndLoc());
14702 ForStmt *InnerFor = new (Context)
14703 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
14704 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
14705 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14706
14707 // Unroll metadata for the inner loop.
14708 // This needs to take into account the remainder portion of the unrolled loop,
14709 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
14710 // supports multiple loop exits. Instead, unroll using a factor equivalent to
14711 // the maximum trip count, which will also generate a remainder loop. Just
14712 // `unroll(enable)` (which could have been useful if the user has not
14713 // specified a concrete factor; even though the outer loop cannot be
14714 // influenced anymore, would avoid more code bloat than necessary) will refuse
14715 // the loop because "Won't unroll; remainder loop could not be generated when
14716 // assuming runtime trip count". Even if it did work, it must not choose a
14717 // larger unroll factor than the maximum loop length, or it would always just
14718 // execute the remainder loop.
14719 LoopHintAttr *UnrollHintAttr =
14720 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14721 LoopHintAttr::Numeric, MakeFactorExpr());
14722 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
14723 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
14724
14725 // Outer For init-statement: auto .unrolled.iv = 0
14727 OuterIVDecl,
14728 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14729 /*DirectInit=*/false);
14730 StmtResult OuterInit = new (Context)
14731 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14732 if (!OuterInit.isUsable())
14733 return StmtError();
14734
14735 // Outer For cond-expression: .unrolled.iv < NumIterations
14736 ExprResult OuterConde =
14737 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14738 MakeOuterRef(), MakeNumIterations());
14739 if (!OuterConde.isUsable())
14740 return StmtError();
14741
14742 // Outer For incr-statement: .unrolled.iv += Factor
14743 ExprResult OuterIncr =
14744 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14745 MakeOuterRef(), MakeFactorExpr());
14746 if (!OuterIncr.isUsable())
14747 return StmtError();
14748
14749 // Outer For statement.
14750 ForStmt *OuterFor = new (Context)
14751 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
14752 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
14753 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14754
14755 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14756 NumGeneratedLoops, OuterFor,
14757 buildPreInits(Context, PreInits));
14758}
14759
14761 SourceLocation StartLoc,
14762 SourceLocation EndLoc) {
14763 ASTContext &Context = getASTContext();
14764 Scope *CurScope = SemaRef.getCurScope();
14765
14766 // Empty statement should only be possible if there already was an error.
14767 if (!AStmt)
14768 return StmtError();
14769
14770 constexpr unsigned NumLoops = 1;
14771 Stmt *Body = nullptr;
14773 NumLoops);
14774 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14775 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14776 Body, OriginalInits))
14777 return StmtError();
14778
14779 // Delay applying the transformation to when template is completely
14780 // instantiated.
14782 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14783 nullptr, nullptr);
14784
14785 assert(LoopHelpers.size() == NumLoops &&
14786 "Expecting a single-dimensional loop iteration space");
14787 assert(OriginalInits.size() == NumLoops &&
14788 "Expecting a single-dimensional loop iteration space");
14789 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14790
14791 // Find the loop statement.
14792 Stmt *LoopStmt = nullptr;
14793 collectLoopStmts(AStmt, {LoopStmt});
14794
14795 // Determine the PreInit declarations.
14796 SmallVector<Stmt *> PreInits;
14797 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14798
14799 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14800 QualType IVTy = IterationVarRef->getType();
14801 uint64_t IVWidth = Context.getTypeSize(IVTy);
14802 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14803
14804 // Iteration variable SourceLocations.
14805 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14806 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14807 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14808
14809 // Locations pointing to the transformation.
14810 SourceLocation TransformLoc = StartLoc;
14811 SourceLocation TransformLocBegin = StartLoc;
14812 SourceLocation TransformLocEnd = EndLoc;
14813
14814 // Internal variable names.
14815 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14816 SmallString<64> ForwardIVName(".forward.iv.");
14817 ForwardIVName += OrigVarName;
14818 SmallString<64> ReversedIVName(".reversed.iv.");
14819 ReversedIVName += OrigVarName;
14820
14821 // LoopHelper.Updates will read the logical iteration number from
14822 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
14823 // that logical iteration from it, then assign it to the user loop counter
14824 // variable. We cannot directly use LoopHelper.IterationVarRef as the
14825 // induction variable of the generated loop because it may cause an underflow:
14826 // \code{.c}
14827 // for (unsigned i = 0; i < n; ++i)
14828 // body(i);
14829 // \endcode
14830 //
14831 // Naive reversal:
14832 // \code{.c}
14833 // for (unsigned i = n-1; i >= 0; --i)
14834 // body(i);
14835 // \endcode
14836 //
14837 // Instead, we introduce a new iteration variable representing the logical
14838 // iteration counter of the original loop, convert it to the logical iteration
14839 // number of the reversed loop, then let LoopHelper.Updates compute the user's
14840 // loop iteration variable from it.
14841 // \code{.cpp}
14842 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
14843 // auto .reversed.iv = n - .forward.iv - 1;
14844 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
14845 // body(i); // Body
14846 // }
14847 // \endcode
14848
14849 // Subexpressions with more than one use. One of the constraints of an AST is
14850 // that every node object must appear at most once, hence we define a lambda
14851 // that creates a new AST node at every use.
14852 CaptureVars CopyTransformer(SemaRef);
14853 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14854 return AssertSuccess(
14855 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14856 };
14857
14858 // Create the iteration variable for the forward loop (from 0 to n-1).
14859 VarDecl *ForwardIVDecl =
14860 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
14861 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
14862 OrigVarLoc]() {
14863 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
14864 };
14865
14866 // Iteration variable for the reversed induction variable (from n-1 downto 0):
14867 // Reuse the iteration variable created by checkOpenMPLoop.
14868 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14869 ReversedIVDecl->setDeclName(
14870 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
14871
14872 // For init-statement:
14873 // \code{.cpp}
14874 // auto .forward.iv = 0;
14875 // \endcode
14876 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
14877 ForwardIVDecl->getType(), OrigVarLoc);
14878 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
14879 StmtResult Init = new (Context)
14880 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14881 if (!Init.isUsable())
14882 return StmtError();
14883
14884 // Forward iv cond-expression:
14885 // \code{.cpp}
14886 // .forward.iv < MakeNumIterations()
14887 // \endcode
14888 ExprResult Cond =
14889 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14890 MakeForwardRef(), MakeNumIterations());
14891 if (!Cond.isUsable())
14892 return StmtError();
14893
14894 // Forward incr-statement:
14895 // \code{.c}
14896 // ++.forward.iv
14897 // \endcode
14898 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
14899 UO_PreInc, MakeForwardRef());
14900 if (!Incr.isUsable())
14901 return StmtError();
14902
14903 // Reverse the forward-iv:
14904 // \code{.cpp}
14905 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
14906 // \endcode
14907 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
14908 TransformLoc);
14909 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
14910 MakeNumIterations(), One);
14911 if (!Minus.isUsable())
14912 return StmtError();
14913 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
14914 MakeForwardRef());
14915 if (!Minus.isUsable())
14916 return StmtError();
14917 StmtResult InitReversed = new (Context) DeclStmt(
14918 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14919 if (!InitReversed.isUsable())
14920 return StmtError();
14921 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
14922 /*DirectInit=*/false);
14923
14924 // The new loop body.
14925 SmallVector<Stmt *, 4> BodyStmts;
14926 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
14927 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14928 BodyStmts.push_back(InitReversed.get());
14929 llvm::append_range(BodyStmts, LoopHelper.Updates);
14930 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14931 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14932 BodyStmts.push_back(Body);
14933 auto *ReversedBody =
14934 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
14935 Body->getBeginLoc(), Body->getEndLoc());
14936
14937 // Finally create the reversed For-statement.
14938 auto *ReversedFor = new (Context)
14939 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
14940 ReversedBody, LoopHelper.Init->getBeginLoc(),
14941 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14942 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14943 ReversedFor,
14944 buildPreInits(Context, PreInits));
14945}
14946
14948 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14949 SourceLocation EndLoc) {
14950 ASTContext &Context = getASTContext();
14951 DeclContext *CurContext = SemaRef.CurContext;
14952 Scope *CurScope = SemaRef.getCurScope();
14953
14954 // Empty statement should only be possible if there already was an error.
14955 if (!AStmt)
14956 return StmtError();
14957
14958 // interchange without permutation clause swaps two loops.
14959 const OMPPermutationClause *PermutationClause =
14960 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
14961 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
14962
14963 // Verify and diagnose loop nest.
14965 Stmt *Body = nullptr;
14966 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
14967 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14968 LoopHelpers, Body, OriginalInits))
14969 return StmtError();
14970
14971 // Delay interchange to when template is completely instantiated.
14972 if (CurContext->isDependentContext())
14973 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14974 NumLoops, AStmt, nullptr, nullptr);
14975
14976 // An invalid expression in the permutation clause is set to nullptr in
14977 // ActOnOpenMPPermutationClause.
14978 if (PermutationClause &&
14979 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
14980 return StmtError();
14981
14982 assert(LoopHelpers.size() == NumLoops &&
14983 "Expecting loop iteration space dimensionaly to match number of "
14984 "affected loops");
14985 assert(OriginalInits.size() == NumLoops &&
14986 "Expecting loop iteration space dimensionaly to match number of "
14987 "affected loops");
14988
14989 // Decode the permutation clause.
14990 SmallVector<uint64_t, 2> Permutation;
14991 if (!PermutationClause) {
14992 Permutation = {1, 0};
14993 } else {
14994 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
14995 llvm::BitVector Flags(PermArgs.size());
14996 for (Expr *PermArg : PermArgs) {
14997 std::optional<llvm::APSInt> PermCstExpr =
14998 PermArg->getIntegerConstantExpr(Context);
14999 if (!PermCstExpr)
15000 continue;
15001 uint64_t PermInt = PermCstExpr->getZExtValue();
15002 assert(1 <= PermInt && PermInt <= NumLoops &&
15003 "Must be a permutation; diagnostic emitted in "
15004 "ActOnOpenMPPermutationClause");
15005 if (Flags[PermInt - 1]) {
15006 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15007 Diag(PermArg->getExprLoc(),
15008 diag::err_omp_interchange_permutation_value_repeated)
15009 << PermInt << ExprRange;
15010 continue;
15011 }
15012 Flags[PermInt - 1] = true;
15013
15014 Permutation.push_back(PermInt - 1);
15015 }
15016
15017 if (Permutation.size() != NumLoops)
15018 return StmtError();
15019 }
15020
15021 // Nothing to transform with trivial permutation.
15022 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15023 auto [Idx, Arg] = P;
15024 return Idx == Arg;
15025 }))
15026 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15027 NumLoops, AStmt, AStmt, nullptr);
15028
15029 // Find the affected loops.
15030 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15031 collectLoopStmts(AStmt, LoopStmts);
15032
15033 // Collect pre-init statements on the order before the permuation.
15034 SmallVector<Stmt *> PreInits;
15035 for (auto I : llvm::seq<int>(NumLoops)) {
15036 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15037
15038 assert(LoopHelper.Counters.size() == 1 &&
15039 "Single-dimensional loop iteration space expected");
15040 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15041
15042 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15043 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15044 PreInits);
15045 }
15046
15047 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15048 CaptureVars CopyTransformer(SemaRef);
15049
15050 // Create the permuted loops from the inside to the outside of the
15051 // interchanged loop nest. Body of the innermost new loop is the original
15052 // innermost body.
15053 Stmt *Inner = Body;
15054 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15055 // Get the original loop that belongs to this new position.
15056 uint64_t SourceIdx = Permutation[TargetIdx];
15057 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15058 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15059 assert(SourceHelper.Counters.size() == 1 &&
15060 "Single-dimensional loop iteration space expected");
15061 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15062
15063 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15064 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15065 QualType IVTy = IterVarRef->getType();
15066 assert(IVTy->isIntegerType() &&
15067 "Expected the logical iteration counter to be an integer");
15068
15069 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15070 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15071
15072 // Make a copy of the NumIterations expression for each use: By the AST
15073 // constraints, every expression object in a DeclContext must be unique.
15074 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15075 return AssertSuccess(
15076 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15077 };
15078
15079 // Iteration variable for the permuted loop. Reuse the one from
15080 // checkOpenMPLoop which will also be used to update the original loop
15081 // variable.
15082 SmallString<64> PermutedCntName(".permuted_");
15083 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15084 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15085 PermutedCntDecl->setDeclName(
15086 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15087 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15088 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15089 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15090 };
15091
15092 // For init-statement:
15093 // \code
15094 // auto .permuted_{target}.iv = 0
15095 // \endcode
15096 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15097 if (!Zero.isUsable())
15098 return StmtError();
15099 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15100 /*DirectInit=*/false);
15101 StmtResult InitStmt = new (Context)
15102 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15103 OrigCntVar->getEndLoc());
15104 if (!InitStmt.isUsable())
15105 return StmtError();
15106
15107 // For cond-expression:
15108 // \code
15109 // .permuted_{target}.iv < MakeNumIterations()
15110 // \endcode
15111 ExprResult CondExpr =
15112 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15113 MakePermutedRef(), MakeNumIterations());
15114 if (!CondExpr.isUsable())
15115 return StmtError();
15116
15117 // For incr-statement:
15118 // \code
15119 // ++.tile.iv
15120 // \endcode
15121 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15122 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15123 if (!IncrStmt.isUsable())
15124 return StmtError();
15125
15126 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15127 SourceHelper.Updates.end());
15128 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15129 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15130 BodyParts.push_back(Inner);
15131 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15132 Inner->getBeginLoc(), Inner->getEndLoc());
15133 Inner = new (Context) ForStmt(
15134 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15135 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15136 SourceHelper.Inc->getEndLoc());
15137 }
15138
15139 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15140 NumLoops, AStmt, Inner,
15141 buildPreInits(Context, PreInits));
15142}
15143
15145 Expr *Expr,
15146 SourceLocation StartLoc,
15147 SourceLocation LParenLoc,
15148 SourceLocation EndLoc) {
15149 OMPClause *Res = nullptr;
15150 switch (Kind) {
15151 case OMPC_final:
15152 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15153 break;
15154 case OMPC_num_threads:
15155 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15156 break;
15157 case OMPC_safelen:
15158 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15159 break;
15160 case OMPC_simdlen:
15161 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15162 break;
15163 case OMPC_allocator:
15164 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15165 break;
15166 case OMPC_collapse:
15167 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15168 break;
15169 case OMPC_ordered:
15170 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15171 break;
15172 case OMPC_priority:
15173 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15174 break;
15175 case OMPC_hint:
15176 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15177 break;
15178 case OMPC_depobj:
15179 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15180 break;
15181 case OMPC_detach:
15182 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15183 break;
15184 case OMPC_novariants:
15185 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15186 break;
15187 case OMPC_nocontext:
15188 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15189 break;
15190 case OMPC_filter:
15191 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15192 break;
15193 case OMPC_partial:
15194 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15195 break;
15196 case OMPC_message:
15197 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15198 break;
15199 case OMPC_align:
15200 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15201 break;
15202 case OMPC_ompx_dyn_cgroup_mem:
15203 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15204 break;
15205 case OMPC_holds:
15206 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
15207 break;
15208 case OMPC_grainsize:
15209 case OMPC_num_tasks:
15210 case OMPC_device:
15211 case OMPC_if:
15212 case OMPC_default:
15213 case OMPC_proc_bind:
15214 case OMPC_schedule:
15215 case OMPC_private:
15216 case OMPC_firstprivate:
15217 case OMPC_lastprivate:
15218 case OMPC_shared:
15219 case OMPC_reduction:
15220 case OMPC_task_reduction:
15221 case OMPC_in_reduction:
15222 case OMPC_linear:
15223 case OMPC_aligned:
15224 case OMPC_copyin:
15225 case OMPC_copyprivate:
15226 case OMPC_nowait:
15227 case OMPC_untied:
15228 case OMPC_mergeable:
15229 case OMPC_threadprivate:
15230 case OMPC_sizes:
15231 case OMPC_allocate:
15232 case OMPC_flush:
15233 case OMPC_read:
15234 case OMPC_write:
15235 case OMPC_update:
15236 case OMPC_capture:
15237 case OMPC_compare:
15238 case OMPC_seq_cst:
15239 case OMPC_acq_rel:
15240 case OMPC_acquire:
15241 case OMPC_release:
15242 case OMPC_relaxed:
15243 case OMPC_depend:
15244 case OMPC_threads:
15245 case OMPC_simd:
15246 case OMPC_map:
15247 case OMPC_nogroup:
15248 case OMPC_dist_schedule:
15249 case OMPC_defaultmap:
15250 case OMPC_unknown:
15251 case OMPC_uniform:
15252 case OMPC_to:
15253 case OMPC_from:
15254 case OMPC_use_device_ptr:
15255 case OMPC_use_device_addr:
15256 case OMPC_is_device_ptr:
15257 case OMPC_unified_address:
15258 case OMPC_unified_shared_memory:
15259 case OMPC_reverse_offload:
15260 case OMPC_dynamic_allocators:
15261 case OMPC_atomic_default_mem_order:
15262 case OMPC_device_type:
15263 case OMPC_match:
15264 case OMPC_nontemporal:
15265 case OMPC_order:
15266 case OMPC_at:
15267 case OMPC_severity:
15268 case OMPC_destroy:
15269 case OMPC_inclusive:
15270 case OMPC_exclusive:
15271 case OMPC_uses_allocators:
15272 case OMPC_affinity:
15273 case OMPC_when:
15274 case OMPC_bind:
15275 case OMPC_num_teams:
15276 case OMPC_thread_limit:
15277 default:
15278 llvm_unreachable("Clause is not allowed.");
15279 }
15280 return Res;
15281}
15282
15283// An OpenMP directive such as 'target parallel' has two captured regions:
15284// for the 'target' and 'parallel' respectively. This function returns
15285// the region in which to capture expressions associated with a clause.
15286// A return value of OMPD_unknown signifies that the expression should not
15287// be captured.
15289 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15290 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15291 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15292 "Invalid directive with CKind-clause");
15293
15294 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15295 if (NameModifier != OMPD_unknown &&
15296 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15297 return OMPD_unknown;
15298
15299 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15300
15301 // [5.2:341:24-30]
15302 // If the clauses have expressions on them, such as for various clauses where
15303 // the argument of the clause is an expression, or lower-bound, length, or
15304 // stride expressions inside array sections (or subscript and stride
15305 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15306 // expressions, the expressions are evaluated immediately before the construct
15307 // to which the clause has been split or duplicated per the above rules
15308 // (therefore inside of the outer leaf constructs). However, the expressions
15309 // inside the num_teams and thread_limit clauses are always evaluated before
15310 // the outermost leaf construct.
15311
15312 // Process special cases first.
15313 switch (CKind) {
15314 case OMPC_if:
15315 switch (DKind) {
15316 case OMPD_teams_loop:
15317 case OMPD_target_teams_loop:
15318 // For [target] teams loop, assume capture region is 'teams' so it's
15319 // available for codegen later to use if/when necessary.
15320 return OMPD_teams;
15321 case OMPD_target_update:
15322 case OMPD_target_enter_data:
15323 case OMPD_target_exit_data:
15324 return OMPD_task;
15325 default:
15326 break;
15327 }
15328 break;
15329 case OMPC_num_teams:
15330 case OMPC_thread_limit:
15331 case OMPC_ompx_dyn_cgroup_mem:
15332 if (Leafs[0] == OMPD_target)
15333 return OMPD_target;
15334 break;
15335 case OMPC_device:
15336 if (Leafs[0] == OMPD_target ||
15337 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15338 OMPD_target_enter_data, OMPD_target_exit_data},
15339 DKind))
15340 return OMPD_task;
15341 break;
15342 case OMPC_novariants:
15343 case OMPC_nocontext:
15344 if (DKind == OMPD_dispatch)
15345 return OMPD_task;
15346 break;
15347 case OMPC_when:
15348 if (DKind == OMPD_metadirective)
15349 return OMPD_metadirective;
15350 break;
15351 case OMPC_filter:
15352 return OMPD_unknown;
15353 default:
15354 break;
15355 }
15356
15357 // If none of the special cases above applied, and DKind is a capturing
15358 // directive, find the innermost enclosing leaf construct that allows the
15359 // clause, and returns the corresponding capture region.
15360
15361 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15362 // Find the index in "Leafs" of the last leaf that allows the given
15363 // clause. The search will only include indexes [0, EndIdx).
15364 // EndIdx may be set to the index of the NameModifier, if present.
15365 int InnermostIdx = [&]() {
15366 for (int I = EndIdx - 1; I >= 0; --I) {
15367 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15368 return I;
15369 }
15370 return -1;
15371 }();
15372
15373 // Find the nearest enclosing capture region.
15375 for (int I = InnermostIdx - 1; I >= 0; --I) {
15376 if (!isOpenMPCapturingDirective(Leafs[I]))
15377 continue;
15378 Regions.clear();
15379 getOpenMPCaptureRegions(Regions, Leafs[I]);
15380 if (Regions[0] != OMPD_unknown)
15381 return Regions.back();
15382 }
15383 return OMPD_unknown;
15384 };
15385
15386 if (isOpenMPCapturingDirective(DKind)) {
15387 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15388 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15389 if (Leafs[I] == Dir)
15390 return I + 1;
15391 }
15392 return 0;
15393 };
15394
15395 int End = NameModifier == OMPD_unknown ? Leafs.size()
15396 : GetLeafIndex(NameModifier);
15397 return GetEnclosingRegion(End, CKind);
15398 }
15399
15400 return OMPD_unknown;
15401}
15402
15404 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15405 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15406 SourceLocation ColonLoc, SourceLocation EndLoc) {
15407 Expr *ValExpr = Condition;
15408 Stmt *HelperValStmt = nullptr;
15409 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15410 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15411 !Condition->isInstantiationDependent() &&
15412 !Condition->containsUnexpandedParameterPack()) {
15414 if (Val.isInvalid())
15415 return nullptr;
15416
15417 ValExpr = Val.get();
15418
15419 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15420 CaptureRegion = getOpenMPCaptureRegionForClause(
15421 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15422 if (CaptureRegion != OMPD_unknown &&
15424 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15425 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15426 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15427 HelperValStmt = buildPreInits(getASTContext(), Captures);
15428 }
15429 }
15430
15431 return new (getASTContext())
15432 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15433 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15434}
15435
15437 SourceLocation StartLoc,
15438 SourceLocation LParenLoc,
15439 SourceLocation EndLoc) {
15440 Expr *ValExpr = Condition;
15441 Stmt *HelperValStmt = nullptr;
15442 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15443 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15444 !Condition->isInstantiationDependent() &&
15445 !Condition->containsUnexpandedParameterPack()) {
15447 if (Val.isInvalid())
15448 return nullptr;
15449
15450 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
15451
15452 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15453 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15454 getLangOpts().OpenMP);
15455 if (CaptureRegion != OMPD_unknown &&
15457 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15458 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15459 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15460 HelperValStmt = buildPreInits(getASTContext(), Captures);
15461 }
15462 }
15463
15464 return new (getASTContext()) OMPFinalClause(
15465 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15466}
15467
15470 Expr *Op) {
15471 if (!Op)
15472 return ExprError();
15473
15474 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15475 public:
15476 IntConvertDiagnoser()
15477 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
15478 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15479 QualType T) override {
15480 return S.Diag(Loc, diag::err_omp_not_integral) << T;
15481 }
15482 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15483 QualType T) override {
15484 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15485 }
15486 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15487 QualType T,
15488 QualType ConvTy) override {
15489 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15490 }
15491 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15492 QualType ConvTy) override {
15493 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15494 << ConvTy->isEnumeralType() << ConvTy;
15495 }
15496 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15497 QualType T) override {
15498 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15499 }
15500 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15501 QualType ConvTy) override {
15502 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15503 << ConvTy->isEnumeralType() << ConvTy;
15504 }
15505 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15506 QualType) override {
15507 llvm_unreachable("conversion functions are permitted");
15508 }
15509 } ConvertDiagnoser;
15510 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
15511}
15512
15513static bool
15515 bool StrictlyPositive, bool BuildCapture = false,
15516 OpenMPDirectiveKind DKind = OMPD_unknown,
15517 OpenMPDirectiveKind *CaptureRegion = nullptr,
15518 Stmt **HelperValStmt = nullptr) {
15519 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15520 !ValExpr->isInstantiationDependent()) {
15521 SourceLocation Loc = ValExpr->getExprLoc();
15524 if (Value.isInvalid())
15525 return false;
15526
15527 ValExpr = Value.get();
15528 // The expression must evaluate to a non-negative integer value.
15529 if (std::optional<llvm::APSInt> Result =
15530 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
15531 if (Result->isSigned() &&
15532 !((!StrictlyPositive && Result->isNonNegative()) ||
15533 (StrictlyPositive && Result->isStrictlyPositive()))) {
15534 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15535 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15536 << ValExpr->getSourceRange();
15537 return false;
15538 }
15539 }
15540 if (!BuildCapture)
15541 return true;
15542 *CaptureRegion =
15543 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15544 if (*CaptureRegion != OMPD_unknown &&
15545 !SemaRef.CurContext->isDependentContext()) {
15546 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15547 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15548 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15549 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
15550 }
15551 }
15552 return true;
15553}
15554
15556 SourceLocation StartLoc,
15557 SourceLocation LParenLoc,
15558 SourceLocation EndLoc) {
15559 Expr *ValExpr = NumThreads;
15560 Stmt *HelperValStmt = nullptr;
15561
15562 // OpenMP [2.5, Restrictions]
15563 // The num_threads expression must evaluate to a positive integer value.
15564 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15565 /*StrictlyPositive=*/true))
15566 return nullptr;
15567
15568 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15570 DKind, OMPC_num_threads, getLangOpts().OpenMP);
15571 if (CaptureRegion != OMPD_unknown &&
15573 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15574 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15575 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15576 HelperValStmt = buildPreInits(getASTContext(), Captures);
15577 }
15578
15579 return new (getASTContext()) OMPNumThreadsClause(
15580 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15581}
15582
15584 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15585 bool SuppressExprDiags) {
15586 if (!E)
15587 return ExprError();
15588 if (E->isValueDependent() || E->isTypeDependent() ||
15590 return E;
15591
15592 llvm::APSInt Result;
15593 ExprResult ICE;
15594 if (SuppressExprDiags) {
15595 // Use a custom diagnoser that suppresses 'note' diagnostics about the
15596 // expression.
15597 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15598 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15600 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15601 llvm_unreachable("Diagnostic suppressed");
15602 }
15603 } Diagnoser;
15606 } else {
15608 /*FIXME*/ Sema::AllowFold);
15609 }
15610 if (ICE.isInvalid())
15611 return ExprError();
15612
15613 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
15614 (!StrictlyPositive && !Result.isNonNegative())) {
15615 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
15616 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15617 << E->getSourceRange();
15618 return ExprError();
15619 }
15620 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
15621 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
15622 << E->getSourceRange();
15623 return ExprError();
15624 }
15625 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
15626 DSAStack->setAssociatedLoops(Result.getExtValue());
15627 else if (CKind == OMPC_ordered)
15628 DSAStack->setAssociatedLoops(Result.getExtValue());
15629 return ICE;
15630}
15631
15633 SourceLocation StartLoc,
15634 SourceLocation LParenLoc,
15635 SourceLocation EndLoc) {
15636 // OpenMP [2.8.1, simd construct, Description]
15637 // The parameter of the safelen clause must be a constant
15638 // positive integer expression.
15639 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
15640 if (Safelen.isInvalid())
15641 return nullptr;
15642 return new (getASTContext())
15643 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
15644}
15645
15647 SourceLocation StartLoc,
15648 SourceLocation LParenLoc,
15649 SourceLocation EndLoc) {
15650 // OpenMP [2.8.1, simd construct, Description]
15651 // The parameter of the simdlen clause must be a constant
15652 // positive integer expression.
15653 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
15654 if (Simdlen.isInvalid())
15655 return nullptr;
15656 return new (getASTContext())
15657 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
15658}
15659
15660/// Tries to find omp_allocator_handle_t type.
15662 DSAStackTy *Stack) {
15663 if (!Stack->getOMPAllocatorHandleT().isNull())
15664 return true;
15665
15666 // Set the allocator handle type.
15667 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
15668 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
15669 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
15670 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15671 << "omp_allocator_handle_t";
15672 return false;
15673 }
15674 QualType AllocatorHandleEnumTy = PT.get();
15675 AllocatorHandleEnumTy.addConst();
15676 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15677
15678 // Fill the predefined allocator map.
15679 bool ErrorFound = false;
15680 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15681 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
15682 StringRef Allocator =
15683 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15684 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
15685 auto *VD = dyn_cast_or_null<ValueDecl>(
15686 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
15687 if (!VD) {
15688 ErrorFound = true;
15689 break;
15690 }
15691 QualType AllocatorType =
15693 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
15694 if (!Res.isUsable()) {
15695 ErrorFound = true;
15696 break;
15697 }
15698 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
15700 /*AllowExplicit=*/true);
15701 if (!Res.isUsable()) {
15702 ErrorFound = true;
15703 break;
15704 }
15705 Stack->setAllocator(AllocatorKind, Res.get());
15706 }
15707 if (ErrorFound) {
15708 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15709 << "omp_allocator_handle_t";
15710 return false;
15711 }
15712
15713 return true;
15714}
15715
15717 SourceLocation StartLoc,
15718 SourceLocation LParenLoc,
15719 SourceLocation EndLoc) {
15720 // OpenMP [2.11.3, allocate Directive, Description]
15721 // allocator is an expression of omp_allocator_handle_t type.
15723 return nullptr;
15724
15726 if (Allocator.isInvalid())
15727 return nullptr;
15729 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
15731 /*AllowExplicit=*/true);
15732 if (Allocator.isInvalid())
15733 return nullptr;
15734 return new (getASTContext())
15735 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
15736}
15737
15739 SourceLocation StartLoc,
15740 SourceLocation LParenLoc,
15741 SourceLocation EndLoc) {
15742 // OpenMP [2.7.1, loop construct, Description]
15743 // OpenMP [2.8.1, simd construct, Description]
15744 // OpenMP [2.9.6, distribute construct, Description]
15745 // The parameter of the collapse clause must be a constant
15746 // positive integer expression.
15747 ExprResult NumForLoopsResult =
15748 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
15749 if (NumForLoopsResult.isInvalid())
15750 return nullptr;
15751 return new (getASTContext())
15752 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
15753}
15754
15756 SourceLocation EndLoc,
15757 SourceLocation LParenLoc,
15758 Expr *NumForLoops) {
15759 // OpenMP [2.7.1, loop construct, Description]
15760 // OpenMP [2.8.1, simd construct, Description]
15761 // OpenMP [2.9.6, distribute construct, Description]
15762 // The parameter of the ordered clause must be a constant
15763 // positive integer expression if any.
15764 if (NumForLoops && LParenLoc.isValid()) {
15765 ExprResult NumForLoopsResult =
15766 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
15767 if (NumForLoopsResult.isInvalid())
15768 return nullptr;
15769 NumForLoops = NumForLoopsResult.get();
15770 } else {
15771 NumForLoops = nullptr;
15772 }
15773 auto *Clause =
15775 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
15776 StartLoc, LParenLoc, EndLoc);
15777 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
15778 return Clause;
15779}
15780
15782 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
15783 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15784 OMPClause *Res = nullptr;
15785 switch (Kind) {
15786 case OMPC_default:
15787 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
15788 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15789 break;
15790 case OMPC_proc_bind:
15791 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
15792 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15793 break;
15794 case OMPC_atomic_default_mem_order:
15796 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
15797 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15798 break;
15799 case OMPC_fail:
15800 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
15801 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15802 break;
15803 case OMPC_update:
15804 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
15805 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15806 break;
15807 case OMPC_bind:
15808 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
15809 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15810 break;
15811 case OMPC_at:
15812 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
15813 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15814 break;
15815 case OMPC_severity:
15817 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
15818 LParenLoc, EndLoc);
15819 break;
15820 case OMPC_if:
15821 case OMPC_final:
15822 case OMPC_num_threads:
15823 case OMPC_safelen:
15824 case OMPC_simdlen:
15825 case OMPC_sizes:
15826 case OMPC_allocator:
15827 case OMPC_collapse:
15828 case OMPC_schedule:
15829 case OMPC_private:
15830 case OMPC_firstprivate:
15831 case OMPC_lastprivate:
15832 case OMPC_shared:
15833 case OMPC_reduction:
15834 case OMPC_task_reduction:
15835 case OMPC_in_reduction:
15836 case OMPC_linear:
15837 case OMPC_aligned:
15838 case OMPC_copyin:
15839 case OMPC_copyprivate:
15840 case OMPC_ordered:
15841 case OMPC_nowait:
15842 case OMPC_untied:
15843 case OMPC_mergeable:
15844 case OMPC_threadprivate:
15845 case OMPC_allocate:
15846 case OMPC_flush:
15847 case OMPC_depobj:
15848 case OMPC_read:
15849 case OMPC_write:
15850 case OMPC_capture:
15851 case OMPC_compare:
15852 case OMPC_seq_cst:
15853 case OMPC_acq_rel:
15854 case OMPC_acquire:
15855 case OMPC_release:
15856 case OMPC_relaxed:
15857 case OMPC_depend:
15858 case OMPC_device:
15859 case OMPC_threads:
15860 case OMPC_simd:
15861 case OMPC_map:
15862 case OMPC_num_teams:
15863 case OMPC_thread_limit:
15864 case OMPC_priority:
15865 case OMPC_grainsize:
15866 case OMPC_nogroup:
15867 case OMPC_num_tasks:
15868 case OMPC_hint:
15869 case OMPC_dist_schedule:
15870 case OMPC_defaultmap:
15871 case OMPC_unknown:
15872 case OMPC_uniform:
15873 case OMPC_to:
15874 case OMPC_from:
15875 case OMPC_use_device_ptr:
15876 case OMPC_use_device_addr:
15877 case OMPC_is_device_ptr:
15878 case OMPC_has_device_addr:
15879 case OMPC_unified_address:
15880 case OMPC_unified_shared_memory:
15881 case OMPC_reverse_offload:
15882 case OMPC_dynamic_allocators:
15883 case OMPC_device_type:
15884 case OMPC_match:
15885 case OMPC_nontemporal:
15886 case OMPC_destroy:
15887 case OMPC_novariants:
15888 case OMPC_nocontext:
15889 case OMPC_detach:
15890 case OMPC_inclusive:
15891 case OMPC_exclusive:
15892 case OMPC_uses_allocators:
15893 case OMPC_affinity:
15894 case OMPC_when:
15895 case OMPC_message:
15896 default:
15897 llvm_unreachable("Clause is not allowed.");
15898 }
15899 return Res;
15900}
15901
15902static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
15903 unsigned Last,
15904 ArrayRef<unsigned> Exclude = {}) {
15905 SmallString<256> Buffer;
15906 llvm::raw_svector_ostream Out(Buffer);
15907 unsigned Skipped = Exclude.size();
15908 for (unsigned I = First; I < Last; ++I) {
15909 if (llvm::is_contained(Exclude, I)) {
15910 --Skipped;
15911 continue;
15912 }
15913 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15914 if (I + Skipped + 2 == Last)
15915 Out << " or ";
15916 else if (I + Skipped + 1 != Last)
15917 Out << ", ";
15918 }
15919 return std::string(Out.str());
15920}
15921
15923 SourceLocation KindKwLoc,
15924 SourceLocation StartLoc,
15925 SourceLocation LParenLoc,
15926 SourceLocation EndLoc) {
15927 if (Kind == OMP_DEFAULT_unknown) {
15928 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15929 << getListOfPossibleValues(OMPC_default, /*First=*/0,
15930 /*Last=*/unsigned(OMP_DEFAULT_unknown))
15931 << getOpenMPClauseName(OMPC_default);
15932 return nullptr;
15933 }
15934
15935 switch (Kind) {
15936 case OMP_DEFAULT_none:
15937 DSAStack->setDefaultDSANone(KindKwLoc);
15938 break;
15939 case OMP_DEFAULT_shared:
15940 DSAStack->setDefaultDSAShared(KindKwLoc);
15941 break;
15942 case OMP_DEFAULT_firstprivate:
15943 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15944 break;
15945 case OMP_DEFAULT_private:
15946 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15947 break;
15948 default:
15949 llvm_unreachable("DSA unexpected in OpenMP default clause");
15950 }
15951
15952 return new (getASTContext())
15953 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15954}
15955
15957 SourceLocation KindKwLoc,
15958 SourceLocation StartLoc,
15959 SourceLocation LParenLoc,
15960 SourceLocation EndLoc) {
15961 if (Kind == OMP_PROC_BIND_unknown) {
15962 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15963 << getListOfPossibleValues(OMPC_proc_bind,
15964 /*First=*/unsigned(OMP_PROC_BIND_master),
15965 /*Last=*/
15966 unsigned(getLangOpts().OpenMP > 50
15967 ? OMP_PROC_BIND_primary
15968 : OMP_PROC_BIND_spread) +
15969 1)
15970 << getOpenMPClauseName(OMPC_proc_bind);
15971 return nullptr;
15972 }
15973 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
15974 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15975 << getListOfPossibleValues(OMPC_proc_bind,
15976 /*First=*/unsigned(OMP_PROC_BIND_master),
15977 /*Last=*/
15978 unsigned(OMP_PROC_BIND_spread) + 1)
15979 << getOpenMPClauseName(OMPC_proc_bind);
15980 return new (getASTContext())
15981 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15982}
15983
15986 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15988 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15990 OMPC_atomic_default_mem_order, /*First=*/0,
15992 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15993 return nullptr;
15994 }
15996 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15997}
15998
16000 SourceLocation KindKwLoc,
16001 SourceLocation StartLoc,
16002 SourceLocation LParenLoc,
16003 SourceLocation EndLoc) {
16004 if (Kind == OMPC_AT_unknown) {
16005 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16006 << getListOfPossibleValues(OMPC_at, /*First=*/0,
16007 /*Last=*/OMPC_AT_unknown)
16008 << getOpenMPClauseName(OMPC_at);
16009 return nullptr;
16010 }
16011 return new (getASTContext())
16012 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16013}
16014
16016 SourceLocation KindKwLoc,
16017 SourceLocation StartLoc,
16018 SourceLocation LParenLoc,
16019 SourceLocation EndLoc) {
16020 if (Kind == OMPC_SEVERITY_unknown) {
16021 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16022 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16023 /*Last=*/OMPC_SEVERITY_unknown)
16024 << getOpenMPClauseName(OMPC_severity);
16025 return nullptr;
16026 }
16027 return new (getASTContext())
16028 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16029}
16030
16032 SourceLocation StartLoc,
16033 SourceLocation LParenLoc,
16034 SourceLocation EndLoc) {
16035 assert(ME && "NULL expr in Message clause");
16036 if (!isa<StringLiteral>(ME)) {
16037 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16038 << getOpenMPClauseName(OMPC_message);
16039 return nullptr;
16040 }
16041 return new (getASTContext())
16042 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16043}
16044
16047 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16048 SourceLocation KindLoc, SourceLocation EndLoc) {
16049 if (Kind != OMPC_ORDER_concurrent ||
16050 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16051 // Kind should be concurrent,
16052 // Modifiers introduced in OpenMP 5.1
16053 static_assert(OMPC_ORDER_unknown > 0,
16054 "OMPC_ORDER_unknown not greater than 0");
16055
16056 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16057 << getListOfPossibleValues(OMPC_order,
16058 /*First=*/0,
16059 /*Last=*/OMPC_ORDER_unknown)
16060 << getOpenMPClauseName(OMPC_order);
16061 return nullptr;
16062 }
16063 if (getLangOpts().OpenMP >= 51) {
16064 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
16065 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16066 << getListOfPossibleValues(OMPC_order,
16067 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16068 /*Last=*/OMPC_ORDER_MODIFIER_last)
16069 << getOpenMPClauseName(OMPC_order);
16070 } else {
16071 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16072 if (DSAStack->getCurScope()) {
16073 // mark the current scope with 'order' flag
16074 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16075 DSAStack->getCurScope()->setFlags(existingFlags |
16077 }
16078 }
16079 }
16080 return new (getASTContext()) OMPOrderClause(
16081 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16082}
16083
16085 SourceLocation KindKwLoc,
16086 SourceLocation StartLoc,
16087 SourceLocation LParenLoc,
16088 SourceLocation EndLoc) {
16089 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16090 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16091 SmallVector<unsigned> Except = {
16092 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16093 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16094 if (getLangOpts().OpenMP < 51)
16095 Except.push_back(OMPC_DEPEND_inoutset);
16096 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16097 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16098 /*Last=*/OMPC_DEPEND_unknown, Except)
16099 << getOpenMPClauseName(OMPC_update);
16100 return nullptr;
16101 }
16102 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
16103 KindKwLoc, Kind, EndLoc);
16104}
16105
16107 SourceLocation StartLoc,
16108 SourceLocation LParenLoc,
16109 SourceLocation EndLoc) {
16110 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16111
16112 for (Expr *&SizeExpr : SanitizedSizeExprs) {
16113 // Skip if already sanitized, e.g. during a partial template instantiation.
16114 if (!SizeExpr)
16115 continue;
16116
16117 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
16118 /*StrictlyPositive=*/true);
16119
16120 // isNonNegativeIntegerValue returns true for non-integral types (but still
16121 // emits error diagnostic), so check for the expected type explicitly.
16122 QualType SizeTy = SizeExpr->getType();
16123 if (!SizeTy->isIntegerType())
16124 IsValid = false;
16125
16126 // Handling in templates is tricky. There are four possibilities to
16127 // consider:
16128 //
16129 // 1a. The expression is valid and we are in a instantiated template or not
16130 // in a template:
16131 // Pass valid expression to be further analysed later in Sema.
16132 // 1b. The expression is valid and we are in a template (including partial
16133 // instantiation):
16134 // isNonNegativeIntegerValue skipped any checks so there is no
16135 // guarantee it will be correct after instantiation.
16136 // ActOnOpenMPSizesClause will be called again at instantiation when
16137 // it is not in a dependent context anymore. This may cause warnings
16138 // to be emitted multiple times.
16139 // 2a. The expression is invalid and we are in an instantiated template or
16140 // not in a template:
16141 // Invalidate the expression with a clearly wrong value (nullptr) so
16142 // later in Sema we do not have to do the same validity analysis again
16143 // or crash from unexpected data. Error diagnostics have already been
16144 // emitted.
16145 // 2b. The expression is invalid and we are in a template (including partial
16146 // instantiation):
16147 // Pass the invalid expression as-is, template instantiation may
16148 // replace unexpected types/values with valid ones. The directives
16149 // with this clause must not try to use these expressions in dependent
16150 // contexts, but delay analysis until full instantiation.
16151 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16152 SizeExpr = nullptr;
16153 }
16154
16155 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16156 SanitizedSizeExprs);
16157}
16158
16160 SourceLocation StartLoc,
16161 SourceLocation LParenLoc,
16162 SourceLocation EndLoc) {
16163 size_t NumLoops = PermExprs.size();
16164 SmallVector<Expr *> SanitizedPermExprs;
16165 llvm::append_range(SanitizedPermExprs, PermExprs);
16166
16167 for (Expr *&PermExpr : SanitizedPermExprs) {
16168 // Skip if template-dependent or already sanitized, e.g. during a partial
16169 // template instantiation.
16170 if (!PermExpr || PermExpr->isInstantiationDependent())
16171 continue;
16172
16173 llvm::APSInt PermVal;
16175 PermExpr, &PermVal, Sema::AllowFold);
16176 bool IsValid = PermEvalExpr.isUsable();
16177 if (IsValid)
16178 PermExpr = PermEvalExpr.get();
16179
16180 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16181 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16182 PermEvalExpr.get()->getEndLoc());
16183 Diag(PermEvalExpr.get()->getExprLoc(),
16184 diag::err_omp_interchange_permutation_value_range)
16185 << NumLoops << ExprRange;
16186 IsValid = false;
16187 }
16188
16189 if (!PermExpr->isInstantiationDependent() && !IsValid)
16190 PermExpr = nullptr;
16191 }
16192
16193 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
16194 EndLoc, SanitizedPermExprs);
16195}
16196
16198 SourceLocation EndLoc) {
16199 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16200}
16201
16203 SourceLocation StartLoc,
16204 SourceLocation LParenLoc,
16205 SourceLocation EndLoc) {
16206 if (FactorExpr) {
16207 // If an argument is specified, it must be a constant (or an unevaluated
16208 // template expression).
16210 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16211 if (FactorResult.isInvalid())
16212 return nullptr;
16213 FactorExpr = FactorResult.get();
16214 }
16215
16216 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16217 FactorExpr);
16218}
16219
16221 SourceLocation LParenLoc,
16222 SourceLocation EndLoc) {
16223 ExprResult AlignVal;
16224 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16225 if (AlignVal.isInvalid())
16226 return nullptr;
16227 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16228 LParenLoc, EndLoc);
16229}
16230
16233 SourceLocation StartLoc, SourceLocation LParenLoc,
16234 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16235 SourceLocation EndLoc) {
16236 OMPClause *Res = nullptr;
16237 switch (Kind) {
16238 case OMPC_schedule:
16239 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16240 assert(Argument.size() == NumberOfElements &&
16241 ArgumentLoc.size() == NumberOfElements);
16243 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16244 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16245 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16246 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16247 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16248 break;
16249 case OMPC_if:
16250 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16251 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16252 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16253 DelimLoc, EndLoc);
16254 break;
16255 case OMPC_dist_schedule:
16257 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16258 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16259 break;
16260 case OMPC_defaultmap:
16261 enum { Modifier, DefaultmapKind };
16263 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16264 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16265 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16266 EndLoc);
16267 break;
16268 case OMPC_order:
16269 enum { OrderModifier, OrderKind };
16271 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16272 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16273 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16274 break;
16275 case OMPC_device:
16276 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16278 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16279 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16280 break;
16281 case OMPC_grainsize:
16282 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16283 "Modifier for grainsize clause and its location are expected.");
16285 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16286 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16287 break;
16288 case OMPC_num_tasks:
16289 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16290 "Modifier for num_tasks clause and its location are expected.");
16292 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16293 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16294 break;
16295 case OMPC_final:
16296 case OMPC_num_threads:
16297 case OMPC_safelen:
16298 case OMPC_simdlen:
16299 case OMPC_sizes:
16300 case OMPC_allocator:
16301 case OMPC_collapse:
16302 case OMPC_default:
16303 case OMPC_proc_bind:
16304 case OMPC_private:
16305 case OMPC_firstprivate:
16306 case OMPC_lastprivate:
16307 case OMPC_shared:
16308 case OMPC_reduction:
16309 case OMPC_task_reduction:
16310 case OMPC_in_reduction:
16311 case OMPC_linear:
16312 case OMPC_aligned:
16313 case OMPC_copyin:
16314 case OMPC_copyprivate:
16315 case OMPC_ordered:
16316 case OMPC_nowait:
16317 case OMPC_untied:
16318 case OMPC_mergeable:
16319 case OMPC_threadprivate:
16320 case OMPC_allocate:
16321 case OMPC_flush:
16322 case OMPC_depobj:
16323 case OMPC_read:
16324 case OMPC_write:
16325 case OMPC_update:
16326 case OMPC_capture:
16327 case OMPC_compare:
16328 case OMPC_seq_cst:
16329 case OMPC_acq_rel:
16330 case OMPC_acquire:
16331 case OMPC_release:
16332 case OMPC_relaxed:
16333 case OMPC_depend:
16334 case OMPC_threads:
16335 case OMPC_simd:
16336 case OMPC_map:
16337 case OMPC_num_teams:
16338 case OMPC_thread_limit:
16339 case OMPC_priority:
16340 case OMPC_nogroup:
16341 case OMPC_hint:
16342 case OMPC_unknown:
16343 case OMPC_uniform:
16344 case OMPC_to:
16345 case OMPC_from:
16346 case OMPC_use_device_ptr:
16347 case OMPC_use_device_addr:
16348 case OMPC_is_device_ptr:
16349 case OMPC_has_device_addr:
16350 case OMPC_unified_address:
16351 case OMPC_unified_shared_memory:
16352 case OMPC_reverse_offload:
16353 case OMPC_dynamic_allocators:
16354 case OMPC_atomic_default_mem_order:
16355 case OMPC_device_type:
16356 case OMPC_match:
16357 case OMPC_nontemporal:
16358 case OMPC_at:
16359 case OMPC_severity:
16360 case OMPC_message:
16361 case OMPC_destroy:
16362 case OMPC_novariants:
16363 case OMPC_nocontext:
16364 case OMPC_detach:
16365 case OMPC_inclusive:
16366 case OMPC_exclusive:
16367 case OMPC_uses_allocators:
16368 case OMPC_affinity:
16369 case OMPC_when:
16370 case OMPC_bind:
16371 default:
16372 llvm_unreachable("Clause is not allowed.");
16373 }
16374 return Res;
16375}
16376
16379 SourceLocation M1Loc, SourceLocation M2Loc) {
16380 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16381 SmallVector<unsigned, 2> Excluded;
16383 Excluded.push_back(M2);
16384 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16385 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16386 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16387 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16388 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16389 << getListOfPossibleValues(OMPC_schedule,
16390 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16392 Excluded)
16393 << getOpenMPClauseName(OMPC_schedule);
16394 return true;
16395 }
16396 return false;
16397}
16398
16401 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16402 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16403 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16404 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16405 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16406 return nullptr;
16407 // OpenMP, 2.7.1, Loop Construct, Restrictions
16408 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16409 // but not both.
16410 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16411 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16412 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16413 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16414 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16415 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16416 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16417 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16418 return nullptr;
16419 }
16420 if (Kind == OMPC_SCHEDULE_unknown) {
16421 std::string Values;
16422 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16423 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16424 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16426 Exclude);
16427 } else {
16428 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16429 /*Last=*/OMPC_SCHEDULE_unknown);
16430 }
16431 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16432 << Values << getOpenMPClauseName(OMPC_schedule);
16433 return nullptr;
16434 }
16435 // OpenMP, 2.7.1, Loop Construct, Restrictions
16436 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16437 // schedule(guided).
16438 // OpenMP 5.0 does not have this restriction.
16439 if (getLangOpts().OpenMP < 50 &&
16440 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16441 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16442 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16443 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16444 diag::err_omp_schedule_nonmonotonic_static);
16445 return nullptr;
16446 }
16447 Expr *ValExpr = ChunkSize;
16448 Stmt *HelperValStmt = nullptr;
16449 if (ChunkSize) {
16450 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16451 !ChunkSize->isInstantiationDependent() &&
16452 !ChunkSize->containsUnexpandedParameterPack()) {
16453 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16454 ExprResult Val =
16455 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16456 if (Val.isInvalid())
16457 return nullptr;
16458
16459 ValExpr = Val.get();
16460
16461 // OpenMP [2.7.1, Restrictions]
16462 // chunk_size must be a loop invariant integer expression with a positive
16463 // value.
16464 if (std::optional<llvm::APSInt> Result =
16466 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16467 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16468 << "schedule" << 1 << ChunkSize->getSourceRange();
16469 return nullptr;
16470 }
16472 DSAStack->getCurrentDirective(), OMPC_schedule,
16473 getLangOpts().OpenMP) != OMPD_unknown &&
16475 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16476 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16477 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16478 HelperValStmt = buildPreInits(getASTContext(), Captures);
16479 }
16480 }
16481 }
16482
16483 return new (getASTContext())
16484 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16485 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16486}
16487
16489 SourceLocation StartLoc,
16490 SourceLocation EndLoc) {
16491 OMPClause *Res = nullptr;
16492 switch (Kind) {
16493 case OMPC_ordered:
16494 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16495 break;
16496 case OMPC_nowait:
16497 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16498 break;
16499 case OMPC_untied:
16500 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16501 break;
16502 case OMPC_mergeable:
16503 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16504 break;
16505 case OMPC_read:
16506 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16507 break;
16508 case OMPC_write:
16509 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16510 break;
16511 case OMPC_update:
16512 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16513 break;
16514 case OMPC_capture:
16515 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16516 break;
16517 case OMPC_compare:
16518 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16519 break;
16520 case OMPC_fail:
16521 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16522 break;
16523 case OMPC_seq_cst:
16524 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16525 break;
16526 case OMPC_acq_rel:
16527 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16528 break;
16529 case OMPC_acquire:
16530 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16531 break;
16532 case OMPC_release:
16533 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16534 break;
16535 case OMPC_relaxed:
16536 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16537 break;
16538 case OMPC_weak:
16539 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16540 break;
16541 case OMPC_threads:
16542 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16543 break;
16544 case OMPC_simd:
16545 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16546 break;
16547 case OMPC_nogroup:
16548 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16549 break;
16550 case OMPC_unified_address:
16551 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16552 break;
16553 case OMPC_unified_shared_memory:
16554 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16555 break;
16556 case OMPC_reverse_offload:
16557 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16558 break;
16559 case OMPC_dynamic_allocators:
16560 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16561 break;
16562 case OMPC_destroy:
16563 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16564 /*LParenLoc=*/SourceLocation(),
16565 /*VarLoc=*/SourceLocation(), EndLoc);
16566 break;
16567 case OMPC_full:
16568 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16569 break;
16570 case OMPC_partial:
16571 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16572 break;
16573 case OMPC_ompx_bare:
16574 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16575 break;
16576 case OMPC_if:
16577 case OMPC_final:
16578 case OMPC_num_threads:
16579 case OMPC_safelen:
16580 case OMPC_simdlen:
16581 case OMPC_sizes:
16582 case OMPC_allocator:
16583 case OMPC_collapse:
16584 case OMPC_schedule:
16585 case OMPC_private:
16586 case OMPC_firstprivate:
16587 case OMPC_lastprivate:
16588 case OMPC_shared:
16589 case OMPC_reduction:
16590 case OMPC_task_reduction:
16591 case OMPC_in_reduction:
16592 case OMPC_linear:
16593 case OMPC_aligned:
16594 case OMPC_copyin:
16595 case OMPC_copyprivate:
16596 case OMPC_default:
16597 case OMPC_proc_bind:
16598 case OMPC_threadprivate:
16599 case OMPC_allocate:
16600 case OMPC_flush:
16601 case OMPC_depobj:
16602 case OMPC_depend:
16603 case OMPC_device:
16604 case OMPC_map:
16605 case OMPC_num_teams:
16606 case OMPC_thread_limit:
16607 case OMPC_priority:
16608 case OMPC_grainsize:
16609 case OMPC_num_tasks:
16610 case OMPC_hint:
16611 case OMPC_dist_schedule:
16612 case OMPC_defaultmap:
16613 case OMPC_unknown:
16614 case OMPC_uniform:
16615 case OMPC_to:
16616 case OMPC_from:
16617 case OMPC_use_device_ptr:
16618 case OMPC_use_device_addr:
16619 case OMPC_is_device_ptr:
16620 case OMPC_has_device_addr:
16621 case OMPC_atomic_default_mem_order:
16622 case OMPC_device_type:
16623 case OMPC_match:
16624 case OMPC_nontemporal:
16625 case OMPC_order:
16626 case OMPC_at:
16627 case OMPC_severity:
16628 case OMPC_message:
16629 case OMPC_novariants:
16630 case OMPC_nocontext:
16631 case OMPC_detach:
16632 case OMPC_inclusive:
16633 case OMPC_exclusive:
16634 case OMPC_uses_allocators:
16635 case OMPC_affinity:
16636 case OMPC_when:
16637 case OMPC_ompx_dyn_cgroup_mem:
16638 default:
16639 llvm_unreachable("Clause is not allowed.");
16640 }
16641 return Res;
16642}
16643
16645 SourceLocation EndLoc) {
16646 DSAStack->setNowaitRegion();
16647 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
16648}
16649
16651 SourceLocation EndLoc) {
16652 DSAStack->setUntiedRegion();
16653 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
16654}
16655
16657 SourceLocation EndLoc) {
16658 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
16659}
16660
16662 SourceLocation EndLoc) {
16663 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
16664}
16665
16667 SourceLocation EndLoc) {
16668 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
16669}
16670
16672 SourceLocation EndLoc) {
16673 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
16674}
16675
16677 SourceLocation EndLoc) {
16678 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
16679}
16680
16682 SourceLocation EndLoc) {
16683 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
16684}
16685
16687 SourceLocation EndLoc) {
16688 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
16689}
16690
16692 SourceLocation KindLoc,
16693 SourceLocation StartLoc,
16694 SourceLocation LParenLoc,
16695 SourceLocation EndLoc) {
16696
16698 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16699 return nullptr;
16700 }
16701 return new (getASTContext())
16702 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
16703}
16704
16706 SourceLocation EndLoc) {
16707 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
16708}
16709
16711 SourceLocation EndLoc) {
16712 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
16713}
16714
16716 SourceLocation EndLoc) {
16717 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
16718}
16719
16721 SourceLocation EndLoc) {
16722 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
16723}
16724
16726 SourceLocation EndLoc) {
16727 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
16728}
16729
16731 SourceLocation EndLoc) {
16732 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
16733}
16734
16736 SourceLocation EndLoc) {
16737 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
16738}
16739
16741 SourceLocation EndLoc) {
16742 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
16743}
16744
16746 SourceLocation EndLoc) {
16747 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
16748}
16749
16751 SourceLocation EndLoc) {
16752 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
16753}
16754
16755OMPClause *
16757 SourceLocation EndLoc) {
16758 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16759}
16760
16762 SourceLocation EndLoc) {
16763 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
16764}
16765
16766OMPClause *
16768 SourceLocation EndLoc) {
16769 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
16770}
16771
16774 SourceLocation StartLoc,
16775 SourceLocation EndLoc) {
16776
16777 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16778 // At least one action-clause must appear on a directive.
16779 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16780 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
16781 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16782 << Expected << getOpenMPDirectiveName(OMPD_interop);
16783 return StmtError();
16784 }
16785
16786 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16787 // A depend clause can only appear on the directive if a targetsync
16788 // interop-type is present or the interop-var was initialized with
16789 // the targetsync interop-type.
16790
16791 // If there is any 'init' clause diagnose if there is no 'init' clause with
16792 // interop-type of 'targetsync'. Cases involving other directives cannot be
16793 // diagnosed.
16794 const OMPDependClause *DependClause = nullptr;
16795 bool HasInitClause = false;
16796 bool IsTargetSync = false;
16797 for (const OMPClause *C : Clauses) {
16798 if (IsTargetSync)
16799 break;
16800 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
16801 HasInitClause = true;
16802 if (InitClause->getIsTargetSync())
16803 IsTargetSync = true;
16804 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
16805 DependClause = DC;
16806 }
16807 }
16808 if (DependClause && HasInitClause && !IsTargetSync) {
16809 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16810 return StmtError();
16811 }
16812
16813 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16814 // Each interop-var may be specified for at most one action-clause of each
16815 // interop construct.
16817 for (OMPClause *C : Clauses) {
16818 OpenMPClauseKind ClauseKind = C->getClauseKind();
16819 std::pair<ValueDecl *, bool> DeclResult;
16820 SourceLocation ELoc;
16821 SourceRange ERange;
16822
16823 if (ClauseKind == OMPC_init) {
16824 auto *E = cast<OMPInitClause>(C)->getInteropVar();
16825 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16826 } else if (ClauseKind == OMPC_use) {
16827 auto *E = cast<OMPUseClause>(C)->getInteropVar();
16828 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16829 } else if (ClauseKind == OMPC_destroy) {
16830 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
16831 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16832 }
16833
16834 if (DeclResult.first) {
16835 if (!InteropVars.insert(DeclResult.first).second) {
16836 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16837 << DeclResult.first;
16838 return StmtError();
16839 }
16840 }
16841 }
16842
16843 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
16844 Clauses);
16845}
16846
16847static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
16848 SourceLocation VarLoc,
16849 OpenMPClauseKind Kind) {
16850 SourceLocation ELoc;
16851 SourceRange ERange;
16852 Expr *RefExpr = InteropVarExpr;
16853 auto Res =
16854 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
16855 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
16856
16857 if (Res.second) {
16858 // It will be analyzed later.
16859 return true;
16860 }
16861
16862 if (!Res.first)
16863 return false;
16864
16865 // Interop variable should be of type omp_interop_t.
16866 bool HasError = false;
16867 QualType InteropType;
16868 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
16869 VarLoc, Sema::LookupOrdinaryName);
16870 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
16871 NamedDecl *ND = Result.getFoundDecl();
16872 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
16873 InteropType = QualType(TD->getTypeForDecl(), 0);
16874 } else {
16875 HasError = true;
16876 }
16877 } else {
16878 HasError = true;
16879 }
16880
16881 if (HasError) {
16882 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
16883 << "omp_interop_t";
16884 return false;
16885 }
16886
16887 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
16888 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
16889 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16890 return false;
16891 }
16892
16893 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16894 // The interop-var passed to init or destroy must be non-const.
16895 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16896 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
16897 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
16898 << /*non-const*/ 1;
16899 return false;
16900 }
16901 return true;
16902}
16903
16905 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
16906 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
16907
16908 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
16909 return nullptr;
16910
16911 // Check prefer_type values. These foreign-runtime-id values are either
16912 // string literals or constant integral expressions.
16913 for (const Expr *E : InteropInfo.PreferTypes) {
16914 if (E->isValueDependent() || E->isTypeDependent() ||
16916 continue;
16918 continue;
16919 if (isa<StringLiteral>(E))
16920 continue;
16921 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
16922 return nullptr;
16923 }
16924
16925 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
16926 StartLoc, LParenLoc, VarLoc, EndLoc);
16927}
16928
16930 SourceLocation StartLoc,
16931 SourceLocation LParenLoc,
16932 SourceLocation VarLoc,
16933 SourceLocation EndLoc) {
16934
16935 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
16936 return nullptr;
16937
16938 return new (getASTContext())
16939 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16940}
16941
16943 SourceLocation StartLoc,
16944 SourceLocation LParenLoc,
16945 SourceLocation VarLoc,
16946 SourceLocation EndLoc) {
16947 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
16948 DSAStack->getCurrentDirective() == OMPD_depobj) {
16949 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16950 << getOpenMPClauseName(OMPC_destroy)
16951 << getOpenMPDirectiveName(OMPD_depobj);
16952 return nullptr;
16953 }
16954 if (InteropVar &&
16955 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
16956 return nullptr;
16957
16958 return new (getASTContext())
16959 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16960}
16961
16963 SourceLocation StartLoc,
16964 SourceLocation LParenLoc,
16965 SourceLocation EndLoc) {
16966 Expr *ValExpr = Condition;
16967 Stmt *HelperValStmt = nullptr;
16968 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16969 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16970 !Condition->isInstantiationDependent() &&
16971 !Condition->containsUnexpandedParameterPack()) {
16973 if (Val.isInvalid())
16974 return nullptr;
16975
16976 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16977
16978 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16979 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
16980 getLangOpts().OpenMP);
16981 if (CaptureRegion != OMPD_unknown &&
16983 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16984 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16985 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16986 HelperValStmt = buildPreInits(getASTContext(), Captures);
16987 }
16988 }
16989
16990 return new (getASTContext()) OMPNovariantsClause(
16991 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16992}
16993
16995 SourceLocation StartLoc,
16996 SourceLocation LParenLoc,
16997 SourceLocation EndLoc) {
16998 Expr *ValExpr = Condition;
16999 Stmt *HelperValStmt = nullptr;
17000 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17001 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17002 !Condition->isInstantiationDependent() &&
17003 !Condition->containsUnexpandedParameterPack()) {
17005 if (Val.isInvalid())
17006 return nullptr;
17007
17008 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17009
17010 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17011 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
17012 getLangOpts().OpenMP);
17013 if (CaptureRegion != OMPD_unknown &&
17015 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17016 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17017 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17018 HelperValStmt = buildPreInits(getASTContext(), Captures);
17019 }
17020 }
17021
17022 return new (getASTContext()) OMPNocontextClause(
17023 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17024}
17025
17027 SourceLocation StartLoc,
17028 SourceLocation LParenLoc,
17029 SourceLocation EndLoc) {
17030 Expr *ValExpr = ThreadID;
17031 Stmt *HelperValStmt = nullptr;
17032
17033 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17034 OpenMPDirectiveKind CaptureRegion =
17035 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
17036 if (CaptureRegion != OMPD_unknown &&
17038 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17039 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17040 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17041 HelperValStmt = buildPreInits(getASTContext(), Captures);
17042 }
17043
17044 return new (getASTContext()) OMPFilterClause(
17045 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17046}
17047
17049 ArrayRef<Expr *> VarList,
17050 const OMPVarListLocTy &Locs,
17052 SourceLocation StartLoc = Locs.StartLoc;
17053 SourceLocation LParenLoc = Locs.LParenLoc;
17054 SourceLocation EndLoc = Locs.EndLoc;
17055 OMPClause *Res = nullptr;
17056 int ExtraModifier = Data.ExtraModifier;
17057 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17058 SourceLocation ColonLoc = Data.ColonLoc;
17059 switch (Kind) {
17060 case OMPC_private:
17061 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17062 break;
17063 case OMPC_firstprivate:
17064 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17065 break;
17066 case OMPC_lastprivate:
17067 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17068 "Unexpected lastprivate modifier.");
17070 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17071 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17072 break;
17073 case OMPC_shared:
17074 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17075 break;
17076 case OMPC_reduction:
17077 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17078 "Unexpected lastprivate modifier.");
17080 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
17081 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17082 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17083 break;
17084 case OMPC_task_reduction:
17086 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17087 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17088 break;
17089 case OMPC_in_reduction:
17091 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17092 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17093 break;
17094 case OMPC_linear:
17095 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17096 "Unexpected linear modifier.");
17098 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17099 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17100 ColonLoc, Data.StepModifierLoc, EndLoc);
17101 break;
17102 case OMPC_aligned:
17103 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17104 LParenLoc, ColonLoc, EndLoc);
17105 break;
17106 case OMPC_copyin:
17107 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17108 break;
17109 case OMPC_copyprivate:
17110 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17111 break;
17112 case OMPC_flush:
17113 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17114 break;
17115 case OMPC_depend:
17116 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17117 "Unexpected depend modifier.");
17119 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17120 ColonLoc, Data.OmpAllMemoryLoc},
17121 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17122 break;
17123 case OMPC_map:
17124 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17125 "Unexpected map modifier.");
17127 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17128 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17129 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17130 ExtraModifierLoc, ColonLoc, VarList, Locs);
17131 break;
17132 case OMPC_to:
17133 Res =
17134 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17135 Data.ReductionOrMapperIdScopeSpec,
17136 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17137 break;
17138 case OMPC_from:
17139 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17140 Data.ReductionOrMapperIdScopeSpec,
17141 Data.ReductionOrMapperId, ColonLoc, VarList,
17142 Locs);
17143 break;
17144 case OMPC_use_device_ptr:
17145 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17146 break;
17147 case OMPC_use_device_addr:
17148 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17149 break;
17150 case OMPC_is_device_ptr:
17151 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17152 break;
17153 case OMPC_has_device_addr:
17154 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17155 break;
17156 case OMPC_allocate:
17157 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr,
17158 Data.AllocClauseModifier, VarList, StartLoc,
17159 LParenLoc, ColonLoc, EndLoc);
17160 break;
17161 case OMPC_nontemporal:
17162 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17163 break;
17164 case OMPC_inclusive:
17165 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17166 break;
17167 case OMPC_exclusive:
17168 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17169 break;
17170 case OMPC_affinity:
17171 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17172 Data.DepModOrTailExpr, VarList);
17173 break;
17174 case OMPC_doacross:
17176 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17177 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17178 break;
17179 case OMPC_num_teams:
17180 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17181 break;
17182 case OMPC_thread_limit:
17183 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17184 break;
17185 case OMPC_if:
17186 case OMPC_depobj:
17187 case OMPC_final:
17188 case OMPC_num_threads:
17189 case OMPC_safelen:
17190 case OMPC_simdlen:
17191 case OMPC_sizes:
17192 case OMPC_allocator:
17193 case OMPC_collapse:
17194 case OMPC_default:
17195 case OMPC_proc_bind:
17196 case OMPC_schedule:
17197 case OMPC_ordered:
17198 case OMPC_nowait:
17199 case OMPC_untied:
17200 case OMPC_mergeable:
17201 case OMPC_threadprivate:
17202 case OMPC_read:
17203 case OMPC_write:
17204 case OMPC_update:
17205 case OMPC_capture:
17206 case OMPC_compare:
17207 case OMPC_seq_cst:
17208 case OMPC_acq_rel:
17209 case OMPC_acquire:
17210 case OMPC_release:
17211 case OMPC_relaxed:
17212 case OMPC_device:
17213 case OMPC_threads:
17214 case OMPC_simd:
17215 case OMPC_priority:
17216 case OMPC_grainsize:
17217 case OMPC_nogroup:
17218 case OMPC_num_tasks:
17219 case OMPC_hint:
17220 case OMPC_dist_schedule:
17221 case OMPC_defaultmap:
17222 case OMPC_unknown:
17223 case OMPC_uniform:
17224 case OMPC_unified_address:
17225 case OMPC_unified_shared_memory:
17226 case OMPC_reverse_offload:
17227 case OMPC_dynamic_allocators:
17228 case OMPC_atomic_default_mem_order:
17229 case OMPC_device_type:
17230 case OMPC_match:
17231 case OMPC_order:
17232 case OMPC_at:
17233 case OMPC_severity:
17234 case OMPC_message:
17235 case OMPC_destroy:
17236 case OMPC_novariants:
17237 case OMPC_nocontext:
17238 case OMPC_detach:
17239 case OMPC_uses_allocators:
17240 case OMPC_when:
17241 case OMPC_bind:
17242 default:
17243 llvm_unreachable("Clause is not allowed.");
17244 }
17245 return Res;
17246}
17247
17249 ExprObjectKind OK,
17252 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17253 if (!Res.isUsable())
17254 return ExprError();
17255 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17256 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17257 if (!Res.isUsable())
17258 return ExprError();
17259 }
17260 if (VK != VK_LValue && Res.get()->isGLValue()) {
17261 Res = SemaRef.DefaultLvalueConversion(Res.get());
17262 if (!Res.isUsable())
17263 return ExprError();
17264 }
17265 return Res;
17266}
17267
17269 SourceLocation StartLoc,
17270 SourceLocation LParenLoc,
17271 SourceLocation EndLoc) {
17273 SmallVector<Expr *, 8> PrivateCopies;
17274 bool IsImplicitClause =
17275 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17276 for (Expr *RefExpr : VarList) {
17277 assert(RefExpr && "NULL expr in OpenMP private clause.");
17278 SourceLocation ELoc;
17279 SourceRange ERange;
17280 Expr *SimpleRefExpr = RefExpr;
17281 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17282 if (Res.second) {
17283 // It will be analyzed later.
17284 Vars.push_back(RefExpr);
17285 PrivateCopies.push_back(nullptr);
17286 }
17287 ValueDecl *D = Res.first;
17288 if (!D)
17289 continue;
17290
17291 QualType Type = D->getType();
17292 auto *VD = dyn_cast<VarDecl>(D);
17293
17294 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17295 // A variable that appears in a private clause must not have an incomplete
17296 // type or a reference type.
17298 diag::err_omp_private_incomplete_type))
17299 continue;
17300 Type = Type.getNonReferenceType();
17301
17302 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17303 // A variable that is privatized must not have a const-qualified type
17304 // unless it is of class type with a mutable member. This restriction does
17305 // not apply to the firstprivate clause.
17306 //
17307 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17308 // A variable that appears in a private clause must not have a
17309 // const-qualified type unless it is of class type with a mutable member.
17310 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17311 continue;
17312
17313 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17314 // in a Construct]
17315 // Variables with the predetermined data-sharing attributes may not be
17316 // listed in data-sharing attributes clauses, except for the cases
17317 // listed below. For these exceptions only, listing a predetermined
17318 // variable in a data-sharing attribute clause is allowed and overrides
17319 // the variable's predetermined data-sharing attributes.
17320 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17321 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17322 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17323 << getOpenMPClauseName(OMPC_private);
17325 continue;
17326 }
17327
17328 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17329 // Variably modified types are not supported for tasks.
17331 isOpenMPTaskingDirective(CurrDir)) {
17332 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17333 << getOpenMPClauseName(OMPC_private) << Type
17334 << getOpenMPDirectiveName(CurrDir);
17335 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17337 Diag(D->getLocation(),
17338 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17339 << D;
17340 continue;
17341 }
17342
17343 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17344 // A list item cannot appear in both a map clause and a data-sharing
17345 // attribute clause on the same construct
17346 //
17347 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17348 // A list item cannot appear in both a map clause and a data-sharing
17349 // attribute clause on the same construct unless the construct is a
17350 // combined construct.
17351 if ((getLangOpts().OpenMP <= 45 &&
17353 CurrDir == OMPD_target) {
17354 OpenMPClauseKind ConflictKind;
17355 if (DSAStack->checkMappableExprComponentListsForDecl(
17356 VD, /*CurrentRegionOnly=*/true,
17358 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17359 ConflictKind = WhereFoundClauseKind;
17360 return true;
17361 })) {
17362 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17363 << getOpenMPClauseName(OMPC_private)
17364 << getOpenMPClauseName(ConflictKind)
17365 << getOpenMPDirectiveName(CurrDir);
17367 continue;
17368 }
17369 }
17370
17371 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17372 // A variable of class type (or array thereof) that appears in a private
17373 // clause requires an accessible, unambiguous default constructor for the
17374 // class type.
17375 // Generate helper private variable and initialize it with the default
17376 // value. The address of the original variable is replaced by the address of
17377 // the new private variable in CodeGen. This new variable is not added to
17378 // IdResolver, so the code in the OpenMP region uses original variable for
17379 // proper diagnostics.
17380 Type = Type.getUnqualifiedType();
17381 VarDecl *VDPrivate =
17382 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17383 D->hasAttrs() ? &D->getAttrs() : nullptr,
17384 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17386 if (VDPrivate->isInvalidDecl())
17387 continue;
17388 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17389 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17390
17391 DeclRefExpr *Ref = nullptr;
17392 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17393 auto *FD = dyn_cast<FieldDecl>(D);
17394 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17395 if (VD)
17397 RefExpr->getExprLoc());
17398 else
17399 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17400 }
17401 if (!IsImplicitClause)
17402 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17403 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17404 ? RefExpr->IgnoreParens()
17405 : Ref);
17406 PrivateCopies.push_back(VDPrivateRefExpr);
17407 }
17408
17409 if (Vars.empty())
17410 return nullptr;
17411
17412 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17413 Vars, PrivateCopies);
17414}
17415
17417 SourceLocation StartLoc,
17418 SourceLocation LParenLoc,
17419 SourceLocation EndLoc) {
17421 SmallVector<Expr *, 8> PrivateCopies;
17423 SmallVector<Decl *, 4> ExprCaptures;
17424 bool IsImplicitClause =
17425 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17426 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17427
17428 for (Expr *RefExpr : VarList) {
17429 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17430 SourceLocation ELoc;
17431 SourceRange ERange;
17432 Expr *SimpleRefExpr = RefExpr;
17433 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17434 if (Res.second) {
17435 // It will be analyzed later.
17436 Vars.push_back(RefExpr);
17437 PrivateCopies.push_back(nullptr);
17438 Inits.push_back(nullptr);
17439 }
17440 ValueDecl *D = Res.first;
17441 if (!D)
17442 continue;
17443
17444 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17445 QualType Type = D->getType();
17446 auto *VD = dyn_cast<VarDecl>(D);
17447
17448 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17449 // A variable that appears in a private clause must not have an incomplete
17450 // type or a reference type.
17452 diag::err_omp_firstprivate_incomplete_type))
17453 continue;
17454 Type = Type.getNonReferenceType();
17455
17456 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17457 // A variable of class type (or array thereof) that appears in a private
17458 // clause requires an accessible, unambiguous copy constructor for the
17459 // class type.
17460 QualType ElemType =
17462
17463 // If an implicit firstprivate variable found it was checked already.
17464 DSAStackTy::DSAVarData TopDVar;
17465 if (!IsImplicitClause) {
17466 DSAStackTy::DSAVarData DVar =
17467 DSAStack->getTopDSA(D, /*FromParent=*/false);
17468 TopDVar = DVar;
17469 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17470 bool IsConstant = ElemType.isConstant(getASTContext());
17471 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17472 // A list item that specifies a given variable may not appear in more
17473 // than one clause on the same directive, except that a variable may be
17474 // specified in both firstprivate and lastprivate clauses.
17475 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17476 // A list item may appear in a firstprivate or lastprivate clause but not
17477 // both.
17478 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17479 (isOpenMPDistributeDirective(CurrDir) ||
17480 DVar.CKind != OMPC_lastprivate) &&
17481 DVar.RefExpr) {
17482 Diag(ELoc, diag::err_omp_wrong_dsa)
17483 << getOpenMPClauseName(DVar.CKind)
17484 << getOpenMPClauseName(OMPC_firstprivate);
17486 continue;
17487 }
17488
17489 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17490 // in a Construct]
17491 // Variables with the predetermined data-sharing attributes may not be
17492 // listed in data-sharing attributes clauses, except for the cases
17493 // listed below. For these exceptions only, listing a predetermined
17494 // variable in a data-sharing attribute clause is allowed and overrides
17495 // the variable's predetermined data-sharing attributes.
17496 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17497 // in a Construct, C/C++, p.2]
17498 // Variables with const-qualified type having no mutable member may be
17499 // listed in a firstprivate clause, even if they are static data members.
17500 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17501 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17502 Diag(ELoc, diag::err_omp_wrong_dsa)
17503 << getOpenMPClauseName(DVar.CKind)
17504 << getOpenMPClauseName(OMPC_firstprivate);
17506 continue;
17507 }
17508
17509 // OpenMP [2.9.3.4, Restrictions, p.2]
17510 // A list item that is private within a parallel region must not appear
17511 // in a firstprivate clause on a worksharing construct if any of the
17512 // worksharing regions arising from the worksharing construct ever bind
17513 // to any of the parallel regions arising from the parallel construct.
17514 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17515 // A list item that is private within a teams region must not appear in a
17516 // firstprivate clause on a distribute construct if any of the distribute
17517 // regions arising from the distribute construct ever bind to any of the
17518 // teams regions arising from the teams construct.
17519 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17520 // A list item that appears in a reduction clause of a teams construct
17521 // must not appear in a firstprivate clause on a distribute construct if
17522 // any of the distribute regions arising from the distribute construct
17523 // ever bind to any of the teams regions arising from the teams construct.
17524 if ((isOpenMPWorksharingDirective(CurrDir) ||
17525 isOpenMPDistributeDirective(CurrDir)) &&
17526 !isOpenMPParallelDirective(CurrDir) &&
17527 !isOpenMPTeamsDirective(CurrDir)) {
17528 DVar = DSAStack->getImplicitDSA(D, true);
17529 if (DVar.CKind != OMPC_shared &&
17530 (isOpenMPParallelDirective(DVar.DKind) ||
17531 isOpenMPTeamsDirective(DVar.DKind) ||
17532 DVar.DKind == OMPD_unknown)) {
17533 Diag(ELoc, diag::err_omp_required_access)
17534 << getOpenMPClauseName(OMPC_firstprivate)
17535 << getOpenMPClauseName(OMPC_shared);
17537 continue;
17538 }
17539 }
17540 // OpenMP [2.9.3.4, Restrictions, p.3]
17541 // A list item that appears in a reduction clause of a parallel construct
17542 // must not appear in a firstprivate clause on a worksharing or task
17543 // construct if any of the worksharing or task regions arising from the
17544 // worksharing or task construct ever bind to any of the parallel regions
17545 // arising from the parallel construct.
17546 // OpenMP [2.9.3.4, Restrictions, p.4]
17547 // A list item that appears in a reduction clause in worksharing
17548 // construct must not appear in a firstprivate clause in a task construct
17549 // encountered during execution of any of the worksharing regions arising
17550 // from the worksharing construct.
17551 if (isOpenMPTaskingDirective(CurrDir)) {
17552 DVar = DSAStack->hasInnermostDSA(
17553 D,
17554 [](OpenMPClauseKind C, bool AppliedToPointee) {
17555 return C == OMPC_reduction && !AppliedToPointee;
17556 },
17557 [](OpenMPDirectiveKind K) {
17558 return isOpenMPParallelDirective(K) ||
17561 },
17562 /*FromParent=*/true);
17563 if (DVar.CKind == OMPC_reduction &&
17564 (isOpenMPParallelDirective(DVar.DKind) ||
17565 isOpenMPWorksharingDirective(DVar.DKind) ||
17566 isOpenMPTeamsDirective(DVar.DKind))) {
17567 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17568 << getOpenMPDirectiveName(DVar.DKind);
17570 continue;
17571 }
17572 }
17573
17574 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17575 // A list item cannot appear in both a map clause and a data-sharing
17576 // attribute clause on the same construct
17577 //
17578 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17579 // A list item cannot appear in both a map clause and a data-sharing
17580 // attribute clause on the same construct unless the construct is a
17581 // combined construct.
17582 if ((getLangOpts().OpenMP <= 45 &&
17584 CurrDir == OMPD_target) {
17585 OpenMPClauseKind ConflictKind;
17586 if (DSAStack->checkMappableExprComponentListsForDecl(
17587 VD, /*CurrentRegionOnly=*/true,
17588 [&ConflictKind](
17590 OpenMPClauseKind WhereFoundClauseKind) {
17591 ConflictKind = WhereFoundClauseKind;
17592 return true;
17593 })) {
17594 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17595 << getOpenMPClauseName(OMPC_firstprivate)
17596 << getOpenMPClauseName(ConflictKind)
17597 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17599 continue;
17600 }
17601 }
17602 }
17603
17604 // Variably modified types are not supported for tasks.
17606 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
17607 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17608 << getOpenMPClauseName(OMPC_firstprivate) << Type
17609 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17610 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17612 Diag(D->getLocation(),
17613 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17614 << D;
17615 continue;
17616 }
17617
17618 Type = Type.getUnqualifiedType();
17619 VarDecl *VDPrivate =
17620 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17621 D->hasAttrs() ? &D->getAttrs() : nullptr,
17622 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17623 // Generate helper private variable and initialize it with the value of the
17624 // original variable. The address of the original variable is replaced by
17625 // the address of the new private variable in the CodeGen. This new variable
17626 // is not added to IdResolver, so the code in the OpenMP region uses
17627 // original variable for proper diagnostics and variable capturing.
17628 Expr *VDInitRefExpr = nullptr;
17629 // For arrays generate initializer for single element and replace it by the
17630 // original array element in CodeGen.
17631 if (Type->isArrayType()) {
17632 VarDecl *VDInit =
17633 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
17634 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
17635 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
17636 ElemType = ElemType.getUnqualifiedType();
17637 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
17638 ElemType, ".firstprivate.temp");
17639 InitializedEntity Entity =
17642
17643 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
17644 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
17645 if (Result.isInvalid())
17646 VDPrivate->setInvalidDecl();
17647 else
17648 VDPrivate->setInit(Result.getAs<Expr>());
17649 // Remove temp variable declaration.
17650 getASTContext().Deallocate(VDInitTemp);
17651 } else {
17652 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
17653 ".firstprivate.temp");
17654 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
17655 RefExpr->getExprLoc());
17657 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
17658 /*DirectInit=*/false);
17659 }
17660 if (VDPrivate->isInvalidDecl()) {
17661 if (IsImplicitClause) {
17662 Diag(RefExpr->getExprLoc(),
17663 diag::note_omp_task_predetermined_firstprivate_here);
17664 }
17665 continue;
17666 }
17667 SemaRef.CurContext->addDecl(VDPrivate);
17668 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17669 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
17670 RefExpr->getExprLoc());
17671 DeclRefExpr *Ref = nullptr;
17672 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17673 if (TopDVar.CKind == OMPC_lastprivate) {
17674 Ref = TopDVar.PrivateCopy;
17675 } else {
17676 auto *FD = dyn_cast<FieldDecl>(D);
17677 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17678 if (VD)
17679 Ref =
17681 RefExpr->getExprLoc());
17682 else
17683 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17684 if (VD || !isOpenMPCapturedDecl(D))
17685 ExprCaptures.push_back(Ref->getDecl());
17686 }
17687 }
17688 if (!IsImplicitClause)
17689 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17690 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17691 ? RefExpr->IgnoreParens()
17692 : Ref);
17693 PrivateCopies.push_back(VDPrivateRefExpr);
17694 Inits.push_back(VDInitRefExpr);
17695 }
17696
17697 if (Vars.empty())
17698 return nullptr;
17699
17701 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17702 buildPreInits(getASTContext(), ExprCaptures));
17703}
17704
17707 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
17708 SourceLocation LParenLoc, SourceLocation EndLoc) {
17709 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
17710 assert(ColonLoc.isValid() && "Colon location must be valid.");
17711 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17712 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
17713 /*Last=*/OMPC_LASTPRIVATE_unknown)
17714 << getOpenMPClauseName(OMPC_lastprivate);
17715 return nullptr;
17716 }
17717
17719 SmallVector<Expr *, 8> SrcExprs;
17720 SmallVector<Expr *, 8> DstExprs;
17721 SmallVector<Expr *, 8> AssignmentOps;
17722 SmallVector<Decl *, 4> ExprCaptures;
17723 SmallVector<Expr *, 4> ExprPostUpdates;
17724 for (Expr *RefExpr : VarList) {
17725 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17726 SourceLocation ELoc;
17727 SourceRange ERange;
17728 Expr *SimpleRefExpr = RefExpr;
17729 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17730 if (Res.second) {
17731 // It will be analyzed later.
17732 Vars.push_back(RefExpr);
17733 SrcExprs.push_back(nullptr);
17734 DstExprs.push_back(nullptr);
17735 AssignmentOps.push_back(nullptr);
17736 }
17737 ValueDecl *D = Res.first;
17738 if (!D)
17739 continue;
17740
17741 QualType Type = D->getType();
17742 auto *VD = dyn_cast<VarDecl>(D);
17743
17744 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
17745 // A variable that appears in a lastprivate clause must not have an
17746 // incomplete type or a reference type.
17748 diag::err_omp_lastprivate_incomplete_type))
17749 continue;
17750 Type = Type.getNonReferenceType();
17751
17752 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17753 // A variable that is privatized must not have a const-qualified type
17754 // unless it is of class type with a mutable member. This restriction does
17755 // not apply to the firstprivate clause.
17756 //
17757 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
17758 // A variable that appears in a lastprivate clause must not have a
17759 // const-qualified type unless it is of class type with a mutable member.
17760 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
17761 continue;
17762
17763 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
17764 // A list item that appears in a lastprivate clause with the conditional
17765 // modifier must be a scalar variable.
17766 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
17767 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17768 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17770 Diag(D->getLocation(),
17771 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17772 << D;
17773 continue;
17774 }
17775
17776 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17777 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
17778 // in a Construct]
17779 // Variables with the predetermined data-sharing attributes may not be
17780 // listed in data-sharing attributes clauses, except for the cases
17781 // listed below.
17782 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17783 // A list item may appear in a firstprivate or lastprivate clause but not
17784 // both.
17785 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17786 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17787 (isOpenMPDistributeDirective(CurrDir) ||
17788 DVar.CKind != OMPC_firstprivate) &&
17789 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
17790 Diag(ELoc, diag::err_omp_wrong_dsa)
17791 << getOpenMPClauseName(DVar.CKind)
17792 << getOpenMPClauseName(OMPC_lastprivate);
17794 continue;
17795 }
17796
17797 // OpenMP [2.14.3.5, Restrictions, p.2]
17798 // A list item that is private within a parallel region, or that appears in
17799 // the reduction clause of a parallel construct, must not appear in a
17800 // lastprivate clause on a worksharing construct if any of the corresponding
17801 // worksharing regions ever binds to any of the corresponding parallel
17802 // regions.
17803 DSAStackTy::DSAVarData TopDVar = DVar;
17804 if (isOpenMPWorksharingDirective(CurrDir) &&
17805 !isOpenMPParallelDirective(CurrDir) &&
17806 !isOpenMPTeamsDirective(CurrDir)) {
17807 DVar = DSAStack->getImplicitDSA(D, true);
17808 if (DVar.CKind != OMPC_shared) {
17809 Diag(ELoc, diag::err_omp_required_access)
17810 << getOpenMPClauseName(OMPC_lastprivate)
17811 << getOpenMPClauseName(OMPC_shared);
17813 continue;
17814 }
17815 }
17816
17817 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
17818 // A variable of class type (or array thereof) that appears in a
17819 // lastprivate clause requires an accessible, unambiguous default
17820 // constructor for the class type, unless the list item is also specified
17821 // in a firstprivate clause.
17822 // A variable of class type (or array thereof) that appears in a
17823 // lastprivate clause requires an accessible, unambiguous copy assignment
17824 // operator for the class type.
17826 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
17827 Type.getUnqualifiedType(), ".lastprivate.src",
17828 D->hasAttrs() ? &D->getAttrs() : nullptr);
17829 DeclRefExpr *PseudoSrcExpr =
17830 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
17831 VarDecl *DstVD =
17832 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
17833 D->hasAttrs() ? &D->getAttrs() : nullptr);
17834 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
17835 // For arrays generate assignment operation for single element and replace
17836 // it by the original array element in CodeGen.
17837 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
17838 PseudoDstExpr, PseudoSrcExpr);
17839 if (AssignmentOp.isInvalid())
17840 continue;
17841 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
17842 /*DiscardedValue=*/false);
17843 if (AssignmentOp.isInvalid())
17844 continue;
17845
17846 DeclRefExpr *Ref = nullptr;
17847 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17848 if (TopDVar.CKind == OMPC_firstprivate) {
17849 Ref = TopDVar.PrivateCopy;
17850 } else {
17851 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17852 if (!isOpenMPCapturedDecl(D))
17853 ExprCaptures.push_back(Ref->getDecl());
17854 }
17855 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17857 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
17859 if (!RefRes.isUsable())
17860 continue;
17861 ExprResult PostUpdateRes =
17862 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
17863 SimpleRefExpr, RefRes.get());
17864 if (!PostUpdateRes.isUsable())
17865 continue;
17866 ExprPostUpdates.push_back(
17867 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
17868 }
17869 }
17870 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17871 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17872 ? RefExpr->IgnoreParens()
17873 : Ref);
17874 SrcExprs.push_back(PseudoSrcExpr);
17875 DstExprs.push_back(PseudoDstExpr);
17876 AssignmentOps.push_back(AssignmentOp.get());
17877 }
17878
17879 if (Vars.empty())
17880 return nullptr;
17881
17883 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17884 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17885 buildPreInits(getASTContext(), ExprCaptures),
17886 buildPostUpdate(SemaRef, ExprPostUpdates));
17887}
17888
17890 SourceLocation StartLoc,
17891 SourceLocation LParenLoc,
17892 SourceLocation EndLoc) {
17894 for (Expr *RefExpr : VarList) {
17895 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17896 SourceLocation ELoc;
17897 SourceRange ERange;
17898 Expr *SimpleRefExpr = RefExpr;
17899 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17900 if (Res.second) {
17901 // It will be analyzed later.
17902 Vars.push_back(RefExpr);
17903 }
17904 ValueDecl *D = Res.first;
17905 if (!D)
17906 continue;
17907
17908 auto *VD = dyn_cast<VarDecl>(D);
17909 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17910 // in a Construct]
17911 // Variables with the predetermined data-sharing attributes may not be
17912 // listed in data-sharing attributes clauses, except for the cases
17913 // listed below. For these exceptions only, listing a predetermined
17914 // variable in a data-sharing attribute clause is allowed and overrides
17915 // the variable's predetermined data-sharing attributes.
17916 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17917 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17918 DVar.RefExpr) {
17919 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17920 << getOpenMPClauseName(OMPC_shared);
17922 continue;
17923 }
17924
17925 DeclRefExpr *Ref = nullptr;
17926 if (!VD && isOpenMPCapturedDecl(D) &&
17928 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17929 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17930 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
17931 ? RefExpr->IgnoreParens()
17932 : Ref);
17933 }
17934
17935 if (Vars.empty())
17936 return nullptr;
17937
17938 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17939 Vars);
17940}
17941
17942namespace {
17943class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
17944 DSAStackTy *Stack;
17945
17946public:
17947 bool VisitDeclRefExpr(DeclRefExpr *E) {
17948 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
17949 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
17950 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17951 return false;
17952 if (DVar.CKind != OMPC_unknown)
17953 return true;
17954 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17955 VD,
17956 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
17957 return isOpenMPPrivate(C) && !AppliedToPointee;
17958 },
17959 [](OpenMPDirectiveKind) { return true; },
17960 /*FromParent=*/true);
17961 return DVarPrivate.CKind != OMPC_unknown;
17962 }
17963 return false;
17964 }
17965 bool VisitStmt(Stmt *S) {
17966 for (Stmt *Child : S->children()) {
17967 if (Child && Visit(Child))
17968 return true;
17969 }
17970 return false;
17971 }
17972 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17973};
17974} // namespace
17975
17976namespace {
17977// Transform MemberExpression for specified FieldDecl of current class to
17978// DeclRefExpr to specified OMPCapturedExprDecl.
17979class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
17980 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
17981 ValueDecl *Field = nullptr;
17982 DeclRefExpr *CapturedExpr = nullptr;
17983
17984public:
17985 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
17986 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
17987
17988 ExprResult TransformMemberExpr(MemberExpr *E) {
17989 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
17990 E->getMemberDecl() == Field) {
17991 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
17992 return CapturedExpr;
17993 }
17994 return BaseTransform::TransformMemberExpr(E);
17995 }
17996 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
17997};
17998} // namespace
17999
18000template <typename T, typename U>
18002 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18003 for (U &Set : Lookups) {
18004 for (auto *D : Set) {
18005 if (T Res = Gen(cast<ValueDecl>(D)))
18006 return Res;
18007 }
18008 }
18009 return T();
18010}
18011
18013 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18014
18015 for (auto *RD : D->redecls()) {
18016 // Don't bother with extra checks if we already know this one isn't visible.
18017 if (RD == D)
18018 continue;
18019
18020 auto ND = cast<NamedDecl>(RD);
18021 if (LookupResult::isVisible(SemaRef, ND))
18022 return ND;
18023 }
18024
18025 return nullptr;
18026}
18027
18028static void
18032 // Find all of the associated namespaces and classes based on the
18033 // arguments we have.
18034 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18035 Sema::AssociatedClassSet AssociatedClasses;
18036 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18037 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18038 AssociatedClasses);
18039
18040 // C++ [basic.lookup.argdep]p3:
18041 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18042 // and let Y be the lookup set produced by argument dependent
18043 // lookup (defined as follows). If X contains [...] then Y is
18044 // empty. Otherwise Y is the set of declarations found in the
18045 // namespaces associated with the argument types as described
18046 // below. The set of declarations found by the lookup of the name
18047 // is the union of X and Y.
18048 //
18049 // Here, we compute Y and add its members to the overloaded
18050 // candidate set.
18051 for (auto *NS : AssociatedNamespaces) {
18052 // When considering an associated namespace, the lookup is the
18053 // same as the lookup performed when the associated namespace is
18054 // used as a qualifier (3.4.3.2) except that:
18055 //
18056 // -- Any using-directives in the associated namespace are
18057 // ignored.
18058 //
18059 // -- Any namespace-scope friend functions declared in
18060 // associated classes are visible within their respective
18061 // namespaces even if they are not visible during an ordinary
18062 // lookup (11.4).
18063 DeclContext::lookup_result R = NS->lookup(Id.getName());
18064 for (auto *D : R) {
18065 auto *Underlying = D;
18066 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18067 Underlying = USD->getTargetDecl();
18068
18069 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18070 !isa<OMPDeclareMapperDecl>(Underlying))
18071 continue;
18072
18073 if (!SemaRef.isVisible(D)) {
18074 D = findAcceptableDecl(SemaRef, D);
18075 if (!D)
18076 continue;
18077 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18078 Underlying = USD->getTargetDecl();
18079 }
18080 Lookups.emplace_back();
18081 Lookups.back().addDecl(Underlying);
18082 }
18083 }
18084}
18085
18086static ExprResult
18088 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18089 const DeclarationNameInfo &ReductionId, QualType Ty,
18090 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18091 if (ReductionIdScopeSpec.isInvalid())
18092 return ExprError();
18093 SmallVector<UnresolvedSet<8>, 4> Lookups;
18094 if (S) {
18095 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18096 Lookup.suppressDiagnostics();
18097 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
18098 /*ObjectType=*/QualType())) {
18099 NamedDecl *D = Lookup.getRepresentativeDecl();
18100 do {
18101 S = S->getParent();
18102 } while (S && !S->isDeclScope(D));
18103 if (S)
18104 S = S->getParent();
18105 Lookups.emplace_back();
18106 Lookups.back().append(Lookup.begin(), Lookup.end());
18107 Lookup.clear();
18108 }
18109 } else if (auto *ULE =
18110 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18111 Lookups.push_back(UnresolvedSet<8>());
18112 Decl *PrevD = nullptr;
18113 for (NamedDecl *D : ULE->decls()) {
18114 if (D == PrevD)
18115 Lookups.push_back(UnresolvedSet<8>());
18116 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18117 Lookups.back().addDecl(DRD);
18118 PrevD = D;
18119 }
18120 }
18121 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18124 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18125 return !D->isInvalidDecl() &&
18126 (D->getType()->isDependentType() ||
18127 D->getType()->isInstantiationDependentType() ||
18128 D->getType()->containsUnexpandedParameterPack());
18129 })) {
18130 UnresolvedSet<8> ResSet;
18131 for (const UnresolvedSet<8> &Set : Lookups) {
18132 if (Set.empty())
18133 continue;
18134 ResSet.append(Set.begin(), Set.end());
18135 // The last item marks the end of all declarations at the specified scope.
18136 ResSet.addDecl(Set[Set.size() - 1]);
18137 }
18139 SemaRef.Context, /*NamingClass=*/nullptr,
18140 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18141 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
18142 /*KnownInstantiationDependent=*/false);
18143 }
18144 // Lookup inside the classes.
18145 // C++ [over.match.oper]p3:
18146 // For a unary operator @ with an operand of a type whose
18147 // cv-unqualified version is T1, and for a binary operator @ with
18148 // a left operand of a type whose cv-unqualified version is T1 and
18149 // a right operand of a type whose cv-unqualified version is T2,
18150 // three sets of candidate functions, designated member
18151 // candidates, non-member candidates and built-in candidates, are
18152 // constructed as follows:
18153 // -- If T1 is a complete class type or a class currently being
18154 // defined, the set of member candidates is the result of the
18155 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18156 // the set of member candidates is empty.
18157 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18158 Lookup.suppressDiagnostics();
18159 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18160 // Complete the type if it can be completed.
18161 // If the type is neither complete nor being defined, bail out now.
18162 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18163 TyRec->getDecl()->getDefinition()) {
18164 Lookup.clear();
18165 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18166 if (Lookup.empty()) {
18167 Lookups.emplace_back();
18168 Lookups.back().append(Lookup.begin(), Lookup.end());
18169 }
18170 }
18171 }
18172 // Perform ADL.
18173 if (SemaRef.getLangOpts().CPlusPlus)
18174 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18175 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18176 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18177 if (!D->isInvalidDecl() &&
18178 SemaRef.Context.hasSameType(D->getType(), Ty))
18179 return D;
18180 return nullptr;
18181 }))
18182 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18183 VK_LValue, Loc);
18184 if (SemaRef.getLangOpts().CPlusPlus) {
18185 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18186 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18187 if (!D->isInvalidDecl() &&
18188 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18189 !Ty.isMoreQualifiedThan(D->getType(),
18190 SemaRef.getASTContext()))
18191 return D;
18192 return nullptr;
18193 })) {
18194 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18195 /*DetectVirtual=*/false);
18196 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18197 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18198 VD->getType().getUnqualifiedType()))) {
18199 if (SemaRef.CheckBaseClassAccess(
18200 Loc, VD->getType(), Ty, Paths.front(),
18201 /*DiagID=*/0) != Sema::AR_inaccessible) {
18202 SemaRef.BuildBasePathArray(Paths, BasePath);
18203 return SemaRef.BuildDeclRefExpr(
18205 }
18206 }
18207 }
18208 }
18209 }
18210 if (ReductionIdScopeSpec.isSet()) {
18211 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18212 << Ty << Range;
18213 return ExprError();
18214 }
18215 return ExprEmpty();
18216}
18217
18218namespace {
18219/// Data for the reduction-based clauses.
18220struct ReductionData {
18221 /// List of original reduction items.
18223 /// List of private copies of the reduction items.
18224 SmallVector<Expr *, 8> Privates;
18225 /// LHS expressions for the reduction_op expressions.
18227 /// RHS expressions for the reduction_op expressions.
18229 /// Reduction operation expression.
18230 SmallVector<Expr *, 8> ReductionOps;
18231 /// inscan copy operation expressions.
18232 SmallVector<Expr *, 8> InscanCopyOps;
18233 /// inscan copy temp array expressions for prefix sums.
18234 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18235 /// inscan copy temp array element expressions for prefix sums.
18236 SmallVector<Expr *, 8> InscanCopyArrayElems;
18237 /// Taskgroup descriptors for the corresponding reduction items in
18238 /// in_reduction clauses.
18239 SmallVector<Expr *, 8> TaskgroupDescriptors;
18240 /// List of captures for clause.
18241 SmallVector<Decl *, 4> ExprCaptures;
18242 /// List of postupdate expressions.
18243 SmallVector<Expr *, 4> ExprPostUpdates;
18244 /// Reduction modifier.
18245 unsigned RedModifier = 0;
18246 ReductionData() = delete;
18247 /// Reserves required memory for the reduction data.
18248 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18249 Vars.reserve(Size);
18250 Privates.reserve(Size);
18251 LHSs.reserve(Size);
18252 RHSs.reserve(Size);
18253 ReductionOps.reserve(Size);
18254 if (RedModifier == OMPC_REDUCTION_inscan) {
18255 InscanCopyOps.reserve(Size);
18256 InscanCopyArrayTemps.reserve(Size);
18257 InscanCopyArrayElems.reserve(Size);
18258 }
18259 TaskgroupDescriptors.reserve(Size);
18260 ExprCaptures.reserve(Size);
18261 ExprPostUpdates.reserve(Size);
18262 }
18263 /// Stores reduction item and reduction operation only (required for dependent
18264 /// reduction item).
18265 void push(Expr *Item, Expr *ReductionOp) {
18266 Vars.emplace_back(Item);
18267 Privates.emplace_back(nullptr);
18268 LHSs.emplace_back(nullptr);
18269 RHSs.emplace_back(nullptr);
18270 ReductionOps.emplace_back(ReductionOp);
18271 TaskgroupDescriptors.emplace_back(nullptr);
18272 if (RedModifier == OMPC_REDUCTION_inscan) {
18273 InscanCopyOps.push_back(nullptr);
18274 InscanCopyArrayTemps.push_back(nullptr);
18275 InscanCopyArrayElems.push_back(nullptr);
18276 }
18277 }
18278 /// Stores reduction data.
18279 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18280 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18281 Expr *CopyArrayElem) {
18282 Vars.emplace_back(Item);
18283 Privates.emplace_back(Private);
18284 LHSs.emplace_back(LHS);
18285 RHSs.emplace_back(RHS);
18286 ReductionOps.emplace_back(ReductionOp);
18287 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18288 if (RedModifier == OMPC_REDUCTION_inscan) {
18289 InscanCopyOps.push_back(CopyOp);
18290 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18291 InscanCopyArrayElems.push_back(CopyArrayElem);
18292 } else {
18293 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18294 CopyArrayElem == nullptr &&
18295 "Copy operation must be used for inscan reductions only.");
18296 }
18297 }
18298};
18299} // namespace
18300
18302 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18303 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18304 const Expr *Length = OASE->getLength();
18305 if (Length == nullptr) {
18306 // For array sections of the form [1:] or [:], we would need to analyze
18307 // the lower bound...
18308 if (OASE->getColonLocFirst().isValid())
18309 return false;
18310
18311 // This is an array subscript which has implicit length 1!
18312 SingleElement = true;
18313 ArraySizes.push_back(llvm::APSInt::get(1));
18314 } else {
18316 if (!Length->EvaluateAsInt(Result, Context))
18317 return false;
18318
18319 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18320 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18321 ArraySizes.push_back(ConstantLengthValue);
18322 }
18323
18324 // Get the base of this array section and walk up from there.
18325 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18326
18327 // We require length = 1 for all array sections except the right-most to
18328 // guarantee that the memory region is contiguous and has no holes in it.
18329 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18330 Length = TempOASE->getLength();
18331 if (Length == nullptr) {
18332 // For array sections of the form [1:] or [:], we would need to analyze
18333 // the lower bound...
18334 if (OASE->getColonLocFirst().isValid())
18335 return false;
18336
18337 // This is an array subscript which has implicit length 1!
18338 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18339 ArraySizes.push_back(ConstantOne);
18340 } else {
18342 if (!Length->EvaluateAsInt(Result, Context))
18343 return false;
18344
18345 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18346 if (ConstantLengthValue.getSExtValue() != 1)
18347 return false;
18348
18349 ArraySizes.push_back(ConstantLengthValue);
18350 }
18351 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18352 }
18353
18354 // If we have a single element, we don't need to add the implicit lengths.
18355 if (!SingleElement) {
18356 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18357 // Has implicit length 1!
18358 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18359 ArraySizes.push_back(ConstantOne);
18360 Base = TempASE->getBase()->IgnoreParenImpCasts();
18361 }
18362 }
18363
18364 // This array section can be privatized as a single value or as a constant
18365 // sized array.
18366 return true;
18367}
18368
18369static BinaryOperatorKind
18371 if (BOK == BO_Add)
18372 return BO_AddAssign;
18373 if (BOK == BO_Mul)
18374 return BO_MulAssign;
18375 if (BOK == BO_And)
18376 return BO_AndAssign;
18377 if (BOK == BO_Or)
18378 return BO_OrAssign;
18379 if (BOK == BO_Xor)
18380 return BO_XorAssign;
18381 return BOK;
18382}
18383
18385 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18386 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18387 SourceLocation ColonLoc, SourceLocation EndLoc,
18388 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18389 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18390 DeclarationName DN = ReductionId.getName();
18392 BinaryOperatorKind BOK = BO_Comma;
18393
18394 ASTContext &Context = S.Context;
18395 // OpenMP [2.14.3.6, reduction clause]
18396 // C
18397 // reduction-identifier is either an identifier or one of the following
18398 // operators: +, -, *, &, |, ^, && and ||
18399 // C++
18400 // reduction-identifier is either an id-expression or one of the following
18401 // operators: +, -, *, &, |, ^, && and ||
18402 switch (OOK) {
18403 case OO_Plus:
18404 BOK = BO_Add;
18405 break;
18406 case OO_Minus:
18407 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18408 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18409 // reduction identifier.
18410 if (S.LangOpts.OpenMP > 52)
18411 BOK = BO_Comma;
18412 else
18413 BOK = BO_Add;
18414 break;
18415 case OO_Star:
18416 BOK = BO_Mul;
18417 break;
18418 case OO_Amp:
18419 BOK = BO_And;
18420 break;
18421 case OO_Pipe:
18422 BOK = BO_Or;
18423 break;
18424 case OO_Caret:
18425 BOK = BO_Xor;
18426 break;
18427 case OO_AmpAmp:
18428 BOK = BO_LAnd;
18429 break;
18430 case OO_PipePipe:
18431 BOK = BO_LOr;
18432 break;
18433 case OO_New:
18434 case OO_Delete:
18435 case OO_Array_New:
18436 case OO_Array_Delete:
18437 case OO_Slash:
18438 case OO_Percent:
18439 case OO_Tilde:
18440 case OO_Exclaim:
18441 case OO_Equal:
18442 case OO_Less:
18443 case OO_Greater:
18444 case OO_LessEqual:
18445 case OO_GreaterEqual:
18446 case OO_PlusEqual:
18447 case OO_MinusEqual:
18448 case OO_StarEqual:
18449 case OO_SlashEqual:
18450 case OO_PercentEqual:
18451 case OO_CaretEqual:
18452 case OO_AmpEqual:
18453 case OO_PipeEqual:
18454 case OO_LessLess:
18455 case OO_GreaterGreater:
18456 case OO_LessLessEqual:
18457 case OO_GreaterGreaterEqual:
18458 case OO_EqualEqual:
18459 case OO_ExclaimEqual:
18460 case OO_Spaceship:
18461 case OO_PlusPlus:
18462 case OO_MinusMinus:
18463 case OO_Comma:
18464 case OO_ArrowStar:
18465 case OO_Arrow:
18466 case OO_Call:
18467 case OO_Subscript:
18468 case OO_Conditional:
18469 case OO_Coawait:
18471 llvm_unreachable("Unexpected reduction identifier");
18472 case OO_None:
18473 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18474 if (II->isStr("max"))
18475 BOK = BO_GT;
18476 else if (II->isStr("min"))
18477 BOK = BO_LT;
18478 }
18479 break;
18480 }
18481
18482 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18483 // A reduction clause with the minus (-) operator was deprecated
18484 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18485 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18486
18487 SourceRange ReductionIdRange;
18488 if (ReductionIdScopeSpec.isValid())
18489 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18490 else
18491 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18492 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18493
18494 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18495 bool FirstIter = true;
18496 for (Expr *RefExpr : VarList) {
18497 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18498 // OpenMP [2.1, C/C++]
18499 // A list item is a variable or array section, subject to the restrictions
18500 // specified in Section 2.4 on page 42 and in each of the sections
18501 // describing clauses and directives for which a list appears.
18502 // OpenMP [2.14.3.3, Restrictions, p.1]
18503 // A variable that is part of another variable (as an array or
18504 // structure element) cannot appear in a private clause.
18505 if (!FirstIter && IR != ER)
18506 ++IR;
18507 FirstIter = false;
18508 SourceLocation ELoc;
18509 SourceRange ERange;
18510 Expr *SimpleRefExpr = RefExpr;
18511 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18512 /*AllowArraySection=*/true);
18513 if (Res.second) {
18514 // Try to find 'declare reduction' corresponding construct before using
18515 // builtin/overloaded operators.
18516 QualType Type = Context.DependentTy;
18517 CXXCastPath BasePath;
18518 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18519 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18520 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18521 Expr *ReductionOp = nullptr;
18522 if (S.CurContext->isDependentContext() &&
18523 (DeclareReductionRef.isUnset() ||
18524 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18525 ReductionOp = DeclareReductionRef.get();
18526 // It will be analyzed later.
18527 RD.push(RefExpr, ReductionOp);
18528 }
18529 ValueDecl *D = Res.first;
18530 if (!D)
18531 continue;
18532
18533 Expr *TaskgroupDescriptor = nullptr;
18534 QualType Type;
18535 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18536 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18537 if (ASE) {
18538 Type = ASE->getType().getNonReferenceType();
18539 } else if (OASE) {
18540 QualType BaseType =
18542 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18543 Type = ATy->getElementType();
18544 else
18545 Type = BaseType->getPointeeType();
18546 Type = Type.getNonReferenceType();
18547 } else {
18548 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
18549 }
18550 auto *VD = dyn_cast<VarDecl>(D);
18551
18552 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18553 // A variable that appears in a private clause must not have an incomplete
18554 // type or a reference type.
18555 if (S.RequireCompleteType(ELoc, D->getType(),
18556 diag::err_omp_reduction_incomplete_type))
18557 continue;
18558 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18559 // A list item that appears in a reduction clause must not be
18560 // const-qualified.
18561 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18562 /*AcceptIfMutable=*/false, ASE || OASE))
18563 continue;
18564
18565 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18566 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18567 // If a list-item is a reference type then it must bind to the same object
18568 // for all threads of the team.
18569 if (!ASE && !OASE) {
18570 if (VD) {
18571 VarDecl *VDDef = VD->getDefinition();
18572 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18573 DSARefChecker Check(Stack);
18574 if (Check.Visit(VDDef->getInit())) {
18575 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18576 << getOpenMPClauseName(ClauseKind) << ERange;
18577 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18578 continue;
18579 }
18580 }
18581 }
18582
18583 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18584 // in a Construct]
18585 // Variables with the predetermined data-sharing attributes may not be
18586 // listed in data-sharing attributes clauses, except for the cases
18587 // listed below. For these exceptions only, listing a predetermined
18588 // variable in a data-sharing attribute clause is allowed and overrides
18589 // the variable's predetermined data-sharing attributes.
18590 // OpenMP [2.14.3.6, Restrictions, p.3]
18591 // Any number of reduction clauses can be specified on the directive,
18592 // but a list item can appear only once in the reduction clauses for that
18593 // directive.
18594 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18595 if (DVar.CKind == OMPC_reduction) {
18596 S.Diag(ELoc, diag::err_omp_once_referenced)
18597 << getOpenMPClauseName(ClauseKind);
18598 if (DVar.RefExpr)
18599 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18600 continue;
18601 }
18602 if (DVar.CKind != OMPC_unknown) {
18603 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18604 << getOpenMPClauseName(DVar.CKind)
18605 << getOpenMPClauseName(OMPC_reduction);
18606 reportOriginalDsa(S, Stack, D, DVar);
18607 continue;
18608 }
18609
18610 // OpenMP [2.14.3.6, Restrictions, p.1]
18611 // A list item that appears in a reduction clause of a worksharing
18612 // construct must be shared in the parallel regions to which any of the
18613 // worksharing regions arising from the worksharing construct bind.
18614 if (isOpenMPWorksharingDirective(CurrDir) &&
18615 !isOpenMPParallelDirective(CurrDir) &&
18616 !isOpenMPTeamsDirective(CurrDir)) {
18617 DVar = Stack->getImplicitDSA(D, true);
18618 if (DVar.CKind != OMPC_shared) {
18619 S.Diag(ELoc, diag::err_omp_required_access)
18620 << getOpenMPClauseName(OMPC_reduction)
18621 << getOpenMPClauseName(OMPC_shared);
18622 reportOriginalDsa(S, Stack, D, DVar);
18623 continue;
18624 }
18625 }
18626 } else {
18627 // Threadprivates cannot be shared between threads, so dignose if the base
18628 // is a threadprivate variable.
18629 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18630 if (DVar.CKind == OMPC_threadprivate) {
18631 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18632 << getOpenMPClauseName(DVar.CKind)
18633 << getOpenMPClauseName(OMPC_reduction);
18634 reportOriginalDsa(S, Stack, D, DVar);
18635 continue;
18636 }
18637 }
18638
18639 // Try to find 'declare reduction' corresponding construct before using
18640 // builtin/overloaded operators.
18641 CXXCastPath BasePath;
18642 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18643 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18644 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18645 if (DeclareReductionRef.isInvalid())
18646 continue;
18647 if (S.CurContext->isDependentContext() &&
18648 (DeclareReductionRef.isUnset() ||
18649 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
18650 RD.push(RefExpr, DeclareReductionRef.get());
18651 continue;
18652 }
18653 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
18654 // Not allowed reduction identifier is found.
18655 if (S.LangOpts.OpenMP > 52)
18656 S.Diag(ReductionId.getBeginLoc(),
18657 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18658 << Type << ReductionIdRange;
18659 else
18660 S.Diag(ReductionId.getBeginLoc(),
18661 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18662 << Type << ReductionIdRange;
18663 continue;
18664 }
18665
18666 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18667 // The type of a list item that appears in a reduction clause must be valid
18668 // for the reduction-identifier. For a max or min reduction in C, the type
18669 // of the list item must be an allowed arithmetic data type: char, int,
18670 // float, double, or _Bool, possibly modified with long, short, signed, or
18671 // unsigned. For a max or min reduction in C++, the type of the list item
18672 // must be an allowed arithmetic data type: char, wchar_t, int, float,
18673 // double, or bool, possibly modified with long, short, signed, or unsigned.
18674 if (DeclareReductionRef.isUnset()) {
18675 if ((BOK == BO_GT || BOK == BO_LT) &&
18676 !(Type->isScalarType() ||
18677 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
18678 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18679 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
18680 if (!ASE && !OASE) {
18681 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18683 S.Diag(D->getLocation(),
18684 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18685 << D;
18686 }
18687 continue;
18688 }
18689 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18690 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
18691 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18692 << getOpenMPClauseName(ClauseKind);
18693 if (!ASE && !OASE) {
18694 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18696 S.Diag(D->getLocation(),
18697 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18698 << D;
18699 }
18700 continue;
18701 }
18702 }
18703
18704 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
18705 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
18706 D->hasAttrs() ? &D->getAttrs() : nullptr);
18707 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
18708 D->hasAttrs() ? &D->getAttrs() : nullptr);
18709 QualType PrivateTy = Type;
18710
18711 // Try if we can determine constant lengths for all array sections and avoid
18712 // the VLA.
18713 bool ConstantLengthOASE = false;
18714 if (OASE) {
18715 bool SingleElement;
18717 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
18718 Context, OASE, SingleElement, ArraySizes);
18719
18720 // If we don't have a single element, we must emit a constant array type.
18721 if (ConstantLengthOASE && !SingleElement) {
18722 for (llvm::APSInt &Size : ArraySizes)
18723 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
18725 /*IndexTypeQuals=*/0);
18726 }
18727 }
18728
18729 if ((OASE && !ConstantLengthOASE) ||
18730 (!OASE && !ASE &&
18731 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18732 if (!Context.getTargetInfo().isVLASupported()) {
18733 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
18734 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18735 S.Diag(ELoc, diag::note_vla_unsupported);
18736 continue;
18737 } else {
18738 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18739 S.targetDiag(ELoc, diag::note_vla_unsupported);
18740 }
18741 }
18742 // For arrays/array sections only:
18743 // Create pseudo array type for private copy. The size for this array will
18744 // be generated during codegen.
18745 // For array subscripts or single variables Private Ty is the same as Type
18746 // (type of the variable or single array element).
18747 PrivateTy = Context.getVariableArrayType(
18748 Type,
18749 new (Context)
18750 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
18751 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
18752 } else if (!ASE && !OASE &&
18753 Context.getAsArrayType(D->getType().getNonReferenceType())) {
18754 PrivateTy = D->getType().getNonReferenceType();
18755 }
18756 // Private copy.
18757 VarDecl *PrivateVD =
18758 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18759 D->hasAttrs() ? &D->getAttrs() : nullptr,
18760 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18761 // Add initializer for private variable.
18762 Expr *Init = nullptr;
18763 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
18764 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
18765 if (DeclareReductionRef.isUsable()) {
18766 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
18767 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18768 if (DRD->getInitializer()) {
18769 Init = DRDRef;
18770 RHSVD->setInit(DRDRef);
18772 }
18773 } else {
18774 switch (BOK) {
18775 case BO_Add:
18776 case BO_Xor:
18777 case BO_Or:
18778 case BO_LOr:
18779 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
18781 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
18782 break;
18783 case BO_Mul:
18784 case BO_LAnd:
18785 if (Type->isScalarType() || Type->isAnyComplexType()) {
18786 // '*' and '&&' reduction ops - initializer is '1'.
18787 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
18788 }
18789 break;
18790 case BO_And: {
18791 // '&' reduction op - initializer is '~0'.
18792 QualType OrigType = Type;
18793 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
18794 Type = ComplexTy->getElementType();
18795 if (Type->isRealFloatingType()) {
18796 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18797 Context.getFloatTypeSemantics(Type));
18798 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18799 Type, ELoc);
18800 } else if (Type->isScalarType()) {
18801 uint64_t Size = Context.getTypeSize(Type);
18802 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
18803 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18804 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18805 }
18806 if (Init && OrigType->isAnyComplexType()) {
18807 // Init = 0xFFFF + 0xFFFFi;
18808 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
18809 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
18810 }
18811 Type = OrigType;
18812 break;
18813 }
18814 case BO_LT:
18815 case BO_GT: {
18816 // 'min' reduction op - initializer is 'Largest representable number in
18817 // the reduction list item type'.
18818 // 'max' reduction op - initializer is 'Least representable number in
18819 // the reduction list item type'.
18820 if (Type->isIntegerType() || Type->isPointerType()) {
18821 bool IsSigned = Type->hasSignedIntegerRepresentation();
18822 uint64_t Size = Context.getTypeSize(Type);
18823 QualType IntTy =
18824 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
18825 llvm::APInt InitValue =
18826 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18827 : llvm::APInt::getMinValue(Size)
18828 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18829 : llvm::APInt::getMaxValue(Size);
18830 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18831 if (Type->isPointerType()) {
18832 // Cast to pointer type.
18834 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
18835 if (CastExpr.isInvalid())
18836 continue;
18837 Init = CastExpr.get();
18838 }
18839 } else if (Type->isRealFloatingType()) {
18840 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18841 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
18842 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18843 Type, ELoc);
18844 }
18845 break;
18846 }
18847 case BO_PtrMemD:
18848 case BO_PtrMemI:
18849 case BO_MulAssign:
18850 case BO_Div:
18851 case BO_Rem:
18852 case BO_Sub:
18853 case BO_Shl:
18854 case BO_Shr:
18855 case BO_LE:
18856 case BO_GE:
18857 case BO_EQ:
18858 case BO_NE:
18859 case BO_Cmp:
18860 case BO_AndAssign:
18861 case BO_XorAssign:
18862 case BO_OrAssign:
18863 case BO_Assign:
18864 case BO_AddAssign:
18865 case BO_SubAssign:
18866 case BO_DivAssign:
18867 case BO_RemAssign:
18868 case BO_ShlAssign:
18869 case BO_ShrAssign:
18870 case BO_Comma:
18871 llvm_unreachable("Unexpected reduction operation");
18872 }
18873 }
18874 if (Init && DeclareReductionRef.isUnset()) {
18875 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
18876 // Store initializer for single element in private copy. Will be used
18877 // during codegen.
18878 PrivateVD->setInit(RHSVD->getInit());
18879 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18880 } else if (!Init) {
18881 S.ActOnUninitializedDecl(RHSVD);
18882 // Store initializer for single element in private copy. Will be used
18883 // during codegen.
18884 PrivateVD->setInit(RHSVD->getInit());
18885 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18886 }
18887 if (RHSVD->isInvalidDecl())
18888 continue;
18889 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
18890 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18891 << Type << ReductionIdRange;
18892 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18894 S.Diag(D->getLocation(),
18895 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18896 << D;
18897 continue;
18898 }
18899 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
18900 ExprResult ReductionOp;
18901 if (DeclareReductionRef.isUsable()) {
18902 QualType RedTy = DeclareReductionRef.get()->getType();
18903 QualType PtrRedTy = Context.getPointerType(RedTy);
18904 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
18905 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
18906 if (!BasePath.empty()) {
18907 LHS = S.DefaultLvalueConversion(LHS.get());
18908 RHS = S.DefaultLvalueConversion(RHS.get());
18910 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
18911 LHS.get()->getValueKind(), FPOptionsOverride());
18913 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
18914 RHS.get()->getValueKind(), FPOptionsOverride());
18915 }
18917 QualType Params[] = {PtrRedTy, PtrRedTy};
18918 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
18919 auto *OVE = new (Context) OpaqueValueExpr(
18920 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
18921 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
18922 Expr *Args[] = {LHS.get(), RHS.get()};
18923 ReductionOp =
18924 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
18926 } else {
18928 if (Type->isRecordType() && CombBOK != BOK) {
18930 ReductionOp =
18931 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18932 CombBOK, LHSDRE, RHSDRE);
18933 }
18934 if (!ReductionOp.isUsable()) {
18935 ReductionOp =
18936 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
18937 LHSDRE, RHSDRE);
18938 if (ReductionOp.isUsable()) {
18939 if (BOK != BO_LT && BOK != BO_GT) {
18940 ReductionOp =
18941 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18942 BO_Assign, LHSDRE, ReductionOp.get());
18943 } else {
18944 auto *ConditionalOp = new (Context)
18945 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
18946 RHSDRE, Type, VK_LValue, OK_Ordinary);
18947 ReductionOp =
18948 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18949 BO_Assign, LHSDRE, ConditionalOp);
18950 }
18951 }
18952 }
18953 if (ReductionOp.isUsable())
18954 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
18955 /*DiscardedValue=*/false);
18956 if (!ReductionOp.isUsable())
18957 continue;
18958 }
18959
18960 // Add copy operations for inscan reductions.
18961 // LHS = RHS;
18962 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18963 if (ClauseKind == OMPC_reduction &&
18964 RD.RedModifier == OMPC_REDUCTION_inscan) {
18965 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
18966 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18967 RHS.get());
18968 if (!CopyOpRes.isUsable())
18969 continue;
18970 CopyOpRes =
18971 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
18972 if (!CopyOpRes.isUsable())
18973 continue;
18974 // For simd directive and simd-based directives in simd mode no need to
18975 // construct temp array, need just a single temp element.
18976 if (Stack->getCurrentDirective() == OMPD_simd ||
18977 (S.getLangOpts().OpenMPSimd &&
18978 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
18979 VarDecl *TempArrayVD =
18980 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18981 D->hasAttrs() ? &D->getAttrs() : nullptr);
18982 // Add a constructor to the temp decl.
18983 S.ActOnUninitializedDecl(TempArrayVD);
18984 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
18985 } else {
18986 // Build temp array for prefix sum.
18987 auto *Dim = new (S.Context)
18990 PrivateTy, Dim, ArraySizeModifier::Normal,
18991 /*IndexTypeQuals=*/0, {ELoc, ELoc});
18992 VarDecl *TempArrayVD =
18993 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
18994 D->hasAttrs() ? &D->getAttrs() : nullptr);
18995 // Add a constructor to the temp decl.
18996 S.ActOnUninitializedDecl(TempArrayVD);
18997 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
18998 TempArrayElem =
18999 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19000 auto *Idx = new (S.Context)
19002 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19003 ELoc, Idx, ELoc);
19004 }
19005 }
19006
19007 // OpenMP [2.15.4.6, Restrictions, p.2]
19008 // A list item that appears in an in_reduction clause of a task construct
19009 // must appear in a task_reduction clause of a construct associated with a
19010 // taskgroup region that includes the participating task in its taskgroup
19011 // set. The construct associated with the innermost region that meets this
19012 // condition must specify the same reduction-identifier as the in_reduction
19013 // clause.
19014 if (ClauseKind == OMPC_in_reduction) {
19015 SourceRange ParentSR;
19016 BinaryOperatorKind ParentBOK;
19017 const Expr *ParentReductionOp = nullptr;
19018 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19019 DSAStackTy::DSAVarData ParentBOKDSA =
19020 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19021 ParentBOKTD);
19022 DSAStackTy::DSAVarData ParentReductionOpDSA =
19023 Stack->getTopMostTaskgroupReductionData(
19024 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19025 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19026 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19027 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19028 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19029 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19030 bool EmitError = true;
19031 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19032 llvm::FoldingSetNodeID RedId, ParentRedId;
19033 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19034 DeclareReductionRef.get()->Profile(RedId, Context,
19035 /*Canonical=*/true);
19036 EmitError = RedId != ParentRedId;
19037 }
19038 if (EmitError) {
19039 S.Diag(ReductionId.getBeginLoc(),
19040 diag::err_omp_reduction_identifier_mismatch)
19041 << ReductionIdRange << RefExpr->getSourceRange();
19042 S.Diag(ParentSR.getBegin(),
19043 diag::note_omp_previous_reduction_identifier)
19044 << ParentSR
19045 << (IsParentBOK ? ParentBOKDSA.RefExpr
19046 : ParentReductionOpDSA.RefExpr)
19047 ->getSourceRange();
19048 continue;
19049 }
19050 }
19051 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19052 }
19053
19054 DeclRefExpr *Ref = nullptr;
19055 Expr *VarsExpr = RefExpr->IgnoreParens();
19056 if (!VD && !S.CurContext->isDependentContext()) {
19057 if (ASE || OASE) {
19058 TransformExprToCaptures RebuildToCapture(S, D);
19059 VarsExpr =
19060 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19061 Ref = RebuildToCapture.getCapturedExpr();
19062 } else {
19063 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19064 }
19065 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
19066 RD.ExprCaptures.emplace_back(Ref->getDecl());
19067 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19068 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19069 if (!RefRes.isUsable())
19070 continue;
19071 ExprResult PostUpdateRes =
19072 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19073 RefRes.get());
19074 if (!PostUpdateRes.isUsable())
19075 continue;
19076 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19077 Stack->getCurrentDirective() == OMPD_taskgroup) {
19078 S.Diag(RefExpr->getExprLoc(),
19079 diag::err_omp_reduction_non_addressable_expression)
19080 << RefExpr->getSourceRange();
19081 continue;
19082 }
19083 RD.ExprPostUpdates.emplace_back(
19084 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19085 }
19086 }
19087 }
19088 // All reduction items are still marked as reduction (to do not increase
19089 // code base size).
19090 unsigned Modifier = RD.RedModifier;
19091 // Consider task_reductions as reductions with task modifier. Required for
19092 // correct analysis of in_reduction clauses.
19093 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19094 Modifier = OMPC_REDUCTION_task;
19095 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19096 ASE || OASE);
19097 if (Modifier == OMPC_REDUCTION_task &&
19098 (CurrDir == OMPD_taskgroup ||
19099 ((isOpenMPParallelDirective(CurrDir) ||
19100 isOpenMPWorksharingDirective(CurrDir)) &&
19101 !isOpenMPSimdDirective(CurrDir)))) {
19102 if (DeclareReductionRef.isUsable())
19103 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19104 DeclareReductionRef.get());
19105 else
19106 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19107 }
19108 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19109 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19110 TempArrayElem.get());
19111 }
19112 return RD.Vars.empty();
19113}
19114
19117 SourceLocation StartLoc, SourceLocation LParenLoc,
19118 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19119 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19120 ArrayRef<Expr *> UnresolvedReductions) {
19121 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19122 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19123 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19124 /*Last=*/OMPC_REDUCTION_unknown)
19125 << getOpenMPClauseName(OMPC_reduction);
19126 return nullptr;
19127 }
19128 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19129 // A reduction clause with the inscan reduction-modifier may only appear on a
19130 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19131 // construct, a parallel worksharing-loop construct or a parallel
19132 // worksharing-loop SIMD construct.
19133 if (Modifier == OMPC_REDUCTION_inscan &&
19134 (DSAStack->getCurrentDirective() != OMPD_for &&
19135 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19136 DSAStack->getCurrentDirective() != OMPD_simd &&
19137 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19138 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19139 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19140 return nullptr;
19141 }
19142
19143 ReductionData RD(VarList.size(), Modifier);
19144 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
19145 StartLoc, LParenLoc, ColonLoc, EndLoc,
19146 ReductionIdScopeSpec, ReductionId,
19147 UnresolvedReductions, RD))
19148 return nullptr;
19149
19151 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19152 Modifier, RD.Vars,
19153 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19154 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19155 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19156 buildPreInits(getASTContext(), RD.ExprCaptures),
19157 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19158}
19159
19161 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19162 SourceLocation ColonLoc, SourceLocation EndLoc,
19163 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19164 ArrayRef<Expr *> UnresolvedReductions) {
19165 ReductionData RD(VarList.size());
19166 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
19167 VarList, StartLoc, LParenLoc, ColonLoc,
19168 EndLoc, ReductionIdScopeSpec, ReductionId,
19169 UnresolvedReductions, RD))
19170 return nullptr;
19171
19173 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19174 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19175 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19176 buildPreInits(getASTContext(), RD.ExprCaptures),
19177 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19178}
19179
19181 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19182 SourceLocation ColonLoc, SourceLocation EndLoc,
19183 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19184 ArrayRef<Expr *> UnresolvedReductions) {
19185 ReductionData RD(VarList.size());
19186 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19187 StartLoc, LParenLoc, ColonLoc, EndLoc,
19188 ReductionIdScopeSpec, ReductionId,
19189 UnresolvedReductions, RD))
19190 return nullptr;
19191
19193 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19194 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19195 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19196 buildPreInits(getASTContext(), RD.ExprCaptures),
19197 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19198}
19199
19201 SourceLocation LinLoc) {
19202 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19203 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19204 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19205 << getLangOpts().CPlusPlus;
19206 return true;
19207 }
19208 return false;
19209}
19210
19212 OpenMPLinearClauseKind LinKind,
19213 QualType Type, bool IsDeclareSimd) {
19214 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19215 // A variable must not have an incomplete type or a reference type.
19217 diag::err_omp_linear_incomplete_type))
19218 return true;
19219 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19220 !Type->isReferenceType()) {
19221 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19222 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19223 return true;
19224 }
19225 Type = Type.getNonReferenceType();
19226
19227 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19228 // A variable that is privatized must not have a const-qualified type
19229 // unless it is of class type with a mutable member. This restriction does
19230 // not apply to the firstprivate clause, nor to the linear clause on
19231 // declarative directives (like declare simd).
19232 if (!IsDeclareSimd &&
19233 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19234 return true;
19235
19236 // A list item must be of integral or pointer type.
19237 Type = Type.getUnqualifiedType().getCanonicalType();
19238 const auto *Ty = Type.getTypePtrOrNull();
19239 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19240 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
19241 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19242 if (D) {
19243 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19245 Diag(D->getLocation(),
19246 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19247 << D;
19248 }
19249 return true;
19250 }
19251 return false;
19252}
19253
19255 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19256 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19257 SourceLocation LinLoc, SourceLocation ColonLoc,
19258 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19260 SmallVector<Expr *, 8> Privates;
19262 SmallVector<Decl *, 4> ExprCaptures;
19263 SmallVector<Expr *, 4> ExprPostUpdates;
19264 // OpenMP 5.2 [Section 5.4.6, linear clause]
19265 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19266 // 'ref'
19267 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19268 getLangOpts().OpenMP >= 52)
19269 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19270 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19271 LinKind = OMPC_LINEAR_val;
19272 for (Expr *RefExpr : VarList) {
19273 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19274 SourceLocation ELoc;
19275 SourceRange ERange;
19276 Expr *SimpleRefExpr = RefExpr;
19277 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19278 if (Res.second) {
19279 // It will be analyzed later.
19280 Vars.push_back(RefExpr);
19281 Privates.push_back(nullptr);
19282 Inits.push_back(nullptr);
19283 }
19284 ValueDecl *D = Res.first;
19285 if (!D)
19286 continue;
19287
19288 QualType Type = D->getType();
19289 auto *VD = dyn_cast<VarDecl>(D);
19290
19291 // OpenMP [2.14.3.7, linear clause]
19292 // A list-item cannot appear in more than one linear clause.
19293 // A list-item that appears in a linear clause cannot appear in any
19294 // other data-sharing attribute clause.
19295 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19296 if (DVar.RefExpr) {
19297 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19298 << getOpenMPClauseName(OMPC_linear);
19300 continue;
19301 }
19302
19303 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19304 continue;
19305 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19306
19307 // Build private copy of original var.
19308 VarDecl *Private =
19309 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19310 D->hasAttrs() ? &D->getAttrs() : nullptr,
19311 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19312 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19313 // Build var to save initial value.
19314 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19315 Expr *InitExpr;
19316 DeclRefExpr *Ref = nullptr;
19317 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19318 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19319 if (!isOpenMPCapturedDecl(D)) {
19320 ExprCaptures.push_back(Ref->getDecl());
19321 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19323 if (!RefRes.isUsable())
19324 continue;
19325 ExprResult PostUpdateRes =
19326 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19327 SimpleRefExpr, RefRes.get());
19328 if (!PostUpdateRes.isUsable())
19329 continue;
19330 ExprPostUpdates.push_back(
19331 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19332 }
19333 }
19334 }
19335 if (LinKind == OMPC_LINEAR_uval)
19336 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19337 else
19338 InitExpr = VD ? SimpleRefExpr : Ref;
19341 /*DirectInit=*/false);
19342 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19343
19344 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19345 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19346 ? RefExpr->IgnoreParens()
19347 : Ref);
19348 Privates.push_back(PrivateRef);
19349 Inits.push_back(InitRef);
19350 }
19351
19352 if (Vars.empty())
19353 return nullptr;
19354
19355 Expr *StepExpr = Step;
19356 Expr *CalcStepExpr = nullptr;
19357 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19358 !Step->isInstantiationDependent() &&
19360 SourceLocation StepLoc = Step->getBeginLoc();
19362 if (Val.isInvalid())
19363 return nullptr;
19364 StepExpr = Val.get();
19365
19366 // Build var to save the step value.
19367 VarDecl *SaveVar =
19368 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19369 ExprResult SaveRef =
19370 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19371 ExprResult CalcStep = SemaRef.BuildBinOp(
19372 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19373 CalcStep =
19374 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
19375
19376 // Warn about zero linear step (it would be probably better specified as
19377 // making corresponding variables 'const').
19378 if (std::optional<llvm::APSInt> Result =
19380 if (!Result->isNegative() && !Result->isStrictlyPositive())
19381 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19382 << Vars[0] << (Vars.size() > 1);
19383 } else if (CalcStep.isUsable()) {
19384 // Calculate the step beforehand instead of doing this on each iteration.
19385 // (This is not used if the number of iterations may be kfold-ed).
19386 CalcStepExpr = CalcStep.get();
19387 }
19388 }
19389
19390 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19391 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19392 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19393 buildPreInits(getASTContext(), ExprCaptures),
19394 buildPostUpdate(SemaRef, ExprPostUpdates));
19395}
19396
19398 Expr *NumIterations, Sema &SemaRef,
19399 Scope *S, DSAStackTy *Stack) {
19400 // Walk the vars and build update/final expressions for the CodeGen.
19401 SmallVector<Expr *, 8> Updates;
19403 SmallVector<Expr *, 8> UsedExprs;
19404 Expr *Step = Clause.getStep();
19405 Expr *CalcStep = Clause.getCalcStep();
19406 // OpenMP [2.14.3.7, linear clause]
19407 // If linear-step is not specified it is assumed to be 1.
19408 if (!Step)
19409 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19410 else if (CalcStep)
19411 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19412 bool HasErrors = false;
19413 auto CurInit = Clause.inits().begin();
19414 auto CurPrivate = Clause.privates().begin();
19415 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19416 for (Expr *RefExpr : Clause.varlist()) {
19417 SourceLocation ELoc;
19418 SourceRange ERange;
19419 Expr *SimpleRefExpr = RefExpr;
19420 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19421 ValueDecl *D = Res.first;
19422 if (Res.second || !D) {
19423 Updates.push_back(nullptr);
19424 Finals.push_back(nullptr);
19425 HasErrors = true;
19426 continue;
19427 }
19428 auto &&Info = Stack->isLoopControlVariable(D);
19429 // OpenMP [2.15.11, distribute simd Construct]
19430 // A list item may not appear in a linear clause, unless it is the loop
19431 // iteration variable.
19432 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19433 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19434 SemaRef.Diag(ELoc,
19435 diag::err_omp_linear_distribute_var_non_loop_iteration);
19436 Updates.push_back(nullptr);
19437 Finals.push_back(nullptr);
19438 HasErrors = true;
19439 continue;
19440 }
19441 Expr *InitExpr = *CurInit;
19442
19443 // Build privatized reference to the current linear var.
19444 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19445 Expr *CapturedRef;
19446 if (LinKind == OMPC_LINEAR_uval)
19447 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19448 else
19449 CapturedRef =
19450 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19451 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19452 /*RefersToCapture=*/true);
19453
19454 // Build update: Var = InitExpr + IV * Step
19456 if (!Info.first)
19458 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19459 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19460 else
19461 Update = *CurPrivate;
19462 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19463 /*DiscardedValue=*/false);
19464
19465 // Build final: Var = PrivCopy;
19466 ExprResult Final;
19467 if (!Info.first)
19468 Final = SemaRef.BuildBinOp(
19469 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19470 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19471 else
19472 Final = *CurPrivate;
19473 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19474 /*DiscardedValue=*/false);
19475
19476 if (!Update.isUsable() || !Final.isUsable()) {
19477 Updates.push_back(nullptr);
19478 Finals.push_back(nullptr);
19479 UsedExprs.push_back(nullptr);
19480 HasErrors = true;
19481 } else {
19482 Updates.push_back(Update.get());
19483 Finals.push_back(Final.get());
19484 if (!Info.first)
19485 UsedExprs.push_back(SimpleRefExpr);
19486 }
19487 ++CurInit;
19488 ++CurPrivate;
19489 }
19490 if (Expr *S = Clause.getStep())
19491 UsedExprs.push_back(S);
19492 // Fill the remaining part with the nullptr.
19493 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19494 Clause.setUpdates(Updates);
19495 Clause.setFinals(Finals);
19496 Clause.setUsedExprs(UsedExprs);
19497 return HasErrors;
19498}
19499
19501 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19502 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19504 for (Expr *RefExpr : VarList) {
19505 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19506 SourceLocation ELoc;
19507 SourceRange ERange;
19508 Expr *SimpleRefExpr = RefExpr;
19509 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19510 if (Res.second) {
19511 // It will be analyzed later.
19512 Vars.push_back(RefExpr);
19513 }
19514 ValueDecl *D = Res.first;
19515 if (!D)
19516 continue;
19517
19518 QualType QType = D->getType();
19519 auto *VD = dyn_cast<VarDecl>(D);
19520
19521 // OpenMP [2.8.1, simd construct, Restrictions]
19522 // The type of list items appearing in the aligned clause must be
19523 // array, pointer, reference to array, or reference to pointer.
19525 const Type *Ty = QType.getTypePtrOrNull();
19526 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19527 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19528 << QType << getLangOpts().CPlusPlus << ERange;
19529 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19531 Diag(D->getLocation(),
19532 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19533 << D;
19534 continue;
19535 }
19536
19537 // OpenMP [2.8.1, simd construct, Restrictions]
19538 // A list-item cannot appear in more than one aligned clause.
19539 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19540 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19541 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19542 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19543 << getOpenMPClauseName(OMPC_aligned);
19544 continue;
19545 }
19546
19547 DeclRefExpr *Ref = nullptr;
19548 if (!VD && isOpenMPCapturedDecl(D))
19549 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19550 Vars.push_back(SemaRef
19551 .DefaultFunctionArrayConversion(
19552 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19553 .get());
19554 }
19555
19556 // OpenMP [2.8.1, simd construct, Description]
19557 // The parameter of the aligned clause, alignment, must be a constant
19558 // positive integer expression.
19559 // If no optional parameter is specified, implementation-defined default
19560 // alignments for SIMD instructions on the target platforms are assumed.
19561 if (Alignment != nullptr) {
19562 ExprResult AlignResult =
19563 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19564 if (AlignResult.isInvalid())
19565 return nullptr;
19566 Alignment = AlignResult.get();
19567 }
19568 if (Vars.empty())
19569 return nullptr;
19570
19571 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
19572 ColonLoc, EndLoc, Vars, Alignment);
19573}
19574
19576 SourceLocation StartLoc,
19577 SourceLocation LParenLoc,
19578 SourceLocation EndLoc) {
19580 SmallVector<Expr *, 8> SrcExprs;
19581 SmallVector<Expr *, 8> DstExprs;
19582 SmallVector<Expr *, 8> AssignmentOps;
19583 for (Expr *RefExpr : VarList) {
19584 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19585 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19586 // It will be analyzed later.
19587 Vars.push_back(RefExpr);
19588 SrcExprs.push_back(nullptr);
19589 DstExprs.push_back(nullptr);
19590 AssignmentOps.push_back(nullptr);
19591 continue;
19592 }
19593
19594 SourceLocation ELoc = RefExpr->getExprLoc();
19595 // OpenMP [2.1, C/C++]
19596 // A list item is a variable name.
19597 // OpenMP [2.14.4.1, Restrictions, p.1]
19598 // A list item that appears in a copyin clause must be threadprivate.
19599 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19600 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19601 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19602 << 0 << RefExpr->getSourceRange();
19603 continue;
19604 }
19605
19606 Decl *D = DE->getDecl();
19607 auto *VD = cast<VarDecl>(D);
19608
19609 QualType Type = VD->getType();
19611 // It will be analyzed later.
19612 Vars.push_back(DE);
19613 SrcExprs.push_back(nullptr);
19614 DstExprs.push_back(nullptr);
19615 AssignmentOps.push_back(nullptr);
19616 continue;
19617 }
19618
19619 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19620 // A list item that appears in a copyin clause must be threadprivate.
19621 if (!DSAStack->isThreadPrivate(VD)) {
19622 Diag(ELoc, diag::err_omp_required_access)
19623 << getOpenMPClauseName(OMPC_copyin)
19624 << getOpenMPDirectiveName(OMPD_threadprivate);
19625 continue;
19626 }
19627
19628 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19629 // A variable of class type (or array thereof) that appears in a
19630 // copyin clause requires an accessible, unambiguous copy assignment
19631 // operator for the class type.
19632 QualType ElemType =
19634 VarDecl *SrcVD =
19635 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
19636 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19637 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
19638 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
19639 VarDecl *DstVD =
19640 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
19641 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19642 DeclRefExpr *PseudoDstExpr =
19643 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
19644 // For arrays generate assignment operation for single element and replace
19645 // it by the original array element in CodeGen.
19646 ExprResult AssignmentOp =
19647 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
19648 PseudoDstExpr, PseudoSrcExpr);
19649 if (AssignmentOp.isInvalid())
19650 continue;
19651 AssignmentOp =
19652 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
19653 /*DiscardedValue=*/false);
19654 if (AssignmentOp.isInvalid())
19655 continue;
19656
19657 DSAStack->addDSA(VD, DE, OMPC_copyin);
19658 Vars.push_back(DE);
19659 SrcExprs.push_back(PseudoSrcExpr);
19660 DstExprs.push_back(PseudoDstExpr);
19661 AssignmentOps.push_back(AssignmentOp.get());
19662 }
19663
19664 if (Vars.empty())
19665 return nullptr;
19666
19667 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19668 Vars, SrcExprs, DstExprs, AssignmentOps);
19669}
19670
19672 SourceLocation StartLoc,
19673 SourceLocation LParenLoc,
19674 SourceLocation EndLoc) {
19676 SmallVector<Expr *, 8> SrcExprs;
19677 SmallVector<Expr *, 8> DstExprs;
19678 SmallVector<Expr *, 8> AssignmentOps;
19679 for (Expr *RefExpr : VarList) {
19680 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19681 SourceLocation ELoc;
19682 SourceRange ERange;
19683 Expr *SimpleRefExpr = RefExpr;
19684 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19685 if (Res.second) {
19686 // It will be analyzed later.
19687 Vars.push_back(RefExpr);
19688 SrcExprs.push_back(nullptr);
19689 DstExprs.push_back(nullptr);
19690 AssignmentOps.push_back(nullptr);
19691 }
19692 ValueDecl *D = Res.first;
19693 if (!D)
19694 continue;
19695
19696 QualType Type = D->getType();
19697 auto *VD = dyn_cast<VarDecl>(D);
19698
19699 // OpenMP [2.14.4.2, Restrictions, p.2]
19700 // A list item that appears in a copyprivate clause may not appear in a
19701 // private or firstprivate clause on the single construct.
19702 if (!VD || !DSAStack->isThreadPrivate(VD)) {
19703 DSAStackTy::DSAVarData DVar =
19704 DSAStack->getTopDSA(D, /*FromParent=*/false);
19705 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19706 DVar.RefExpr) {
19707 Diag(ELoc, diag::err_omp_wrong_dsa)
19708 << getOpenMPClauseName(DVar.CKind)
19709 << getOpenMPClauseName(OMPC_copyprivate);
19711 continue;
19712 }
19713
19714 // OpenMP [2.11.4.2, Restrictions, p.1]
19715 // All list items that appear in a copyprivate clause must be either
19716 // threadprivate or private in the enclosing context.
19717 if (DVar.CKind == OMPC_unknown) {
19718 DVar = DSAStack->getImplicitDSA(D, false);
19719 if (DVar.CKind == OMPC_shared) {
19720 Diag(ELoc, diag::err_omp_required_access)
19721 << getOpenMPClauseName(OMPC_copyprivate)
19722 << "threadprivate or private in the enclosing context";
19724 continue;
19725 }
19726 }
19727 }
19728
19729 // Variably modified types are not supported.
19731 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19732 << getOpenMPClauseName(OMPC_copyprivate) << Type
19733 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
19734 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19736 Diag(D->getLocation(),
19737 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19738 << D;
19739 continue;
19740 }
19741
19742 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19743 // A variable of class type (or array thereof) that appears in a
19744 // copyin clause requires an accessible, unambiguous copy assignment
19745 // operator for the class type.
19747 .getBaseElementType(Type.getNonReferenceType())
19749 VarDecl *SrcVD =
19750 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
19751 D->hasAttrs() ? &D->getAttrs() : nullptr);
19752 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
19753 VarDecl *DstVD =
19754 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
19755 D->hasAttrs() ? &D->getAttrs() : nullptr);
19756 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19757 ExprResult AssignmentOp = SemaRef.BuildBinOp(
19758 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19759 if (AssignmentOp.isInvalid())
19760 continue;
19761 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19762 /*DiscardedValue=*/false);
19763 if (AssignmentOp.isInvalid())
19764 continue;
19765
19766 // No need to mark vars as copyprivate, they are already threadprivate or
19767 // implicitly private.
19768 assert(VD || isOpenMPCapturedDecl(D));
19769 Vars.push_back(
19770 VD ? RefExpr->IgnoreParens()
19771 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
19772 SrcExprs.push_back(PseudoSrcExpr);
19773 DstExprs.push_back(PseudoDstExpr);
19774 AssignmentOps.push_back(AssignmentOp.get());
19775 }
19776
19777 if (Vars.empty())
19778 return nullptr;
19779
19780 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
19781 EndLoc, Vars, SrcExprs, DstExprs,
19782 AssignmentOps);
19783}
19784
19786 SourceLocation StartLoc,
19787 SourceLocation LParenLoc,
19788 SourceLocation EndLoc) {
19789 if (VarList.empty())
19790 return nullptr;
19791
19792 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19793 VarList);
19794}
19795
19796/// Tries to find omp_depend_t. type.
19797static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
19798 bool Diagnose = true) {
19799 QualType OMPDependT = Stack->getOMPDependT();
19800 if (!OMPDependT.isNull())
19801 return true;
19802 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
19803 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
19804 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
19805 if (Diagnose)
19806 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
19807 return false;
19808 }
19809 Stack->setOMPDependT(PT.get());
19810 return true;
19811}
19812
19814 SourceLocation StartLoc,
19815 SourceLocation LParenLoc,
19816 SourceLocation EndLoc) {
19817 if (!Depobj)
19818 return nullptr;
19819
19820 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
19821
19822 // OpenMP 5.0, 2.17.10.1 depobj Construct
19823 // depobj is an lvalue expression of type omp_depend_t.
19824 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
19825 !Depobj->isInstantiationDependent() &&
19827 (OMPDependTFound && !getASTContext().typesAreCompatible(
19828 DSAStack->getOMPDependT(), Depobj->getType(),
19829 /*CompareUnqualified=*/true))) {
19830 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19831 << 0 << Depobj->getType() << Depobj->getSourceRange();
19832 }
19833
19834 if (!Depobj->isLValue()) {
19835 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19836 << 1 << Depobj->getSourceRange();
19837 }
19838
19839 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19840 Depobj);
19841}
19842
19843namespace {
19844// Utility struct that gathers the related info for doacross clause.
19845struct DoacrossDataInfoTy {
19846 // The list of expressions.
19848 // The OperatorOffset for doacross loop.
19850 // The depended loop count.
19851 llvm::APSInt TotalDepCount;
19852};
19853} // namespace
19854static DoacrossDataInfoTy
19856 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
19857 SourceLocation EndLoc) {
19858
19861 llvm::APSInt DepCounter(/*BitWidth=*/32);
19862 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19863
19864 if (const Expr *OrderedCountExpr =
19865 Stack->getParentOrderedRegionParam().first) {
19866 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
19867 TotalDepCount.setIsUnsigned(/*Val=*/true);
19868 }
19869
19870 for (Expr *RefExpr : VarList) {
19871 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
19872 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19873 // It will be analyzed later.
19874 Vars.push_back(RefExpr);
19875 continue;
19876 }
19877
19878 SourceLocation ELoc = RefExpr->getExprLoc();
19879 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19880 if (!IsSource) {
19881 if (Stack->getParentOrderedRegionParam().first &&
19882 DepCounter >= TotalDepCount) {
19883 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19884 continue;
19885 }
19886 ++DepCounter;
19887 // OpenMP [2.13.9, Summary]
19888 // depend(dependence-type : vec), where dependence-type is:
19889 // 'sink' and where vec is the iteration vector, which has the form:
19890 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
19891 // where n is the value specified by the ordered clause in the loop
19892 // directive, xi denotes the loop iteration variable of the i-th nested
19893 // loop associated with the loop directive, and di is a constant
19894 // non-negative integer.
19895 if (SemaRef.CurContext->isDependentContext()) {
19896 // It will be analyzed later.
19897 Vars.push_back(RefExpr);
19898 continue;
19899 }
19900 SimpleExpr = SimpleExpr->IgnoreImplicit();
19902 SourceLocation OOLoc;
19903 Expr *LHS = SimpleExpr;
19904 Expr *RHS = nullptr;
19905 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19906 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
19907 OOLoc = BO->getOperatorLoc();
19908 LHS = BO->getLHS()->IgnoreParenImpCasts();
19909 RHS = BO->getRHS()->IgnoreParenImpCasts();
19910 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19911 OOK = OCE->getOperator();
19912 OOLoc = OCE->getOperatorLoc();
19913 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19914 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
19915 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19916 OOK = MCE->getMethodDecl()
19917 ->getNameInfo()
19918 .getName()
19919 .getCXXOverloadedOperator();
19920 OOLoc = MCE->getCallee()->getExprLoc();
19921 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
19922 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19923 }
19924 SourceLocation ELoc;
19925 SourceRange ERange;
19926 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
19927 if (Res.second) {
19928 // It will be analyzed later.
19929 Vars.push_back(RefExpr);
19930 }
19931 ValueDecl *D = Res.first;
19932 if (!D)
19933 continue;
19934
19935 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
19936 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19937 continue;
19938 }
19939 if (RHS) {
19940 ExprResult RHSRes =
19942 RHS, OMPC_depend, /*StrictlyPositive=*/false);
19943 if (RHSRes.isInvalid())
19944 continue;
19945 }
19946 if (!SemaRef.CurContext->isDependentContext() &&
19947 Stack->getParentOrderedRegionParam().first &&
19948 DepCounter != Stack->isParentLoopControlVariable(D).first) {
19949 const ValueDecl *VD =
19950 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19951 if (VD)
19952 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19953 << 1 << VD;
19954 else
19955 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19956 << 0;
19957 continue;
19958 }
19959 OpsOffs.emplace_back(RHS, OOK);
19960 }
19961 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19962 }
19963 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
19964 TotalDepCount > VarList.size() &&
19965 Stack->getParentOrderedRegionParam().first &&
19966 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19967 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19968 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19969 }
19970 return {Vars, OpsOffs, TotalDepCount};
19971}
19972
19974 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
19975 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19976 SourceLocation EndLoc) {
19977 OpenMPDependClauseKind DepKind = Data.DepKind;
19978 SourceLocation DepLoc = Data.DepLoc;
19979 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
19980 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19981 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19982 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19983 return nullptr;
19984 }
19985 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
19986 DepKind == OMPC_DEPEND_mutexinoutset) {
19987 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19988 return nullptr;
19989 }
19990 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
19991 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19992 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
19993 DepKind == OMPC_DEPEND_sink ||
19994 ((getLangOpts().OpenMP < 50 ||
19995 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19996 DepKind == OMPC_DEPEND_depobj))) {
19997 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
19998 OMPC_DEPEND_outallmemory,
19999 OMPC_DEPEND_inoutallmemory};
20000 if (getLangOpts().OpenMP < 50 ||
20001 DSAStack->getCurrentDirective() == OMPD_depobj)
20002 Except.push_back(OMPC_DEPEND_depobj);
20003 if (getLangOpts().OpenMP < 51)
20004 Except.push_back(OMPC_DEPEND_inoutset);
20005 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
20006 ? "depend modifier(iterator) or "
20007 : "";
20008 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20009 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20010 /*Last=*/OMPC_DEPEND_unknown,
20011 Except)
20012 << getOpenMPClauseName(OMPC_depend);
20013 return nullptr;
20014 }
20015 if (DepModifier &&
20016 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20017 Diag(DepModifier->getExprLoc(),
20018 diag::err_omp_depend_sink_source_with_modifier);
20019 return nullptr;
20020 }
20021 if (DepModifier &&
20022 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20023 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20024
20027 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20028
20029 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20030 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20031 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20032 Vars = VarOffset.Vars;
20033 OpsOffs = VarOffset.OpsOffs;
20034 TotalDepCount = VarOffset.TotalDepCount;
20035 } else {
20036 for (Expr *RefExpr : VarList) {
20037 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20038 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20039 // It will be analyzed later.
20040 Vars.push_back(RefExpr);
20041 continue;
20042 }
20043
20044 SourceLocation ELoc = RefExpr->getExprLoc();
20045 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20046 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20047 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
20048 if (OMPDependTFound)
20049 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
20050 DepKind == OMPC_DEPEND_depobj);
20051 if (DepKind == OMPC_DEPEND_depobj) {
20052 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20053 // List items used in depend clauses with the depobj dependence type
20054 // must be expressions of the omp_depend_t type.
20055 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20056 !RefExpr->isInstantiationDependent() &&
20057 !RefExpr->containsUnexpandedParameterPack() &&
20058 (OMPDependTFound &&
20059 !getASTContext().hasSameUnqualifiedType(
20060 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20061 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20062 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20063 continue;
20064 }
20065 if (!RefExpr->isLValue()) {
20066 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20067 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20068 continue;
20069 }
20070 } else {
20071 // OpenMP 5.0 [2.17.11, Restrictions]
20072 // List items used in depend clauses cannot be zero-length array
20073 // sections.
20074 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20075 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
20076 if (OASE) {
20077 QualType BaseType =
20079 if (BaseType.isNull())
20080 return nullptr;
20081 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20082 ExprTy = ATy->getElementType();
20083 else
20084 ExprTy = BaseType->getPointeeType();
20085 if (BaseType.isNull() || ExprTy.isNull())
20086 return nullptr;
20087 ExprTy = ExprTy.getNonReferenceType();
20088 const Expr *Length = OASE->getLength();
20090 if (Length && !Length->isValueDependent() &&
20091 Length->EvaluateAsInt(Result, getASTContext()) &&
20092 Result.Val.getInt().isZero()) {
20093 Diag(ELoc,
20094 diag::err_omp_depend_zero_length_array_section_not_allowed)
20095 << SimpleExpr->getSourceRange();
20096 continue;
20097 }
20098 }
20099
20100 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20101 // List items used in depend clauses with the in, out, inout,
20102 // inoutset, or mutexinoutset dependence types cannot be
20103 // expressions of the omp_depend_t type.
20104 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20105 !RefExpr->isInstantiationDependent() &&
20106 !RefExpr->containsUnexpandedParameterPack() &&
20107 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20108 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20109 ExprTy.getTypePtr()))) {
20110 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20111 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20112 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20113 << RefExpr->getSourceRange();
20114 continue;
20115 }
20116
20117 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20118 if (ASE && !ASE->getBase()->isTypeDependent() &&
20119 !ASE->getBase()
20120 ->getType()
20121 .getNonReferenceType()
20122 ->isPointerType() &&
20123 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20124 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20125 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20126 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20127 << RefExpr->getSourceRange();
20128 continue;
20129 }
20130
20131 ExprResult Res;
20132 {
20134 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20135 RefExpr->IgnoreParenImpCasts());
20136 }
20137 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20138 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20139 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20140 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20141 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20142 << RefExpr->getSourceRange();
20143 continue;
20144 }
20145 }
20146 }
20147 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20148 }
20149 }
20150
20151 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20152 DepKind != OMPC_DEPEND_outallmemory &&
20153 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20154 return nullptr;
20155
20156 auto *C = OMPDependClause::Create(
20157 getASTContext(), StartLoc, LParenLoc, EndLoc,
20158 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20159 TotalDepCount.getZExtValue());
20160 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20161 DSAStack->isParentOrderedRegion())
20162 DSAStack->addDoacrossDependClause(C, OpsOffs);
20163 return C;
20164}
20165
20168 SourceLocation LParenLoc, SourceLocation ModifierLoc,
20169 SourceLocation EndLoc) {
20170 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20171 "Unexpected device modifier in OpenMP < 50.");
20172
20173 bool ErrorFound = false;
20174 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20175 std::string Values =
20176 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20177 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20178 << Values << getOpenMPClauseName(OMPC_device);
20179 ErrorFound = true;
20180 }
20181
20182 Expr *ValExpr = Device;
20183 Stmt *HelperValStmt = nullptr;
20184
20185 // OpenMP [2.9.1, Restrictions]
20186 // The device expression must evaluate to a non-negative integer value.
20187 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20188 /*StrictlyPositive=*/false) ||
20189 ErrorFound;
20190 if (ErrorFound)
20191 return nullptr;
20192
20193 // OpenMP 5.0 [2.12.5, Restrictions]
20194 // In case of ancestor device-modifier, a requires directive with
20195 // the reverse_offload clause must be specified.
20196 if (Modifier == OMPC_DEVICE_ancestor) {
20197 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20199 StartLoc,
20200 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20201 ErrorFound = true;
20202 }
20203 }
20204
20205 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20206 OpenMPDirectiveKind CaptureRegion =
20207 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20208 if (CaptureRegion != OMPD_unknown &&
20210 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20211 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20212 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20213 HelperValStmt = buildPreInits(getASTContext(), Captures);
20214 }
20215
20216 return new (getASTContext())
20217 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20218 LParenLoc, ModifierLoc, EndLoc);
20219}
20220
20222 DSAStackTy *Stack, QualType QTy,
20223 bool FullCheck = true) {
20224 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20225 return false;
20226 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20227 !QTy.isTriviallyCopyableType(SemaRef.Context))
20228 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20229 return true;
20230}
20231
20232/// Return true if it can be proven that the provided array expression
20233/// (array section or array subscript) does NOT specify the whole size of the
20234/// array whose base type is \a BaseQTy.
20236 const Expr *E,
20237 QualType BaseQTy) {
20238 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20239
20240 // If this is an array subscript, it refers to the whole size if the size of
20241 // the dimension is constant and equals 1. Also, an array section assumes the
20242 // format of an array subscript if no colon is used.
20243 if (isa<ArraySubscriptExpr>(E) ||
20244 (OASE && OASE->getColonLocFirst().isInvalid())) {
20245 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20246 return ATy->getSExtSize() != 1;
20247 // Size can't be evaluated statically.
20248 return false;
20249 }
20250
20251 assert(OASE && "Expecting array section if not an array subscript.");
20252 const Expr *LowerBound = OASE->getLowerBound();
20253 const Expr *Length = OASE->getLength();
20254
20255 // If there is a lower bound that does not evaluates to zero, we are not
20256 // covering the whole dimension.
20257 if (LowerBound) {
20259 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20260 return false; // Can't get the integer value as a constant.
20261
20262 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20263 if (ConstLowerBound.getSExtValue())
20264 return true;
20265 }
20266
20267 // If we don't have a length we covering the whole dimension.
20268 if (!Length)
20269 return false;
20270
20271 // If the base is a pointer, we don't have a way to get the size of the
20272 // pointee.
20273 if (BaseQTy->isPointerType())
20274 return false;
20275
20276 // We can only check if the length is the same as the size of the dimension
20277 // if we have a constant array.
20278 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20279 if (!CATy)
20280 return false;
20281
20283 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20284 return false; // Can't get the integer value as a constant.
20285
20286 llvm::APSInt ConstLength = Result.Val.getInt();
20287 return CATy->getSExtSize() != ConstLength.getSExtValue();
20288}
20289
20290// Return true if it can be proven that the provided array expression (array
20291// section or array subscript) does NOT specify a single element of the array
20292// whose base type is \a BaseQTy.
20294 const Expr *E,
20295 QualType BaseQTy) {
20296 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20297
20298 // An array subscript always refer to a single element. Also, an array section
20299 // assumes the format of an array subscript if no colon is used.
20300 if (isa<ArraySubscriptExpr>(E) ||
20301 (OASE && OASE->getColonLocFirst().isInvalid()))
20302 return false;
20303
20304 assert(OASE && "Expecting array section if not an array subscript.");
20305 const Expr *Length = OASE->getLength();
20306
20307 // If we don't have a length we have to check if the array has unitary size
20308 // for this dimension. Also, we should always expect a length if the base type
20309 // is pointer.
20310 if (!Length) {
20311 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20312 return ATy->getSExtSize() != 1;
20313 // We cannot assume anything.
20314 return false;
20315 }
20316
20317 // Check if the length evaluates to 1.
20319 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20320 return false; // Can't get the integer value as a constant.
20321
20322 llvm::APSInt ConstLength = Result.Val.getInt();
20323 return ConstLength.getSExtValue() != 1;
20324}
20325
20326// The base of elements of list in a map clause have to be either:
20327// - a reference to variable or field.
20328// - a member expression.
20329// - an array expression.
20330//
20331// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20332// reference to 'r'.
20333//
20334// If we have:
20335//
20336// struct SS {
20337// Bla S;
20338// foo() {
20339// #pragma omp target map (S.Arr[:12]);
20340// }
20341// }
20342//
20343// We want to retrieve the member expression 'this->S';
20344
20345// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20346// If a list item is an array section, it must specify contiguous storage.
20347//
20348// For this restriction it is sufficient that we make sure only references
20349// to variables or fields and array expressions, and that no array sections
20350// exist except in the rightmost expression (unless they cover the whole
20351// dimension of the array). E.g. these would be invalid:
20352//
20353// r.ArrS[3:5].Arr[6:7]
20354//
20355// r.ArrS[3:5].x
20356//
20357// but these would be valid:
20358// r.ArrS[3].Arr[6:7]
20359//
20360// r.ArrS[3].x
20361namespace {
20362class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20363 Sema &SemaRef;
20364 OpenMPClauseKind CKind = OMPC_unknown;
20365 OpenMPDirectiveKind DKind = OMPD_unknown;
20367 bool IsNonContiguous = false;
20368 bool NoDiagnose = false;
20369 const Expr *RelevantExpr = nullptr;
20370 bool AllowUnitySizeArraySection = true;
20371 bool AllowWholeSizeArraySection = true;
20372 bool AllowAnotherPtr = true;
20373 SourceLocation ELoc;
20374 SourceRange ERange;
20375
20376 void emitErrorMsg() {
20377 // If nothing else worked, this is not a valid map clause expression.
20378 if (SemaRef.getLangOpts().OpenMP < 50) {
20379 SemaRef.Diag(ELoc,
20380 diag::err_omp_expected_named_var_member_or_array_expression)
20381 << ERange;
20382 } else {
20383 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20384 << getOpenMPClauseName(CKind) << ERange;
20385 }
20386 }
20387
20388public:
20389 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20390 if (!isa<VarDecl>(DRE->getDecl())) {
20391 emitErrorMsg();
20392 return false;
20393 }
20394 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20395 RelevantExpr = DRE;
20396 // Record the component.
20397 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20398 return true;
20399 }
20400
20401 bool VisitMemberExpr(MemberExpr *ME) {
20402 Expr *E = ME;
20403 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20404
20405 if (isa<CXXThisExpr>(BaseE)) {
20406 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20407 // We found a base expression: this->Val.
20408 RelevantExpr = ME;
20409 } else {
20410 E = BaseE;
20411 }
20412
20413 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20414 if (!NoDiagnose) {
20415 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20416 << ME->getSourceRange();
20417 return false;
20418 }
20419 if (RelevantExpr)
20420 return false;
20421 return Visit(E);
20422 }
20423
20424 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20425
20426 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20427 // A bit-field cannot appear in a map clause.
20428 //
20429 if (FD->isBitField()) {
20430 if (!NoDiagnose) {
20431 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20432 << ME->getSourceRange() << getOpenMPClauseName(CKind);
20433 return false;
20434 }
20435 if (RelevantExpr)
20436 return false;
20437 return Visit(E);
20438 }
20439
20440 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20441 // If the type of a list item is a reference to a type T then the type
20442 // will be considered to be T for all purposes of this clause.
20443 QualType CurType = BaseE->getType().getNonReferenceType();
20444
20445 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20446 // A list item cannot be a variable that is a member of a structure with
20447 // a union type.
20448 //
20449 if (CurType->isUnionType()) {
20450 if (!NoDiagnose) {
20451 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20452 << ME->getSourceRange();
20453 return false;
20454 }
20455 return RelevantExpr || Visit(E);
20456 }
20457
20458 // If we got a member expression, we should not expect any array section
20459 // before that:
20460 //
20461 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20462 // If a list item is an element of a structure, only the rightmost symbol
20463 // of the variable reference can be an array section.
20464 //
20465 AllowUnitySizeArraySection = false;
20466 AllowWholeSizeArraySection = false;
20467
20468 // Record the component.
20469 Components.emplace_back(ME, FD, IsNonContiguous);
20470 return RelevantExpr || Visit(E);
20471 }
20472
20473 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20474 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20475
20476 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20477 if (!NoDiagnose) {
20478 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20479 << 0 << AE->getSourceRange();
20480 return false;
20481 }
20482 return RelevantExpr || Visit(E);
20483 }
20484
20485 // If we got an array subscript that express the whole dimension we
20486 // can have any array expressions before. If it only expressing part of
20487 // the dimension, we can only have unitary-size array expressions.
20489 AllowWholeSizeArraySection = false;
20490
20491 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20492 Expr::EvalResult Result;
20493 if (!AE->getIdx()->isValueDependent() &&
20494 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20495 !Result.Val.getInt().isZero()) {
20496 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20497 diag::err_omp_invalid_map_this_expr);
20498 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20499 diag::note_omp_invalid_subscript_on_this_ptr_map);
20500 }
20501 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20502 RelevantExpr = TE;
20503 }
20504
20505 // Record the component - we don't have any declaration associated.
20506 Components.emplace_back(AE, nullptr, IsNonContiguous);
20507
20508 return RelevantExpr || Visit(E);
20509 }
20510
20511 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
20512 // After OMP 5.0 Array section in reduction clause will be implicitly
20513 // mapped
20514 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20515 "Array sections cannot be implicitly mapped.");
20516 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20517 QualType CurType =
20519
20520 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20521 // If the type of a list item is a reference to a type T then the type
20522 // will be considered to be T for all purposes of this clause.
20523 if (CurType->isReferenceType())
20524 CurType = CurType->getPointeeType();
20525
20526 bool IsPointer = CurType->isAnyPointerType();
20527
20528 if (!IsPointer && !CurType->isArrayType()) {
20529 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20530 << 0 << OASE->getSourceRange();
20531 return false;
20532 }
20533
20534 bool NotWhole =
20535 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20536 bool NotUnity =
20537 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20538
20539 if (AllowWholeSizeArraySection) {
20540 // Any array section is currently allowed. Allowing a whole size array
20541 // section implies allowing a unity array section as well.
20542 //
20543 // If this array section refers to the whole dimension we can still
20544 // accept other array sections before this one, except if the base is a
20545 // pointer. Otherwise, only unitary sections are accepted.
20546 if (NotWhole || IsPointer)
20547 AllowWholeSizeArraySection = false;
20548 } else if (DKind == OMPD_target_update &&
20549 SemaRef.getLangOpts().OpenMP >= 50) {
20550 if (IsPointer && !AllowAnotherPtr)
20551 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20552 << /*array of unknown bound */ 1;
20553 else
20554 IsNonContiguous = true;
20555 } else if (AllowUnitySizeArraySection && NotUnity) {
20556 // A unity or whole array section is not allowed and that is not
20557 // compatible with the properties of the current array section.
20558 if (NoDiagnose)
20559 return false;
20560 SemaRef.Diag(ELoc,
20561 diag::err_array_section_does_not_specify_contiguous_storage)
20562 << OASE->getSourceRange();
20563 return false;
20564 }
20565
20566 if (IsPointer)
20567 AllowAnotherPtr = false;
20568
20569 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20570 Expr::EvalResult ResultR;
20571 Expr::EvalResult ResultL;
20572 if (!OASE->getLength()->isValueDependent() &&
20573 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20574 !ResultR.Val.getInt().isOne()) {
20575 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20576 diag::err_omp_invalid_map_this_expr);
20577 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20578 diag::note_omp_invalid_length_on_this_ptr_mapping);
20579 }
20580 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20581 OASE->getLowerBound()->EvaluateAsInt(ResultL,
20582 SemaRef.getASTContext()) &&
20583 !ResultL.Val.getInt().isZero()) {
20584 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20585 diag::err_omp_invalid_map_this_expr);
20586 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20587 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20588 }
20589 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20590 RelevantExpr = TE;
20591 }
20592
20593 // Record the component - we don't have any declaration associated.
20594 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20595 return RelevantExpr || Visit(E);
20596 }
20597 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20598 Expr *Base = E->getBase();
20599
20600 // Record the component - we don't have any declaration associated.
20601 Components.emplace_back(E, nullptr, IsNonContiguous);
20602
20603 return Visit(Base->IgnoreParenImpCasts());
20604 }
20605
20606 bool VisitUnaryOperator(UnaryOperator *UO) {
20607 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20608 UO->getOpcode() != UO_Deref) {
20609 emitErrorMsg();
20610 return false;
20611 }
20612 if (!RelevantExpr) {
20613 // Record the component if haven't found base decl.
20614 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20615 }
20616 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20617 }
20618 bool VisitBinaryOperator(BinaryOperator *BO) {
20619 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20620 emitErrorMsg();
20621 return false;
20622 }
20623
20624 // Pointer arithmetic is the only thing we expect to happen here so after we
20625 // make sure the binary operator is a pointer type, the only thing we need
20626 // to do is to visit the subtree that has the same type as root (so that we
20627 // know the other subtree is just an offset)
20628 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20629 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20630 Components.emplace_back(BO, nullptr, false);
20631 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20632 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20633 "Either LHS or RHS have base decl inside");
20634 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20635 return RelevantExpr || Visit(LE);
20636 return RelevantExpr || Visit(RE);
20637 }
20638 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20639 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20640 RelevantExpr = CTE;
20641 Components.emplace_back(CTE, nullptr, IsNonContiguous);
20642 return true;
20643 }
20644 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20645 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20646 Components.emplace_back(COCE, nullptr, IsNonContiguous);
20647 return true;
20648 }
20649 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20650 Expr *Source = E->getSourceExpr();
20651 if (!Source) {
20652 emitErrorMsg();
20653 return false;
20654 }
20655 return Visit(Source);
20656 }
20657 bool VisitStmt(Stmt *) {
20658 emitErrorMsg();
20659 return false;
20660 }
20661 const Expr *getFoundBase() const { return RelevantExpr; }
20662 explicit MapBaseChecker(
20663 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20665 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20666 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20667 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20668};
20669} // namespace
20670
20671/// Return the expression of the base of the mappable expression or null if it
20672/// cannot be determined and do all the necessary checks to see if the
20673/// expression is valid as a standalone mappable expression. In the process,
20674/// record all the components of the expression.
20676 Sema &SemaRef, Expr *E,
20678 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20679 SourceLocation ELoc = E->getExprLoc();
20680 SourceRange ERange = E->getSourceRange();
20681 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20682 ERange);
20683 if (Checker.Visit(E->IgnoreParens())) {
20684 // Check if the highest dimension array section has length specified
20685 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20686 (CKind == OMPC_to || CKind == OMPC_from)) {
20687 auto CI = CurComponents.rbegin();
20688 auto CE = CurComponents.rend();
20689 for (; CI != CE; ++CI) {
20690 const auto *OASE =
20691 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20692 if (!OASE)
20693 continue;
20694 if (OASE && OASE->getLength())
20695 break;
20696 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
20697 << ERange;
20698 }
20699 }
20700 return Checker.getFoundBase();
20701 }
20702 return nullptr;
20703}
20704
20705// Return true if expression E associated with value VD has conflicts with other
20706// map information.
20708 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
20709 bool CurrentRegionOnly,
20711 OpenMPClauseKind CKind) {
20712 assert(VD && E);
20713 SourceLocation ELoc = E->getExprLoc();
20714 SourceRange ERange = E->getSourceRange();
20715
20716 // In order to easily check the conflicts we need to match each component of
20717 // the expression under test with the components of the expressions that are
20718 // already in the stack.
20719
20720 assert(!CurComponents.empty() && "Map clause expression with no components!");
20721 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20722 "Map clause expression with unexpected base!");
20723
20724 // Variables to help detecting enclosing problems in data environment nests.
20725 bool IsEnclosedByDataEnvironmentExpr = false;
20726 const Expr *EnclosingExpr = nullptr;
20727
20728 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20729 VD, CurrentRegionOnly,
20730 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20731 ERange, CKind, &EnclosingExpr,
20733 StackComponents,
20734 OpenMPClauseKind Kind) {
20735 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
20736 return false;
20737 assert(!StackComponents.empty() &&
20738 "Map clause expression with no components!");
20739 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20740 "Map clause expression with unexpected base!");
20741 (void)VD;
20742
20743 // The whole expression in the stack.
20744 const Expr *RE = StackComponents.front().getAssociatedExpression();
20745
20746 // Expressions must start from the same base. Here we detect at which
20747 // point both expressions diverge from each other and see if we can
20748 // detect if the memory referred to both expressions is contiguous and
20749 // do not overlap.
20750 auto CI = CurComponents.rbegin();
20751 auto CE = CurComponents.rend();
20752 auto SI = StackComponents.rbegin();
20753 auto SE = StackComponents.rend();
20754 for (; CI != CE && SI != SE; ++CI, ++SI) {
20755
20756 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
20757 // At most one list item can be an array item derived from a given
20758 // variable in map clauses of the same construct.
20759 if (CurrentRegionOnly &&
20760 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20761 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20762 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20763 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20764 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20765 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20766 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20767 diag::err_omp_multiple_array_items_in_map_clause)
20768 << CI->getAssociatedExpression()->getSourceRange();
20769 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20770 diag::note_used_here)
20771 << SI->getAssociatedExpression()->getSourceRange();
20772 return true;
20773 }
20774
20775 // Do both expressions have the same kind?
20776 if (CI->getAssociatedExpression()->getStmtClass() !=
20777 SI->getAssociatedExpression()->getStmtClass())
20778 break;
20779
20780 // Are we dealing with different variables/fields?
20781 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20782 break;
20783 }
20784 // Check if the extra components of the expressions in the enclosing
20785 // data environment are redundant for the current base declaration.
20786 // If they are, the maps completely overlap, which is legal.
20787 for (; SI != SE; ++SI) {
20788 QualType Type;
20789 if (const auto *ASE =
20790 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20791 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20792 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
20793 SI->getAssociatedExpression())) {
20794 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20795 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20796 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20797 SI->getAssociatedExpression())) {
20798 Type = OASE->getBase()->getType()->getPointeeType();
20799 }
20800 if (Type.isNull() || Type->isAnyPointerType() ||
20802 SemaRef, SI->getAssociatedExpression(), Type))
20803 break;
20804 }
20805
20806 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20807 // List items of map clauses in the same construct must not share
20808 // original storage.
20809 //
20810 // If the expressions are exactly the same or one is a subset of the
20811 // other, it means they are sharing storage.
20812 if (CI == CE && SI == SE) {
20813 if (CurrentRegionOnly) {
20814 if (CKind == OMPC_map) {
20815 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20816 } else {
20817 assert(CKind == OMPC_to || CKind == OMPC_from);
20818 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20819 << ERange;
20820 }
20821 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20822 << RE->getSourceRange();
20823 return true;
20824 }
20825 // If we find the same expression in the enclosing data environment,
20826 // that is legal.
20827 IsEnclosedByDataEnvironmentExpr = true;
20828 return false;
20829 }
20830
20831 QualType DerivedType =
20832 std::prev(CI)->getAssociatedDeclaration()->getType();
20833 SourceLocation DerivedLoc =
20834 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20835
20836 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20837 // If the type of a list item is a reference to a type T then the type
20838 // will be considered to be T for all purposes of this clause.
20839 DerivedType = DerivedType.getNonReferenceType();
20840
20841 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
20842 // A variable for which the type is pointer and an array section
20843 // derived from that variable must not appear as list items of map
20844 // clauses of the same construct.
20845 //
20846 // Also, cover one of the cases in:
20847 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20848 // If any part of the original storage of a list item has corresponding
20849 // storage in the device data environment, all of the original storage
20850 // must have corresponding storage in the device data environment.
20851 //
20852 if (DerivedType->isAnyPointerType()) {
20853 if (CI == CE || SI == SE) {
20854 SemaRef.Diag(
20855 DerivedLoc,
20856 diag::err_omp_pointer_mapped_along_with_derived_section)
20857 << DerivedLoc;
20858 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20859 << RE->getSourceRange();
20860 return true;
20861 }
20862 if (CI->getAssociatedExpression()->getStmtClass() !=
20863 SI->getAssociatedExpression()->getStmtClass() ||
20864 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20865 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20866 assert(CI != CE && SI != SE);
20867 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20868 << DerivedLoc;
20869 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20870 << RE->getSourceRange();
20871 return true;
20872 }
20873 }
20874
20875 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20876 // List items of map clauses in the same construct must not share
20877 // original storage.
20878 //
20879 // An expression is a subset of the other.
20880 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20881 if (CKind == OMPC_map) {
20882 if (CI != CE || SI != SE) {
20883 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
20884 // a pointer.
20885 auto Begin =
20886 CI != CE ? CurComponents.begin() : StackComponents.begin();
20887 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20888 auto It = Begin;
20889 while (It != End && !It->getAssociatedDeclaration())
20890 std::advance(It, 1);
20891 assert(It != End &&
20892 "Expected at least one component with the declaration.");
20893 if (It != Begin && It->getAssociatedDeclaration()
20894 ->getType()
20895 .getCanonicalType()
20896 ->isAnyPointerType()) {
20897 IsEnclosedByDataEnvironmentExpr = false;
20898 EnclosingExpr = nullptr;
20899 return false;
20900 }
20901 }
20902 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20903 } else {
20904 assert(CKind == OMPC_to || CKind == OMPC_from);
20905 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20906 << ERange;
20907 }
20908 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20909 << RE->getSourceRange();
20910 return true;
20911 }
20912
20913 // The current expression uses the same base as other expression in the
20914 // data environment but does not contain it completely.
20915 if (!CurrentRegionOnly && SI != SE)
20916 EnclosingExpr = RE;
20917
20918 // The current expression is a subset of the expression in the data
20919 // environment.
20920 IsEnclosedByDataEnvironmentExpr |=
20921 (!CurrentRegionOnly && CI != CE && SI == SE);
20922
20923 return false;
20924 });
20925
20926 if (CurrentRegionOnly)
20927 return FoundError;
20928
20929 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20930 // If any part of the original storage of a list item has corresponding
20931 // storage in the device data environment, all of the original storage must
20932 // have corresponding storage in the device data environment.
20933 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
20934 // If a list item is an element of a structure, and a different element of
20935 // the structure has a corresponding list item in the device data environment
20936 // prior to a task encountering the construct associated with the map clause,
20937 // then the list item must also have a corresponding list item in the device
20938 // data environment prior to the task encountering the construct.
20939 //
20940 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20941 SemaRef.Diag(ELoc,
20942 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20943 << ERange;
20944 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
20945 << EnclosingExpr->getSourceRange();
20946 return true;
20947 }
20948
20949 return FoundError;
20950}
20951
20952// Look up the user-defined mapper given the mapper name and mapped type, and
20953// build a reference to it.
20955 CXXScopeSpec &MapperIdScopeSpec,
20956 const DeclarationNameInfo &MapperId,
20957 QualType Type,
20958 Expr *UnresolvedMapper) {
20959 if (MapperIdScopeSpec.isInvalid())
20960 return ExprError();
20961 // Get the actual type for the array type.
20962 if (Type->isArrayType()) {
20963 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
20965 }
20966 // Find all user-defined mappers with the given MapperId.
20967 SmallVector<UnresolvedSet<8>, 4> Lookups;
20968 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
20969 Lookup.suppressDiagnostics();
20970 if (S) {
20971 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
20972 /*ObjectType=*/QualType())) {
20973 NamedDecl *D = Lookup.getRepresentativeDecl();
20974 while (S && !S->isDeclScope(D))
20975 S = S->getParent();
20976 if (S)
20977 S = S->getParent();
20978 Lookups.emplace_back();
20979 Lookups.back().append(Lookup.begin(), Lookup.end());
20980 Lookup.clear();
20981 }
20982 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20983 // Extract the user-defined mappers with the given MapperId.
20984 Lookups.push_back(UnresolvedSet<8>());
20985 for (NamedDecl *D : ULE->decls()) {
20986 auto *DMD = cast<OMPDeclareMapperDecl>(D);
20987 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
20988 Lookups.back().addDecl(DMD);
20989 }
20990 }
20991 // Defer the lookup for dependent types. The results will be passed through
20992 // UnresolvedMapper on instantiation.
20993 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
20996 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
20997 return !D->isInvalidDecl() &&
20998 (D->getType()->isDependentType() ||
20999 D->getType()->isInstantiationDependentType() ||
21000 D->getType()->containsUnexpandedParameterPack());
21001 })) {
21002 UnresolvedSet<8> URS;
21003 for (const UnresolvedSet<8> &Set : Lookups) {
21004 if (Set.empty())
21005 continue;
21006 URS.append(Set.begin(), Set.end());
21007 }
21009 SemaRef.Context, /*NamingClass=*/nullptr,
21010 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21011 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
21012 /*KnownInstantiationDependent=*/false);
21013 }
21014 SourceLocation Loc = MapperId.getLoc();
21015 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21016 // The type must be of struct, union or class type in C and C++
21018 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21019 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21020 return ExprError();
21021 }
21022 // Perform argument dependent lookup.
21023 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21024 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21025 // Return the first user-defined mapper with the desired type.
21026 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21027 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21028 if (!D->isInvalidDecl() &&
21029 SemaRef.Context.hasSameType(D->getType(), Type))
21030 return D;
21031 return nullptr;
21032 }))
21033 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21034 // Find the first user-defined mapper with a type derived from the desired
21035 // type.
21036 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21037 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21038 if (!D->isInvalidDecl() &&
21039 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21040 !Type.isMoreQualifiedThan(D->getType(),
21041 SemaRef.getASTContext()))
21042 return D;
21043 return nullptr;
21044 })) {
21045 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21046 /*DetectVirtual=*/false);
21047 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21048 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21049 VD->getType().getUnqualifiedType()))) {
21050 if (SemaRef.CheckBaseClassAccess(
21051 Loc, VD->getType(), Type, Paths.front(),
21052 /*DiagID=*/0) != Sema::AR_inaccessible) {
21053 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21054 }
21055 }
21056 }
21057 }
21058 // Report error if a mapper is specified, but cannot be found.
21059 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21060 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21061 << Type << MapperId.getName();
21062 return ExprError();
21063 }
21064 return ExprEmpty();
21065}
21066
21067namespace {
21068// Utility struct that gathers all the related lists associated with a mappable
21069// expression.
21070struct MappableVarListInfo {
21071 // The list of expressions.
21072 ArrayRef<Expr *> VarList;
21073 // The list of processed expressions.
21074 SmallVector<Expr *, 16> ProcessedVarList;
21075 // The mappble components for each expression.
21077 // The base declaration of the variable.
21078 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21079 // The reference to the user-defined mapper associated with every expression.
21080 SmallVector<Expr *, 16> UDMapperList;
21081
21082 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21083 // We have a list of components and base declarations for each entry in the
21084 // variable list.
21085 VarComponents.reserve(VarList.size());
21086 VarBaseDeclarations.reserve(VarList.size());
21087 }
21088};
21089} // namespace
21090
21092 DSAStackTy *Stack,
21094
21095 const RecordDecl *RD = BaseType->getAsRecordDecl();
21097 DeclarationNameInfo ImplicitName;
21098 // Dummy variable _s for Mapper.
21099 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
21100 DeclRefExpr *MapperVarRef =
21101 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
21102
21103 // Create implicit map clause for mapper.
21105 for (auto *FD : RD->fields()) {
21106 Expr *BE = S.BuildMemberExpr(
21107 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
21110 /*HadMultipleCandidates=*/false,
21112 FD->getType(), VK_LValue, OK_Ordinary);
21113 SExprs.push_back(BE);
21114 }
21115 CXXScopeSpec MapperIdScopeSpec;
21116 DeclarationNameInfo MapperId;
21117 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21118
21119 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21120 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
21121 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21122 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
21123 OMPVarListLocTy());
21124 Maps.push_back(MapClause);
21125 return MapperVarRef;
21126}
21127
21129 DSAStackTy *Stack) {
21130
21131 // Build impilicit map for mapper
21133 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21134
21135 const RecordDecl *RD = BaseType->getAsRecordDecl();
21136 // AST context is RD's ParentASTContext().
21137 ASTContext &Ctx = RD->getParentASTContext();
21138 // DeclContext is RD's DeclContext.
21139 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21140
21141 // Create implicit default mapper for "RD".
21142 DeclarationName MapperId;
21143 auto &DeclNames = Ctx.DeclarationNames;
21144 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
21145 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
21146 BaseType, MapperId, Maps, nullptr);
21147 Scope *Scope = S.getScopeForContext(DCT);
21148 if (Scope)
21149 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
21150 DCT->addDecl(DMD);
21151 DMD->setAccess(clang::AS_none);
21152 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21153 VD->setDeclContext(DMD);
21154 VD->setLexicalDeclContext(DMD);
21155 DMD->addDecl(VD);
21156 DMD->setMapperVarRef(MapperVarRef);
21157 FieldDecl *FD = *RD->field_begin();
21158 // create mapper refence.
21160 DMD, false, SourceLocation(), BaseType, VK_LValue);
21161}
21162
21163// Look up the user-defined mapper given the mapper name and mapper type,
21164// return true if found one.
21165static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21166 CXXScopeSpec &MapperIdScopeSpec,
21167 const DeclarationNameInfo &MapperId,
21168 QualType Type) {
21169 // Find all user-defined mappers with the given MapperId.
21170 SmallVector<UnresolvedSet<8>, 4> Lookups;
21171 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21172 Lookup.suppressDiagnostics();
21173 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21174 /*ObjectType=*/QualType())) {
21175 NamedDecl *D = Lookup.getRepresentativeDecl();
21176 while (S && !S->isDeclScope(D))
21177 S = S->getParent();
21178 if (S)
21179 S = S->getParent();
21180 Lookups.emplace_back();
21181 Lookups.back().append(Lookup.begin(), Lookup.end());
21182 Lookup.clear();
21183 }
21184 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21187 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21188 return !D->isInvalidDecl() &&
21189 (D->getType()->isDependentType() ||
21190 D->getType()->isInstantiationDependentType() ||
21191 D->getType()->containsUnexpandedParameterPack());
21192 }))
21193 return false;
21194 // Perform argument dependent lookup.
21195 SourceLocation Loc = MapperId.getLoc();
21196 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21197 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21198 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21199 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21200 if (!D->isInvalidDecl() &&
21201 SemaRef.Context.hasSameType(D->getType(), Type))
21202 return D;
21203 return nullptr;
21204 }))
21205 return true;
21206 // Find the first user-defined mapper with a type derived from the desired
21207 // type.
21208 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21209 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21210 if (!D->isInvalidDecl() &&
21211 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21212 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
21213 return D;
21214 return nullptr;
21215 });
21216 if (!VD)
21217 return false;
21218 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21219 /*DetectVirtual=*/false);
21220 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21221 bool IsAmbiguous = !Paths.isAmbiguous(
21223 if (IsAmbiguous)
21224 return false;
21225 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
21226 /*DiagID=*/0) != Sema::AR_inaccessible)
21227 return true;
21228 }
21229 return false;
21230}
21231
21232static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21233 QualType CanonType, const Expr *E) {
21234
21235 // DFS over data members in structures/classes.
21237 {CanonType, nullptr});
21238 llvm::DenseMap<const Type *, bool> Visited;
21239 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21240 while (!Types.empty()) {
21241 auto [BaseType, CurFD] = Types.pop_back_val();
21242 while (ParentChain.back().second == 0)
21243 ParentChain.pop_back();
21244 --ParentChain.back().second;
21245 if (BaseType.isNull())
21246 continue;
21247 // Only structs/classes are allowed to have mappers.
21248 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21249 if (!RD)
21250 continue;
21251 auto It = Visited.find(BaseType.getTypePtr());
21252 if (It == Visited.end()) {
21253 // Try to find the associated user-defined mapper.
21254 CXXScopeSpec MapperIdScopeSpec;
21255 DeclarationNameInfo DefaultMapperId;
21257 &S.Context.Idents.get("default")));
21258 DefaultMapperId.setLoc(E->getExprLoc());
21259 bool HasUDMapper =
21260 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
21261 DefaultMapperId, BaseType);
21262 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21263 }
21264 // Found default mapper.
21265 if (It->second)
21266 return true;
21267 // Check for the "default" mapper for data members.
21268 bool FirstIter = true;
21269 for (FieldDecl *FD : RD->fields()) {
21270 if (!FD)
21271 continue;
21272 QualType FieldTy = FD->getType();
21273 if (FieldTy.isNull() ||
21274 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21275 continue;
21276 if (FirstIter) {
21277 FirstIter = false;
21278 ParentChain.emplace_back(CurFD, 1);
21279 } else {
21280 ++ParentChain.back().second;
21281 }
21282 Types.emplace_back(FieldTy, FD);
21283 }
21284 }
21285 return false;
21286}
21287
21288// Check the validity of the provided variable list for the provided clause kind
21289// \a CKind. In the check process the valid expressions, mappable expression
21290// components, variables, and user-defined mappers are extracted and used to
21291// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21292// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21293// and \a MapperId are expected to be valid if the clause kind is 'map'.
21295 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21296 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21297 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21298 ArrayRef<Expr *> UnresolvedMappers,
21300 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
21301 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21302 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21303 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21304 "Unexpected clause kind with mappable expressions!");
21305
21306 // If the identifier of user-defined mapper is not specified, it is "default".
21307 // We do not change the actual name in this clause to distinguish whether a
21308 // mapper is specified explicitly, i.e., it is not explicitly specified when
21309 // MapperId.getName() is empty.
21310 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21311 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21312 MapperId.setName(DeclNames.getIdentifier(
21313 &SemaRef.getASTContext().Idents.get("default")));
21314 MapperId.setLoc(StartLoc);
21315 }
21316
21317 // Iterators to find the current unresolved mapper expression.
21318 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21319 bool UpdateUMIt = false;
21320 Expr *UnresolvedMapper = nullptr;
21321
21322 bool HasHoldModifier =
21323 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21324
21325 // Keep track of the mappable components and base declarations in this clause.
21326 // Each entry in the list is going to have a list of components associated. We
21327 // record each set of the components so that we can build the clause later on.
21328 // In the end we should have the same amount of declarations and component
21329 // lists.
21330
21331 for (Expr *RE : MVLI.VarList) {
21332 assert(RE && "Null expr in omp to/from/map clause");
21333 SourceLocation ELoc = RE->getExprLoc();
21334
21335 // Find the current unresolved mapper expression.
21336 if (UpdateUMIt && UMIt != UMEnd) {
21337 UMIt++;
21338 assert(
21339 UMIt != UMEnd &&
21340 "Expect the size of UnresolvedMappers to match with that of VarList");
21341 }
21342 UpdateUMIt = true;
21343 if (UMIt != UMEnd)
21344 UnresolvedMapper = *UMIt;
21345
21346 const Expr *VE = RE->IgnoreParenLValueCasts();
21347
21348 if (VE->isValueDependent() || VE->isTypeDependent() ||
21351 // Try to find the associated user-defined mapper.
21353 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21354 VE->getType().getCanonicalType(), UnresolvedMapper);
21355 if (ER.isInvalid())
21356 continue;
21357 MVLI.UDMapperList.push_back(ER.get());
21358 // We can only analyze this information once the missing information is
21359 // resolved.
21360 MVLI.ProcessedVarList.push_back(RE);
21361 continue;
21362 }
21363
21364 Expr *SimpleExpr = RE->IgnoreParenCasts();
21365
21366 if (!RE->isLValue()) {
21367 if (SemaRef.getLangOpts().OpenMP < 50) {
21368 SemaRef.Diag(
21369 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21370 << RE->getSourceRange();
21371 } else {
21372 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21373 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21374 }
21375 continue;
21376 }
21377
21379 ValueDecl *CurDeclaration = nullptr;
21380
21381 // Obtain the array or member expression bases if required. Also, fill the
21382 // components array with all the components identified in the process.
21383 const Expr *BE =
21384 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21385 DSAS->getCurrentDirective(), NoDiagnose);
21386 if (!BE)
21387 continue;
21388
21389 assert(!CurComponents.empty() &&
21390 "Invalid mappable expression information.");
21391
21392 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21393 // Add store "this" pointer to class in DSAStackTy for future checking
21394 DSAS->addMappedClassesQualTypes(TE->getType());
21395 // Try to find the associated user-defined mapper.
21397 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21398 VE->getType().getCanonicalType(), UnresolvedMapper);
21399 if (ER.isInvalid())
21400 continue;
21401 MVLI.UDMapperList.push_back(ER.get());
21402 // Skip restriction checking for variable or field declarations
21403 MVLI.ProcessedVarList.push_back(RE);
21404 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21405 MVLI.VarComponents.back().append(CurComponents.begin(),
21406 CurComponents.end());
21407 MVLI.VarBaseDeclarations.push_back(nullptr);
21408 continue;
21409 }
21410
21411 // For the following checks, we rely on the base declaration which is
21412 // expected to be associated with the last component. The declaration is
21413 // expected to be a variable or a field (if 'this' is being mapped).
21414 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21415 assert(CurDeclaration && "Null decl on map clause.");
21416 assert(
21417 CurDeclaration->isCanonicalDecl() &&
21418 "Expecting components to have associated only canonical declarations.");
21419
21420 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21421 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21422
21423 assert((VD || FD) && "Only variables or fields are expected here!");
21424 (void)FD;
21425
21426 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21427 // threadprivate variables cannot appear in a map clause.
21428 // OpenMP 4.5 [2.10.5, target update Construct]
21429 // threadprivate variables cannot appear in a from clause.
21430 if (VD && DSAS->isThreadPrivate(VD)) {
21431 if (NoDiagnose)
21432 continue;
21433 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21434 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21435 << getOpenMPClauseName(CKind);
21436 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21437 continue;
21438 }
21439
21440 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21441 // A list item cannot appear in both a map clause and a data-sharing
21442 // attribute clause on the same construct.
21443
21444 // Check conflicts with other map clause expressions. We check the conflicts
21445 // with the current construct separately from the enclosing data
21446 // environment, because the restrictions are different. We only have to
21447 // check conflicts across regions for the map clauses.
21448 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21449 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21450 break;
21451 if (CKind == OMPC_map &&
21452 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21453 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21454 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21455 break;
21456
21457 // OpenMP 4.5 [2.10.5, target update Construct]
21458 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21459 // If the type of a list item is a reference to a type T then the type will
21460 // be considered to be T for all purposes of this clause.
21461 auto I = llvm::find_if(
21462 CurComponents,
21464 return MC.getAssociatedDeclaration();
21465 });
21466 assert(I != CurComponents.end() && "Null decl on map clause.");
21467 (void)I;
21468 QualType Type;
21469 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21470 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
21471 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21472 if (ASE) {
21473 Type = ASE->getType().getNonReferenceType();
21474 } else if (OASE) {
21475 QualType BaseType =
21477 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21478 Type = ATy->getElementType();
21479 else
21480 Type = BaseType->getPointeeType();
21481 Type = Type.getNonReferenceType();
21482 } else if (OAShE) {
21483 Type = OAShE->getBase()->getType()->getPointeeType();
21484 } else {
21485 Type = VE->getType();
21486 }
21487
21488 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21489 // A list item in a to or from clause must have a mappable type.
21490 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21491 // A list item must have a mappable type.
21492 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21493 DSAS, Type, /*FullCheck=*/true))
21494 continue;
21495
21496 if (CKind == OMPC_map) {
21497 // target enter data
21498 // OpenMP [2.10.2, Restrictions, p. 99]
21499 // A map-type must be specified in all map clauses and must be either
21500 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21501 // no map type is present.
21502 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21503 if (DKind == OMPD_target_enter_data &&
21504 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21505 SemaRef.getLangOpts().OpenMP >= 52)) {
21506 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21507 << (IsMapTypeImplicit ? 1 : 0)
21508 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21509 << getOpenMPDirectiveName(DKind);
21510 continue;
21511 }
21512
21513 // target exit_data
21514 // OpenMP [2.10.3, Restrictions, p. 102]
21515 // A map-type must be specified in all map clauses and must be either
21516 // from, release, or delete. Starting with OpenMP 5.2 the default map
21517 // type is `from` if no map type is present.
21518 if (DKind == OMPD_target_exit_data &&
21519 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21520 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21521 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21522 << (IsMapTypeImplicit ? 1 : 0)
21523 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21524 << getOpenMPDirectiveName(DKind);
21525 continue;
21526 }
21527
21528 // The 'ompx_hold' modifier is specifically intended to be used on a
21529 // 'target' or 'target data' directive to prevent data from being unmapped
21530 // during the associated statement. It is not permitted on a 'target
21531 // enter data' or 'target exit data' directive, which have no associated
21532 // statement.
21533 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21534 HasHoldModifier) {
21535 SemaRef.Diag(StartLoc,
21536 diag::err_omp_invalid_map_type_modifier_for_directive)
21538 OMPC_MAP_MODIFIER_ompx_hold)
21539 << getOpenMPDirectiveName(DKind);
21540 continue;
21541 }
21542
21543 // target, target data
21544 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21545 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21546 // A map-type in a map clause must be to, from, tofrom or alloc
21547 if ((DKind == OMPD_target_data ||
21549 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21550 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21551 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21552 << (IsMapTypeImplicit ? 1 : 0)
21553 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21554 << getOpenMPDirectiveName(DKind);
21555 continue;
21556 }
21557
21558 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21559 // A list item cannot appear in both a map clause and a data-sharing
21560 // attribute clause on the same construct
21561 //
21562 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21563 // A list item cannot appear in both a map clause and a data-sharing
21564 // attribute clause on the same construct unless the construct is a
21565 // combined construct.
21566 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21568 DKind == OMPD_target)) {
21569 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21570 if (isOpenMPPrivate(DVar.CKind)) {
21571 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21572 << getOpenMPClauseName(DVar.CKind)
21573 << getOpenMPClauseName(OMPC_map)
21574 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21575 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21576 continue;
21577 }
21578 }
21579 }
21580
21581 // Try to find the associated user-defined mapper.
21583 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21584 Type.getCanonicalType(), UnresolvedMapper);
21585 if (ER.isInvalid())
21586 continue;
21587 if (!ER.get() && isa<ArraySectionExpr>(VE)) {
21588 // Create implicit mapper as needed.
21589 QualType BaseType = VE->getType().getCanonicalType();
21590 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
21591 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
21593 QualType ElemType;
21594 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
21595 ElemType = ATy->getElementType();
21596 else
21597 ElemType = BType->getPointeeType();
21598 BaseType = ElemType.getCanonicalType();
21599 }
21600 if (BaseType->getAsRecordDecl() &&
21601 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
21602 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
21603 }
21604 }
21605 MVLI.UDMapperList.push_back(ER.get());
21606
21607 // Save the current expression.
21608 MVLI.ProcessedVarList.push_back(RE);
21609
21610 // Store the components in the stack so that they can be used to check
21611 // against other clauses later on.
21612 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21613 /*WhereFoundClauseKind=*/OMPC_map);
21614
21615 // Save the components and declaration to create the clause. For purposes of
21616 // the clause creation, any component list that has base 'this' uses
21617 // null as base declaration.
21618 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21619 MVLI.VarComponents.back().append(CurComponents.begin(),
21620 CurComponents.end());
21621 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21622 : CurDeclaration);
21623 }
21624}
21625
21627 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21628 ArrayRef<SourceLocation> MapTypeModifiersLoc,
21629 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21630 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21631 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21632 const OMPVarListLocTy &Locs, bool NoDiagnose,
21633 ArrayRef<Expr *> UnresolvedMappers) {
21634 OpenMPMapModifierKind Modifiers[] = {
21639
21640 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
21641 BuiltinType::OMPIterator))
21642 Diag(IteratorModifier->getExprLoc(),
21643 diag::err_omp_map_modifier_not_iterator);
21644
21645 // Process map-type-modifiers, flag errors for duplicate modifiers.
21646 unsigned Count = 0;
21647 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21648 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21649 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21650 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21651 continue;
21652 }
21653 assert(Count < NumberOfOMPMapClauseModifiers &&
21654 "Modifiers exceed the allowed number of map type modifiers");
21655 Modifiers[Count] = MapTypeModifiers[I];
21656 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21657 ++Count;
21658 }
21659
21660 MappableVarListInfo MVLI(VarList);
21662 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21663 MapType, Modifiers, IsMapTypeImplicit,
21664 NoDiagnose);
21665
21666 // We need to produce a map clause even if we don't have variables so that
21667 // other diagnostics related with non-existing map clauses are accurate.
21668 return OMPMapClause::Create(
21669 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21670 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21671 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
21672 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21673}
21674
21677 assert(ParsedType.isUsable());
21678
21679 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
21680 if (ReductionType.isNull())
21681 return QualType();
21682
21683 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21684 // A type name in a declare reduction directive cannot be a function type, an
21685 // array type, a reference type, or a type qualified with const, volatile or
21686 // restrict.
21687 if (ReductionType.hasQualifiers()) {
21688 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21689 return QualType();
21690 }
21691
21692 if (ReductionType->isFunctionType()) {
21693 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21694 return QualType();
21695 }
21696 if (ReductionType->isReferenceType()) {
21697 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21698 return QualType();
21699 }
21700 if (ReductionType->isArrayType()) {
21701 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21702 return QualType();
21703 }
21704 return ReductionType;
21705}
21706
21709 Scope *S, DeclContext *DC, DeclarationName Name,
21710 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21711 AccessSpecifier AS, Decl *PrevDeclInScope) {
21713 Decls.reserve(ReductionTypes.size());
21714
21715 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21718 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21719 // A reduction-identifier may not be re-declared in the current scope for the
21720 // same type or for a type that is compatible according to the base language
21721 // rules.
21722 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21723 OMPDeclareReductionDecl *PrevDRD = nullptr;
21724 bool InCompoundScope = true;
21725 if (S != nullptr) {
21726 // Find previous declaration with the same name not referenced in other
21727 // declarations.
21729 InCompoundScope =
21730 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21731 SemaRef.LookupName(Lookup, S);
21732 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21733 /*AllowInlineNamespace=*/false);
21734 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21735 LookupResult::Filter Filter = Lookup.makeFilter();
21736 while (Filter.hasNext()) {
21737 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21738 if (InCompoundScope) {
21739 UsedAsPrevious.try_emplace(PrevDecl, false);
21740 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21741 UsedAsPrevious[D] = true;
21742 }
21743 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21744 PrevDecl->getLocation();
21745 }
21746 Filter.done();
21747 if (InCompoundScope) {
21748 for (const auto &PrevData : UsedAsPrevious) {
21749 if (!PrevData.second) {
21750 PrevDRD = PrevData.first;
21751 break;
21752 }
21753 }
21754 }
21755 } else if (PrevDeclInScope != nullptr) {
21756 auto *PrevDRDInScope = PrevDRD =
21757 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21758 do {
21759 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21760 PrevDRDInScope->getLocation();
21761 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21762 } while (PrevDRDInScope != nullptr);
21763 }
21764 for (const auto &TyData : ReductionTypes) {
21765 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21766 bool Invalid = false;
21767 if (I != PreviousRedeclTypes.end()) {
21768 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21769 << TyData.first;
21770 Diag(I->second, diag::note_previous_definition);
21771 Invalid = true;
21772 }
21773 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21775 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21776 DC->addDecl(DRD);
21777 DRD->setAccess(AS);
21778 Decls.push_back(DRD);
21779 if (Invalid)
21780 DRD->setInvalidDecl();
21781 else
21782 PrevDRD = DRD;
21783 }
21784
21785 return DeclGroupPtrTy::make(
21786 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
21787}
21788
21790 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21791
21792 // Enter new function scope.
21796
21797 if (S != nullptr)
21798 SemaRef.PushDeclContext(S, DRD);
21799 else
21800 SemaRef.CurContext = DRD;
21801
21804
21805 QualType ReductionType = DRD->getType();
21806 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21807 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21808 // uses semantics of argument handles by value, but it should be passed by
21809 // reference. C lang does not support references, so pass all parameters as
21810 // pointers.
21811 // Create 'T omp_in;' variable.
21812 VarDecl *OmpInParm =
21813 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
21814 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21815 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21816 // uses semantics of argument handles by value, but it should be passed by
21817 // reference. C lang does not support references, so pass all parameters as
21818 // pointers.
21819 // Create 'T omp_out;' variable.
21820 VarDecl *OmpOutParm =
21821 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
21822 if (S != nullptr) {
21823 SemaRef.PushOnScopeChains(OmpInParm, S);
21824 SemaRef.PushOnScopeChains(OmpOutParm, S);
21825 } else {
21826 DRD->addDecl(OmpInParm);
21827 DRD->addDecl(OmpOutParm);
21828 }
21829 Expr *InE =
21830 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
21831 Expr *OutE =
21832 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
21833 DRD->setCombinerData(InE, OutE);
21834}
21835
21837 Expr *Combiner) {
21838 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21841
21844
21845 if (Combiner != nullptr)
21846 DRD->setCombiner(Combiner);
21847 else
21848 DRD->setInvalidDecl();
21849}
21850
21852 Decl *D) {
21853 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21854
21855 // Enter new function scope.
21858
21859 if (S != nullptr)
21860 SemaRef.PushDeclContext(S, DRD);
21861 else
21862 SemaRef.CurContext = DRD;
21863
21866
21867 QualType ReductionType = DRD->getType();
21868 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21869 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21870 // uses semantics of argument handles by value, but it should be passed by
21871 // reference. C lang does not support references, so pass all parameters as
21872 // pointers.
21873 // Create 'T omp_priv;' variable.
21874 VarDecl *OmpPrivParm =
21875 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
21876 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21877 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21878 // uses semantics of argument handles by value, but it should be passed by
21879 // reference. C lang does not support references, so pass all parameters as
21880 // pointers.
21881 // Create 'T omp_orig;' variable.
21882 VarDecl *OmpOrigParm =
21883 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
21884 if (S != nullptr) {
21885 SemaRef.PushOnScopeChains(OmpPrivParm, S);
21886 SemaRef.PushOnScopeChains(OmpOrigParm, S);
21887 } else {
21888 DRD->addDecl(OmpPrivParm);
21889 DRD->addDecl(OmpOrigParm);
21890 }
21891 Expr *OrigE =
21892 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
21893 Expr *PrivE =
21894 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
21895 DRD->setInitializerData(OrigE, PrivE);
21896 return OmpPrivParm;
21897}
21898
21900 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
21901 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21904
21907
21908 if (Initializer != nullptr) {
21909 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
21910 } else if (OmpPrivParm->hasInit()) {
21911 DRD->setInitializer(OmpPrivParm->getInit(),
21912 OmpPrivParm->isDirectInit()
21915 } else {
21916 DRD->setInvalidDecl();
21917 }
21918}
21919
21921 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
21922 for (Decl *D : DeclReductions.get()) {
21923 if (IsValid) {
21924 if (S)
21925 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
21926 /*AddToContext=*/false);
21927 } else {
21928 D->setInvalidDecl();
21929 }
21930 }
21931 return DeclReductions;
21932}
21933
21935 Declarator &D) {
21937 QualType T = TInfo->getType();
21938 if (D.isInvalidType())
21939 return true;
21940
21941 if (getLangOpts().CPlusPlus) {
21942 // Check that there are no default arguments (C++ only).
21944 }
21945
21946 return SemaRef.CreateParsedType(T, TInfo);
21947}
21948
21951 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
21952
21954 assert(!MapperType.isNull() && "Expect valid mapper type");
21955
21956 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21957 // The type must be of struct, union or class type in C and C++
21958 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
21959 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21960 return QualType();
21961 }
21962 return MapperType;
21963}
21964
21966 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
21968 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
21969 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21972 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21973 // A mapper-identifier may not be redeclared in the current scope for the
21974 // same type or for a type that is compatible according to the base language
21975 // rules.
21976 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21977 OMPDeclareMapperDecl *PrevDMD = nullptr;
21978 bool InCompoundScope = true;
21979 if (S != nullptr) {
21980 // Find previous declaration with the same name not referenced in other
21981 // declarations.
21983 InCompoundScope =
21984 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21985 SemaRef.LookupName(Lookup, S);
21986 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21987 /*AllowInlineNamespace=*/false);
21988 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21989 LookupResult::Filter Filter = Lookup.makeFilter();
21990 while (Filter.hasNext()) {
21991 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21992 if (InCompoundScope) {
21993 UsedAsPrevious.try_emplace(PrevDecl, false);
21994 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
21995 UsedAsPrevious[D] = true;
21996 }
21997 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21998 PrevDecl->getLocation();
21999 }
22000 Filter.done();
22001 if (InCompoundScope) {
22002 for (const auto &PrevData : UsedAsPrevious) {
22003 if (!PrevData.second) {
22004 PrevDMD = PrevData.first;
22005 break;
22006 }
22007 }
22008 }
22009 } else if (PrevDeclInScope) {
22010 auto *PrevDMDInScope = PrevDMD =
22011 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22012 do {
22013 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22014 PrevDMDInScope->getLocation();
22015 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22016 } while (PrevDMDInScope != nullptr);
22017 }
22018 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22019 bool Invalid = false;
22020 if (I != PreviousRedeclTypes.end()) {
22021 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22022 << MapperType << Name;
22023 Diag(I->second, diag::note_previous_definition);
22024 Invalid = true;
22025 }
22026 // Build expressions for implicit maps of data members with 'default'
22027 // mappers.
22028 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
22029 if (getLangOpts().OpenMP >= 50)
22031 ClausesWithImplicit);
22032 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
22033 MapperType, VN, ClausesWithImplicit,
22034 PrevDMD);
22035 if (S)
22036 SemaRef.PushOnScopeChains(DMD, S);
22037 else
22038 DC->addDecl(DMD);
22039 DMD->setAccess(AS);
22040 if (Invalid)
22041 DMD->setInvalidDecl();
22042
22043 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22044 VD->setDeclContext(DMD);
22045 VD->setLexicalDeclContext(DMD);
22046 DMD->addDecl(VD);
22047 DMD->setMapperVarRef(MapperVarRef);
22048
22050}
22051
22053 Scope *S, QualType MapperType, SourceLocation StartLoc,
22054 DeclarationName VN) {
22055 TypeSourceInfo *TInfo =
22056 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
22057 auto *VD = VarDecl::Create(
22058 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
22059 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
22060 if (S)
22061 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
22062 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
22063 DSAStack->addDeclareMapperVarRef(E);
22064 return E;
22065}
22066
22068 if (DSAStack->getDeclareMapperVarRef())
22069 DSAStack->addIteratorVarDecl(VD);
22070}
22071
22073 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22074 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22075 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22076 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22077 return true;
22079 return true;
22080 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22081 return true;
22082 return false;
22083 }
22084 return true;
22085}
22086
22088 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22089 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22090}
22091
22093 SourceLocation StartLoc,
22094 SourceLocation LParenLoc,
22095 SourceLocation EndLoc) {
22096 if (VarList.empty())
22097 return nullptr;
22098
22099 for (Expr *ValExpr : VarList) {
22100 // OpenMP [teams Constrcut, Restrictions]
22101 // The num_teams expression must evaluate to a positive integer value.
22102 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
22103 /*StrictlyPositive=*/true))
22104 return nullptr;
22105 }
22106
22107 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22109 DKind, OMPC_num_teams, getLangOpts().OpenMP);
22110 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22111 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22112 LParenLoc, EndLoc, VarList,
22113 /*PreInit=*/nullptr);
22114
22115 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22117 for (Expr *ValExpr : VarList) {
22118 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22119 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22120 Vars.push_back(ValExpr);
22121 }
22122
22123 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22124 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22125 LParenLoc, EndLoc, Vars, PreInit);
22126}
22127
22129 SourceLocation StartLoc,
22130 SourceLocation LParenLoc,
22131 SourceLocation EndLoc) {
22132 if (VarList.empty())
22133 return nullptr;
22134
22135 for (Expr *ValExpr : VarList) {
22136 // OpenMP [teams Constrcut, Restrictions]
22137 // The thread_limit expression must evaluate to a positive integer value.
22138 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
22139 /*StrictlyPositive=*/true))
22140 return nullptr;
22141 }
22142
22143 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22145 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
22146 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22147 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
22148 StartLoc, LParenLoc, EndLoc, VarList,
22149 /*PreInit=*/nullptr);
22150
22151 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22153 for (Expr *ValExpr : VarList) {
22154 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22155 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22156 Vars.push_back(ValExpr);
22157 }
22158
22159 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22160 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
22161 LParenLoc, EndLoc, Vars, PreInit);
22162}
22163
22165 SourceLocation StartLoc,
22166 SourceLocation LParenLoc,
22167 SourceLocation EndLoc) {
22168 Expr *ValExpr = Priority;
22169 Stmt *HelperValStmt = nullptr;
22170 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22171
22172 // OpenMP [2.9.1, task Constrcut]
22173 // The priority-value is a non-negative numerical scalar expression.
22175 ValExpr, SemaRef, OMPC_priority,
22176 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22177 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22178 return nullptr;
22179
22180 return new (getASTContext()) OMPPriorityClause(
22181 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22182}
22183
22185 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22186 SourceLocation StartLoc, SourceLocation LParenLoc,
22187 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22188 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22189 "Unexpected grainsize modifier in OpenMP < 51.");
22190
22191 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22192 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22194 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22195 << Values << getOpenMPClauseName(OMPC_grainsize);
22196 return nullptr;
22197 }
22198
22199 Expr *ValExpr = Grainsize;
22200 Stmt *HelperValStmt = nullptr;
22201 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22202
22203 // OpenMP [2.9.2, taskloop Constrcut]
22204 // The parameter of the grainsize clause must be a positive integer
22205 // expression.
22206 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22207 /*StrictlyPositive=*/true,
22208 /*BuildCapture=*/true,
22209 DSAStack->getCurrentDirective(),
22210 &CaptureRegion, &HelperValStmt))
22211 return nullptr;
22212
22213 return new (getASTContext())
22214 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22215 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22216}
22217
22219 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22220 SourceLocation StartLoc, SourceLocation LParenLoc,
22221 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22222 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22223 "Unexpected num_tasks modifier in OpenMP < 51.");
22224
22225 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22226 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22228 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22229 << Values << getOpenMPClauseName(OMPC_num_tasks);
22230 return nullptr;
22231 }
22232
22233 Expr *ValExpr = NumTasks;
22234 Stmt *HelperValStmt = nullptr;
22235 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22236
22237 // OpenMP [2.9.2, taskloop Constrcut]
22238 // The parameter of the num_tasks clause must be a positive integer
22239 // expression.
22241 ValExpr, SemaRef, OMPC_num_tasks,
22242 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22243 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22244 return nullptr;
22245
22246 return new (getASTContext())
22247 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22248 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22249}
22250
22252 SourceLocation StartLoc,
22253 SourceLocation LParenLoc,
22254 SourceLocation EndLoc) {
22255 // OpenMP [2.13.2, critical construct, Description]
22256 // ... where hint-expression is an integer constant expression that evaluates
22257 // to a valid lock hint.
22258 ExprResult HintExpr =
22259 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22260 if (HintExpr.isInvalid())
22261 return nullptr;
22262 return new (getASTContext())
22263 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22264}
22265
22266/// Tries to find omp_event_handle_t type.
22268 DSAStackTy *Stack) {
22269 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22270 if (!OMPEventHandleT.isNull())
22271 return true;
22272 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22273 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22274 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22275 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22276 return false;
22277 }
22278 Stack->setOMPEventHandleT(PT.get());
22279 return true;
22280}
22281
22283 SourceLocation StartLoc,
22284 SourceLocation LParenLoc,
22285 SourceLocation EndLoc) {
22286 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22287 !Evt->isInstantiationDependent() &&
22290 return nullptr;
22291 // OpenMP 5.0, 2.10.1 task Construct.
22292 // event-handle is a variable of the omp_event_handle_t type.
22293 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22294 if (!Ref) {
22295 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22296 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22297 return nullptr;
22298 }
22299 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22300 if (!VD) {
22301 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22302 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22303 return nullptr;
22304 }
22305 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22306 VD->getType()) ||
22307 VD->getType().isConstant(getASTContext())) {
22308 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22309 << "omp_event_handle_t" << 1 << VD->getType()
22310 << Evt->getSourceRange();
22311 return nullptr;
22312 }
22313 // OpenMP 5.0, 2.10.1 task Construct
22314 // [detach clause]... The event-handle will be considered as if it was
22315 // specified on a firstprivate clause.
22316 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22317 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22318 DVar.RefExpr) {
22319 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22320 << getOpenMPClauseName(DVar.CKind)
22321 << getOpenMPClauseName(OMPC_firstprivate);
22323 return nullptr;
22324 }
22325 }
22326
22327 return new (getASTContext())
22328 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22329}
22330
22332 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22333 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22334 SourceLocation EndLoc) {
22335 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22336 std::string Values;
22337 Values += "'";
22338 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22339 Values += "'";
22340 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22341 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22342 return nullptr;
22343 }
22344 Expr *ValExpr = ChunkSize;
22345 Stmt *HelperValStmt = nullptr;
22346 if (ChunkSize) {
22347 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22348 !ChunkSize->isInstantiationDependent() &&
22349 !ChunkSize->containsUnexpandedParameterPack()) {
22350 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22351 ExprResult Val =
22352 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22353 if (Val.isInvalid())
22354 return nullptr;
22355
22356 ValExpr = Val.get();
22357
22358 // OpenMP [2.7.1, Restrictions]
22359 // chunk_size must be a loop invariant integer expression with a positive
22360 // value.
22361 if (std::optional<llvm::APSInt> Result =
22363 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22364 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22365 << "dist_schedule" << ChunkSize->getSourceRange();
22366 return nullptr;
22367 }
22369 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22370 getLangOpts().OpenMP) != OMPD_unknown &&
22372 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22373 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22374 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22375 HelperValStmt = buildPreInits(getASTContext(), Captures);
22376 }
22377 }
22378 }
22379
22380 return new (getASTContext())
22381 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22382 Kind, ValExpr, HelperValStmt);
22383}
22384
22387 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22388 SourceLocation KindLoc, SourceLocation EndLoc) {
22389 if (getLangOpts().OpenMP < 50) {
22390 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22391 Kind != OMPC_DEFAULTMAP_scalar) {
22392 std::string Value;
22394 Value += "'";
22395 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22396 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22397 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22398 Loc = MLoc;
22399 } else {
22400 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22401 OMPC_DEFAULTMAP_scalar);
22402 Loc = KindLoc;
22403 }
22404 Value += "'";
22405 Diag(Loc, diag::err_omp_unexpected_clause_value)
22406 << Value << getOpenMPClauseName(OMPC_defaultmap);
22407 return nullptr;
22408 }
22409 } else {
22410 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22411 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22412 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22413 if (!isDefaultmapKind || !isDefaultmapModifier) {
22414 StringRef KindValue = getLangOpts().OpenMP < 52
22415 ? "'scalar', 'aggregate', 'pointer'"
22416 : "'scalar', 'aggregate', 'pointer', 'all'";
22417 if (getLangOpts().OpenMP == 50) {
22418 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22419 "'firstprivate', 'none', 'default'";
22420 if (!isDefaultmapKind && isDefaultmapModifier) {
22421 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22422 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22423 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22424 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22425 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22426 } else {
22427 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22428 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22429 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22430 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22431 }
22432 } else {
22433 StringRef ModifierValue =
22434 "'alloc', 'from', 'to', 'tofrom', "
22435 "'firstprivate', 'none', 'default', 'present'";
22436 if (!isDefaultmapKind && isDefaultmapModifier) {
22437 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22438 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22439 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22440 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22441 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22442 } else {
22443 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22444 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22445 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22446 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22447 }
22448 }
22449 return nullptr;
22450 }
22451
22452 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22453 // At most one defaultmap clause for each category can appear on the
22454 // directive.
22455 if (DSAStack->checkDefaultmapCategory(Kind)) {
22456 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22457 return nullptr;
22458 }
22459 }
22460 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
22461 // Variable category is not specified - mark all categories.
22462 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22463 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22464 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22465 } else {
22466 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22467 }
22468
22469 return new (getASTContext())
22470 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22471}
22472
22475 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22476 if (!CurLexicalContext->isFileContext() &&
22477 !CurLexicalContext->isExternCContext() &&
22478 !CurLexicalContext->isExternCXXContext() &&
22479 !isa<CXXRecordDecl>(CurLexicalContext) &&
22480 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22481 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22482 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22483 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22484 return false;
22485 }
22486
22487 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22488 if (getLangOpts().HIP)
22489 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
22490
22491 DeclareTargetNesting.push_back(DTCI);
22492 return true;
22493}
22494
22497 assert(!DeclareTargetNesting.empty() &&
22498 "check isInOpenMPDeclareTargetContext() first!");
22499 return DeclareTargetNesting.pop_back_val();
22500}
22501
22504 for (auto &It : DTCI.ExplicitlyMapped)
22505 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22506}
22507
22509 if (DeclareTargetNesting.empty())
22510 return;
22511 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22512 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22513 << getOpenMPDirectiveName(DTCI.Kind);
22514}
22515
22517 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
22519 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
22520 /*ObjectType=*/QualType(),
22521 /*AllowBuiltinCreation=*/true);
22522
22523 if (Lookup.isAmbiguous())
22524 return nullptr;
22525 Lookup.suppressDiagnostics();
22526
22527 if (!Lookup.isSingleResult()) {
22528 VarOrFuncDeclFilterCCC CCC(SemaRef);
22529 if (TypoCorrection Corrected =
22530 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
22532 SemaRef.diagnoseTypo(Corrected,
22533 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
22534 << Id.getName());
22535 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22536 return nullptr;
22537 }
22538
22539 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22540 return nullptr;
22541 }
22542
22543 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22544 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22545 !isa<FunctionTemplateDecl>(ND)) {
22546 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22547 return nullptr;
22548 }
22549 return ND;
22550}
22551
22553 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
22555 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22556 isa<FunctionTemplateDecl>(ND)) &&
22557 "Expected variable, function or function template.");
22558
22559 if (auto *VD = dyn_cast<VarDecl>(ND)) {
22560 // Only global variables can be marked as declare target.
22561 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22562 !VD->isStaticDataMember()) {
22563 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
22564 << VD->getNameAsString();
22565 return;
22566 }
22567 }
22568 // Diagnose marking after use as it may lead to incorrect diagnosis and
22569 // codegen.
22570 if (getLangOpts().OpenMP >= 50 &&
22571 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22572 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22573
22574 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22575 if (getLangOpts().HIP)
22576 Diag(Loc, diag::warn_hip_omp_target_directives);
22577
22578 // Explicit declare target lists have precedence.
22579 const unsigned Level = -1;
22580
22581 auto *VD = cast<ValueDecl>(ND);
22582 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22583 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22584 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22585 (*ActiveAttr)->getLevel() == Level) {
22586 Diag(Loc, diag::err_omp_device_type_mismatch)
22587 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22588 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22589 (*ActiveAttr)->getDevType());
22590 return;
22591 }
22592 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22593 (*ActiveAttr)->getLevel() == Level) {
22594 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22595 return;
22596 }
22597
22598 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22599 return;
22600
22601 Expr *IndirectE = nullptr;
22602 bool IsIndirect = false;
22603 if (DTCI.Indirect) {
22604 IndirectE = *DTCI.Indirect;
22605 if (!IndirectE)
22606 IsIndirect = true;
22607 }
22608 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22609 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
22610 SourceRange(Loc, Loc));
22611 ND->addAttr(A);
22612 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22613 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22615 if (auto *VD = dyn_cast<VarDecl>(ND);
22616 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
22617 VD->hasGlobalStorage())
22619}
22620
22622 Sema &SemaRef, Decl *D) {
22623 if (!D || !isa<VarDecl>(D))
22624 return;
22625 auto *VD = cast<VarDecl>(D);
22626 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22627 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22628 if (SemaRef.LangOpts.OpenMP >= 50 &&
22629 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22630 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22631 VD->hasGlobalStorage()) {
22632 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22633 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22634 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22635 // If a lambda declaration and definition appears between a
22636 // declare target directive and the matching end declare target
22637 // directive, all variables that are captured by the lambda
22638 // expression must also appear in a to clause.
22639 SemaRef.Diag(VD->getLocation(),
22640 diag::err_omp_lambda_capture_in_declare_target_not_to);
22641 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22642 << VD << 0 << SR;
22643 return;
22644 }
22645 }
22646 if (MapTy)
22647 return;
22648 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22649 SemaRef.Diag(SL, diag::note_used_here) << SR;
22650}
22651
22653 Sema &SemaRef, DSAStackTy *Stack,
22654 ValueDecl *VD) {
22655 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22656 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22657 /*FullCheck=*/false);
22658}
22659
22661 SourceLocation IdLoc) {
22662 if (!D || D->isInvalidDecl())
22663 return;
22665 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22666 if (auto *VD = dyn_cast<VarDecl>(D)) {
22667 // Only global variables can be marked as declare target.
22668 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22669 !VD->isStaticDataMember())
22670 return;
22671 // 2.10.6: threadprivate variable cannot appear in a declare target
22672 // directive.
22673 if (DSAStack->isThreadPrivate(VD)) {
22674 Diag(SL, diag::err_omp_threadprivate_in_target);
22675 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22676 return;
22677 }
22678 }
22679 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22680 D = FTD->getTemplatedDecl();
22681 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22682 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22683 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22684 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22685 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22686 Diag(FD->getLocation(), diag::note_defined_here) << FD;
22687 return;
22688 }
22689 }
22690 if (auto *VD = dyn_cast<ValueDecl>(D)) {
22691 // Problem if any with var declared with incomplete type will be reported
22692 // as normal, so no need to check it here.
22693 if ((E || !VD->getType()->isIncompleteType()) &&
22695 return;
22697 // Checking declaration inside declare target region.
22698 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22699 isa<FunctionTemplateDecl>(D)) {
22700 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22701 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22702 unsigned Level = DeclareTargetNesting.size();
22703 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22704 return;
22705 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22706 Expr *IndirectE = nullptr;
22707 bool IsIndirect = false;
22708 if (DTCI.Indirect) {
22709 IndirectE = *DTCI.Indirect;
22710 if (!IndirectE)
22711 IsIndirect = true;
22712 }
22713 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22714 getASTContext(),
22715 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22716 : OMPDeclareTargetDeclAttr::MT_To,
22717 DTCI.DT, IndirectE, IsIndirect, Level,
22718 SourceRange(DTCI.Loc, DTCI.Loc));
22719 D->addAttr(A);
22720 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22721 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22722 }
22723 return;
22724 }
22725 }
22726 if (!E)
22727 return;
22729}
22730
22731/// This class visits every VarDecl that the initializer references and adds
22732/// OMPDeclareTargetDeclAttr to each of them.
22733class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
22734 SmallVector<VarDecl *> DeclVector;
22735 Attr *A;
22736
22737public:
22738 /// A StmtVisitor class function that visits all DeclRefExpr and adds
22739 /// OMPDeclareTargetDeclAttr to them.
22741 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
22742 VD->addAttr(A);
22743 DeclVector.push_back(VD);
22744 }
22745 }
22746 /// A function that iterates across each of the Expr's children.
22747 void VisitExpr(Expr *Ex) {
22748 for (auto *Child : Ex->children()) {
22749 Visit(Child);
22750 }
22751 }
22752 /// A function that keeps a record of all the Decls that are variables, has
22753 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
22754 /// each Decl one at a time and use the inherited 'visit' functions to look
22755 /// for DeclRefExpr.
22757 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
22758 DeclVector.push_back(cast<VarDecl>(TD));
22759 while (!DeclVector.empty()) {
22760 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22761 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
22762 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
22763 if (Expr *Ex = TargetVarDecl->getInit())
22764 Visit(Ex);
22765 }
22766 }
22767 }
22768};
22769
22770/// Adding OMPDeclareTargetDeclAttr to variables with static storage
22771/// duration that are referenced in the initializer expression list of
22772/// variables with static storage duration in declare target directive.
22774 GlobalDeclRefChecker Checker;
22775 if (isa<VarDecl>(TargetDecl))
22776 Checker.declareTargetInitializer(TargetDecl);
22777}
22778
22780 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22781 ArrayRef<SourceLocation> MotionModifiersLoc,
22782 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22783 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22784 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22788
22789 // Process motion-modifiers, flag errors for duplicate modifiers.
22790 unsigned Count = 0;
22791 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22792 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22793 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22794 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22795 continue;
22796 }
22797 assert(Count < NumberOfOMPMotionModifiers &&
22798 "Modifiers exceed the allowed number of motion modifiers");
22799 Modifiers[Count] = MotionModifiers[I];
22800 ModifiersLoc[Count] = MotionModifiersLoc[I];
22801 ++Count;
22802 }
22803
22804 MappableVarListInfo MVLI(VarList);
22806 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22807 if (MVLI.ProcessedVarList.empty())
22808 return nullptr;
22809
22810 return OMPToClause::Create(
22811 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22812 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22813 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22814}
22815
22817 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22818 ArrayRef<SourceLocation> MotionModifiersLoc,
22819 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22820 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22821 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22825
22826 // Process motion-modifiers, flag errors for duplicate modifiers.
22827 unsigned Count = 0;
22828 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22829 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22830 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22831 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22832 continue;
22833 }
22834 assert(Count < NumberOfOMPMotionModifiers &&
22835 "Modifiers exceed the allowed number of motion modifiers");
22836 Modifiers[Count] = MotionModifiers[I];
22837 ModifiersLoc[Count] = MotionModifiersLoc[I];
22838 ++Count;
22839 }
22840
22841 MappableVarListInfo MVLI(VarList);
22842 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22843 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22844 if (MVLI.ProcessedVarList.empty())
22845 return nullptr;
22846
22847 return OMPFromClause::Create(
22848 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22849 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22850 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22851}
22852
22853OMPClause *
22855 const OMPVarListLocTy &Locs) {
22856 MappableVarListInfo MVLI(VarList);
22857 SmallVector<Expr *, 8> PrivateCopies;
22859
22860 for (Expr *RefExpr : VarList) {
22861 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22862 SourceLocation ELoc;
22863 SourceRange ERange;
22864 Expr *SimpleRefExpr = RefExpr;
22865 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22866 if (Res.second) {
22867 // It will be analyzed later.
22868 MVLI.ProcessedVarList.push_back(RefExpr);
22869 PrivateCopies.push_back(nullptr);
22870 Inits.push_back(nullptr);
22871 }
22872 ValueDecl *D = Res.first;
22873 if (!D)
22874 continue;
22875
22876 QualType Type = D->getType();
22877 Type = Type.getNonReferenceType().getUnqualifiedType();
22878
22879 auto *VD = dyn_cast<VarDecl>(D);
22880
22881 // Item should be a pointer or reference to pointer.
22882 if (!Type->isPointerType()) {
22883 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22884 << 0 << RefExpr->getSourceRange();
22885 continue;
22886 }
22887
22888 // Build the private variable and the expression that refers to it.
22889 auto VDPrivate =
22890 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
22891 D->hasAttrs() ? &D->getAttrs() : nullptr,
22892 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22893 if (VDPrivate->isInvalidDecl())
22894 continue;
22895
22896 SemaRef.CurContext->addDecl(VDPrivate);
22897 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22898 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22899
22900 // Add temporary variable to initialize the private copy of the pointer.
22901 VarDecl *VDInit =
22902 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
22903 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22904 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22906 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
22907 /*DirectInit=*/false);
22908
22909 // If required, build a capture to implement the privatization initialized
22910 // with the current list item value.
22911 DeclRefExpr *Ref = nullptr;
22912 if (!VD)
22913 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22914 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22915 PrivateCopies.push_back(VDPrivateRefExpr);
22916 Inits.push_back(VDInitRefExpr);
22917
22918 // We need to add a data sharing attribute for this variable to make sure it
22919 // is correctly captured. A variable that shows up in a use_device_ptr has
22920 // similar properties of a first private variable.
22921 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22922
22923 // Create a mappable component for the list item. List items in this clause
22924 // only need a component.
22925 MVLI.VarBaseDeclarations.push_back(D);
22926 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22927 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22928 /*IsNonContiguous=*/false);
22929 }
22930
22931 if (MVLI.ProcessedVarList.empty())
22932 return nullptr;
22933
22935 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22936 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22937}
22938
22939OMPClause *
22941 const OMPVarListLocTy &Locs) {
22942 MappableVarListInfo MVLI(VarList);
22943
22944 for (Expr *RefExpr : VarList) {
22945 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22946 SourceLocation ELoc;
22947 SourceRange ERange;
22948 Expr *SimpleRefExpr = RefExpr;
22949 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22950 /*AllowArraySection=*/true);
22951 if (Res.second) {
22952 // It will be analyzed later.
22953 MVLI.ProcessedVarList.push_back(RefExpr);
22954 }
22955 ValueDecl *D = Res.first;
22956 if (!D)
22957 continue;
22958 auto *VD = dyn_cast<VarDecl>(D);
22959
22960 // If required, build a capture to implement the privatization initialized
22961 // with the current list item value.
22962 DeclRefExpr *Ref = nullptr;
22963 if (!VD)
22964 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22965 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22966
22967 // We need to add a data sharing attribute for this variable to make sure it
22968 // is correctly captured. A variable that shows up in a use_device_addr has
22969 // similar properties of a first private variable.
22970 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22971
22972 // Create a mappable component for the list item. List items in this clause
22973 // only need a component.
22974 MVLI.VarBaseDeclarations.push_back(D);
22975 MVLI.VarComponents.emplace_back();
22976 Expr *Component = SimpleRefExpr;
22977 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22978 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22979 Component =
22981 MVLI.VarComponents.back().emplace_back(Component, D,
22982 /*IsNonContiguous=*/false);
22983 }
22984
22985 if (MVLI.ProcessedVarList.empty())
22986 return nullptr;
22987
22989 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22990 MVLI.VarComponents);
22991}
22992
22993OMPClause *
22995 const OMPVarListLocTy &Locs) {
22996 MappableVarListInfo MVLI(VarList);
22997 for (Expr *RefExpr : VarList) {
22998 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
22999 SourceLocation ELoc;
23000 SourceRange ERange;
23001 Expr *SimpleRefExpr = RefExpr;
23002 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23003 if (Res.second) {
23004 // It will be analyzed later.
23005 MVLI.ProcessedVarList.push_back(RefExpr);
23006 }
23007 ValueDecl *D = Res.first;
23008 if (!D)
23009 continue;
23010
23011 QualType Type = D->getType();
23012 // item should be a pointer or array or reference to pointer or array
23013 if (!Type.getNonReferenceType()->isPointerType() &&
23014 !Type.getNonReferenceType()->isArrayType()) {
23015 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23016 << 0 << RefExpr->getSourceRange();
23017 continue;
23018 }
23019
23020 // Check if the declaration in the clause does not show up in any data
23021 // sharing attribute.
23022 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23023 if (isOpenMPPrivate(DVar.CKind)) {
23024 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23025 << getOpenMPClauseName(DVar.CKind)
23026 << getOpenMPClauseName(OMPC_is_device_ptr)
23027 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23029 continue;
23030 }
23031
23032 const Expr *ConflictExpr;
23033 if (DSAStack->checkMappableExprComponentListsForDecl(
23034 D, /*CurrentRegionOnly=*/true,
23035 [&ConflictExpr](
23037 OpenMPClauseKind) -> bool {
23038 ConflictExpr = R.front().getAssociatedExpression();
23039 return true;
23040 })) {
23041 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23042 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23043 << ConflictExpr->getSourceRange();
23044 continue;
23045 }
23046
23047 // Store the components in the stack so that they can be used to check
23048 // against other clauses later on.
23050 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23051 DSAStack->addMappableExpressionComponents(
23052 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23053
23054 // Record the expression we've just processed.
23055 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23056
23057 // Create a mappable component for the list item. List items in this clause
23058 // only need a component. We use a null declaration to signal fields in
23059 // 'this'.
23060 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23061 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23062 "Unexpected device pointer expression!");
23063 MVLI.VarBaseDeclarations.push_back(
23064 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23065 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23066 MVLI.VarComponents.back().push_back(MC);
23067 }
23068
23069 if (MVLI.ProcessedVarList.empty())
23070 return nullptr;
23071
23073 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23074 MVLI.VarComponents);
23075}
23076
23077OMPClause *
23079 const OMPVarListLocTy &Locs) {
23080 MappableVarListInfo MVLI(VarList);
23081 for (Expr *RefExpr : VarList) {
23082 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23083 SourceLocation ELoc;
23084 SourceRange ERange;
23085 Expr *SimpleRefExpr = RefExpr;
23086 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23087 /*AllowArraySection=*/true);
23088 if (Res.second) {
23089 // It will be analyzed later.
23090 MVLI.ProcessedVarList.push_back(RefExpr);
23091 }
23092 ValueDecl *D = Res.first;
23093 if (!D)
23094 continue;
23095
23096 // Check if the declaration in the clause does not show up in any data
23097 // sharing attribute.
23098 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23099 if (isOpenMPPrivate(DVar.CKind)) {
23100 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23101 << getOpenMPClauseName(DVar.CKind)
23102 << getOpenMPClauseName(OMPC_has_device_addr)
23103 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23105 continue;
23106 }
23107
23108 const Expr *ConflictExpr;
23109 if (DSAStack->checkMappableExprComponentListsForDecl(
23110 D, /*CurrentRegionOnly=*/true,
23111 [&ConflictExpr](
23113 OpenMPClauseKind) -> bool {
23114 ConflictExpr = R.front().getAssociatedExpression();
23115 return true;
23116 })) {
23117 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23118 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23119 << ConflictExpr->getSourceRange();
23120 continue;
23121 }
23122
23123 // Store the components in the stack so that they can be used to check
23124 // against other clauses later on.
23125 Expr *Component = SimpleRefExpr;
23126 auto *VD = dyn_cast<VarDecl>(D);
23127 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23128 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23129 Component =
23132 Component, D, /*IsNonContiguous=*/false);
23133 DSAStack->addMappableExpressionComponents(
23134 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23135
23136 // Record the expression we've just processed.
23137 if (!VD && !SemaRef.CurContext->isDependentContext()) {
23138 DeclRefExpr *Ref =
23139 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23140 assert(Ref && "has_device_addr capture failed");
23141 MVLI.ProcessedVarList.push_back(Ref);
23142 } else
23143 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23144
23145 // Create a mappable component for the list item. List items in this clause
23146 // only need a component. We use a null declaration to signal fields in
23147 // 'this'.
23148 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23149 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23150 "Unexpected device pointer expression!");
23151 MVLI.VarBaseDeclarations.push_back(
23152 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23153 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23154 MVLI.VarComponents.back().push_back(MC);
23155 }
23156
23157 if (MVLI.ProcessedVarList.empty())
23158 return nullptr;
23159
23161 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23162 MVLI.VarComponents);
23163}
23164
23166 Expr *Allocator, OpenMPAllocateClauseModifier AllocClauseModifier,
23167 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
23168 SourceLocation ColonLoc, SourceLocation EndLoc) {
23169
23170 if (Allocator) {
23171 // Allocator expression is dependent - skip it for now and build the
23172 // allocator when instantiated.
23173 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23174 Allocator->isInstantiationDependent() ||
23175 Allocator->containsUnexpandedParameterPack())
23176 return nullptr;
23177 // OpenMP [2.11.4 allocate Clause, Description]
23178 // allocator is an expression of omp_allocator_handle_t type.
23179 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
23180 return nullptr;
23181
23182 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
23183 if (AllocatorRes.isInvalid())
23184 return nullptr;
23185 AllocatorRes = SemaRef.PerformImplicitConversion(
23186 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23188 /*AllowExplicit=*/true);
23189 if (AllocatorRes.isInvalid())
23190 return nullptr;
23191 Allocator = AllocatorRes.get();
23192 } else {
23193 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23194 // allocate clauses that appear on a target construct or on constructs in a
23195 // target region must specify an allocator expression unless a requires
23196 // directive with the dynamic_allocators clause is present in the same
23197 // compilation unit.
23198 if (getLangOpts().OpenMPIsTargetDevice &&
23199 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23200 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
23201 }
23202 // Analyze and build list of variables.
23204 for (Expr *RefExpr : VarList) {
23205 assert(RefExpr && "NULL expr in OpenMP private clause.");
23206 SourceLocation ELoc;
23207 SourceRange ERange;
23208 Expr *SimpleRefExpr = RefExpr;
23209 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23210 if (Res.second) {
23211 // It will be analyzed later.
23212 Vars.push_back(RefExpr);
23213 }
23214 ValueDecl *D = Res.first;
23215 if (!D)
23216 continue;
23217
23218 auto *VD = dyn_cast<VarDecl>(D);
23219 DeclRefExpr *Ref = nullptr;
23220 if (!VD && !SemaRef.CurContext->isDependentContext())
23221 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
23222 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
23223 ? RefExpr->IgnoreParens()
23224 : Ref);
23225 }
23226
23227 if (Vars.empty())
23228 return nullptr;
23229
23230 if (Allocator)
23231 DSAStack->addInnerAllocatorExpr(Allocator);
23232
23233 OpenMPAllocateClauseModifier AllocatorModifier = AllocClauseModifier;
23234 SourceLocation AllocatorModifierLoc;
23235 return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc,
23236 Allocator, ColonLoc, AllocatorModifier,
23237 AllocatorModifierLoc, EndLoc, Vars);
23238}
23239
23241 SourceLocation StartLoc,
23242 SourceLocation LParenLoc,
23243 SourceLocation EndLoc) {
23245 for (Expr *RefExpr : VarList) {
23246 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23247 SourceLocation ELoc;
23248 SourceRange ERange;
23249 Expr *SimpleRefExpr = RefExpr;
23250 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23251 if (Res.second)
23252 // It will be analyzed later.
23253 Vars.push_back(RefExpr);
23254 ValueDecl *D = Res.first;
23255 if (!D)
23256 continue;
23257
23258 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23259 // A list-item cannot appear in more than one nontemporal clause.
23260 if (const Expr *PrevRef =
23261 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23262 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23263 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23264 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23265 << getOpenMPClauseName(OMPC_nontemporal);
23266 continue;
23267 }
23268
23269 Vars.push_back(RefExpr);
23270 }
23271
23272 if (Vars.empty())
23273 return nullptr;
23274
23275 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
23276 EndLoc, Vars);
23277}
23278
23280 Stmt *AStmt,
23281 SourceLocation StartLoc,
23282 SourceLocation EndLoc) {
23283 if (!AStmt)
23284 return StmtError();
23285
23287
23288 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
23289 AStmt);
23290}
23291
23293 SourceLocation StartLoc,
23294 SourceLocation LParenLoc,
23295 SourceLocation EndLoc) {
23297 for (Expr *RefExpr : VarList) {
23298 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23299 SourceLocation ELoc;
23300 SourceRange ERange;
23301 Expr *SimpleRefExpr = RefExpr;
23302 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23303 /*AllowArraySection=*/true);
23304 if (Res.second)
23305 // It will be analyzed later.
23306 Vars.push_back(RefExpr);
23307 ValueDecl *D = Res.first;
23308 if (!D)
23309 continue;
23310
23311 const DSAStackTy::DSAVarData DVar =
23312 DSAStack->getTopDSA(D, /*FromParent=*/true);
23313 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23314 // A list item that appears in the inclusive or exclusive clause must appear
23315 // in a reduction clause with the inscan modifier on the enclosing
23316 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23317 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23318 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23319 << RefExpr->getSourceRange();
23320
23321 if (DSAStack->getParentDirective() != OMPD_unknown)
23322 DSAStack->markDeclAsUsedInScanDirective(D);
23323 Vars.push_back(RefExpr);
23324 }
23325
23326 if (Vars.empty())
23327 return nullptr;
23328
23329 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23330 EndLoc, Vars);
23331}
23332
23334 SourceLocation StartLoc,
23335 SourceLocation LParenLoc,
23336 SourceLocation EndLoc) {
23338 for (Expr *RefExpr : VarList) {
23339 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23340 SourceLocation ELoc;
23341 SourceRange ERange;
23342 Expr *SimpleRefExpr = RefExpr;
23343 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23344 /*AllowArraySection=*/true);
23345 if (Res.second)
23346 // It will be analyzed later.
23347 Vars.push_back(RefExpr);
23348 ValueDecl *D = Res.first;
23349 if (!D)
23350 continue;
23351
23352 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23353 DSAStackTy::DSAVarData DVar;
23354 if (ParentDirective != OMPD_unknown)
23355 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23356 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23357 // A list item that appears in the inclusive or exclusive clause must appear
23358 // in a reduction clause with the inscan modifier on the enclosing
23359 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23360 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23361 DVar.Modifier != OMPC_REDUCTION_inscan) {
23362 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23363 << RefExpr->getSourceRange();
23364 } else {
23365 DSAStack->markDeclAsUsedInScanDirective(D);
23366 }
23367 Vars.push_back(RefExpr);
23368 }
23369
23370 if (Vars.empty())
23371 return nullptr;
23372
23373 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23374 EndLoc, Vars);
23375}
23376
23377/// Tries to find omp_alloctrait_t type.
23378static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23379 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23380 if (!OMPAlloctraitT.isNull())
23381 return true;
23382 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23383 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23384 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23385 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23386 return false;
23387 }
23388 Stack->setOMPAlloctraitT(PT.get());
23389 return true;
23390}
23391
23393 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23395 ASTContext &Context = getASTContext();
23396 // OpenMP [2.12.5, target Construct]
23397 // allocator is an identifier of omp_allocator_handle_t type.
23398 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
23399 return nullptr;
23400 // OpenMP [2.12.5, target Construct]
23401 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23402 if (llvm::any_of(
23403 Data,
23404 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23405 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
23406 return nullptr;
23407 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23408 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23409 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23410 StringRef Allocator =
23411 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23412 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23413 PredefinedAllocators.insert(SemaRef.LookupSingleName(
23414 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23415 }
23416
23418 for (const UsesAllocatorsData &D : Data) {
23419 Expr *AllocatorExpr = nullptr;
23420 // Check allocator expression.
23421 if (D.Allocator->isTypeDependent()) {
23422 AllocatorExpr = D.Allocator;
23423 } else {
23424 // Traits were specified - need to assign new allocator to the specified
23425 // allocator, so it must be an lvalue.
23426 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23427 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23428 bool IsPredefinedAllocator = false;
23429 if (DRE) {
23430 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23431 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
23432 IsPredefinedAllocator =
23433 AllocatorTy !=
23434 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23435 }
23436 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23437 QualType AllocatorExprType = AllocatorExpr->getType();
23438 bool IsTypeCompatible = IsPredefinedAllocator;
23439 IsTypeCompatible = IsTypeCompatible ||
23440 Context.hasSameUnqualifiedType(AllocatorExprType,
23441 OMPAllocatorHandleT);
23442 IsTypeCompatible =
23443 IsTypeCompatible ||
23444 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23445 bool IsNonConstantLValue =
23446 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23447 if (!DRE || !IsTypeCompatible ||
23448 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23449 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23450 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23451 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23452 continue;
23453 }
23454 // OpenMP [2.12.5, target Construct]
23455 // Predefined allocators appearing in a uses_allocators clause cannot have
23456 // traits specified.
23457 if (IsPredefinedAllocator && D.AllocatorTraits) {
23458 Diag(D.AllocatorTraits->getExprLoc(),
23459 diag::err_omp_predefined_allocator_with_traits)
23460 << D.AllocatorTraits->getSourceRange();
23461 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23462 << cast<NamedDecl>(DRE->getDecl())->getName()
23463 << D.Allocator->getSourceRange();
23464 continue;
23465 }
23466 // OpenMP [2.12.5, target Construct]
23467 // Non-predefined allocators appearing in a uses_allocators clause must
23468 // have traits specified.
23469 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23470 Diag(D.Allocator->getExprLoc(),
23471 diag::err_omp_nonpredefined_allocator_without_traits);
23472 continue;
23473 }
23474 // No allocator traits - just convert it to rvalue.
23475 if (!D.AllocatorTraits)
23476 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
23477 DSAStack->addUsesAllocatorsDecl(
23478 DRE->getDecl(),
23479 IsPredefinedAllocator
23480 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23481 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23482 }
23483 Expr *AllocatorTraitsExpr = nullptr;
23484 if (D.AllocatorTraits) {
23485 if (D.AllocatorTraits->isTypeDependent()) {
23486 AllocatorTraitsExpr = D.AllocatorTraits;
23487 } else {
23488 // OpenMP [2.12.5, target Construct]
23489 // Arrays that contain allocator traits that appear in a uses_allocators
23490 // clause must be constant arrays, have constant values and be defined
23491 // in the same scope as the construct in which the clause appears.
23492 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23493 // Check that traits expr is a constant array.
23494 QualType TraitTy;
23495 if (const ArrayType *Ty =
23496 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23497 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23498 TraitTy = ConstArrayTy->getElementType();
23499 if (TraitTy.isNull() ||
23500 !(Context.hasSameUnqualifiedType(TraitTy,
23501 DSAStack->getOMPAlloctraitT()) ||
23502 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23503 /*CompareUnqualified=*/true))) {
23504 Diag(D.AllocatorTraits->getExprLoc(),
23505 diag::err_omp_expected_array_alloctraits)
23506 << AllocatorTraitsExpr->getType();
23507 continue;
23508 }
23509 // Do not map by default allocator traits if it is a standalone
23510 // variable.
23511 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23512 DSAStack->addUsesAllocatorsDecl(
23513 DRE->getDecl(),
23514 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23515 }
23516 }
23517 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23518 NewD.Allocator = AllocatorExpr;
23519 NewD.AllocatorTraits = AllocatorTraitsExpr;
23520 NewD.LParenLoc = D.LParenLoc;
23521 NewD.RParenLoc = D.RParenLoc;
23522 }
23523 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
23524 EndLoc, NewData);
23525}
23526
23528 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23529 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23531 for (Expr *RefExpr : Locators) {
23532 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23533 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23534 // It will be analyzed later.
23535 Vars.push_back(RefExpr);
23536 continue;
23537 }
23538
23539 SourceLocation ELoc = RefExpr->getExprLoc();
23540 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23541
23542 if (!SimpleExpr->isLValue()) {
23543 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23544 << 1 << 0 << RefExpr->getSourceRange();
23545 continue;
23546 }
23547
23548 ExprResult Res;
23549 {
23551 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23552 }
23553 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23554 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23555 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23556 << 1 << 0 << RefExpr->getSourceRange();
23557 continue;
23558 }
23559 Vars.push_back(SimpleExpr);
23560 }
23561
23562 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
23563 ColonLoc, EndLoc, Modifier, Vars);
23564}
23565
23567 SourceLocation KindLoc,
23568 SourceLocation StartLoc,
23569 SourceLocation LParenLoc,
23570 SourceLocation EndLoc) {
23571 if (Kind == OMPC_BIND_unknown) {
23572 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23573 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23574 /*Last=*/unsigned(OMPC_BIND_unknown))
23575 << getOpenMPClauseName(OMPC_bind);
23576 return nullptr;
23577 }
23578
23579 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
23580 LParenLoc, EndLoc);
23581}
23582
23584 SourceLocation StartLoc,
23585 SourceLocation LParenLoc,
23586 SourceLocation EndLoc) {
23587 Expr *ValExpr = Size;
23588 Stmt *HelperValStmt = nullptr;
23589
23590 // OpenMP [2.5, Restrictions]
23591 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23592 // value.
23593 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
23594 /*StrictlyPositive=*/false))
23595 return nullptr;
23596
23597 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23599 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
23600 if (CaptureRegion != OMPD_unknown &&
23602 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23603 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23604 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23605 HelperValStmt = buildPreInits(getASTContext(), Captures);
23606 }
23607
23609 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23610}
23611
23614 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23615 SourceLocation LParenLoc, SourceLocation EndLoc) {
23616
23617 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
23618 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23619 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23620 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23621 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23622 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23623 return nullptr;
23624 }
23625
23628 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23629 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
23630 SemaRef,
23631 DepType == OMPC_DOACROSS_source ||
23632 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23633 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23634 VarList, DSAStack, EndLoc);
23635 Vars = VarOffset.Vars;
23636 OpsOffs = VarOffset.OpsOffs;
23637 TotalDepCount = VarOffset.TotalDepCount;
23638 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
23639 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23640 TotalDepCount.getZExtValue());
23641 if (DSAStack->isParentOrderedRegion())
23642 DSAStack->addDoacrossDependClause(C, OpsOffs);
23643 return C;
23644}
23645
23647 SourceLocation StartLoc,
23648 SourceLocation LParenLoc,
23649 SourceLocation EndLoc) {
23650 return new (getASTContext())
23651 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
23652}
23653
23655 SourceLocation EndLoc) {
23656 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
23657}
23658
23660 SourceLocation LParenLoc,
23661 SourceLocation EndLoc) {
23662 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
23663}
23664
23668 switch (CK) {
23669 case OMPC_absent:
23670 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23671 case OMPC_contains:
23672 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23673 default:
23674 llvm_unreachable("Unexpected OpenMP clause");
23675 }
23676}
23677
23680 SourceLocation RLoc) {
23681 switch (CK) {
23682 case OMPC_no_openmp:
23683 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
23684 case OMPC_no_openmp_routines:
23685 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
23686 case OMPC_no_parallelism:
23687 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
23688 default:
23689 llvm_unreachable("Unexpected OpenMP clause");
23690 }
23691}
23692
23694 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
23695 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
23696 Expr *Stride, SourceLocation RBLoc) {
23697 ASTContext &Context = getASTContext();
23698 if (Base->hasPlaceholderType() &&
23699 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23701 if (Result.isInvalid())
23702 return ExprError();
23703 Base = Result.get();
23704 }
23705 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
23707 if (Result.isInvalid())
23708 return ExprError();
23710 if (Result.isInvalid())
23711 return ExprError();
23712 LowerBound = Result.get();
23713 }
23714 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23716 if (Result.isInvalid())
23717 return ExprError();
23719 if (Result.isInvalid())
23720 return ExprError();
23721 Length = Result.get();
23722 }
23723 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
23725 if (Result.isInvalid())
23726 return ExprError();
23728 if (Result.isInvalid())
23729 return ExprError();
23730 Stride = Result.get();
23731 }
23732
23733 // Build an unanalyzed expression if either operand is type-dependent.
23734 if (Base->isTypeDependent() ||
23735 (LowerBound &&
23736 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
23737 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23738 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
23739 return new (Context) ArraySectionExpr(
23740 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
23741 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23742 }
23743
23744 // Perform default conversions.
23746 QualType ResultTy;
23747 if (OriginalTy->isAnyPointerType()) {
23748 ResultTy = OriginalTy->getPointeeType();
23749 } else if (OriginalTy->isArrayType()) {
23750 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
23751 } else {
23752 return ExprError(
23753 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23754 << Base->getSourceRange());
23755 }
23756 // C99 6.5.2.1p1
23757 if (LowerBound) {
23758 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
23759 LowerBound);
23760 if (Res.isInvalid())
23761 return ExprError(Diag(LowerBound->getExprLoc(),
23762 diag::err_omp_typecheck_section_not_integer)
23763 << 0 << LowerBound->getSourceRange());
23764 LowerBound = Res.get();
23765
23766 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23767 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23768 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
23769 << 0 << LowerBound->getSourceRange();
23770 }
23771 if (Length) {
23772 auto Res =
23773 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
23774 if (Res.isInvalid())
23775 return ExprError(Diag(Length->getExprLoc(),
23776 diag::err_omp_typecheck_section_not_integer)
23777 << 1 << Length->getSourceRange());
23778 Length = Res.get();
23779
23780 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23781 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23782 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23783 << 1 << Length->getSourceRange();
23784 }
23785 if (Stride) {
23786 ExprResult Res =
23788 if (Res.isInvalid())
23789 return ExprError(Diag(Stride->getExprLoc(),
23790 diag::err_omp_typecheck_section_not_integer)
23791 << 1 << Stride->getSourceRange());
23792 Stride = Res.get();
23793
23794 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23795 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23796 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
23797 << 1 << Stride->getSourceRange();
23798 }
23799
23800 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
23801 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
23802 // type. Note that functions are not objects, and that (in C99 parlance)
23803 // incomplete types are not object types.
23804 if (ResultTy->isFunctionType()) {
23805 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
23806 << ResultTy << Base->getSourceRange();
23807 return ExprError();
23808 }
23809
23810 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
23811 diag::err_omp_section_incomplete_type, Base))
23812 return ExprError();
23813
23814 if (LowerBound && !OriginalTy->isAnyPointerType()) {
23816 if (LowerBound->EvaluateAsInt(Result, Context)) {
23817 // OpenMP 5.0, [2.1.5 Array Sections]
23818 // The array section must be a subset of the original array.
23819 llvm::APSInt LowerBoundValue = Result.Val.getInt();
23820 if (LowerBoundValue.isNegative()) {
23821 Diag(LowerBound->getExprLoc(),
23822 diag::err_omp_section_not_subset_of_array)
23823 << LowerBound->getSourceRange();
23824 return ExprError();
23825 }
23826 }
23827 }
23828
23829 if (Length) {
23831 if (Length->EvaluateAsInt(Result, Context)) {
23832 // OpenMP 5.0, [2.1.5 Array Sections]
23833 // The length must evaluate to non-negative integers.
23834 llvm::APSInt LengthValue = Result.Val.getInt();
23835 if (LengthValue.isNegative()) {
23836 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23837 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
23838 << Length->getSourceRange();
23839 return ExprError();
23840 }
23841 }
23842 } else if (ColonLocFirst.isValid() &&
23843 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
23844 !OriginalTy->isVariableArrayType()))) {
23845 // OpenMP 5.0, [2.1.5 Array Sections]
23846 // When the size of the array dimension is not known, the length must be
23847 // specified explicitly.
23848 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23849 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
23850 return ExprError();
23851 }
23852
23853 if (Stride) {
23855 if (Stride->EvaluateAsInt(Result, Context)) {
23856 // OpenMP 5.0, [2.1.5 Array Sections]
23857 // The stride must evaluate to a positive integer.
23858 llvm::APSInt StrideValue = Result.Val.getInt();
23859 if (!StrideValue.isStrictlyPositive()) {
23860 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
23861 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
23862 << Stride->getSourceRange();
23863 return ExprError();
23864 }
23865 }
23866 }
23867
23868 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23870 if (Result.isInvalid())
23871 return ExprError();
23872 Base = Result.get();
23873 }
23874 return new (Context) ArraySectionExpr(
23875 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
23876 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23877}
23878
23880 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
23881 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
23882 ASTContext &Context = getASTContext();
23883 if (Base->hasPlaceholderType()) {
23885 if (Result.isInvalid())
23886 return ExprError();
23888 if (Result.isInvalid())
23889 return ExprError();
23890 Base = Result.get();
23891 }
23892 QualType BaseTy = Base->getType();
23893 // Delay analysis of the types/expressions if instantiation/specialization is
23894 // required.
23895 if (!BaseTy->isPointerType() && Base->isTypeDependent())
23896 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
23897 LParenLoc, RParenLoc, Dims, Brackets);
23898 if (!BaseTy->isPointerType() ||
23899 (!Base->isTypeDependent() &&
23900 BaseTy->getPointeeType()->isIncompleteType()))
23901 return ExprError(Diag(Base->getExprLoc(),
23902 diag::err_omp_non_pointer_type_array_shaping_base)
23903 << Base->getSourceRange());
23904
23905 SmallVector<Expr *, 4> NewDims;
23906 bool ErrorFound = false;
23907 for (Expr *Dim : Dims) {
23908 if (Dim->hasPlaceholderType()) {
23910 if (Result.isInvalid()) {
23911 ErrorFound = true;
23912 continue;
23913 }
23915 if (Result.isInvalid()) {
23916 ErrorFound = true;
23917 continue;
23918 }
23919 Dim = Result.get();
23920 }
23921 if (!Dim->isTypeDependent()) {
23924 if (Result.isInvalid()) {
23925 ErrorFound = true;
23926 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23927 << Dim->getSourceRange();
23928 continue;
23929 }
23930 Dim = Result.get();
23931 Expr::EvalResult EvResult;
23932 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23933 // OpenMP 5.0, [2.1.4 Array Shaping]
23934 // Each si is an integral type expression that must evaluate to a
23935 // positive integer.
23936 llvm::APSInt Value = EvResult.Val.getInt();
23937 if (!Value.isStrictlyPositive()) {
23938 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23939 << toString(Value, /*Radix=*/10, /*Signed=*/true)
23940 << Dim->getSourceRange();
23941 ErrorFound = true;
23942 continue;
23943 }
23944 }
23945 }
23946 NewDims.push_back(Dim);
23947 }
23948 if (ErrorFound)
23949 return ExprError();
23950 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
23951 LParenLoc, RParenLoc, NewDims, Brackets);
23952}
23953
23955 SourceLocation IteratorKwLoc,
23956 SourceLocation LLoc,
23957 SourceLocation RLoc,
23959 ASTContext &Context = getASTContext();
23961 bool IsCorrect = true;
23962 for (const OMPIteratorData &D : Data) {
23963 TypeSourceInfo *TInfo = nullptr;
23964 SourceLocation StartLoc;
23965 QualType DeclTy;
23966 if (!D.Type.getAsOpaquePtr()) {
23967 // OpenMP 5.0, 2.1.6 Iterators
23968 // In an iterator-specifier, if the iterator-type is not specified then
23969 // the type of that iterator is of int type.
23970 DeclTy = Context.IntTy;
23971 StartLoc = D.DeclIdentLoc;
23972 } else {
23973 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
23974 StartLoc = TInfo->getTypeLoc().getBeginLoc();
23975 }
23976
23977 bool IsDeclTyDependent = DeclTy->isDependentType() ||
23978 DeclTy->containsUnexpandedParameterPack() ||
23979 DeclTy->isInstantiationDependentType();
23980 if (!IsDeclTyDependent) {
23981 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23982 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23983 // The iterator-type must be an integral or pointer type.
23984 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23985 << DeclTy;
23986 IsCorrect = false;
23987 continue;
23988 }
23989 if (DeclTy.isConstant(Context)) {
23990 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23991 // The iterator-type must not be const qualified.
23992 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23993 << DeclTy;
23994 IsCorrect = false;
23995 continue;
23996 }
23997 }
23998
23999 // Iterator declaration.
24000 assert(D.DeclIdent && "Identifier expected.");
24001 // Always try to create iterator declarator to avoid extra error messages
24002 // about unknown declarations use.
24003 auto *VD =
24004 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
24005 D.DeclIdent, DeclTy, TInfo, SC_None);
24006 VD->setImplicit();
24007 if (S) {
24008 // Check for conflicting previous declaration.
24009 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24011 RedeclarationKind::ForVisibleRedeclaration);
24012 Previous.suppressDiagnostics();
24014
24016 /*ConsiderLinkage=*/false,
24017 /*AllowInlineNamespace=*/false);
24018 if (!Previous.empty()) {
24019 NamedDecl *Old = Previous.getRepresentativeDecl();
24020 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
24021 Diag(Old->getLocation(), diag::note_previous_definition);
24022 } else {
24024 }
24025 } else {
24027 }
24028
24029 /// Act on the iterator variable declaration.
24031
24032 Expr *Begin = D.Range.Begin;
24033 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24036 Begin = BeginRes.get();
24037 }
24038 Expr *End = D.Range.End;
24039 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24041 End, DeclTy, AssignmentAction::Converting);
24042 End = EndRes.get();
24043 }
24044 Expr *Step = D.Range.Step;
24045 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24046 if (!Step->getType()->isIntegralType(Context)) {
24047 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
24048 << Step << Step->getSourceRange();
24049 IsCorrect = false;
24050 continue;
24051 }
24052 std::optional<llvm::APSInt> Result =
24053 Step->getIntegerConstantExpr(Context);
24054 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24055 // If the step expression of a range-specification equals zero, the
24056 // behavior is unspecified.
24057 if (Result && Result->isZero()) {
24058 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24059 << Step << Step->getSourceRange();
24060 IsCorrect = false;
24061 continue;
24062 }
24063 }
24064 if (!Begin || !End || !IsCorrect) {
24065 IsCorrect = false;
24066 continue;
24067 }
24068 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
24069 IDElem.IteratorDecl = VD;
24070 IDElem.AssignmentLoc = D.AssignLoc;
24071 IDElem.Range.Begin = Begin;
24072 IDElem.Range.End = End;
24073 IDElem.Range.Step = Step;
24074 IDElem.ColonLoc = D.ColonLoc;
24075 IDElem.SecondColonLoc = D.SecColonLoc;
24076 }
24077 if (!IsCorrect) {
24078 // Invalidate all created iterator declarations if error is found.
24079 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24080 if (Decl *ID = D.IteratorDecl)
24081 ID->setInvalidDecl();
24082 }
24083 return ExprError();
24084 }
24087 // Build number of ityeration for each iteration range.
24088 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
24089 // ((Begini-Stepi-1-Endi) / -Stepi);
24091 // (Endi - Begini)
24092 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
24093 D.Range.End, D.Range.Begin);
24094 if (!Res.isUsable()) {
24095 IsCorrect = false;
24096 continue;
24097 }
24098 ExprResult St, St1;
24099 if (D.Range.Step) {
24100 St = D.Range.Step;
24101 // (Endi - Begini) + Stepi
24102 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
24103 St.get());
24104 if (!Res.isUsable()) {
24105 IsCorrect = false;
24106 continue;
24107 }
24108 // (Endi - Begini) + Stepi - 1
24110 D.AssignmentLoc, BO_Sub, Res.get(),
24111 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24112 if (!Res.isUsable()) {
24113 IsCorrect = false;
24114 continue;
24115 }
24116 // ((Endi - Begini) + Stepi - 1) / Stepi
24117 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
24118 St.get());
24119 if (!Res.isUsable()) {
24120 IsCorrect = false;
24121 continue;
24122 }
24123 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
24124 D.Range.Step);
24125 // (Begini - Endi)
24127 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
24128 if (!Res1.isUsable()) {
24129 IsCorrect = false;
24130 continue;
24131 }
24132 // (Begini - Endi) - Stepi
24133 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
24134 St1.get());
24135 if (!Res1.isUsable()) {
24136 IsCorrect = false;
24137 continue;
24138 }
24139 // (Begini - Endi) - Stepi - 1
24141 D.AssignmentLoc, BO_Sub, Res1.get(),
24142 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24143 if (!Res1.isUsable()) {
24144 IsCorrect = false;
24145 continue;
24146 }
24147 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24148 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
24149 St1.get());
24150 if (!Res1.isUsable()) {
24151 IsCorrect = false;
24152 continue;
24153 }
24154 // Stepi > 0.
24156 D.AssignmentLoc, BO_GT, D.Range.Step,
24157 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
24158 if (!CmpRes.isUsable()) {
24159 IsCorrect = false;
24160 continue;
24161 }
24162 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
24163 CmpRes.get(), Res.get(), Res1.get());
24164 if (!Res.isUsable()) {
24165 IsCorrect = false;
24166 continue;
24167 }
24168 }
24169 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
24170 if (!Res.isUsable()) {
24171 IsCorrect = false;
24172 continue;
24173 }
24174
24175 // Build counter update.
24176 // Build counter.
24177 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
24178 D.IteratorDecl->getBeginLoc(),
24179 D.IteratorDecl->getBeginLoc(), nullptr,
24180 Res.get()->getType(), nullptr, SC_None);
24181 CounterVD->setImplicit();
24182 ExprResult RefRes =
24183 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
24184 D.IteratorDecl->getBeginLoc());
24185 // Build counter update.
24186 // I = Begini + counter * Stepi;
24187 ExprResult UpdateRes;
24188 if (D.Range.Step) {
24189 UpdateRes = SemaRef.CreateBuiltinBinOp(
24190 D.AssignmentLoc, BO_Mul,
24191 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
24192 } else {
24193 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
24194 }
24195 if (!UpdateRes.isUsable()) {
24196 IsCorrect = false;
24197 continue;
24198 }
24199 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
24200 D.Range.Begin, UpdateRes.get());
24201 if (!UpdateRes.isUsable()) {
24202 IsCorrect = false;
24203 continue;
24204 }
24205 ExprResult VDRes =
24206 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
24207 cast<VarDecl>(D.IteratorDecl)->getType(),
24208 VK_LValue, D.IteratorDecl->getBeginLoc());
24209 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
24210 VDRes.get(), UpdateRes.get());
24211 if (!UpdateRes.isUsable()) {
24212 IsCorrect = false;
24213 continue;
24214 }
24215 UpdateRes =
24216 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
24217 if (!UpdateRes.isUsable()) {
24218 IsCorrect = false;
24219 continue;
24220 }
24221 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24222 D.AssignmentLoc, UO_PreInc, RefRes.get());
24223 if (!CounterUpdateRes.isUsable()) {
24224 IsCorrect = false;
24225 continue;
24226 }
24227 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
24228 /*DiscardedValue=*/true);
24229 if (!CounterUpdateRes.isUsable()) {
24230 IsCorrect = false;
24231 continue;
24232 }
24233 OMPIteratorHelperData &HD = Helpers.emplace_back();
24234 HD.CounterVD = CounterVD;
24235 HD.Upper = Res.get();
24236 HD.Update = UpdateRes.get();
24237 HD.CounterUpdate = CounterUpdateRes.get();
24238 }
24239 } else {
24240 Helpers.assign(ID.size(), {});
24241 }
24242 if (!IsCorrect) {
24243 // Invalidate all created iterator declarations if error is found.
24244 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24245 if (Decl *ID = D.IteratorDecl)
24246 ID->setInvalidDecl();
24247 }
24248 return ExprError();
24249 }
24250 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
24251 LLoc, RLoc, ID, Helpers);
24252}
24253
24254/// Check if \p AssumptionStr is a known assumption and warn if not.
24256 StringRef AssumptionStr) {
24257 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24258 return;
24259
24260 unsigned BestEditDistance = 3;
24261 StringRef Suggestion;
24262 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24263 unsigned EditDistance =
24264 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24265 if (EditDistance < BestEditDistance) {
24266 Suggestion = KnownAssumptionIt.getKey();
24267 BestEditDistance = EditDistance;
24268 }
24269 }
24270
24271 if (!Suggestion.empty())
24272 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24273 << AssumptionStr << Suggestion;
24274 else
24275 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
24276 << AssumptionStr;
24277}
24278
24280 // Handle the case where the attribute has a text message.
24281 StringRef Str;
24282 SourceLocation AttrStrLoc;
24283 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
24284 return;
24285
24286 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
24287
24288 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24289}
24290
24292 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3443
NodeId Parent
Definition: ASTDiff.cpp:191
DynTypedNode Node
StringRef P
const Decl * D
enum clang::sema::@1714::IndirectLocalPathEntry::EntryKind Kind
Expr * E
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:3036
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:145
unsigned Iter
Definition: HTMLLogger.cpp:153
static const Decl * getCanonicalDecl(const Decl *D)
#define X(type, name)
Definition: Value.h:144
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.
llvm::MachO::TargetList TargetList
Definition: MachO.h:52
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Definition: ParentMap.cpp:21
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.
uint32_t Id
Definition: SemaARM.cpp:1134
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:758
SourceLocation Loc
Definition: SemaObjC.cpp:759
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 bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
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 checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
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 bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
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 SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
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 SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, StringRef DiagType="")
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
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 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 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={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
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, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
#define DSAStack
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static VarDecl * buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, StringRef Name, const AttrVec *Attrs=nullptr, DeclRefExpr *OrigRef=nullptr)
Build a variable declaration for OpenMP loop iteration variable.
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
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 appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propageted from the selected loop.
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 SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
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 checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
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.
static QualType getPointeeType(const MemRegion *R)
SourceLocation Begin
StateNode * Previous
#define bool
Definition: amdgpuintrin.h:20
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override
bool VisitVarDecl(VarDecl *D) override
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F) override
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:465
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
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:684
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:1289
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2716
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2732
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:1201
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1187
void Deallocate(void *Ptr) const
Definition: ASTContext.h:760
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:1188
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:1703
CanQualType OMPIteratorTy
Definition: ASTContext.h:1201
IdentifierTable & Idents
Definition: ASTContext.h:680
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:1200
CanQualType BoolTy
Definition: ASTContext.h:1161
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:1188
CanQualType IntTy
Definition: ASTContext.h:1169
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:2763
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:2482
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1160
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:1681
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:799
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:6986
Expr * getBase()
Get base of the array section.
Definition: Expr.h:7052
Expr * getLength()
Get length of array section.
Definition: Expr.h:7062
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5177
Expr * getLowerBound()
Get lower bound of array section.
Definition: Expr.h:7056
SourceLocation getColonLocFirst() const
Definition: Expr.h:7083
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2718
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3577
QualType getElementType() const
Definition: Type.h:3589
Attr - This represents one attribute.
Definition: Attr.h:43
Represents an attribute applied to a statement.
Definition: Stmt.h:2117
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition: Stmt.cpp:423
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3909
Expr * getLHS() const
Definition: Expr.h:3959
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2189
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition: Expr.h:4056
bool isRelationalOp() const
Definition: Expr.h:4004
SourceLocation getOperatorLoc() const
Definition: Expr.h:3951
SourceLocation getExprLoc() const
Definition: Expr.h:3950
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:4028
Expr * getRHS() const
Definition: Expr.h:3961
Opcode getOpcode() const
Definition: Expr.h:3954
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2151
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:2553
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2880
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition: StmtCXX.h:135
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:1245
bool hasDefinition() const
Definition: DeclCXX.h:572
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:149
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:1152
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2874
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:1492
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:3047
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:348
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition: Decl.h:4673
unsigned getNumParams() const
Definition: Decl.h:4715
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5467
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4717
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition: Stmt.h:3807
This captures a statement into a function.
Definition: Stmt.h:3794
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1405
SourceRange getSourceRange() const LLVM_READONLY
Definition: Stmt.h:3997
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3898
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition: Stmt.cpp:1429
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:3989
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3547
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition: Type.h:3145
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1638
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition: Stmt.cpp:381
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4262
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:1368
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1435
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2089
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2218
bool isFileContext() const
Definition: DeclBase.h:2160
ASTContext & getParentASTContext() const
Definition: DeclBase.h:2118
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1400
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1334
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
Definition: DeclBase.h:2105
bool isNamespace() const
Definition: DeclBase.h:2178
bool isTranslationUnit() const
Definition: DeclBase.h:2165
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1768
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2349
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1385
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
Definition: DeclBase.cpp:1404
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1742
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:1265
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:1333
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Expr.cpp:556
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1529
SourceLocation getEndLoc() const
Definition: Stmt.h:1552
const DeclGroupRef getDeclGroup() const
Definition: Stmt.h:1547
const Decl * getSingleDecl() const
Definition: Stmt.h:1544
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:1555
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:576
bool hasAttrs() const
Definition: DeclBase.h:521
void addAttr(Attr *A)
Definition: DeclBase.cpp:1010
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:596
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:151
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition: DeclBase.cpp:564
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition: DeclBase.cpp:574
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition: DeclBase.h:973
bool isInvalidDecl() const
Definition: DeclBase.h:591
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:562
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:505
SourceLocation getLocation() const
Definition: DeclBase.h:442
void setImplicit(bool I=true)
Definition: DeclBase.h:597
void setReferenced(bool R=true)
Definition: DeclBase.h:626
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: DeclBase.h:1038
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition: DeclBase.cpp:549
DeclContext * getDeclContext()
Definition: DeclBase.h:451
AccessSpecifier getAccess() const
Definition: DeclBase.h:510
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:434
AttrVec & getAttrs()
Definition: DeclBase.h:527
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition: DeclBase.cpp:355
bool hasAttr() const
Definition: DeclBase.h:580
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:359
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:967
Kind getKind() const
Definition: DeclBase.h:445
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:430
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:1903
Recursive AST visitor that supports extension via dynamic dispatch.
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:3095
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:3107
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3090
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3078
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:3086
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:3070
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:978
Represents a member of a struct/union/class.
Definition: Decl.h:3033
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3124
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4676
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3261
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1074
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2818
Stmt * getBody()
Definition: Stmt.h:2862
Represents a function declaration or definition.
Definition: Decl.h:1935
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2672
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2649
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2398
bool isConsteval() const
Definition: Decl.h:2410
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3702
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5102
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.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2175
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition: Expr.h:1717
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2082
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition: Overload.h:567
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:7584
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:973
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:499
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:3236
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3319
Expr * getBase() const
Definition: Expr.h:3313
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:3297
This represents a decl that may have a name.
Definition: Decl.h:253
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:274
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:280
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:319
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:296
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:1818
A C++ nested-name-specifier augmented with source location information.
static OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
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, OpenMPAllocateClauseModifier AllocatorModifier, SourceLocation AllocatorModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
Definition: OpenMPClause.h:600
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:414
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
Definition: ExprOpenMP.h:24
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Definition: Expr.cpp:5258
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
Definition: StmtOpenMP.cpp:801
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:969
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:833
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:889
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Definition: StmtOpenMP.cpp:875
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 'schedule',...
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.
This represents 'compare' clause in the '#pragma omp atomic' directive.
static OMPContainsClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
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:2076
static OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:618
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:920
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)
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:818
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:556
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:715
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:905
static OMPForDirective * 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: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:488
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.
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 the 'holds' clause in the '#pragma omp assume' directive.
This represents 'if' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:612
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 OMPInterchangeDirective * 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 interchange'.
Definition: StmtOpenMP.cpp:467
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:5387
This represents clause 'lastprivate' in the '#pragma omp ...' directives.
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:683
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:960
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:603
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 the 'no_openmp' clause in the '#pragma omp assume' directive.
This represents the 'no_openmp_routines' clause in the '#pragma omp assume' directive.
This represents the 'no_parallelism' clause in the '#pragma omp assume' directive.
This represents 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
This represents clause 'nontemporal' in the '#pragma omp ...' directives.
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.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:761
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:950
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:634
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:679
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:739
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:723
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:755
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
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.
This class represents the 'permutation' clause in the '#pragma omp interchange' directive.
Definition: OpenMPClause.h:968
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
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
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
Definition: DeclOpenMP.cpp:86
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp reverse'.
Definition: StmtOpenMP.cpp:451
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:806
Expr * getSafelen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:826
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:935
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:569
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
Definition: StmtOpenMP.cpp:551
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:531
This represents 'seq_cst' clause in the '#pragma omp atomic|flush' directives.
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)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:301
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:841
Expr * getSimdlen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:861
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:586
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:994
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.
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.
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:774
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:859
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
Definition: StmtOpenMP.cpp:845
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:790
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.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
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:408
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:429
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.
This represents clause 'uses_allocators' in the '#pragma omp target'-based directives.
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 varlist()
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:1173
void setIsUnique(bool V)
Definition: Expr.h:1225
Represents a parameter to a function.
Definition: Decl.h:1725
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:2922
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
Definition: Expr.cpp:4989
A (possibly-)qualified type.
Definition: Type.h:929
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition: Type.cpp:2796
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: Type.h:8020
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:3521
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:996
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7931
bool isConstant(const ASTContext &Ctx) const
Definition: Type.h:1089
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:8134
QualType getCanonicalType() const
Definition: Type.h:7983
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:8025
bool isMoreQualifiedThan(QualType Other, const ASTContext &Ctx) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition: Type.h:8103
const Type * getTypePtrOrNull() const
Definition: Type.h:7935
Represents a struct/union/class.
Definition: Decl.h:4148
field_range fields() const
Definition: Decl.h:4354
field_iterator field_begin() const
Definition: Decl.cpp:5092
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:6072
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Definition: Redeclarable.h:203
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Definition: Redeclarable.h:225
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3439
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:382
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition: Scope.h:306
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition: Scope.h:531
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition: Scope.h:271
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition: Scope.h:524
@ 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:60
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition: SemaBase.cpp:32
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.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' 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...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'to' clause.
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.
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)
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, OpenMPAllocateClauseModifier ACModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
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 * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' 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 * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' 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.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' 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)
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)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition: SemaOpenMP.h:111
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.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'task_reduction' clause.
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 * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'reduction' 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.
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interchange' after parsing of its clauses and the associated state...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'in_reduction' clause.
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.
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...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
Definition: SemaOpenMP.h:243
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...
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.
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:55
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 ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
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)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
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.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp reverse'.
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:56
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 * 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={})
Called on well-formed 'map' clause.
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:371
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.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
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.
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.
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:431
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:915
Expr * get() const
Definition: Sema.h:7273
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:12118
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:7222
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:463
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
Definition: SemaType.cpp:6394
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:731
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:1559
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15491
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:8983
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:9024
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:9026
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:9028
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
SemaOpenMP & OpenMP()
Definition: Sema.h:1125
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt={})
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
Definition: SemaExpr.cpp:20155
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition: Sema.h:4318
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17380
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:20371
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:848
@ AR_inaccessible
Definition: Sema.h:1262
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:2290
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition: Sema.cpp:2159
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:6218
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:17138
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1658
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:1568
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ASTContext & Context
Definition: Sema.h:908
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4614
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:70
@ AllowFold
Definition: Sema.h:7238
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1497
void CleanupVarDeclMarking()
Definition: SemaExpr.cpp:19651
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:752
ASTContext & getASTContext() const
Definition: Sema.h:531
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15770
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:18923
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:19899
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:17813
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:816
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2204
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:2178
const LangOptions & getLangOpts() const
Definition: Sema.h:524
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:907
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:6481
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:906
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2404
DeclContext * getCurLexicalContext() const
Definition: Sema.h:735
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3351
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
Definition: SemaStmt.cpp:4525
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:939
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:640
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition: Sema.h:14983
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20344
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2359
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1043
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4629
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4115
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:20955
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:13483
@ TryCapture_ExplicitByVal
Definition: Sema.h:6588
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:11193
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:8782
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:14938
@ CTK_ErrorRecovery
Definition: Sema.h:9377
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2344
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:10914
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
Definition: SemaDecl.cpp:286
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5126
@ 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:5703
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:76
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9068
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:871
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:17890
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1308
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
Definition: SemaExpr.cpp:3604
void PopDeclContext()
Definition: SemaDecl.cpp:1315
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:1579
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:13945
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13386
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition: Sema.cpp:1961
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
Definition: SemaExpr.cpp:15338
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:14761
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:2374
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2733
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:2750
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:451
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:7287
bool checkStringLiteralArgumentAttr(const AttributeCommonInfo &CI, const Expr *E, StringRef &Str, SourceLocation *ArgLocation=nullptr)
Check if the argument E is a ASCII string literal.
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition: Sema.h:8261
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 getEnd() const
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:348
child_range children()
Definition: Stmt.cpp:285
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:324
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:195
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:336
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4743
bool isTLSSupported() const
Whether the target supports thread-local storage.
Definition: TargetInfo.h:1576
bool isVLASupported() const
Whether target supports variable-length arrays.
Definition: TargetInfo.h:1587
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition: Decl.h:3370
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7902
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:7913
The base class of the type hierarchy.
Definition: Type.h:1828
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1916
bool isConstantArrayType() const
Definition: Type.h:8262
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:2055
bool isArrayType() const
Definition: Type.h:8258
bool isArithmeticType() const
Definition: Type.cpp:2315
bool isPointerType() const
Definition: Type.h:8186
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8550
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8800
bool isReferenceType() const
Definition: Type.h:8204
bool isEnumeralType() const
Definition: Type.h:8290
bool isScalarType() const
Definition: Type.h:8609
bool isVariableArrayType() const
Definition: Type.h:8270
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2092
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:738
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2270
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: Type.h:8504
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2714
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:8479
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2706
bool isAnyComplexType() const
Definition: Type.h:8294
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: Type.h:2361
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2220
bool isFunctionProtoType() const
Definition: Type.h:2535
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition: Type.h:8651
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: Type.h:2724
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8786
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition: Type.cpp:2396
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition: Type.h:8748
bool isFunctionType() const
Definition: Type.h:8182
bool isStructureOrClassType() const
Definition: Type.cpp:690
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2300
bool isFloatingType() const
Definition: Type.cpp:2283
bool isAnyPointerType() const
Definition: Type.h:8194
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8731
bool isRecordType() const
Definition: Type.h:8286
bool isUnionType() const
Definition: Type.cpp:704
bool isFunctionNoProtoType() const
Definition: Type.h:2534
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1920
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:2232
Expr * getSubExpr() const
Definition: Expr.h:2277
Opcode getOpcode() const
Definition: Expr.h:2272
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
Definition: ExprCXX.cpp:419
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
Definition: UnresolvedSet.h:92
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:671
void setType(QualType newType)
Definition: Decl.h:683
QualType getType() const
Definition: Decl.h:682
VarDecl * getPotentiallyDecomposedVarDecl()
Definition: DeclCXX.cpp:3392
Represents a variable declaration or definition.
Definition: Decl.h:882
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition: Decl.cpp:2140
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition: Decl.h:1218
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1513
TLSKind getTLSKind() const
Definition: Decl.cpp:2157
bool hasInit() const
Definition: Decl.cpp:2387
void setInitStyle(InitializationStyle Style)
Definition: Decl.h:1396
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition: Decl.h:1410
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition: Decl.cpp:2249
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:2179
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:2246
@ CInit
C-style initialization with assignment.
Definition: Decl.h:887
@ CallInit
Call-style initialization (C++98)
Definition: Decl.h:890
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition: Decl.h:1234
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1177
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:1159
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition: Decl.h:1293
const Expr * getInit() const
Definition: Decl.h:1319
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1135
@ TLS_None
Not a TLS variable.
Definition: Decl.h:902
void setInit(Expr *I)
Definition: Decl.cpp:2449
@ DeclarationOnly
This declaration is only a declaration.
Definition: Decl.h:1246
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition: Decl.h:1204
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition: Decl.h:1415
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition: Decl.h:1180
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1119
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:2500
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition: Decl.h:1213
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition: Decl.h:1309
Directive - Abstract class representing a parsed verify directive.
Retains information about a captured region.
Definition: ScopeInfo.h:816
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:35
Defines the clang::TargetInfo interface.
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1171
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.
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:25
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
Definition: OpenMPKinds.h:119
@ OMPC_DEFAULTMAP_MODIFIER_last
Definition: OpenMPKinds.h:124
@ OMPC_DEFAULTMAP_MODIFIER_unknown
Definition: OpenMPKinds.h:120
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
Definition: OpenMPKinds.h:172
@ OMPC_ORDER_MODIFIER_unknown
Definition: OpenMPKinds.h:173
@ OMPC_ORDER_MODIFIER_last
Definition: OpenMPKinds.h:176
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition: Specifiers.h:149
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Definition: OpenMPKinds.h:136
@ OMPC_AT_unknown
Definition: OpenMPKinds.h:139
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:187
@ OMPC_REDUCTION_unknown
Definition: OpenMPKinds.h:190
BinaryOperatorKind
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition: OpenMPKinds.h:39
@ OMPC_SCHEDULE_MODIFIER_last
Definition: OpenMPKinds.h:44
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition: OpenMPKinds.h:40
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:28
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:256
@ SC_Register
Definition: Specifiers.h:257
@ SC_None
Definition: Specifiers.h:250
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
Definition: OpenMPKinds.h:104
@ OMPC_DIST_SCHEDULE_unknown
Definition: OpenMPKinds.h:107
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition: Decl.h:5034
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
Definition: OpenMPKinds.h:220
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:88
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:331
@ 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:201
@ OMPC_BIND_unknown
Definition: OpenMPKinds.h:204
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
Definition: OpenMPKinds.h:158
@ OMPC_LASTPRIVATE_unknown
Definition: OpenMPKinds.h:161
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition: OpenMPKinds.h:55
@ OMPC_DEPEND_unknown
Definition: OpenMPKinds.h:59
OpenMPGrainsizeClauseModifier
Definition: OpenMPKinds.h:207
@ OMPC_GRAINSIZE_unknown
Definition: OpenMPKinds.h:210
OpenMPNumTasksClauseModifier
Definition: OpenMPKinds.h:213
@ OMPC_NUMTASKS_unknown
Definition: OpenMPKinds.h:216
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.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
Definition: OpenMPKinds.h:143
@ OMPC_SEVERITY_unknown
Definition: OpenMPKinds.h:146
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:100
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition: OpenMPKinds.h:92
@ OMPC_MOTION_MODIFIER_unknown
Definition: OpenMPKinds.h:96
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
Definition: OpenMPKinds.h:111
@ OMPC_DEFAULTMAP_unknown
Definition: OpenMPKinds.h:115
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
Definition: OpenMPKinds.h:227
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:63
@ OMPC_LINEAR_unknown
Definition: OpenMPKinds.h:67
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
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:132
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
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:128
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
Definition: OpenMPKinds.h:132
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:48
@ OMPC_DEVICE_unknown
Definition: OpenMPKinds.h:51
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition: OpenMPKinds.h:79
@ OMPC_MAP_MODIFIER_unknown
Definition: OpenMPKinds.h:80
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:165
@ OMPC_ORDER_unknown
Definition: OpenMPKinds.h:168
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition: OpenMPKinds.h:31
@ OMPC_SCHEDULE_unknown
Definition: OpenMPKinds.h:35
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:123
@ AS_public
Definition: Specifiers.h:124
@ AS_none
Definition: Specifiers.h:127
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition: OpenMPKinds.h:71
@ OMPC_MAP_unknown
Definition: OpenMPKinds.h:75
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition: Specifiers.h:177
unsigned long uint64_t
#define true
Definition: stdbool.h:25
#define false
Definition: stdbool.h:26
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:5187
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:240
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:736
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:710
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Definition: StmtOpenMP.h:720
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:729
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Definition: StmtOpenMP.h:716
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:713
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:726
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Definition: StmtOpenMP.h:732
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:723
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Definition: StmtOpenMP.h:741
Expr * LastIteration
Loop last iteration number.
Definition: StmtOpenMP.h:745
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:803
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Definition: StmtOpenMP.h:793
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Definition: StmtOpenMP.h:787
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Definition: StmtOpenMP.h:781
Expr * IL
IsLastIteration - local flag variable passed to runtime.
Definition: StmtOpenMP.h:759
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
Definition: StmtOpenMP.h:791
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Definition: StmtOpenMP.h:815
Expr * CalcLastIteration
Calculation of last iteration.
Definition: StmtOpenMP.h:749
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Definition: StmtOpenMP.h:795
Expr * ST
Stride - local variable passed to runtime.
Definition: StmtOpenMP.h:765
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
Definition: StmtOpenMP.h:797
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:806
Expr * PreCond
Loop pre-condition.
Definition: StmtOpenMP.h:751
Stmt * PreInits
Init statement for all captured expressions.
Definition: StmtOpenMP.h:808
Expr * IterationVarRef
Loop iteration variable.
Definition: StmtOpenMP.h:743
Expr * NumIterations
Loop number of iterations.
Definition: StmtOpenMP.h:747
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Definition: StmtOpenMP.h:789
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:769
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:777
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
Definition: StmtOpenMP.h:811
void clear(unsigned Size)
Initialize all the fields to null.
Definition: StmtOpenMP.h:825
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Definition: StmtOpenMP.h:767
Expr * UB
UpperBound - local variable passed to runtime.
Definition: StmtOpenMP.h:763
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:771
Expr * LB
LowerBound - local variable passed to runtime.
Definition: StmtOpenMP.h:761
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:774
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:800
Expr * Init
Loop iteration variable init.
Definition: StmtOpenMP.h:755
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:316
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition: SemaOpenMP.h:313
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition: SemaOpenMP.h:310
SourceLocation Loc
The directive location.
Definition: SemaOpenMP.h:319
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition: SemaOpenMP.h:307
Data structure for iterator expression.
Definition: SemaOpenMP.h:1387
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1130
Data for list of allocators.
Definition: SemaOpenMP.h:1327
Clang specific specialization of the OMPContext to lookup target features.