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 if (!VD)
5324 continue;
5325 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5326 if (!isOpenMPPrivate(Data.CKind)) {
5327 S.Diag(E->getExprLoc(),
5328 diag::err_omp_expected_private_copy_for_allocate);
5329 continue;
5330 }
5331 VarDecl *PrivateVD = DeclToCopy[VD];
5332 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5333 AllocatorKind, AC->getAllocator()))
5334 continue;
5335 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5336 AC->getAlignment(), 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 ||
15621 CKind == OMPC_allocate) &&
15622 !Result.isPowerOf2()) {
15623 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
15624 << E->getSourceRange();
15625 return ExprError();
15626 }
15627 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
15628 DSAStack->setAssociatedLoops(Result.getExtValue());
15629 else if (CKind == OMPC_ordered)
15630 DSAStack->setAssociatedLoops(Result.getExtValue());
15631 return ICE;
15632}
15633
15635 SourceLocation StartLoc,
15636 SourceLocation LParenLoc,
15637 SourceLocation EndLoc) {
15638 // OpenMP [2.8.1, simd construct, Description]
15639 // The parameter of the safelen clause must be a constant
15640 // positive integer expression.
15641 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
15642 if (Safelen.isInvalid())
15643 return nullptr;
15644 return new (getASTContext())
15645 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
15646}
15647
15649 SourceLocation StartLoc,
15650 SourceLocation LParenLoc,
15651 SourceLocation EndLoc) {
15652 // OpenMP [2.8.1, simd construct, Description]
15653 // The parameter of the simdlen clause must be a constant
15654 // positive integer expression.
15655 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
15656 if (Simdlen.isInvalid())
15657 return nullptr;
15658 return new (getASTContext())
15659 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
15660}
15661
15662/// Tries to find omp_allocator_handle_t type.
15664 DSAStackTy *Stack) {
15665 if (!Stack->getOMPAllocatorHandleT().isNull())
15666 return true;
15667
15668 // Set the allocator handle type.
15669 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
15670 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
15671 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
15672 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15673 << "omp_allocator_handle_t";
15674 return false;
15675 }
15676 QualType AllocatorHandleEnumTy = PT.get();
15677 AllocatorHandleEnumTy.addConst();
15678 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15679
15680 // Fill the predefined allocator map.
15681 bool ErrorFound = false;
15682 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15683 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
15684 StringRef Allocator =
15685 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15686 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
15687 auto *VD = dyn_cast_or_null<ValueDecl>(
15688 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
15689 if (!VD) {
15690 ErrorFound = true;
15691 break;
15692 }
15693 QualType AllocatorType =
15695 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
15696 if (!Res.isUsable()) {
15697 ErrorFound = true;
15698 break;
15699 }
15700 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
15702 /*AllowExplicit=*/true);
15703 if (!Res.isUsable()) {
15704 ErrorFound = true;
15705 break;
15706 }
15707 Stack->setAllocator(AllocatorKind, Res.get());
15708 }
15709 if (ErrorFound) {
15710 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15711 << "omp_allocator_handle_t";
15712 return false;
15713 }
15714
15715 return true;
15716}
15717
15719 SourceLocation StartLoc,
15720 SourceLocation LParenLoc,
15721 SourceLocation EndLoc) {
15722 // OpenMP [2.11.3, allocate Directive, Description]
15723 // allocator is an expression of omp_allocator_handle_t type.
15725 return nullptr;
15726
15728 if (Allocator.isInvalid())
15729 return nullptr;
15731 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
15733 /*AllowExplicit=*/true);
15734 if (Allocator.isInvalid())
15735 return nullptr;
15736 return new (getASTContext())
15737 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
15738}
15739
15741 SourceLocation StartLoc,
15742 SourceLocation LParenLoc,
15743 SourceLocation EndLoc) {
15744 // OpenMP [2.7.1, loop construct, Description]
15745 // OpenMP [2.8.1, simd construct, Description]
15746 // OpenMP [2.9.6, distribute construct, Description]
15747 // The parameter of the collapse clause must be a constant
15748 // positive integer expression.
15749 ExprResult NumForLoopsResult =
15750 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
15751 if (NumForLoopsResult.isInvalid())
15752 return nullptr;
15753 return new (getASTContext())
15754 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
15755}
15756
15758 SourceLocation EndLoc,
15759 SourceLocation LParenLoc,
15760 Expr *NumForLoops) {
15761 // OpenMP [2.7.1, loop construct, Description]
15762 // OpenMP [2.8.1, simd construct, Description]
15763 // OpenMP [2.9.6, distribute construct, Description]
15764 // The parameter of the ordered clause must be a constant
15765 // positive integer expression if any.
15766 if (NumForLoops && LParenLoc.isValid()) {
15767 ExprResult NumForLoopsResult =
15768 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
15769 if (NumForLoopsResult.isInvalid())
15770 return nullptr;
15771 NumForLoops = NumForLoopsResult.get();
15772 } else {
15773 NumForLoops = nullptr;
15774 }
15775 auto *Clause =
15777 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
15778 StartLoc, LParenLoc, EndLoc);
15779 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
15780 return Clause;
15781}
15782
15784 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
15785 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15786 OMPClause *Res = nullptr;
15787 switch (Kind) {
15788 case OMPC_default:
15789 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
15790 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15791 break;
15792 case OMPC_proc_bind:
15793 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
15794 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15795 break;
15796 case OMPC_atomic_default_mem_order:
15798 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
15799 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15800 break;
15801 case OMPC_fail:
15802 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
15803 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15804 break;
15805 case OMPC_update:
15806 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
15807 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15808 break;
15809 case OMPC_bind:
15810 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
15811 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15812 break;
15813 case OMPC_at:
15814 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
15815 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15816 break;
15817 case OMPC_severity:
15819 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
15820 LParenLoc, EndLoc);
15821 break;
15822 case OMPC_if:
15823 case OMPC_final:
15824 case OMPC_num_threads:
15825 case OMPC_safelen:
15826 case OMPC_simdlen:
15827 case OMPC_sizes:
15828 case OMPC_allocator:
15829 case OMPC_collapse:
15830 case OMPC_schedule:
15831 case OMPC_private:
15832 case OMPC_firstprivate:
15833 case OMPC_lastprivate:
15834 case OMPC_shared:
15835 case OMPC_reduction:
15836 case OMPC_task_reduction:
15837 case OMPC_in_reduction:
15838 case OMPC_linear:
15839 case OMPC_aligned:
15840 case OMPC_copyin:
15841 case OMPC_copyprivate:
15842 case OMPC_ordered:
15843 case OMPC_nowait:
15844 case OMPC_untied:
15845 case OMPC_mergeable:
15846 case OMPC_threadprivate:
15847 case OMPC_allocate:
15848 case OMPC_flush:
15849 case OMPC_depobj:
15850 case OMPC_read:
15851 case OMPC_write:
15852 case OMPC_capture:
15853 case OMPC_compare:
15854 case OMPC_seq_cst:
15855 case OMPC_acq_rel:
15856 case OMPC_acquire:
15857 case OMPC_release:
15858 case OMPC_relaxed:
15859 case OMPC_depend:
15860 case OMPC_device:
15861 case OMPC_threads:
15862 case OMPC_simd:
15863 case OMPC_map:
15864 case OMPC_num_teams:
15865 case OMPC_thread_limit:
15866 case OMPC_priority:
15867 case OMPC_grainsize:
15868 case OMPC_nogroup:
15869 case OMPC_num_tasks:
15870 case OMPC_hint:
15871 case OMPC_dist_schedule:
15872 case OMPC_defaultmap:
15873 case OMPC_unknown:
15874 case OMPC_uniform:
15875 case OMPC_to:
15876 case OMPC_from:
15877 case OMPC_use_device_ptr:
15878 case OMPC_use_device_addr:
15879 case OMPC_is_device_ptr:
15880 case OMPC_has_device_addr:
15881 case OMPC_unified_address:
15882 case OMPC_unified_shared_memory:
15883 case OMPC_reverse_offload:
15884 case OMPC_dynamic_allocators:
15885 case OMPC_device_type:
15886 case OMPC_match:
15887 case OMPC_nontemporal:
15888 case OMPC_destroy:
15889 case OMPC_novariants:
15890 case OMPC_nocontext:
15891 case OMPC_detach:
15892 case OMPC_inclusive:
15893 case OMPC_exclusive:
15894 case OMPC_uses_allocators:
15895 case OMPC_affinity:
15896 case OMPC_when:
15897 case OMPC_message:
15898 default:
15899 llvm_unreachable("Clause is not allowed.");
15900 }
15901 return Res;
15902}
15903
15904static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
15905 unsigned Last,
15906 ArrayRef<unsigned> Exclude = {}) {
15907 SmallString<256> Buffer;
15908 llvm::raw_svector_ostream Out(Buffer);
15909 unsigned Skipped = Exclude.size();
15910 for (unsigned I = First; I < Last; ++I) {
15911 if (llvm::is_contained(Exclude, I)) {
15912 --Skipped;
15913 continue;
15914 }
15915 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15916 if (I + Skipped + 2 == Last)
15917 Out << " or ";
15918 else if (I + Skipped + 1 != Last)
15919 Out << ", ";
15920 }
15921 return std::string(Out.str());
15922}
15923
15925 SourceLocation KindKwLoc,
15926 SourceLocation StartLoc,
15927 SourceLocation LParenLoc,
15928 SourceLocation EndLoc) {
15929 if (Kind == OMP_DEFAULT_unknown) {
15930 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15931 << getListOfPossibleValues(OMPC_default, /*First=*/0,
15932 /*Last=*/unsigned(OMP_DEFAULT_unknown))
15933 << getOpenMPClauseName(OMPC_default);
15934 return nullptr;
15935 }
15936
15937 switch (Kind) {
15938 case OMP_DEFAULT_none:
15939 DSAStack->setDefaultDSANone(KindKwLoc);
15940 break;
15941 case OMP_DEFAULT_shared:
15942 DSAStack->setDefaultDSAShared(KindKwLoc);
15943 break;
15944 case OMP_DEFAULT_firstprivate:
15945 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15946 break;
15947 case OMP_DEFAULT_private:
15948 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15949 break;
15950 default:
15951 llvm_unreachable("DSA unexpected in OpenMP default clause");
15952 }
15953
15954 return new (getASTContext())
15955 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15956}
15957
15959 SourceLocation KindKwLoc,
15960 SourceLocation StartLoc,
15961 SourceLocation LParenLoc,
15962 SourceLocation EndLoc) {
15963 if (Kind == OMP_PROC_BIND_unknown) {
15964 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15965 << getListOfPossibleValues(OMPC_proc_bind,
15966 /*First=*/unsigned(OMP_PROC_BIND_master),
15967 /*Last=*/
15968 unsigned(getLangOpts().OpenMP > 50
15969 ? OMP_PROC_BIND_primary
15970 : OMP_PROC_BIND_spread) +
15971 1)
15972 << getOpenMPClauseName(OMPC_proc_bind);
15973 return nullptr;
15974 }
15975 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
15976 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15977 << getListOfPossibleValues(OMPC_proc_bind,
15978 /*First=*/unsigned(OMP_PROC_BIND_master),
15979 /*Last=*/
15980 unsigned(OMP_PROC_BIND_spread) + 1)
15981 << getOpenMPClauseName(OMPC_proc_bind);
15982 return new (getASTContext())
15983 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15984}
15985
15988 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15990 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15992 OMPC_atomic_default_mem_order, /*First=*/0,
15994 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15995 return nullptr;
15996 }
15998 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15999}
16000
16002 SourceLocation KindKwLoc,
16003 SourceLocation StartLoc,
16004 SourceLocation LParenLoc,
16005 SourceLocation EndLoc) {
16006 if (Kind == OMPC_AT_unknown) {
16007 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16008 << getListOfPossibleValues(OMPC_at, /*First=*/0,
16009 /*Last=*/OMPC_AT_unknown)
16010 << getOpenMPClauseName(OMPC_at);
16011 return nullptr;
16012 }
16013 return new (getASTContext())
16014 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16015}
16016
16018 SourceLocation KindKwLoc,
16019 SourceLocation StartLoc,
16020 SourceLocation LParenLoc,
16021 SourceLocation EndLoc) {
16022 if (Kind == OMPC_SEVERITY_unknown) {
16023 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16024 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16025 /*Last=*/OMPC_SEVERITY_unknown)
16026 << getOpenMPClauseName(OMPC_severity);
16027 return nullptr;
16028 }
16029 return new (getASTContext())
16030 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16031}
16032
16034 SourceLocation StartLoc,
16035 SourceLocation LParenLoc,
16036 SourceLocation EndLoc) {
16037 assert(ME && "NULL expr in Message clause");
16038 if (!isa<StringLiteral>(ME)) {
16039 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16040 << getOpenMPClauseName(OMPC_message);
16041 return nullptr;
16042 }
16043 return new (getASTContext())
16044 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16045}
16046
16049 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16050 SourceLocation KindLoc, SourceLocation EndLoc) {
16051 if (Kind != OMPC_ORDER_concurrent ||
16052 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16053 // Kind should be concurrent,
16054 // Modifiers introduced in OpenMP 5.1
16055 static_assert(OMPC_ORDER_unknown > 0,
16056 "OMPC_ORDER_unknown not greater than 0");
16057
16058 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16059 << getListOfPossibleValues(OMPC_order,
16060 /*First=*/0,
16061 /*Last=*/OMPC_ORDER_unknown)
16062 << getOpenMPClauseName(OMPC_order);
16063 return nullptr;
16064 }
16065 if (getLangOpts().OpenMP >= 51) {
16066 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
16067 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16068 << getListOfPossibleValues(OMPC_order,
16069 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16070 /*Last=*/OMPC_ORDER_MODIFIER_last)
16071 << getOpenMPClauseName(OMPC_order);
16072 } else {
16073 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16074 if (DSAStack->getCurScope()) {
16075 // mark the current scope with 'order' flag
16076 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16077 DSAStack->getCurScope()->setFlags(existingFlags |
16079 }
16080 }
16081 }
16082 return new (getASTContext()) OMPOrderClause(
16083 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16084}
16085
16087 SourceLocation KindKwLoc,
16088 SourceLocation StartLoc,
16089 SourceLocation LParenLoc,
16090 SourceLocation EndLoc) {
16091 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16092 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16093 SmallVector<unsigned> Except = {
16094 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16095 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16096 if (getLangOpts().OpenMP < 51)
16097 Except.push_back(OMPC_DEPEND_inoutset);
16098 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16099 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16100 /*Last=*/OMPC_DEPEND_unknown, Except)
16101 << getOpenMPClauseName(OMPC_update);
16102 return nullptr;
16103 }
16104 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
16105 KindKwLoc, Kind, EndLoc);
16106}
16107
16109 SourceLocation StartLoc,
16110 SourceLocation LParenLoc,
16111 SourceLocation EndLoc) {
16112 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16113
16114 for (Expr *&SizeExpr : SanitizedSizeExprs) {
16115 // Skip if already sanitized, e.g. during a partial template instantiation.
16116 if (!SizeExpr)
16117 continue;
16118
16119 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
16120 /*StrictlyPositive=*/true);
16121
16122 // isNonNegativeIntegerValue returns true for non-integral types (but still
16123 // emits error diagnostic), so check for the expected type explicitly.
16124 QualType SizeTy = SizeExpr->getType();
16125 if (!SizeTy->isIntegerType())
16126 IsValid = false;
16127
16128 // Handling in templates is tricky. There are four possibilities to
16129 // consider:
16130 //
16131 // 1a. The expression is valid and we are in a instantiated template or not
16132 // in a template:
16133 // Pass valid expression to be further analysed later in Sema.
16134 // 1b. The expression is valid and we are in a template (including partial
16135 // instantiation):
16136 // isNonNegativeIntegerValue skipped any checks so there is no
16137 // guarantee it will be correct after instantiation.
16138 // ActOnOpenMPSizesClause will be called again at instantiation when
16139 // it is not in a dependent context anymore. This may cause warnings
16140 // to be emitted multiple times.
16141 // 2a. The expression is invalid and we are in an instantiated template or
16142 // not in a template:
16143 // Invalidate the expression with a clearly wrong value (nullptr) so
16144 // later in Sema we do not have to do the same validity analysis again
16145 // or crash from unexpected data. Error diagnostics have already been
16146 // emitted.
16147 // 2b. The expression is invalid and we are in a template (including partial
16148 // instantiation):
16149 // Pass the invalid expression as-is, template instantiation may
16150 // replace unexpected types/values with valid ones. The directives
16151 // with this clause must not try to use these expressions in dependent
16152 // contexts, but delay analysis until full instantiation.
16153 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16154 SizeExpr = nullptr;
16155 }
16156
16157 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16158 SanitizedSizeExprs);
16159}
16160
16162 SourceLocation StartLoc,
16163 SourceLocation LParenLoc,
16164 SourceLocation EndLoc) {
16165 size_t NumLoops = PermExprs.size();
16166 SmallVector<Expr *> SanitizedPermExprs;
16167 llvm::append_range(SanitizedPermExprs, PermExprs);
16168
16169 for (Expr *&PermExpr : SanitizedPermExprs) {
16170 // Skip if template-dependent or already sanitized, e.g. during a partial
16171 // template instantiation.
16172 if (!PermExpr || PermExpr->isInstantiationDependent())
16173 continue;
16174
16175 llvm::APSInt PermVal;
16177 PermExpr, &PermVal, Sema::AllowFold);
16178 bool IsValid = PermEvalExpr.isUsable();
16179 if (IsValid)
16180 PermExpr = PermEvalExpr.get();
16181
16182 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16183 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16184 PermEvalExpr.get()->getEndLoc());
16185 Diag(PermEvalExpr.get()->getExprLoc(),
16186 diag::err_omp_interchange_permutation_value_range)
16187 << NumLoops << ExprRange;
16188 IsValid = false;
16189 }
16190
16191 if (!PermExpr->isInstantiationDependent() && !IsValid)
16192 PermExpr = nullptr;
16193 }
16194
16195 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
16196 EndLoc, SanitizedPermExprs);
16197}
16198
16200 SourceLocation EndLoc) {
16201 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16202}
16203
16205 SourceLocation StartLoc,
16206 SourceLocation LParenLoc,
16207 SourceLocation EndLoc) {
16208 if (FactorExpr) {
16209 // If an argument is specified, it must be a constant (or an unevaluated
16210 // template expression).
16212 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16213 if (FactorResult.isInvalid())
16214 return nullptr;
16215 FactorExpr = FactorResult.get();
16216 }
16217
16218 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16219 FactorExpr);
16220}
16221
16223 SourceLocation LParenLoc,
16224 SourceLocation EndLoc) {
16225 ExprResult AlignVal;
16226 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16227 if (AlignVal.isInvalid())
16228 return nullptr;
16229 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16230 LParenLoc, EndLoc);
16231}
16232
16235 SourceLocation StartLoc, SourceLocation LParenLoc,
16236 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16237 SourceLocation EndLoc) {
16238 OMPClause *Res = nullptr;
16239 switch (Kind) {
16240 case OMPC_schedule:
16241 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16242 assert(Argument.size() == NumberOfElements &&
16243 ArgumentLoc.size() == NumberOfElements);
16245 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16246 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16247 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16248 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16249 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16250 break;
16251 case OMPC_if:
16252 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16253 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16254 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16255 DelimLoc, EndLoc);
16256 break;
16257 case OMPC_dist_schedule:
16259 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16260 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16261 break;
16262 case OMPC_defaultmap:
16263 enum { Modifier, DefaultmapKind };
16265 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16266 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16267 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16268 EndLoc);
16269 break;
16270 case OMPC_order:
16271 enum { OrderModifier, OrderKind };
16273 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16274 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16275 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16276 break;
16277 case OMPC_device:
16278 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16280 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16281 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16282 break;
16283 case OMPC_grainsize:
16284 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16285 "Modifier for grainsize clause and its location are expected.");
16287 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16288 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16289 break;
16290 case OMPC_num_tasks:
16291 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16292 "Modifier for num_tasks clause and its location are expected.");
16294 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16295 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16296 break;
16297 case OMPC_final:
16298 case OMPC_num_threads:
16299 case OMPC_safelen:
16300 case OMPC_simdlen:
16301 case OMPC_sizes:
16302 case OMPC_allocator:
16303 case OMPC_collapse:
16304 case OMPC_default:
16305 case OMPC_proc_bind:
16306 case OMPC_private:
16307 case OMPC_firstprivate:
16308 case OMPC_lastprivate:
16309 case OMPC_shared:
16310 case OMPC_reduction:
16311 case OMPC_task_reduction:
16312 case OMPC_in_reduction:
16313 case OMPC_linear:
16314 case OMPC_aligned:
16315 case OMPC_copyin:
16316 case OMPC_copyprivate:
16317 case OMPC_ordered:
16318 case OMPC_nowait:
16319 case OMPC_untied:
16320 case OMPC_mergeable:
16321 case OMPC_threadprivate:
16322 case OMPC_allocate:
16323 case OMPC_flush:
16324 case OMPC_depobj:
16325 case OMPC_read:
16326 case OMPC_write:
16327 case OMPC_update:
16328 case OMPC_capture:
16329 case OMPC_compare:
16330 case OMPC_seq_cst:
16331 case OMPC_acq_rel:
16332 case OMPC_acquire:
16333 case OMPC_release:
16334 case OMPC_relaxed:
16335 case OMPC_depend:
16336 case OMPC_threads:
16337 case OMPC_simd:
16338 case OMPC_map:
16339 case OMPC_num_teams:
16340 case OMPC_thread_limit:
16341 case OMPC_priority:
16342 case OMPC_nogroup:
16343 case OMPC_hint:
16344 case OMPC_unknown:
16345 case OMPC_uniform:
16346 case OMPC_to:
16347 case OMPC_from:
16348 case OMPC_use_device_ptr:
16349 case OMPC_use_device_addr:
16350 case OMPC_is_device_ptr:
16351 case OMPC_has_device_addr:
16352 case OMPC_unified_address:
16353 case OMPC_unified_shared_memory:
16354 case OMPC_reverse_offload:
16355 case OMPC_dynamic_allocators:
16356 case OMPC_atomic_default_mem_order:
16357 case OMPC_device_type:
16358 case OMPC_match:
16359 case OMPC_nontemporal:
16360 case OMPC_at:
16361 case OMPC_severity:
16362 case OMPC_message:
16363 case OMPC_destroy:
16364 case OMPC_novariants:
16365 case OMPC_nocontext:
16366 case OMPC_detach:
16367 case OMPC_inclusive:
16368 case OMPC_exclusive:
16369 case OMPC_uses_allocators:
16370 case OMPC_affinity:
16371 case OMPC_when:
16372 case OMPC_bind:
16373 default:
16374 llvm_unreachable("Clause is not allowed.");
16375 }
16376 return Res;
16377}
16378
16381 SourceLocation M1Loc, SourceLocation M2Loc) {
16382 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16383 SmallVector<unsigned, 2> Excluded;
16385 Excluded.push_back(M2);
16386 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16387 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16388 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16389 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16390 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16391 << getListOfPossibleValues(OMPC_schedule,
16392 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16394 Excluded)
16395 << getOpenMPClauseName(OMPC_schedule);
16396 return true;
16397 }
16398 return false;
16399}
16400
16403 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16404 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16405 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16406 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16407 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16408 return nullptr;
16409 // OpenMP, 2.7.1, Loop Construct, Restrictions
16410 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16411 // but not both.
16412 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16413 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16414 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16415 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16416 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16417 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16418 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16419 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16420 return nullptr;
16421 }
16422 if (Kind == OMPC_SCHEDULE_unknown) {
16423 std::string Values;
16424 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16425 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16426 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16428 Exclude);
16429 } else {
16430 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16431 /*Last=*/OMPC_SCHEDULE_unknown);
16432 }
16433 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16434 << Values << getOpenMPClauseName(OMPC_schedule);
16435 return nullptr;
16436 }
16437 // OpenMP, 2.7.1, Loop Construct, Restrictions
16438 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16439 // schedule(guided).
16440 // OpenMP 5.0 does not have this restriction.
16441 if (getLangOpts().OpenMP < 50 &&
16442 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16443 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16444 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16445 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16446 diag::err_omp_schedule_nonmonotonic_static);
16447 return nullptr;
16448 }
16449 Expr *ValExpr = ChunkSize;
16450 Stmt *HelperValStmt = nullptr;
16451 if (ChunkSize) {
16452 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16453 !ChunkSize->isInstantiationDependent() &&
16454 !ChunkSize->containsUnexpandedParameterPack()) {
16455 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16456 ExprResult Val =
16457 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16458 if (Val.isInvalid())
16459 return nullptr;
16460
16461 ValExpr = Val.get();
16462
16463 // OpenMP [2.7.1, Restrictions]
16464 // chunk_size must be a loop invariant integer expression with a positive
16465 // value.
16466 if (std::optional<llvm::APSInt> Result =
16468 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16469 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16470 << "schedule" << 1 << ChunkSize->getSourceRange();
16471 return nullptr;
16472 }
16474 DSAStack->getCurrentDirective(), OMPC_schedule,
16475 getLangOpts().OpenMP) != OMPD_unknown &&
16477 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16478 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16479 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16480 HelperValStmt = buildPreInits(getASTContext(), Captures);
16481 }
16482 }
16483 }
16484
16485 return new (getASTContext())
16486 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16487 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16488}
16489
16491 SourceLocation StartLoc,
16492 SourceLocation EndLoc) {
16493 OMPClause *Res = nullptr;
16494 switch (Kind) {
16495 case OMPC_ordered:
16496 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16497 break;
16498 case OMPC_nowait:
16499 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16500 break;
16501 case OMPC_untied:
16502 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16503 break;
16504 case OMPC_mergeable:
16505 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16506 break;
16507 case OMPC_read:
16508 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16509 break;
16510 case OMPC_write:
16511 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16512 break;
16513 case OMPC_update:
16514 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16515 break;
16516 case OMPC_capture:
16517 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16518 break;
16519 case OMPC_compare:
16520 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16521 break;
16522 case OMPC_fail:
16523 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16524 break;
16525 case OMPC_seq_cst:
16526 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16527 break;
16528 case OMPC_acq_rel:
16529 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16530 break;
16531 case OMPC_acquire:
16532 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16533 break;
16534 case OMPC_release:
16535 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16536 break;
16537 case OMPC_relaxed:
16538 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16539 break;
16540 case OMPC_weak:
16541 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16542 break;
16543 case OMPC_threads:
16544 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16545 break;
16546 case OMPC_simd:
16547 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16548 break;
16549 case OMPC_nogroup:
16550 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16551 break;
16552 case OMPC_unified_address:
16553 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16554 break;
16555 case OMPC_unified_shared_memory:
16556 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16557 break;
16558 case OMPC_reverse_offload:
16559 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16560 break;
16561 case OMPC_dynamic_allocators:
16562 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16563 break;
16564 case OMPC_destroy:
16565 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16566 /*LParenLoc=*/SourceLocation(),
16567 /*VarLoc=*/SourceLocation(), EndLoc);
16568 break;
16569 case OMPC_full:
16570 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16571 break;
16572 case OMPC_partial:
16573 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16574 break;
16575 case OMPC_ompx_bare:
16576 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16577 break;
16578 case OMPC_if:
16579 case OMPC_final:
16580 case OMPC_num_threads:
16581 case OMPC_safelen:
16582 case OMPC_simdlen:
16583 case OMPC_sizes:
16584 case OMPC_allocator:
16585 case OMPC_collapse:
16586 case OMPC_schedule:
16587 case OMPC_private:
16588 case OMPC_firstprivate:
16589 case OMPC_lastprivate:
16590 case OMPC_shared:
16591 case OMPC_reduction:
16592 case OMPC_task_reduction:
16593 case OMPC_in_reduction:
16594 case OMPC_linear:
16595 case OMPC_aligned:
16596 case OMPC_copyin:
16597 case OMPC_copyprivate:
16598 case OMPC_default:
16599 case OMPC_proc_bind:
16600 case OMPC_threadprivate:
16601 case OMPC_allocate:
16602 case OMPC_flush:
16603 case OMPC_depobj:
16604 case OMPC_depend:
16605 case OMPC_device:
16606 case OMPC_map:
16607 case OMPC_num_teams:
16608 case OMPC_thread_limit:
16609 case OMPC_priority:
16610 case OMPC_grainsize:
16611 case OMPC_num_tasks:
16612 case OMPC_hint:
16613 case OMPC_dist_schedule:
16614 case OMPC_defaultmap:
16615 case OMPC_unknown:
16616 case OMPC_uniform:
16617 case OMPC_to:
16618 case OMPC_from:
16619 case OMPC_use_device_ptr:
16620 case OMPC_use_device_addr:
16621 case OMPC_is_device_ptr:
16622 case OMPC_has_device_addr:
16623 case OMPC_atomic_default_mem_order:
16624 case OMPC_device_type:
16625 case OMPC_match:
16626 case OMPC_nontemporal:
16627 case OMPC_order:
16628 case OMPC_at:
16629 case OMPC_severity:
16630 case OMPC_message:
16631 case OMPC_novariants:
16632 case OMPC_nocontext:
16633 case OMPC_detach:
16634 case OMPC_inclusive:
16635 case OMPC_exclusive:
16636 case OMPC_uses_allocators:
16637 case OMPC_affinity:
16638 case OMPC_when:
16639 case OMPC_ompx_dyn_cgroup_mem:
16640 default:
16641 llvm_unreachable("Clause is not allowed.");
16642 }
16643 return Res;
16644}
16645
16647 SourceLocation EndLoc) {
16648 DSAStack->setNowaitRegion();
16649 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
16650}
16651
16653 SourceLocation EndLoc) {
16654 DSAStack->setUntiedRegion();
16655 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
16656}
16657
16659 SourceLocation EndLoc) {
16660 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
16661}
16662
16664 SourceLocation EndLoc) {
16665 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
16666}
16667
16669 SourceLocation EndLoc) {
16670 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
16671}
16672
16674 SourceLocation EndLoc) {
16675 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
16676}
16677
16679 SourceLocation EndLoc) {
16680 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
16681}
16682
16684 SourceLocation EndLoc) {
16685 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
16686}
16687
16689 SourceLocation EndLoc) {
16690 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
16691}
16692
16694 SourceLocation KindLoc,
16695 SourceLocation StartLoc,
16696 SourceLocation LParenLoc,
16697 SourceLocation EndLoc) {
16698
16700 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16701 return nullptr;
16702 }
16703 return new (getASTContext())
16704 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
16705}
16706
16708 SourceLocation EndLoc) {
16709 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
16710}
16711
16713 SourceLocation EndLoc) {
16714 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
16715}
16716
16718 SourceLocation EndLoc) {
16719 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
16720}
16721
16723 SourceLocation EndLoc) {
16724 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
16725}
16726
16728 SourceLocation EndLoc) {
16729 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
16730}
16731
16733 SourceLocation EndLoc) {
16734 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
16735}
16736
16738 SourceLocation EndLoc) {
16739 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
16740}
16741
16743 SourceLocation EndLoc) {
16744 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
16745}
16746
16748 SourceLocation EndLoc) {
16749 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
16750}
16751
16753 SourceLocation EndLoc) {
16754 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
16755}
16756
16757OMPClause *
16759 SourceLocation EndLoc) {
16760 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16761}
16762
16764 SourceLocation EndLoc) {
16765 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
16766}
16767
16768OMPClause *
16770 SourceLocation EndLoc) {
16771 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
16772}
16773
16776 SourceLocation StartLoc,
16777 SourceLocation EndLoc) {
16778
16779 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16780 // At least one action-clause must appear on a directive.
16781 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16782 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
16783 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16784 << Expected << getOpenMPDirectiveName(OMPD_interop);
16785 return StmtError();
16786 }
16787
16788 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16789 // A depend clause can only appear on the directive if a targetsync
16790 // interop-type is present or the interop-var was initialized with
16791 // the targetsync interop-type.
16792
16793 // If there is any 'init' clause diagnose if there is no 'init' clause with
16794 // interop-type of 'targetsync'. Cases involving other directives cannot be
16795 // diagnosed.
16796 const OMPDependClause *DependClause = nullptr;
16797 bool HasInitClause = false;
16798 bool IsTargetSync = false;
16799 for (const OMPClause *C : Clauses) {
16800 if (IsTargetSync)
16801 break;
16802 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
16803 HasInitClause = true;
16804 if (InitClause->getIsTargetSync())
16805 IsTargetSync = true;
16806 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
16807 DependClause = DC;
16808 }
16809 }
16810 if (DependClause && HasInitClause && !IsTargetSync) {
16811 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16812 return StmtError();
16813 }
16814
16815 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16816 // Each interop-var may be specified for at most one action-clause of each
16817 // interop construct.
16819 for (OMPClause *C : Clauses) {
16820 OpenMPClauseKind ClauseKind = C->getClauseKind();
16821 std::pair<ValueDecl *, bool> DeclResult;
16822 SourceLocation ELoc;
16823 SourceRange ERange;
16824
16825 if (ClauseKind == OMPC_init) {
16826 auto *E = cast<OMPInitClause>(C)->getInteropVar();
16827 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16828 } else if (ClauseKind == OMPC_use) {
16829 auto *E = cast<OMPUseClause>(C)->getInteropVar();
16830 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16831 } else if (ClauseKind == OMPC_destroy) {
16832 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
16833 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16834 }
16835
16836 if (DeclResult.first) {
16837 if (!InteropVars.insert(DeclResult.first).second) {
16838 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16839 << DeclResult.first;
16840 return StmtError();
16841 }
16842 }
16843 }
16844
16845 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
16846 Clauses);
16847}
16848
16849static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
16850 SourceLocation VarLoc,
16851 OpenMPClauseKind Kind) {
16852 SourceLocation ELoc;
16853 SourceRange ERange;
16854 Expr *RefExpr = InteropVarExpr;
16855 auto Res =
16856 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
16857 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
16858
16859 if (Res.second) {
16860 // It will be analyzed later.
16861 return true;
16862 }
16863
16864 if (!Res.first)
16865 return false;
16866
16867 // Interop variable should be of type omp_interop_t.
16868 bool HasError = false;
16869 QualType InteropType;
16870 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
16871 VarLoc, Sema::LookupOrdinaryName);
16872 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
16873 NamedDecl *ND = Result.getFoundDecl();
16874 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
16875 InteropType = QualType(TD->getTypeForDecl(), 0);
16876 } else {
16877 HasError = true;
16878 }
16879 } else {
16880 HasError = true;
16881 }
16882
16883 if (HasError) {
16884 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
16885 << "omp_interop_t";
16886 return false;
16887 }
16888
16889 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
16890 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
16891 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16892 return false;
16893 }
16894
16895 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16896 // The interop-var passed to init or destroy must be non-const.
16897 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16898 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
16899 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
16900 << /*non-const*/ 1;
16901 return false;
16902 }
16903 return true;
16904}
16905
16907 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
16908 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
16909
16910 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
16911 return nullptr;
16912
16913 // Check prefer_type values. These foreign-runtime-id values are either
16914 // string literals or constant integral expressions.
16915 for (const Expr *E : InteropInfo.PreferTypes) {
16916 if (E->isValueDependent() || E->isTypeDependent() ||
16918 continue;
16920 continue;
16921 if (isa<StringLiteral>(E))
16922 continue;
16923 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
16924 return nullptr;
16925 }
16926
16927 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
16928 StartLoc, LParenLoc, VarLoc, EndLoc);
16929}
16930
16932 SourceLocation StartLoc,
16933 SourceLocation LParenLoc,
16934 SourceLocation VarLoc,
16935 SourceLocation EndLoc) {
16936
16937 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
16938 return nullptr;
16939
16940 return new (getASTContext())
16941 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16942}
16943
16945 SourceLocation StartLoc,
16946 SourceLocation LParenLoc,
16947 SourceLocation VarLoc,
16948 SourceLocation EndLoc) {
16949 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
16950 DSAStack->getCurrentDirective() == OMPD_depobj) {
16951 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16952 << getOpenMPClauseName(OMPC_destroy)
16953 << getOpenMPDirectiveName(OMPD_depobj);
16954 return nullptr;
16955 }
16956 if (InteropVar &&
16957 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
16958 return nullptr;
16959
16960 return new (getASTContext())
16961 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16962}
16963
16965 SourceLocation StartLoc,
16966 SourceLocation LParenLoc,
16967 SourceLocation EndLoc) {
16968 Expr *ValExpr = Condition;
16969 Stmt *HelperValStmt = nullptr;
16970 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16971 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16972 !Condition->isInstantiationDependent() &&
16973 !Condition->containsUnexpandedParameterPack()) {
16975 if (Val.isInvalid())
16976 return nullptr;
16977
16978 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16979
16980 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16981 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
16982 getLangOpts().OpenMP);
16983 if (CaptureRegion != OMPD_unknown &&
16985 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16986 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16987 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16988 HelperValStmt = buildPreInits(getASTContext(), Captures);
16989 }
16990 }
16991
16992 return new (getASTContext()) OMPNovariantsClause(
16993 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16994}
16995
16997 SourceLocation StartLoc,
16998 SourceLocation LParenLoc,
16999 SourceLocation EndLoc) {
17000 Expr *ValExpr = Condition;
17001 Stmt *HelperValStmt = nullptr;
17002 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17003 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17004 !Condition->isInstantiationDependent() &&
17005 !Condition->containsUnexpandedParameterPack()) {
17007 if (Val.isInvalid())
17008 return nullptr;
17009
17010 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17011
17012 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17013 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
17014 getLangOpts().OpenMP);
17015 if (CaptureRegion != OMPD_unknown &&
17017 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17018 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17019 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17020 HelperValStmt = buildPreInits(getASTContext(), Captures);
17021 }
17022 }
17023
17024 return new (getASTContext()) OMPNocontextClause(
17025 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17026}
17027
17029 SourceLocation StartLoc,
17030 SourceLocation LParenLoc,
17031 SourceLocation EndLoc) {
17032 Expr *ValExpr = ThreadID;
17033 Stmt *HelperValStmt = nullptr;
17034
17035 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17036 OpenMPDirectiveKind CaptureRegion =
17037 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
17038 if (CaptureRegion != OMPD_unknown &&
17040 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17041 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17042 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17043 HelperValStmt = buildPreInits(getASTContext(), Captures);
17044 }
17045
17046 return new (getASTContext()) OMPFilterClause(
17047 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17048}
17049
17051 ArrayRef<Expr *> VarList,
17052 const OMPVarListLocTy &Locs,
17054 SourceLocation StartLoc = Locs.StartLoc;
17055 SourceLocation LParenLoc = Locs.LParenLoc;
17056 SourceLocation EndLoc = Locs.EndLoc;
17057 OMPClause *Res = nullptr;
17058 int ExtraModifier = Data.ExtraModifier;
17059 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17060 SourceLocation ColonLoc = Data.ColonLoc;
17061 switch (Kind) {
17062 case OMPC_private:
17063 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17064 break;
17065 case OMPC_firstprivate:
17066 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17067 break;
17068 case OMPC_lastprivate:
17069 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17070 "Unexpected lastprivate modifier.");
17072 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17073 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17074 break;
17075 case OMPC_shared:
17076 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17077 break;
17078 case OMPC_reduction:
17079 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17080 "Unexpected lastprivate modifier.");
17082 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
17083 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17084 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17085 break;
17086 case OMPC_task_reduction:
17088 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17089 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17090 break;
17091 case OMPC_in_reduction:
17093 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17094 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17095 break;
17096 case OMPC_linear:
17097 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17098 "Unexpected linear modifier.");
17100 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17101 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17102 ColonLoc, Data.StepModifierLoc, EndLoc);
17103 break;
17104 case OMPC_aligned:
17105 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17106 LParenLoc, ColonLoc, EndLoc);
17107 break;
17108 case OMPC_copyin:
17109 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17110 break;
17111 case OMPC_copyprivate:
17112 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17113 break;
17114 case OMPC_flush:
17115 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17116 break;
17117 case OMPC_depend:
17118 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17119 "Unexpected depend modifier.");
17121 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17122 ColonLoc, Data.OmpAllMemoryLoc},
17123 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17124 break;
17125 case OMPC_map:
17126 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17127 "Unexpected map modifier.");
17129 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17130 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17131 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17132 ExtraModifierLoc, ColonLoc, VarList, Locs);
17133 break;
17134 case OMPC_to:
17135 Res =
17136 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17137 Data.ReductionOrMapperIdScopeSpec,
17138 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17139 break;
17140 case OMPC_from:
17141 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17142 Data.ReductionOrMapperIdScopeSpec,
17143 Data.ReductionOrMapperId, ColonLoc, VarList,
17144 Locs);
17145 break;
17146 case OMPC_use_device_ptr:
17147 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17148 break;
17149 case OMPC_use_device_addr:
17150 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17151 break;
17152 case OMPC_is_device_ptr:
17153 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17154 break;
17155 case OMPC_has_device_addr:
17156 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17157 break;
17158 case OMPC_allocate: {
17161 SourceLocation Modifier1Loc, Modifier2Loc;
17162 if (!Data.AllocClauseModifiers.empty()) {
17163 assert(Data.AllocClauseModifiers.size() <= 2 &&
17164 "More allocate modifiers than expected");
17165 Modifier1 = Data.AllocClauseModifiers[0];
17166 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
17167 if (Data.AllocClauseModifiers.size() == 2) {
17168 Modifier2 = Data.AllocClauseModifiers[1];
17169 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
17170 }
17171 }
17173 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
17174 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
17175 EndLoc);
17176 break;
17177 }
17178 case OMPC_nontemporal:
17179 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17180 break;
17181 case OMPC_inclusive:
17182 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17183 break;
17184 case OMPC_exclusive:
17185 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17186 break;
17187 case OMPC_affinity:
17188 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17189 Data.DepModOrTailExpr, VarList);
17190 break;
17191 case OMPC_doacross:
17193 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17194 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17195 break;
17196 case OMPC_num_teams:
17197 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17198 break;
17199 case OMPC_thread_limit:
17200 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17201 break;
17202 case OMPC_if:
17203 case OMPC_depobj:
17204 case OMPC_final:
17205 case OMPC_num_threads:
17206 case OMPC_safelen:
17207 case OMPC_simdlen:
17208 case OMPC_sizes:
17209 case OMPC_allocator:
17210 case OMPC_collapse:
17211 case OMPC_default:
17212 case OMPC_proc_bind:
17213 case OMPC_schedule:
17214 case OMPC_ordered:
17215 case OMPC_nowait:
17216 case OMPC_untied:
17217 case OMPC_mergeable:
17218 case OMPC_threadprivate:
17219 case OMPC_read:
17220 case OMPC_write:
17221 case OMPC_update:
17222 case OMPC_capture:
17223 case OMPC_compare:
17224 case OMPC_seq_cst:
17225 case OMPC_acq_rel:
17226 case OMPC_acquire:
17227 case OMPC_release:
17228 case OMPC_relaxed:
17229 case OMPC_device:
17230 case OMPC_threads:
17231 case OMPC_simd:
17232 case OMPC_priority:
17233 case OMPC_grainsize:
17234 case OMPC_nogroup:
17235 case OMPC_num_tasks:
17236 case OMPC_hint:
17237 case OMPC_dist_schedule:
17238 case OMPC_defaultmap:
17239 case OMPC_unknown:
17240 case OMPC_uniform:
17241 case OMPC_unified_address:
17242 case OMPC_unified_shared_memory:
17243 case OMPC_reverse_offload:
17244 case OMPC_dynamic_allocators:
17245 case OMPC_atomic_default_mem_order:
17246 case OMPC_device_type:
17247 case OMPC_match:
17248 case OMPC_order:
17249 case OMPC_at:
17250 case OMPC_severity:
17251 case OMPC_message:
17252 case OMPC_destroy:
17253 case OMPC_novariants:
17254 case OMPC_nocontext:
17255 case OMPC_detach:
17256 case OMPC_uses_allocators:
17257 case OMPC_when:
17258 case OMPC_bind:
17259 default:
17260 llvm_unreachable("Clause is not allowed.");
17261 }
17262 return Res;
17263}
17264
17266 ExprObjectKind OK,
17269 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17270 if (!Res.isUsable())
17271 return ExprError();
17272 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17273 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17274 if (!Res.isUsable())
17275 return ExprError();
17276 }
17277 if (VK != VK_LValue && Res.get()->isGLValue()) {
17278 Res = SemaRef.DefaultLvalueConversion(Res.get());
17279 if (!Res.isUsable())
17280 return ExprError();
17281 }
17282 return Res;
17283}
17284
17286 SourceLocation StartLoc,
17287 SourceLocation LParenLoc,
17288 SourceLocation EndLoc) {
17290 SmallVector<Expr *, 8> PrivateCopies;
17291 bool IsImplicitClause =
17292 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17293 for (Expr *RefExpr : VarList) {
17294 assert(RefExpr && "NULL expr in OpenMP private clause.");
17295 SourceLocation ELoc;
17296 SourceRange ERange;
17297 Expr *SimpleRefExpr = RefExpr;
17298 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17299 if (Res.second) {
17300 // It will be analyzed later.
17301 Vars.push_back(RefExpr);
17302 PrivateCopies.push_back(nullptr);
17303 }
17304 ValueDecl *D = Res.first;
17305 if (!D)
17306 continue;
17307
17308 QualType Type = D->getType();
17309 auto *VD = dyn_cast<VarDecl>(D);
17310
17311 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17312 // A variable that appears in a private clause must not have an incomplete
17313 // type or a reference type.
17315 diag::err_omp_private_incomplete_type))
17316 continue;
17317 Type = Type.getNonReferenceType();
17318
17319 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17320 // A variable that is privatized must not have a const-qualified type
17321 // unless it is of class type with a mutable member. This restriction does
17322 // not apply to the firstprivate clause.
17323 //
17324 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17325 // A variable that appears in a private clause must not have a
17326 // const-qualified type unless it is of class type with a mutable member.
17327 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17328 continue;
17329
17330 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17331 // in a Construct]
17332 // Variables with the predetermined data-sharing attributes may not be
17333 // listed in data-sharing attributes clauses, except for the cases
17334 // listed below. For these exceptions only, listing a predetermined
17335 // variable in a data-sharing attribute clause is allowed and overrides
17336 // the variable's predetermined data-sharing attributes.
17337 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17338 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17339 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17340 << getOpenMPClauseName(OMPC_private);
17342 continue;
17343 }
17344
17345 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17346 // Variably modified types are not supported for tasks.
17348 isOpenMPTaskingDirective(CurrDir)) {
17349 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17350 << getOpenMPClauseName(OMPC_private) << Type
17351 << getOpenMPDirectiveName(CurrDir);
17352 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17354 Diag(D->getLocation(),
17355 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17356 << D;
17357 continue;
17358 }
17359
17360 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17361 // A list item cannot appear in both a map clause and a data-sharing
17362 // attribute clause on the same construct
17363 //
17364 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17365 // A list item cannot appear in both a map clause and a data-sharing
17366 // attribute clause on the same construct unless the construct is a
17367 // combined construct.
17368 if ((getLangOpts().OpenMP <= 45 &&
17370 CurrDir == OMPD_target) {
17371 OpenMPClauseKind ConflictKind;
17372 if (DSAStack->checkMappableExprComponentListsForDecl(
17373 VD, /*CurrentRegionOnly=*/true,
17375 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17376 ConflictKind = WhereFoundClauseKind;
17377 return true;
17378 })) {
17379 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17380 << getOpenMPClauseName(OMPC_private)
17381 << getOpenMPClauseName(ConflictKind)
17382 << getOpenMPDirectiveName(CurrDir);
17384 continue;
17385 }
17386 }
17387
17388 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17389 // A variable of class type (or array thereof) that appears in a private
17390 // clause requires an accessible, unambiguous default constructor for the
17391 // class type.
17392 // Generate helper private variable and initialize it with the default
17393 // value. The address of the original variable is replaced by the address of
17394 // the new private variable in CodeGen. This new variable is not added to
17395 // IdResolver, so the code in the OpenMP region uses original variable for
17396 // proper diagnostics.
17397 Type = Type.getUnqualifiedType();
17398 VarDecl *VDPrivate =
17399 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17400 D->hasAttrs() ? &D->getAttrs() : nullptr,
17401 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17403 if (VDPrivate->isInvalidDecl())
17404 continue;
17405 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17406 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17407
17408 DeclRefExpr *Ref = nullptr;
17409 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17410 auto *FD = dyn_cast<FieldDecl>(D);
17411 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17412 if (VD)
17414 RefExpr->getExprLoc());
17415 else
17416 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17417 }
17418 if (!IsImplicitClause)
17419 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17420 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17421 ? RefExpr->IgnoreParens()
17422 : Ref);
17423 PrivateCopies.push_back(VDPrivateRefExpr);
17424 }
17425
17426 if (Vars.empty())
17427 return nullptr;
17428
17429 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17430 Vars, PrivateCopies);
17431}
17432
17434 SourceLocation StartLoc,
17435 SourceLocation LParenLoc,
17436 SourceLocation EndLoc) {
17438 SmallVector<Expr *, 8> PrivateCopies;
17440 SmallVector<Decl *, 4> ExprCaptures;
17441 bool IsImplicitClause =
17442 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17443 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17444
17445 for (Expr *RefExpr : VarList) {
17446 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17447 SourceLocation ELoc;
17448 SourceRange ERange;
17449 Expr *SimpleRefExpr = RefExpr;
17450 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17451 if (Res.second) {
17452 // It will be analyzed later.
17453 Vars.push_back(RefExpr);
17454 PrivateCopies.push_back(nullptr);
17455 Inits.push_back(nullptr);
17456 }
17457 ValueDecl *D = Res.first;
17458 if (!D)
17459 continue;
17460
17461 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17462 QualType Type = D->getType();
17463 auto *VD = dyn_cast<VarDecl>(D);
17464
17465 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17466 // A variable that appears in a private clause must not have an incomplete
17467 // type or a reference type.
17469 diag::err_omp_firstprivate_incomplete_type))
17470 continue;
17471 Type = Type.getNonReferenceType();
17472
17473 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17474 // A variable of class type (or array thereof) that appears in a private
17475 // clause requires an accessible, unambiguous copy constructor for the
17476 // class type.
17477 QualType ElemType =
17479
17480 // If an implicit firstprivate variable found it was checked already.
17481 DSAStackTy::DSAVarData TopDVar;
17482 if (!IsImplicitClause) {
17483 DSAStackTy::DSAVarData DVar =
17484 DSAStack->getTopDSA(D, /*FromParent=*/false);
17485 TopDVar = DVar;
17486 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17487 bool IsConstant = ElemType.isConstant(getASTContext());
17488 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17489 // A list item that specifies a given variable may not appear in more
17490 // than one clause on the same directive, except that a variable may be
17491 // specified in both firstprivate and lastprivate clauses.
17492 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17493 // A list item may appear in a firstprivate or lastprivate clause but not
17494 // both.
17495 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17496 (isOpenMPDistributeDirective(CurrDir) ||
17497 DVar.CKind != OMPC_lastprivate) &&
17498 DVar.RefExpr) {
17499 Diag(ELoc, diag::err_omp_wrong_dsa)
17500 << getOpenMPClauseName(DVar.CKind)
17501 << getOpenMPClauseName(OMPC_firstprivate);
17503 continue;
17504 }
17505
17506 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17507 // in a Construct]
17508 // Variables with the predetermined data-sharing attributes may not be
17509 // listed in data-sharing attributes clauses, except for the cases
17510 // listed below. For these exceptions only, listing a predetermined
17511 // variable in a data-sharing attribute clause is allowed and overrides
17512 // the variable's predetermined data-sharing attributes.
17513 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17514 // in a Construct, C/C++, p.2]
17515 // Variables with const-qualified type having no mutable member may be
17516 // listed in a firstprivate clause, even if they are static data members.
17517 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17518 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17519 Diag(ELoc, diag::err_omp_wrong_dsa)
17520 << getOpenMPClauseName(DVar.CKind)
17521 << getOpenMPClauseName(OMPC_firstprivate);
17523 continue;
17524 }
17525
17526 // OpenMP [2.9.3.4, Restrictions, p.2]
17527 // A list item that is private within a parallel region must not appear
17528 // in a firstprivate clause on a worksharing construct if any of the
17529 // worksharing regions arising from the worksharing construct ever bind
17530 // to any of the parallel regions arising from the parallel construct.
17531 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17532 // A list item that is private within a teams region must not appear in a
17533 // firstprivate clause on a distribute construct if any of the distribute
17534 // regions arising from the distribute construct ever bind to any of the
17535 // teams regions arising from the teams construct.
17536 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17537 // A list item that appears in a reduction clause of a teams construct
17538 // must not appear in a firstprivate clause on a distribute construct if
17539 // any of the distribute regions arising from the distribute construct
17540 // ever bind to any of the teams regions arising from the teams construct.
17541 if ((isOpenMPWorksharingDirective(CurrDir) ||
17542 isOpenMPDistributeDirective(CurrDir)) &&
17543 !isOpenMPParallelDirective(CurrDir) &&
17544 !isOpenMPTeamsDirective(CurrDir)) {
17545 DVar = DSAStack->getImplicitDSA(D, true);
17546 if (DVar.CKind != OMPC_shared &&
17547 (isOpenMPParallelDirective(DVar.DKind) ||
17548 isOpenMPTeamsDirective(DVar.DKind) ||
17549 DVar.DKind == OMPD_unknown)) {
17550 Diag(ELoc, diag::err_omp_required_access)
17551 << getOpenMPClauseName(OMPC_firstprivate)
17552 << getOpenMPClauseName(OMPC_shared);
17554 continue;
17555 }
17556 }
17557 // OpenMP [2.9.3.4, Restrictions, p.3]
17558 // A list item that appears in a reduction clause of a parallel construct
17559 // must not appear in a firstprivate clause on a worksharing or task
17560 // construct if any of the worksharing or task regions arising from the
17561 // worksharing or task construct ever bind to any of the parallel regions
17562 // arising from the parallel construct.
17563 // OpenMP [2.9.3.4, Restrictions, p.4]
17564 // A list item that appears in a reduction clause in worksharing
17565 // construct must not appear in a firstprivate clause in a task construct
17566 // encountered during execution of any of the worksharing regions arising
17567 // from the worksharing construct.
17568 if (isOpenMPTaskingDirective(CurrDir)) {
17569 DVar = DSAStack->hasInnermostDSA(
17570 D,
17571 [](OpenMPClauseKind C, bool AppliedToPointee) {
17572 return C == OMPC_reduction && !AppliedToPointee;
17573 },
17574 [](OpenMPDirectiveKind K) {
17575 return isOpenMPParallelDirective(K) ||
17578 },
17579 /*FromParent=*/true);
17580 if (DVar.CKind == OMPC_reduction &&
17581 (isOpenMPParallelDirective(DVar.DKind) ||
17582 isOpenMPWorksharingDirective(DVar.DKind) ||
17583 isOpenMPTeamsDirective(DVar.DKind))) {
17584 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17585 << getOpenMPDirectiveName(DVar.DKind);
17587 continue;
17588 }
17589 }
17590
17591 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17592 // A list item cannot appear in both a map clause and a data-sharing
17593 // attribute clause on the same construct
17594 //
17595 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17596 // A list item cannot appear in both a map clause and a data-sharing
17597 // attribute clause on the same construct unless the construct is a
17598 // combined construct.
17599 if ((getLangOpts().OpenMP <= 45 &&
17601 CurrDir == OMPD_target) {
17602 OpenMPClauseKind ConflictKind;
17603 if (DSAStack->checkMappableExprComponentListsForDecl(
17604 VD, /*CurrentRegionOnly=*/true,
17605 [&ConflictKind](
17607 OpenMPClauseKind WhereFoundClauseKind) {
17608 ConflictKind = WhereFoundClauseKind;
17609 return true;
17610 })) {
17611 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17612 << getOpenMPClauseName(OMPC_firstprivate)
17613 << getOpenMPClauseName(ConflictKind)
17614 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17616 continue;
17617 }
17618 }
17619 }
17620
17621 // Variably modified types are not supported for tasks.
17623 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
17624 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17625 << getOpenMPClauseName(OMPC_firstprivate) << Type
17626 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17627 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17629 Diag(D->getLocation(),
17630 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17631 << D;
17632 continue;
17633 }
17634
17635 Type = Type.getUnqualifiedType();
17636 VarDecl *VDPrivate =
17637 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17638 D->hasAttrs() ? &D->getAttrs() : nullptr,
17639 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17640 // Generate helper private variable and initialize it with the value of the
17641 // original variable. The address of the original variable is replaced by
17642 // the address of the new private variable in the CodeGen. This new variable
17643 // is not added to IdResolver, so the code in the OpenMP region uses
17644 // original variable for proper diagnostics and variable capturing.
17645 Expr *VDInitRefExpr = nullptr;
17646 // For arrays generate initializer for single element and replace it by the
17647 // original array element in CodeGen.
17648 if (Type->isArrayType()) {
17649 VarDecl *VDInit =
17650 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
17651 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
17652 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
17653 ElemType = ElemType.getUnqualifiedType();
17654 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
17655 ElemType, ".firstprivate.temp");
17656 InitializedEntity Entity =
17659
17660 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
17661 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
17662 if (Result.isInvalid())
17663 VDPrivate->setInvalidDecl();
17664 else
17665 VDPrivate->setInit(Result.getAs<Expr>());
17666 // Remove temp variable declaration.
17667 getASTContext().Deallocate(VDInitTemp);
17668 } else {
17669 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
17670 ".firstprivate.temp");
17671 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
17672 RefExpr->getExprLoc());
17674 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
17675 /*DirectInit=*/false);
17676 }
17677 if (VDPrivate->isInvalidDecl()) {
17678 if (IsImplicitClause) {
17679 Diag(RefExpr->getExprLoc(),
17680 diag::note_omp_task_predetermined_firstprivate_here);
17681 }
17682 continue;
17683 }
17684 SemaRef.CurContext->addDecl(VDPrivate);
17685 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17686 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
17687 RefExpr->getExprLoc());
17688 DeclRefExpr *Ref = nullptr;
17689 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17690 if (TopDVar.CKind == OMPC_lastprivate) {
17691 Ref = TopDVar.PrivateCopy;
17692 } else {
17693 auto *FD = dyn_cast<FieldDecl>(D);
17694 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17695 if (VD)
17696 Ref =
17698 RefExpr->getExprLoc());
17699 else
17700 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17701 if (VD || !isOpenMPCapturedDecl(D))
17702 ExprCaptures.push_back(Ref->getDecl());
17703 }
17704 }
17705 if (!IsImplicitClause)
17706 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17707 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17708 ? RefExpr->IgnoreParens()
17709 : Ref);
17710 PrivateCopies.push_back(VDPrivateRefExpr);
17711 Inits.push_back(VDInitRefExpr);
17712 }
17713
17714 if (Vars.empty())
17715 return nullptr;
17716
17718 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17719 buildPreInits(getASTContext(), ExprCaptures));
17720}
17721
17724 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
17725 SourceLocation LParenLoc, SourceLocation EndLoc) {
17726 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
17727 assert(ColonLoc.isValid() && "Colon location must be valid.");
17728 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17729 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
17730 /*Last=*/OMPC_LASTPRIVATE_unknown)
17731 << getOpenMPClauseName(OMPC_lastprivate);
17732 return nullptr;
17733 }
17734
17736 SmallVector<Expr *, 8> SrcExprs;
17737 SmallVector<Expr *, 8> DstExprs;
17738 SmallVector<Expr *, 8> AssignmentOps;
17739 SmallVector<Decl *, 4> ExprCaptures;
17740 SmallVector<Expr *, 4> ExprPostUpdates;
17741 for (Expr *RefExpr : VarList) {
17742 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17743 SourceLocation ELoc;
17744 SourceRange ERange;
17745 Expr *SimpleRefExpr = RefExpr;
17746 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17747 if (Res.second) {
17748 // It will be analyzed later.
17749 Vars.push_back(RefExpr);
17750 SrcExprs.push_back(nullptr);
17751 DstExprs.push_back(nullptr);
17752 AssignmentOps.push_back(nullptr);
17753 }
17754 ValueDecl *D = Res.first;
17755 if (!D)
17756 continue;
17757
17758 QualType Type = D->getType();
17759 auto *VD = dyn_cast<VarDecl>(D);
17760
17761 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
17762 // A variable that appears in a lastprivate clause must not have an
17763 // incomplete type or a reference type.
17765 diag::err_omp_lastprivate_incomplete_type))
17766 continue;
17767 Type = Type.getNonReferenceType();
17768
17769 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17770 // A variable that is privatized must not have a const-qualified type
17771 // unless it is of class type with a mutable member. This restriction does
17772 // not apply to the firstprivate clause.
17773 //
17774 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
17775 // A variable that appears in a lastprivate clause must not have a
17776 // const-qualified type unless it is of class type with a mutable member.
17777 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
17778 continue;
17779
17780 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
17781 // A list item that appears in a lastprivate clause with the conditional
17782 // modifier must be a scalar variable.
17783 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
17784 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17785 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17787 Diag(D->getLocation(),
17788 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17789 << D;
17790 continue;
17791 }
17792
17793 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17794 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
17795 // in a Construct]
17796 // Variables with the predetermined data-sharing attributes may not be
17797 // listed in data-sharing attributes clauses, except for the cases
17798 // listed below.
17799 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17800 // A list item may appear in a firstprivate or lastprivate clause but not
17801 // both.
17802 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17803 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17804 (isOpenMPDistributeDirective(CurrDir) ||
17805 DVar.CKind != OMPC_firstprivate) &&
17806 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
17807 Diag(ELoc, diag::err_omp_wrong_dsa)
17808 << getOpenMPClauseName(DVar.CKind)
17809 << getOpenMPClauseName(OMPC_lastprivate);
17811 continue;
17812 }
17813
17814 // OpenMP [2.14.3.5, Restrictions, p.2]
17815 // A list item that is private within a parallel region, or that appears in
17816 // the reduction clause of a parallel construct, must not appear in a
17817 // lastprivate clause on a worksharing construct if any of the corresponding
17818 // worksharing regions ever binds to any of the corresponding parallel
17819 // regions.
17820 DSAStackTy::DSAVarData TopDVar = DVar;
17821 if (isOpenMPWorksharingDirective(CurrDir) &&
17822 !isOpenMPParallelDirective(CurrDir) &&
17823 !isOpenMPTeamsDirective(CurrDir)) {
17824 DVar = DSAStack->getImplicitDSA(D, true);
17825 if (DVar.CKind != OMPC_shared) {
17826 Diag(ELoc, diag::err_omp_required_access)
17827 << getOpenMPClauseName(OMPC_lastprivate)
17828 << getOpenMPClauseName(OMPC_shared);
17830 continue;
17831 }
17832 }
17833
17834 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
17835 // A variable of class type (or array thereof) that appears in a
17836 // lastprivate clause requires an accessible, unambiguous default
17837 // constructor for the class type, unless the list item is also specified
17838 // in a firstprivate clause.
17839 // A variable of class type (or array thereof) that appears in a
17840 // lastprivate clause requires an accessible, unambiguous copy assignment
17841 // operator for the class type.
17843 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
17844 Type.getUnqualifiedType(), ".lastprivate.src",
17845 D->hasAttrs() ? &D->getAttrs() : nullptr);
17846 DeclRefExpr *PseudoSrcExpr =
17847 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
17848 VarDecl *DstVD =
17849 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
17850 D->hasAttrs() ? &D->getAttrs() : nullptr);
17851 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
17852 // For arrays generate assignment operation for single element and replace
17853 // it by the original array element in CodeGen.
17854 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
17855 PseudoDstExpr, PseudoSrcExpr);
17856 if (AssignmentOp.isInvalid())
17857 continue;
17858 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
17859 /*DiscardedValue=*/false);
17860 if (AssignmentOp.isInvalid())
17861 continue;
17862
17863 DeclRefExpr *Ref = nullptr;
17864 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17865 if (TopDVar.CKind == OMPC_firstprivate) {
17866 Ref = TopDVar.PrivateCopy;
17867 } else {
17868 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17869 if (!isOpenMPCapturedDecl(D))
17870 ExprCaptures.push_back(Ref->getDecl());
17871 }
17872 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17874 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
17876 if (!RefRes.isUsable())
17877 continue;
17878 ExprResult PostUpdateRes =
17879 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
17880 SimpleRefExpr, RefRes.get());
17881 if (!PostUpdateRes.isUsable())
17882 continue;
17883 ExprPostUpdates.push_back(
17884 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
17885 }
17886 }
17887 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17888 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17889 ? RefExpr->IgnoreParens()
17890 : Ref);
17891 SrcExprs.push_back(PseudoSrcExpr);
17892 DstExprs.push_back(PseudoDstExpr);
17893 AssignmentOps.push_back(AssignmentOp.get());
17894 }
17895
17896 if (Vars.empty())
17897 return nullptr;
17898
17900 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17901 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17902 buildPreInits(getASTContext(), ExprCaptures),
17903 buildPostUpdate(SemaRef, ExprPostUpdates));
17904}
17905
17907 SourceLocation StartLoc,
17908 SourceLocation LParenLoc,
17909 SourceLocation EndLoc) {
17911 for (Expr *RefExpr : VarList) {
17912 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17913 SourceLocation ELoc;
17914 SourceRange ERange;
17915 Expr *SimpleRefExpr = RefExpr;
17916 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17917 if (Res.second) {
17918 // It will be analyzed later.
17919 Vars.push_back(RefExpr);
17920 }
17921 ValueDecl *D = Res.first;
17922 if (!D)
17923 continue;
17924
17925 auto *VD = dyn_cast<VarDecl>(D);
17926 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17927 // in a Construct]
17928 // Variables with the predetermined data-sharing attributes may not be
17929 // listed in data-sharing attributes clauses, except for the cases
17930 // listed below. For these exceptions only, listing a predetermined
17931 // variable in a data-sharing attribute clause is allowed and overrides
17932 // the variable's predetermined data-sharing attributes.
17933 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17934 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17935 DVar.RefExpr) {
17936 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17937 << getOpenMPClauseName(OMPC_shared);
17939 continue;
17940 }
17941
17942 DeclRefExpr *Ref = nullptr;
17943 if (!VD && isOpenMPCapturedDecl(D) &&
17945 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17946 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17947 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
17948 ? RefExpr->IgnoreParens()
17949 : Ref);
17950 }
17951
17952 if (Vars.empty())
17953 return nullptr;
17954
17955 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17956 Vars);
17957}
17958
17959namespace {
17960class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
17961 DSAStackTy *Stack;
17962
17963public:
17964 bool VisitDeclRefExpr(DeclRefExpr *E) {
17965 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
17966 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
17967 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17968 return false;
17969 if (DVar.CKind != OMPC_unknown)
17970 return true;
17971 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17972 VD,
17973 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
17974 return isOpenMPPrivate(C) && !AppliedToPointee;
17975 },
17976 [](OpenMPDirectiveKind) { return true; },
17977 /*FromParent=*/true);
17978 return DVarPrivate.CKind != OMPC_unknown;
17979 }
17980 return false;
17981 }
17982 bool VisitStmt(Stmt *S) {
17983 for (Stmt *Child : S->children()) {
17984 if (Child && Visit(Child))
17985 return true;
17986 }
17987 return false;
17988 }
17989 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17990};
17991} // namespace
17992
17993namespace {
17994// Transform MemberExpression for specified FieldDecl of current class to
17995// DeclRefExpr to specified OMPCapturedExprDecl.
17996class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
17997 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
17998 ValueDecl *Field = nullptr;
17999 DeclRefExpr *CapturedExpr = nullptr;
18000
18001public:
18002 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18003 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18004
18005 ExprResult TransformMemberExpr(MemberExpr *E) {
18006 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18007 E->getMemberDecl() == Field) {
18008 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18009 return CapturedExpr;
18010 }
18011 return BaseTransform::TransformMemberExpr(E);
18012 }
18013 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18014};
18015} // namespace
18016
18017template <typename T, typename U>
18019 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18020 for (U &Set : Lookups) {
18021 for (auto *D : Set) {
18022 if (T Res = Gen(cast<ValueDecl>(D)))
18023 return Res;
18024 }
18025 }
18026 return T();
18027}
18028
18030 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18031
18032 for (auto *RD : D->redecls()) {
18033 // Don't bother with extra checks if we already know this one isn't visible.
18034 if (RD == D)
18035 continue;
18036
18037 auto ND = cast<NamedDecl>(RD);
18038 if (LookupResult::isVisible(SemaRef, ND))
18039 return ND;
18040 }
18041
18042 return nullptr;
18043}
18044
18045static void
18049 // Find all of the associated namespaces and classes based on the
18050 // arguments we have.
18051 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18052 Sema::AssociatedClassSet AssociatedClasses;
18053 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18054 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18055 AssociatedClasses);
18056
18057 // C++ [basic.lookup.argdep]p3:
18058 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18059 // and let Y be the lookup set produced by argument dependent
18060 // lookup (defined as follows). If X contains [...] then Y is
18061 // empty. Otherwise Y is the set of declarations found in the
18062 // namespaces associated with the argument types as described
18063 // below. The set of declarations found by the lookup of the name
18064 // is the union of X and Y.
18065 //
18066 // Here, we compute Y and add its members to the overloaded
18067 // candidate set.
18068 for (auto *NS : AssociatedNamespaces) {
18069 // When considering an associated namespace, the lookup is the
18070 // same as the lookup performed when the associated namespace is
18071 // used as a qualifier (3.4.3.2) except that:
18072 //
18073 // -- Any using-directives in the associated namespace are
18074 // ignored.
18075 //
18076 // -- Any namespace-scope friend functions declared in
18077 // associated classes are visible within their respective
18078 // namespaces even if they are not visible during an ordinary
18079 // lookup (11.4).
18080 DeclContext::lookup_result R = NS->lookup(Id.getName());
18081 for (auto *D : R) {
18082 auto *Underlying = D;
18083 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18084 Underlying = USD->getTargetDecl();
18085
18086 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18087 !isa<OMPDeclareMapperDecl>(Underlying))
18088 continue;
18089
18090 if (!SemaRef.isVisible(D)) {
18091 D = findAcceptableDecl(SemaRef, D);
18092 if (!D)
18093 continue;
18094 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18095 Underlying = USD->getTargetDecl();
18096 }
18097 Lookups.emplace_back();
18098 Lookups.back().addDecl(Underlying);
18099 }
18100 }
18101}
18102
18103static ExprResult
18105 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18106 const DeclarationNameInfo &ReductionId, QualType Ty,
18107 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18108 if (ReductionIdScopeSpec.isInvalid())
18109 return ExprError();
18110 SmallVector<UnresolvedSet<8>, 4> Lookups;
18111 if (S) {
18112 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18113 Lookup.suppressDiagnostics();
18114 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
18115 /*ObjectType=*/QualType())) {
18116 NamedDecl *D = Lookup.getRepresentativeDecl();
18117 do {
18118 S = S->getParent();
18119 } while (S && !S->isDeclScope(D));
18120 if (S)
18121 S = S->getParent();
18122 Lookups.emplace_back();
18123 Lookups.back().append(Lookup.begin(), Lookup.end());
18124 Lookup.clear();
18125 }
18126 } else if (auto *ULE =
18127 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18128 Lookups.push_back(UnresolvedSet<8>());
18129 Decl *PrevD = nullptr;
18130 for (NamedDecl *D : ULE->decls()) {
18131 if (D == PrevD)
18132 Lookups.push_back(UnresolvedSet<8>());
18133 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18134 Lookups.back().addDecl(DRD);
18135 PrevD = D;
18136 }
18137 }
18138 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18141 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18142 return !D->isInvalidDecl() &&
18143 (D->getType()->isDependentType() ||
18144 D->getType()->isInstantiationDependentType() ||
18145 D->getType()->containsUnexpandedParameterPack());
18146 })) {
18147 UnresolvedSet<8> ResSet;
18148 for (const UnresolvedSet<8> &Set : Lookups) {
18149 if (Set.empty())
18150 continue;
18151 ResSet.append(Set.begin(), Set.end());
18152 // The last item marks the end of all declarations at the specified scope.
18153 ResSet.addDecl(Set[Set.size() - 1]);
18154 }
18156 SemaRef.Context, /*NamingClass=*/nullptr,
18157 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18158 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
18159 /*KnownInstantiationDependent=*/false);
18160 }
18161 // Lookup inside the classes.
18162 // C++ [over.match.oper]p3:
18163 // For a unary operator @ with an operand of a type whose
18164 // cv-unqualified version is T1, and for a binary operator @ with
18165 // a left operand of a type whose cv-unqualified version is T1 and
18166 // a right operand of a type whose cv-unqualified version is T2,
18167 // three sets of candidate functions, designated member
18168 // candidates, non-member candidates and built-in candidates, are
18169 // constructed as follows:
18170 // -- If T1 is a complete class type or a class currently being
18171 // defined, the set of member candidates is the result of the
18172 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18173 // the set of member candidates is empty.
18174 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18175 Lookup.suppressDiagnostics();
18176 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18177 // Complete the type if it can be completed.
18178 // If the type is neither complete nor being defined, bail out now.
18179 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18180 TyRec->getDecl()->getDefinition()) {
18181 Lookup.clear();
18182 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18183 if (Lookup.empty()) {
18184 Lookups.emplace_back();
18185 Lookups.back().append(Lookup.begin(), Lookup.end());
18186 }
18187 }
18188 }
18189 // Perform ADL.
18190 if (SemaRef.getLangOpts().CPlusPlus)
18191 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18192 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18193 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18194 if (!D->isInvalidDecl() &&
18195 SemaRef.Context.hasSameType(D->getType(), Ty))
18196 return D;
18197 return nullptr;
18198 }))
18199 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18200 VK_LValue, Loc);
18201 if (SemaRef.getLangOpts().CPlusPlus) {
18202 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18203 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18204 if (!D->isInvalidDecl() &&
18205 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18206 !Ty.isMoreQualifiedThan(D->getType(),
18207 SemaRef.getASTContext()))
18208 return D;
18209 return nullptr;
18210 })) {
18211 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18212 /*DetectVirtual=*/false);
18213 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18214 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18215 VD->getType().getUnqualifiedType()))) {
18216 if (SemaRef.CheckBaseClassAccess(
18217 Loc, VD->getType(), Ty, Paths.front(),
18218 /*DiagID=*/0) != Sema::AR_inaccessible) {
18219 SemaRef.BuildBasePathArray(Paths, BasePath);
18220 return SemaRef.BuildDeclRefExpr(
18222 }
18223 }
18224 }
18225 }
18226 }
18227 if (ReductionIdScopeSpec.isSet()) {
18228 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18229 << Ty << Range;
18230 return ExprError();
18231 }
18232 return ExprEmpty();
18233}
18234
18235namespace {
18236/// Data for the reduction-based clauses.
18237struct ReductionData {
18238 /// List of original reduction items.
18240 /// List of private copies of the reduction items.
18241 SmallVector<Expr *, 8> Privates;
18242 /// LHS expressions for the reduction_op expressions.
18244 /// RHS expressions for the reduction_op expressions.
18246 /// Reduction operation expression.
18247 SmallVector<Expr *, 8> ReductionOps;
18248 /// inscan copy operation expressions.
18249 SmallVector<Expr *, 8> InscanCopyOps;
18250 /// inscan copy temp array expressions for prefix sums.
18251 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18252 /// inscan copy temp array element expressions for prefix sums.
18253 SmallVector<Expr *, 8> InscanCopyArrayElems;
18254 /// Taskgroup descriptors for the corresponding reduction items in
18255 /// in_reduction clauses.
18256 SmallVector<Expr *, 8> TaskgroupDescriptors;
18257 /// List of captures for clause.
18258 SmallVector<Decl *, 4> ExprCaptures;
18259 /// List of postupdate expressions.
18260 SmallVector<Expr *, 4> ExprPostUpdates;
18261 /// Reduction modifier.
18262 unsigned RedModifier = 0;
18263 ReductionData() = delete;
18264 /// Reserves required memory for the reduction data.
18265 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18266 Vars.reserve(Size);
18267 Privates.reserve(Size);
18268 LHSs.reserve(Size);
18269 RHSs.reserve(Size);
18270 ReductionOps.reserve(Size);
18271 if (RedModifier == OMPC_REDUCTION_inscan) {
18272 InscanCopyOps.reserve(Size);
18273 InscanCopyArrayTemps.reserve(Size);
18274 InscanCopyArrayElems.reserve(Size);
18275 }
18276 TaskgroupDescriptors.reserve(Size);
18277 ExprCaptures.reserve(Size);
18278 ExprPostUpdates.reserve(Size);
18279 }
18280 /// Stores reduction item and reduction operation only (required for dependent
18281 /// reduction item).
18282 void push(Expr *Item, Expr *ReductionOp) {
18283 Vars.emplace_back(Item);
18284 Privates.emplace_back(nullptr);
18285 LHSs.emplace_back(nullptr);
18286 RHSs.emplace_back(nullptr);
18287 ReductionOps.emplace_back(ReductionOp);
18288 TaskgroupDescriptors.emplace_back(nullptr);
18289 if (RedModifier == OMPC_REDUCTION_inscan) {
18290 InscanCopyOps.push_back(nullptr);
18291 InscanCopyArrayTemps.push_back(nullptr);
18292 InscanCopyArrayElems.push_back(nullptr);
18293 }
18294 }
18295 /// Stores reduction data.
18296 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18297 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18298 Expr *CopyArrayElem) {
18299 Vars.emplace_back(Item);
18300 Privates.emplace_back(Private);
18301 LHSs.emplace_back(LHS);
18302 RHSs.emplace_back(RHS);
18303 ReductionOps.emplace_back(ReductionOp);
18304 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18305 if (RedModifier == OMPC_REDUCTION_inscan) {
18306 InscanCopyOps.push_back(CopyOp);
18307 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18308 InscanCopyArrayElems.push_back(CopyArrayElem);
18309 } else {
18310 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18311 CopyArrayElem == nullptr &&
18312 "Copy operation must be used for inscan reductions only.");
18313 }
18314 }
18315};
18316} // namespace
18317
18319 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18320 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18321 const Expr *Length = OASE->getLength();
18322 if (Length == nullptr) {
18323 // For array sections of the form [1:] or [:], we would need to analyze
18324 // the lower bound...
18325 if (OASE->getColonLocFirst().isValid())
18326 return false;
18327
18328 // This is an array subscript which has implicit length 1!
18329 SingleElement = true;
18330 ArraySizes.push_back(llvm::APSInt::get(1));
18331 } else {
18333 if (!Length->EvaluateAsInt(Result, Context))
18334 return false;
18335
18336 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18337 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18338 ArraySizes.push_back(ConstantLengthValue);
18339 }
18340
18341 // Get the base of this array section and walk up from there.
18342 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18343
18344 // We require length = 1 for all array sections except the right-most to
18345 // guarantee that the memory region is contiguous and has no holes in it.
18346 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18347 Length = TempOASE->getLength();
18348 if (Length == nullptr) {
18349 // For array sections of the form [1:] or [:], we would need to analyze
18350 // the lower bound...
18351 if (OASE->getColonLocFirst().isValid())
18352 return false;
18353
18354 // This is an array subscript which has implicit length 1!
18355 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18356 ArraySizes.push_back(ConstantOne);
18357 } else {
18359 if (!Length->EvaluateAsInt(Result, Context))
18360 return false;
18361
18362 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18363 if (ConstantLengthValue.getSExtValue() != 1)
18364 return false;
18365
18366 ArraySizes.push_back(ConstantLengthValue);
18367 }
18368 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18369 }
18370
18371 // If we have a single element, we don't need to add the implicit lengths.
18372 if (!SingleElement) {
18373 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18374 // Has implicit length 1!
18375 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18376 ArraySizes.push_back(ConstantOne);
18377 Base = TempASE->getBase()->IgnoreParenImpCasts();
18378 }
18379 }
18380
18381 // This array section can be privatized as a single value or as a constant
18382 // sized array.
18383 return true;
18384}
18385
18386static BinaryOperatorKind
18388 if (BOK == BO_Add)
18389 return BO_AddAssign;
18390 if (BOK == BO_Mul)
18391 return BO_MulAssign;
18392 if (BOK == BO_And)
18393 return BO_AndAssign;
18394 if (BOK == BO_Or)
18395 return BO_OrAssign;
18396 if (BOK == BO_Xor)
18397 return BO_XorAssign;
18398 return BOK;
18399}
18400
18402 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18403 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18404 SourceLocation ColonLoc, SourceLocation EndLoc,
18405 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18406 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18407 DeclarationName DN = ReductionId.getName();
18409 BinaryOperatorKind BOK = BO_Comma;
18410
18411 ASTContext &Context = S.Context;
18412 // OpenMP [2.14.3.6, reduction clause]
18413 // C
18414 // reduction-identifier is either an identifier or one of the following
18415 // operators: +, -, *, &, |, ^, && and ||
18416 // C++
18417 // reduction-identifier is either an id-expression or one of the following
18418 // operators: +, -, *, &, |, ^, && and ||
18419 switch (OOK) {
18420 case OO_Plus:
18421 BOK = BO_Add;
18422 break;
18423 case OO_Minus:
18424 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18425 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18426 // reduction identifier.
18427 if (S.LangOpts.OpenMP > 52)
18428 BOK = BO_Comma;
18429 else
18430 BOK = BO_Add;
18431 break;
18432 case OO_Star:
18433 BOK = BO_Mul;
18434 break;
18435 case OO_Amp:
18436 BOK = BO_And;
18437 break;
18438 case OO_Pipe:
18439 BOK = BO_Or;
18440 break;
18441 case OO_Caret:
18442 BOK = BO_Xor;
18443 break;
18444 case OO_AmpAmp:
18445 BOK = BO_LAnd;
18446 break;
18447 case OO_PipePipe:
18448 BOK = BO_LOr;
18449 break;
18450 case OO_New:
18451 case OO_Delete:
18452 case OO_Array_New:
18453 case OO_Array_Delete:
18454 case OO_Slash:
18455 case OO_Percent:
18456 case OO_Tilde:
18457 case OO_Exclaim:
18458 case OO_Equal:
18459 case OO_Less:
18460 case OO_Greater:
18461 case OO_LessEqual:
18462 case OO_GreaterEqual:
18463 case OO_PlusEqual:
18464 case OO_MinusEqual:
18465 case OO_StarEqual:
18466 case OO_SlashEqual:
18467 case OO_PercentEqual:
18468 case OO_CaretEqual:
18469 case OO_AmpEqual:
18470 case OO_PipeEqual:
18471 case OO_LessLess:
18472 case OO_GreaterGreater:
18473 case OO_LessLessEqual:
18474 case OO_GreaterGreaterEqual:
18475 case OO_EqualEqual:
18476 case OO_ExclaimEqual:
18477 case OO_Spaceship:
18478 case OO_PlusPlus:
18479 case OO_MinusMinus:
18480 case OO_Comma:
18481 case OO_ArrowStar:
18482 case OO_Arrow:
18483 case OO_Call:
18484 case OO_Subscript:
18485 case OO_Conditional:
18486 case OO_Coawait:
18488 llvm_unreachable("Unexpected reduction identifier");
18489 case OO_None:
18490 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18491 if (II->isStr("max"))
18492 BOK = BO_GT;
18493 else if (II->isStr("min"))
18494 BOK = BO_LT;
18495 }
18496 break;
18497 }
18498
18499 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18500 // A reduction clause with the minus (-) operator was deprecated
18501 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18502 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18503
18504 SourceRange ReductionIdRange;
18505 if (ReductionIdScopeSpec.isValid())
18506 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18507 else
18508 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18509 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18510
18511 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18512 bool FirstIter = true;
18513 for (Expr *RefExpr : VarList) {
18514 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18515 // OpenMP [2.1, C/C++]
18516 // A list item is a variable or array section, subject to the restrictions
18517 // specified in Section 2.4 on page 42 and in each of the sections
18518 // describing clauses and directives for which a list appears.
18519 // OpenMP [2.14.3.3, Restrictions, p.1]
18520 // A variable that is part of another variable (as an array or
18521 // structure element) cannot appear in a private clause.
18522 if (!FirstIter && IR != ER)
18523 ++IR;
18524 FirstIter = false;
18525 SourceLocation ELoc;
18526 SourceRange ERange;
18527 Expr *SimpleRefExpr = RefExpr;
18528 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18529 /*AllowArraySection=*/true);
18530 if (Res.second) {
18531 // Try to find 'declare reduction' corresponding construct before using
18532 // builtin/overloaded operators.
18533 QualType Type = Context.DependentTy;
18534 CXXCastPath BasePath;
18535 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18536 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18537 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18538 Expr *ReductionOp = nullptr;
18539 if (S.CurContext->isDependentContext() &&
18540 (DeclareReductionRef.isUnset() ||
18541 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18542 ReductionOp = DeclareReductionRef.get();
18543 // It will be analyzed later.
18544 RD.push(RefExpr, ReductionOp);
18545 }
18546 ValueDecl *D = Res.first;
18547 if (!D)
18548 continue;
18549
18550 Expr *TaskgroupDescriptor = nullptr;
18551 QualType Type;
18552 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18553 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18554 if (ASE) {
18555 Type = ASE->getType().getNonReferenceType();
18556 } else if (OASE) {
18557 QualType BaseType =
18559 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18560 Type = ATy->getElementType();
18561 else
18562 Type = BaseType->getPointeeType();
18563 Type = Type.getNonReferenceType();
18564 } else {
18565 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
18566 }
18567 auto *VD = dyn_cast<VarDecl>(D);
18568
18569 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18570 // A variable that appears in a private clause must not have an incomplete
18571 // type or a reference type.
18572 if (S.RequireCompleteType(ELoc, D->getType(),
18573 diag::err_omp_reduction_incomplete_type))
18574 continue;
18575 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18576 // A list item that appears in a reduction clause must not be
18577 // const-qualified.
18578 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18579 /*AcceptIfMutable=*/false, ASE || OASE))
18580 continue;
18581
18582 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18583 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18584 // If a list-item is a reference type then it must bind to the same object
18585 // for all threads of the team.
18586 if (!ASE && !OASE) {
18587 if (VD) {
18588 VarDecl *VDDef = VD->getDefinition();
18589 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18590 DSARefChecker Check(Stack);
18591 if (Check.Visit(VDDef->getInit())) {
18592 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18593 << getOpenMPClauseName(ClauseKind) << ERange;
18594 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18595 continue;
18596 }
18597 }
18598 }
18599
18600 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18601 // in a Construct]
18602 // Variables with the predetermined data-sharing attributes may not be
18603 // listed in data-sharing attributes clauses, except for the cases
18604 // listed below. For these exceptions only, listing a predetermined
18605 // variable in a data-sharing attribute clause is allowed and overrides
18606 // the variable's predetermined data-sharing attributes.
18607 // OpenMP [2.14.3.6, Restrictions, p.3]
18608 // Any number of reduction clauses can be specified on the directive,
18609 // but a list item can appear only once in the reduction clauses for that
18610 // directive.
18611 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18612 if (DVar.CKind == OMPC_reduction) {
18613 S.Diag(ELoc, diag::err_omp_once_referenced)
18614 << getOpenMPClauseName(ClauseKind);
18615 if (DVar.RefExpr)
18616 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18617 continue;
18618 }
18619 if (DVar.CKind != OMPC_unknown) {
18620 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18621 << getOpenMPClauseName(DVar.CKind)
18622 << getOpenMPClauseName(OMPC_reduction);
18623 reportOriginalDsa(S, Stack, D, DVar);
18624 continue;
18625 }
18626
18627 // OpenMP [2.14.3.6, Restrictions, p.1]
18628 // A list item that appears in a reduction clause of a worksharing
18629 // construct must be shared in the parallel regions to which any of the
18630 // worksharing regions arising from the worksharing construct bind.
18631 if (isOpenMPWorksharingDirective(CurrDir) &&
18632 !isOpenMPParallelDirective(CurrDir) &&
18633 !isOpenMPTeamsDirective(CurrDir)) {
18634 DVar = Stack->getImplicitDSA(D, true);
18635 if (DVar.CKind != OMPC_shared) {
18636 S.Diag(ELoc, diag::err_omp_required_access)
18637 << getOpenMPClauseName(OMPC_reduction)
18638 << getOpenMPClauseName(OMPC_shared);
18639 reportOriginalDsa(S, Stack, D, DVar);
18640 continue;
18641 }
18642 }
18643 } else {
18644 // Threadprivates cannot be shared between threads, so dignose if the base
18645 // is a threadprivate variable.
18646 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18647 if (DVar.CKind == OMPC_threadprivate) {
18648 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18649 << getOpenMPClauseName(DVar.CKind)
18650 << getOpenMPClauseName(OMPC_reduction);
18651 reportOriginalDsa(S, Stack, D, DVar);
18652 continue;
18653 }
18654 }
18655
18656 // Try to find 'declare reduction' corresponding construct before using
18657 // builtin/overloaded operators.
18658 CXXCastPath BasePath;
18659 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18660 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18661 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18662 if (DeclareReductionRef.isInvalid())
18663 continue;
18664 if (S.CurContext->isDependentContext() &&
18665 (DeclareReductionRef.isUnset() ||
18666 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
18667 RD.push(RefExpr, DeclareReductionRef.get());
18668 continue;
18669 }
18670 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
18671 // Not allowed reduction identifier is found.
18672 if (S.LangOpts.OpenMP > 52)
18673 S.Diag(ReductionId.getBeginLoc(),
18674 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18675 << Type << ReductionIdRange;
18676 else
18677 S.Diag(ReductionId.getBeginLoc(),
18678 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18679 << Type << ReductionIdRange;
18680 continue;
18681 }
18682
18683 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18684 // The type of a list item that appears in a reduction clause must be valid
18685 // for the reduction-identifier. For a max or min reduction in C, the type
18686 // of the list item must be an allowed arithmetic data type: char, int,
18687 // float, double, or _Bool, possibly modified with long, short, signed, or
18688 // unsigned. For a max or min reduction in C++, the type of the list item
18689 // must be an allowed arithmetic data type: char, wchar_t, int, float,
18690 // double, or bool, possibly modified with long, short, signed, or unsigned.
18691 if (DeclareReductionRef.isUnset()) {
18692 if ((BOK == BO_GT || BOK == BO_LT) &&
18693 !(Type->isScalarType() ||
18694 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
18695 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18696 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
18697 if (!ASE && !OASE) {
18698 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18700 S.Diag(D->getLocation(),
18701 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18702 << D;
18703 }
18704 continue;
18705 }
18706 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18707 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
18708 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18709 << getOpenMPClauseName(ClauseKind);
18710 if (!ASE && !OASE) {
18711 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18713 S.Diag(D->getLocation(),
18714 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18715 << D;
18716 }
18717 continue;
18718 }
18719 }
18720
18721 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
18722 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
18723 D->hasAttrs() ? &D->getAttrs() : nullptr);
18724 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
18725 D->hasAttrs() ? &D->getAttrs() : nullptr);
18726 QualType PrivateTy = Type;
18727
18728 // Try if we can determine constant lengths for all array sections and avoid
18729 // the VLA.
18730 bool ConstantLengthOASE = false;
18731 if (OASE) {
18732 bool SingleElement;
18734 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
18735 Context, OASE, SingleElement, ArraySizes);
18736
18737 // If we don't have a single element, we must emit a constant array type.
18738 if (ConstantLengthOASE && !SingleElement) {
18739 for (llvm::APSInt &Size : ArraySizes)
18740 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
18742 /*IndexTypeQuals=*/0);
18743 }
18744 }
18745
18746 if ((OASE && !ConstantLengthOASE) ||
18747 (!OASE && !ASE &&
18748 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18749 if (!Context.getTargetInfo().isVLASupported()) {
18750 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
18751 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18752 S.Diag(ELoc, diag::note_vla_unsupported);
18753 continue;
18754 } else {
18755 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18756 S.targetDiag(ELoc, diag::note_vla_unsupported);
18757 }
18758 }
18759 // For arrays/array sections only:
18760 // Create pseudo array type for private copy. The size for this array will
18761 // be generated during codegen.
18762 // For array subscripts or single variables Private Ty is the same as Type
18763 // (type of the variable or single array element).
18764 PrivateTy = Context.getVariableArrayType(
18765 Type,
18766 new (Context)
18767 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
18768 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
18769 } else if (!ASE && !OASE &&
18770 Context.getAsArrayType(D->getType().getNonReferenceType())) {
18771 PrivateTy = D->getType().getNonReferenceType();
18772 }
18773 // Private copy.
18774 VarDecl *PrivateVD =
18775 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18776 D->hasAttrs() ? &D->getAttrs() : nullptr,
18777 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18778 // Add initializer for private variable.
18779 Expr *Init = nullptr;
18780 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
18781 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
18782 if (DeclareReductionRef.isUsable()) {
18783 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
18784 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18785 if (DRD->getInitializer()) {
18786 Init = DRDRef;
18787 RHSVD->setInit(DRDRef);
18789 }
18790 } else {
18791 switch (BOK) {
18792 case BO_Add:
18793 case BO_Xor:
18794 case BO_Or:
18795 case BO_LOr:
18796 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
18798 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
18799 break;
18800 case BO_Mul:
18801 case BO_LAnd:
18802 if (Type->isScalarType() || Type->isAnyComplexType()) {
18803 // '*' and '&&' reduction ops - initializer is '1'.
18804 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
18805 }
18806 break;
18807 case BO_And: {
18808 // '&' reduction op - initializer is '~0'.
18809 QualType OrigType = Type;
18810 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
18811 Type = ComplexTy->getElementType();
18812 if (Type->isRealFloatingType()) {
18813 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18814 Context.getFloatTypeSemantics(Type));
18815 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18816 Type, ELoc);
18817 } else if (Type->isScalarType()) {
18818 uint64_t Size = Context.getTypeSize(Type);
18819 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
18820 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18821 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18822 }
18823 if (Init && OrigType->isAnyComplexType()) {
18824 // Init = 0xFFFF + 0xFFFFi;
18825 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
18826 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
18827 }
18828 Type = OrigType;
18829 break;
18830 }
18831 case BO_LT:
18832 case BO_GT: {
18833 // 'min' reduction op - initializer is 'Largest representable number in
18834 // the reduction list item type'.
18835 // 'max' reduction op - initializer is 'Least representable number in
18836 // the reduction list item type'.
18837 if (Type->isIntegerType() || Type->isPointerType()) {
18838 bool IsSigned = Type->hasSignedIntegerRepresentation();
18839 uint64_t Size = Context.getTypeSize(Type);
18840 QualType IntTy =
18841 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
18842 llvm::APInt InitValue =
18843 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18844 : llvm::APInt::getMinValue(Size)
18845 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18846 : llvm::APInt::getMaxValue(Size);
18847 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18848 if (Type->isPointerType()) {
18849 // Cast to pointer type.
18851 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
18852 if (CastExpr.isInvalid())
18853 continue;
18854 Init = CastExpr.get();
18855 }
18856 } else if (Type->isRealFloatingType()) {
18857 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18858 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
18859 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18860 Type, ELoc);
18861 }
18862 break;
18863 }
18864 case BO_PtrMemD:
18865 case BO_PtrMemI:
18866 case BO_MulAssign:
18867 case BO_Div:
18868 case BO_Rem:
18869 case BO_Sub:
18870 case BO_Shl:
18871 case BO_Shr:
18872 case BO_LE:
18873 case BO_GE:
18874 case BO_EQ:
18875 case BO_NE:
18876 case BO_Cmp:
18877 case BO_AndAssign:
18878 case BO_XorAssign:
18879 case BO_OrAssign:
18880 case BO_Assign:
18881 case BO_AddAssign:
18882 case BO_SubAssign:
18883 case BO_DivAssign:
18884 case BO_RemAssign:
18885 case BO_ShlAssign:
18886 case BO_ShrAssign:
18887 case BO_Comma:
18888 llvm_unreachable("Unexpected reduction operation");
18889 }
18890 }
18891 if (Init && DeclareReductionRef.isUnset()) {
18892 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
18893 // Store initializer for single element in private copy. Will be used
18894 // during codegen.
18895 PrivateVD->setInit(RHSVD->getInit());
18896 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18897 } else if (!Init) {
18898 S.ActOnUninitializedDecl(RHSVD);
18899 // Store initializer for single element in private copy. Will be used
18900 // during codegen.
18901 PrivateVD->setInit(RHSVD->getInit());
18902 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18903 }
18904 if (RHSVD->isInvalidDecl())
18905 continue;
18906 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
18907 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18908 << Type << ReductionIdRange;
18909 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18911 S.Diag(D->getLocation(),
18912 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18913 << D;
18914 continue;
18915 }
18916 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
18917 ExprResult ReductionOp;
18918 if (DeclareReductionRef.isUsable()) {
18919 QualType RedTy = DeclareReductionRef.get()->getType();
18920 QualType PtrRedTy = Context.getPointerType(RedTy);
18921 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
18922 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
18923 if (!BasePath.empty()) {
18924 LHS = S.DefaultLvalueConversion(LHS.get());
18925 RHS = S.DefaultLvalueConversion(RHS.get());
18927 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
18928 LHS.get()->getValueKind(), FPOptionsOverride());
18930 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
18931 RHS.get()->getValueKind(), FPOptionsOverride());
18932 }
18934 QualType Params[] = {PtrRedTy, PtrRedTy};
18935 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
18936 auto *OVE = new (Context) OpaqueValueExpr(
18937 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
18938 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
18939 Expr *Args[] = {LHS.get(), RHS.get()};
18940 ReductionOp =
18941 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
18943 } else {
18945 if (Type->isRecordType() && CombBOK != BOK) {
18947 ReductionOp =
18948 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18949 CombBOK, LHSDRE, RHSDRE);
18950 }
18951 if (!ReductionOp.isUsable()) {
18952 ReductionOp =
18953 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
18954 LHSDRE, RHSDRE);
18955 if (ReductionOp.isUsable()) {
18956 if (BOK != BO_LT && BOK != BO_GT) {
18957 ReductionOp =
18958 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18959 BO_Assign, LHSDRE, ReductionOp.get());
18960 } else {
18961 auto *ConditionalOp = new (Context)
18962 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
18963 RHSDRE, Type, VK_LValue, OK_Ordinary);
18964 ReductionOp =
18965 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18966 BO_Assign, LHSDRE, ConditionalOp);
18967 }
18968 }
18969 }
18970 if (ReductionOp.isUsable())
18971 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
18972 /*DiscardedValue=*/false);
18973 if (!ReductionOp.isUsable())
18974 continue;
18975 }
18976
18977 // Add copy operations for inscan reductions.
18978 // LHS = RHS;
18979 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18980 if (ClauseKind == OMPC_reduction &&
18981 RD.RedModifier == OMPC_REDUCTION_inscan) {
18982 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
18983 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18984 RHS.get());
18985 if (!CopyOpRes.isUsable())
18986 continue;
18987 CopyOpRes =
18988 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
18989 if (!CopyOpRes.isUsable())
18990 continue;
18991 // For simd directive and simd-based directives in simd mode no need to
18992 // construct temp array, need just a single temp element.
18993 if (Stack->getCurrentDirective() == OMPD_simd ||
18994 (S.getLangOpts().OpenMPSimd &&
18995 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
18996 VarDecl *TempArrayVD =
18997 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18998 D->hasAttrs() ? &D->getAttrs() : nullptr);
18999 // Add a constructor to the temp decl.
19000 S.ActOnUninitializedDecl(TempArrayVD);
19001 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19002 } else {
19003 // Build temp array for prefix sum.
19004 auto *Dim = new (S.Context)
19007 PrivateTy, Dim, ArraySizeModifier::Normal,
19008 /*IndexTypeQuals=*/0, {ELoc, ELoc});
19009 VarDecl *TempArrayVD =
19010 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19011 D->hasAttrs() ? &D->getAttrs() : nullptr);
19012 // Add a constructor to the temp decl.
19013 S.ActOnUninitializedDecl(TempArrayVD);
19014 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19015 TempArrayElem =
19016 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19017 auto *Idx = new (S.Context)
19019 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19020 ELoc, Idx, ELoc);
19021 }
19022 }
19023
19024 // OpenMP [2.15.4.6, Restrictions, p.2]
19025 // A list item that appears in an in_reduction clause of a task construct
19026 // must appear in a task_reduction clause of a construct associated with a
19027 // taskgroup region that includes the participating task in its taskgroup
19028 // set. The construct associated with the innermost region that meets this
19029 // condition must specify the same reduction-identifier as the in_reduction
19030 // clause.
19031 if (ClauseKind == OMPC_in_reduction) {
19032 SourceRange ParentSR;
19033 BinaryOperatorKind ParentBOK;
19034 const Expr *ParentReductionOp = nullptr;
19035 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19036 DSAStackTy::DSAVarData ParentBOKDSA =
19037 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19038 ParentBOKTD);
19039 DSAStackTy::DSAVarData ParentReductionOpDSA =
19040 Stack->getTopMostTaskgroupReductionData(
19041 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19042 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19043 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19044 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19045 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19046 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19047 bool EmitError = true;
19048 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19049 llvm::FoldingSetNodeID RedId, ParentRedId;
19050 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19051 DeclareReductionRef.get()->Profile(RedId, Context,
19052 /*Canonical=*/true);
19053 EmitError = RedId != ParentRedId;
19054 }
19055 if (EmitError) {
19056 S.Diag(ReductionId.getBeginLoc(),
19057 diag::err_omp_reduction_identifier_mismatch)
19058 << ReductionIdRange << RefExpr->getSourceRange();
19059 S.Diag(ParentSR.getBegin(),
19060 diag::note_omp_previous_reduction_identifier)
19061 << ParentSR
19062 << (IsParentBOK ? ParentBOKDSA.RefExpr
19063 : ParentReductionOpDSA.RefExpr)
19064 ->getSourceRange();
19065 continue;
19066 }
19067 }
19068 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19069 }
19070
19071 DeclRefExpr *Ref = nullptr;
19072 Expr *VarsExpr = RefExpr->IgnoreParens();
19073 if (!VD && !S.CurContext->isDependentContext()) {
19074 if (ASE || OASE) {
19075 TransformExprToCaptures RebuildToCapture(S, D);
19076 VarsExpr =
19077 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19078 Ref = RebuildToCapture.getCapturedExpr();
19079 } else {
19080 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19081 }
19082 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
19083 RD.ExprCaptures.emplace_back(Ref->getDecl());
19084 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19085 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19086 if (!RefRes.isUsable())
19087 continue;
19088 ExprResult PostUpdateRes =
19089 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19090 RefRes.get());
19091 if (!PostUpdateRes.isUsable())
19092 continue;
19093 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19094 Stack->getCurrentDirective() == OMPD_taskgroup) {
19095 S.Diag(RefExpr->getExprLoc(),
19096 diag::err_omp_reduction_non_addressable_expression)
19097 << RefExpr->getSourceRange();
19098 continue;
19099 }
19100 RD.ExprPostUpdates.emplace_back(
19101 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19102 }
19103 }
19104 }
19105 // All reduction items are still marked as reduction (to do not increase
19106 // code base size).
19107 unsigned Modifier = RD.RedModifier;
19108 // Consider task_reductions as reductions with task modifier. Required for
19109 // correct analysis of in_reduction clauses.
19110 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19111 Modifier = OMPC_REDUCTION_task;
19112 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19113 ASE || OASE);
19114 if (Modifier == OMPC_REDUCTION_task &&
19115 (CurrDir == OMPD_taskgroup ||
19116 ((isOpenMPParallelDirective(CurrDir) ||
19117 isOpenMPWorksharingDirective(CurrDir)) &&
19118 !isOpenMPSimdDirective(CurrDir)))) {
19119 if (DeclareReductionRef.isUsable())
19120 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19121 DeclareReductionRef.get());
19122 else
19123 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19124 }
19125 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19126 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19127 TempArrayElem.get());
19128 }
19129 return RD.Vars.empty();
19130}
19131
19134 SourceLocation StartLoc, SourceLocation LParenLoc,
19135 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19136 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19137 ArrayRef<Expr *> UnresolvedReductions) {
19138 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19139 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19140 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19141 /*Last=*/OMPC_REDUCTION_unknown)
19142 << getOpenMPClauseName(OMPC_reduction);
19143 return nullptr;
19144 }
19145 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19146 // A reduction clause with the inscan reduction-modifier may only appear on a
19147 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19148 // construct, a parallel worksharing-loop construct or a parallel
19149 // worksharing-loop SIMD construct.
19150 if (Modifier == OMPC_REDUCTION_inscan &&
19151 (DSAStack->getCurrentDirective() != OMPD_for &&
19152 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19153 DSAStack->getCurrentDirective() != OMPD_simd &&
19154 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19155 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19156 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19157 return nullptr;
19158 }
19159
19160 ReductionData RD(VarList.size(), Modifier);
19161 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
19162 StartLoc, LParenLoc, ColonLoc, EndLoc,
19163 ReductionIdScopeSpec, ReductionId,
19164 UnresolvedReductions, RD))
19165 return nullptr;
19166
19168 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19169 Modifier, RD.Vars,
19170 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19171 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19172 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19173 buildPreInits(getASTContext(), RD.ExprCaptures),
19174 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19175}
19176
19178 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19179 SourceLocation ColonLoc, SourceLocation EndLoc,
19180 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19181 ArrayRef<Expr *> UnresolvedReductions) {
19182 ReductionData RD(VarList.size());
19183 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
19184 VarList, StartLoc, LParenLoc, ColonLoc,
19185 EndLoc, ReductionIdScopeSpec, ReductionId,
19186 UnresolvedReductions, RD))
19187 return nullptr;
19188
19190 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19191 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19192 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19193 buildPreInits(getASTContext(), RD.ExprCaptures),
19194 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19195}
19196
19198 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19199 SourceLocation ColonLoc, SourceLocation EndLoc,
19200 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19201 ArrayRef<Expr *> UnresolvedReductions) {
19202 ReductionData RD(VarList.size());
19203 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19204 StartLoc, LParenLoc, ColonLoc, EndLoc,
19205 ReductionIdScopeSpec, ReductionId,
19206 UnresolvedReductions, RD))
19207 return nullptr;
19208
19210 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19211 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19212 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19213 buildPreInits(getASTContext(), RD.ExprCaptures),
19214 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19215}
19216
19218 SourceLocation LinLoc) {
19219 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19220 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19221 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19222 << getLangOpts().CPlusPlus;
19223 return true;
19224 }
19225 return false;
19226}
19227
19229 OpenMPLinearClauseKind LinKind,
19230 QualType Type, bool IsDeclareSimd) {
19231 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19232 // A variable must not have an incomplete type or a reference type.
19234 diag::err_omp_linear_incomplete_type))
19235 return true;
19236 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19237 !Type->isReferenceType()) {
19238 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19239 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19240 return true;
19241 }
19242 Type = Type.getNonReferenceType();
19243
19244 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19245 // A variable that is privatized must not have a const-qualified type
19246 // unless it is of class type with a mutable member. This restriction does
19247 // not apply to the firstprivate clause, nor to the linear clause on
19248 // declarative directives (like declare simd).
19249 if (!IsDeclareSimd &&
19250 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19251 return true;
19252
19253 // A list item must be of integral or pointer type.
19254 Type = Type.getUnqualifiedType().getCanonicalType();
19255 const auto *Ty = Type.getTypePtrOrNull();
19256 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19257 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
19258 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19259 if (D) {
19260 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19262 Diag(D->getLocation(),
19263 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19264 << D;
19265 }
19266 return true;
19267 }
19268 return false;
19269}
19270
19272 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19273 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19274 SourceLocation LinLoc, SourceLocation ColonLoc,
19275 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19277 SmallVector<Expr *, 8> Privates;
19279 SmallVector<Decl *, 4> ExprCaptures;
19280 SmallVector<Expr *, 4> ExprPostUpdates;
19281 // OpenMP 5.2 [Section 5.4.6, linear clause]
19282 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19283 // 'ref'
19284 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19285 getLangOpts().OpenMP >= 52)
19286 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19287 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19288 LinKind = OMPC_LINEAR_val;
19289 for (Expr *RefExpr : VarList) {
19290 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19291 SourceLocation ELoc;
19292 SourceRange ERange;
19293 Expr *SimpleRefExpr = RefExpr;
19294 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19295 if (Res.second) {
19296 // It will be analyzed later.
19297 Vars.push_back(RefExpr);
19298 Privates.push_back(nullptr);
19299 Inits.push_back(nullptr);
19300 }
19301 ValueDecl *D = Res.first;
19302 if (!D)
19303 continue;
19304
19305 QualType Type = D->getType();
19306 auto *VD = dyn_cast<VarDecl>(D);
19307
19308 // OpenMP [2.14.3.7, linear clause]
19309 // A list-item cannot appear in more than one linear clause.
19310 // A list-item that appears in a linear clause cannot appear in any
19311 // other data-sharing attribute clause.
19312 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19313 if (DVar.RefExpr) {
19314 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19315 << getOpenMPClauseName(OMPC_linear);
19317 continue;
19318 }
19319
19320 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19321 continue;
19322 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19323
19324 // Build private copy of original var.
19325 VarDecl *Private =
19326 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19327 D->hasAttrs() ? &D->getAttrs() : nullptr,
19328 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19329 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19330 // Build var to save initial value.
19331 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19332 Expr *InitExpr;
19333 DeclRefExpr *Ref = nullptr;
19334 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19335 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19336 if (!isOpenMPCapturedDecl(D)) {
19337 ExprCaptures.push_back(Ref->getDecl());
19338 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19340 if (!RefRes.isUsable())
19341 continue;
19342 ExprResult PostUpdateRes =
19343 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19344 SimpleRefExpr, RefRes.get());
19345 if (!PostUpdateRes.isUsable())
19346 continue;
19347 ExprPostUpdates.push_back(
19348 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19349 }
19350 }
19351 }
19352 if (LinKind == OMPC_LINEAR_uval)
19353 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19354 else
19355 InitExpr = VD ? SimpleRefExpr : Ref;
19358 /*DirectInit=*/false);
19359 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19360
19361 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19362 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19363 ? RefExpr->IgnoreParens()
19364 : Ref);
19365 Privates.push_back(PrivateRef);
19366 Inits.push_back(InitRef);
19367 }
19368
19369 if (Vars.empty())
19370 return nullptr;
19371
19372 Expr *StepExpr = Step;
19373 Expr *CalcStepExpr = nullptr;
19374 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19375 !Step->isInstantiationDependent() &&
19377 SourceLocation StepLoc = Step->getBeginLoc();
19379 if (Val.isInvalid())
19380 return nullptr;
19381 StepExpr = Val.get();
19382
19383 // Build var to save the step value.
19384 VarDecl *SaveVar =
19385 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19386 ExprResult SaveRef =
19387 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19388 ExprResult CalcStep = SemaRef.BuildBinOp(
19389 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19390 CalcStep =
19391 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
19392
19393 // Warn about zero linear step (it would be probably better specified as
19394 // making corresponding variables 'const').
19395 if (std::optional<llvm::APSInt> Result =
19397 if (!Result->isNegative() && !Result->isStrictlyPositive())
19398 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19399 << Vars[0] << (Vars.size() > 1);
19400 } else if (CalcStep.isUsable()) {
19401 // Calculate the step beforehand instead of doing this on each iteration.
19402 // (This is not used if the number of iterations may be kfold-ed).
19403 CalcStepExpr = CalcStep.get();
19404 }
19405 }
19406
19407 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19408 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19409 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19410 buildPreInits(getASTContext(), ExprCaptures),
19411 buildPostUpdate(SemaRef, ExprPostUpdates));
19412}
19413
19415 Expr *NumIterations, Sema &SemaRef,
19416 Scope *S, DSAStackTy *Stack) {
19417 // Walk the vars and build update/final expressions for the CodeGen.
19418 SmallVector<Expr *, 8> Updates;
19420 SmallVector<Expr *, 8> UsedExprs;
19421 Expr *Step = Clause.getStep();
19422 Expr *CalcStep = Clause.getCalcStep();
19423 // OpenMP [2.14.3.7, linear clause]
19424 // If linear-step is not specified it is assumed to be 1.
19425 if (!Step)
19426 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19427 else if (CalcStep)
19428 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19429 bool HasErrors = false;
19430 auto CurInit = Clause.inits().begin();
19431 auto CurPrivate = Clause.privates().begin();
19432 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19433 for (Expr *RefExpr : Clause.varlist()) {
19434 SourceLocation ELoc;
19435 SourceRange ERange;
19436 Expr *SimpleRefExpr = RefExpr;
19437 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19438 ValueDecl *D = Res.first;
19439 if (Res.second || !D) {
19440 Updates.push_back(nullptr);
19441 Finals.push_back(nullptr);
19442 HasErrors = true;
19443 continue;
19444 }
19445 auto &&Info = Stack->isLoopControlVariable(D);
19446 // OpenMP [2.15.11, distribute simd Construct]
19447 // A list item may not appear in a linear clause, unless it is the loop
19448 // iteration variable.
19449 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19450 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19451 SemaRef.Diag(ELoc,
19452 diag::err_omp_linear_distribute_var_non_loop_iteration);
19453 Updates.push_back(nullptr);
19454 Finals.push_back(nullptr);
19455 HasErrors = true;
19456 continue;
19457 }
19458 Expr *InitExpr = *CurInit;
19459
19460 // Build privatized reference to the current linear var.
19461 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19462 Expr *CapturedRef;
19463 if (LinKind == OMPC_LINEAR_uval)
19464 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19465 else
19466 CapturedRef =
19467 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19468 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19469 /*RefersToCapture=*/true);
19470
19471 // Build update: Var = InitExpr + IV * Step
19473 if (!Info.first)
19475 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19476 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19477 else
19478 Update = *CurPrivate;
19479 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19480 /*DiscardedValue=*/false);
19481
19482 // Build final: Var = PrivCopy;
19483 ExprResult Final;
19484 if (!Info.first)
19485 Final = SemaRef.BuildBinOp(
19486 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19487 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19488 else
19489 Final = *CurPrivate;
19490 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19491 /*DiscardedValue=*/false);
19492
19493 if (!Update.isUsable() || !Final.isUsable()) {
19494 Updates.push_back(nullptr);
19495 Finals.push_back(nullptr);
19496 UsedExprs.push_back(nullptr);
19497 HasErrors = true;
19498 } else {
19499 Updates.push_back(Update.get());
19500 Finals.push_back(Final.get());
19501 if (!Info.first)
19502 UsedExprs.push_back(SimpleRefExpr);
19503 }
19504 ++CurInit;
19505 ++CurPrivate;
19506 }
19507 if (Expr *S = Clause.getStep())
19508 UsedExprs.push_back(S);
19509 // Fill the remaining part with the nullptr.
19510 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19511 Clause.setUpdates(Updates);
19512 Clause.setFinals(Finals);
19513 Clause.setUsedExprs(UsedExprs);
19514 return HasErrors;
19515}
19516
19518 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19519 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19521 for (Expr *RefExpr : VarList) {
19522 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19523 SourceLocation ELoc;
19524 SourceRange ERange;
19525 Expr *SimpleRefExpr = RefExpr;
19526 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19527 if (Res.second) {
19528 // It will be analyzed later.
19529 Vars.push_back(RefExpr);
19530 }
19531 ValueDecl *D = Res.first;
19532 if (!D)
19533 continue;
19534
19535 QualType QType = D->getType();
19536 auto *VD = dyn_cast<VarDecl>(D);
19537
19538 // OpenMP [2.8.1, simd construct, Restrictions]
19539 // The type of list items appearing in the aligned clause must be
19540 // array, pointer, reference to array, or reference to pointer.
19542 const Type *Ty = QType.getTypePtrOrNull();
19543 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19544 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19545 << QType << getLangOpts().CPlusPlus << ERange;
19546 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19548 Diag(D->getLocation(),
19549 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19550 << D;
19551 continue;
19552 }
19553
19554 // OpenMP [2.8.1, simd construct, Restrictions]
19555 // A list-item cannot appear in more than one aligned clause.
19556 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19557 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19558 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19559 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19560 << getOpenMPClauseName(OMPC_aligned);
19561 continue;
19562 }
19563
19564 DeclRefExpr *Ref = nullptr;
19565 if (!VD && isOpenMPCapturedDecl(D))
19566 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19567 Vars.push_back(SemaRef
19568 .DefaultFunctionArrayConversion(
19569 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19570 .get());
19571 }
19572
19573 // OpenMP [2.8.1, simd construct, Description]
19574 // The parameter of the aligned clause, alignment, must be a constant
19575 // positive integer expression.
19576 // If no optional parameter is specified, implementation-defined default
19577 // alignments for SIMD instructions on the target platforms are assumed.
19578 if (Alignment != nullptr) {
19579 ExprResult AlignResult =
19580 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19581 if (AlignResult.isInvalid())
19582 return nullptr;
19583 Alignment = AlignResult.get();
19584 }
19585 if (Vars.empty())
19586 return nullptr;
19587
19588 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
19589 ColonLoc, EndLoc, Vars, Alignment);
19590}
19591
19593 SourceLocation StartLoc,
19594 SourceLocation LParenLoc,
19595 SourceLocation EndLoc) {
19597 SmallVector<Expr *, 8> SrcExprs;
19598 SmallVector<Expr *, 8> DstExprs;
19599 SmallVector<Expr *, 8> AssignmentOps;
19600 for (Expr *RefExpr : VarList) {
19601 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19602 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19603 // It will be analyzed later.
19604 Vars.push_back(RefExpr);
19605 SrcExprs.push_back(nullptr);
19606 DstExprs.push_back(nullptr);
19607 AssignmentOps.push_back(nullptr);
19608 continue;
19609 }
19610
19611 SourceLocation ELoc = RefExpr->getExprLoc();
19612 // OpenMP [2.1, C/C++]
19613 // A list item is a variable name.
19614 // OpenMP [2.14.4.1, Restrictions, p.1]
19615 // A list item that appears in a copyin clause must be threadprivate.
19616 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19617 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19618 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19619 << 0 << RefExpr->getSourceRange();
19620 continue;
19621 }
19622
19623 Decl *D = DE->getDecl();
19624 auto *VD = cast<VarDecl>(D);
19625
19626 QualType Type = VD->getType();
19628 // It will be analyzed later.
19629 Vars.push_back(DE);
19630 SrcExprs.push_back(nullptr);
19631 DstExprs.push_back(nullptr);
19632 AssignmentOps.push_back(nullptr);
19633 continue;
19634 }
19635
19636 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19637 // A list item that appears in a copyin clause must be threadprivate.
19638 if (!DSAStack->isThreadPrivate(VD)) {
19639 Diag(ELoc, diag::err_omp_required_access)
19640 << getOpenMPClauseName(OMPC_copyin)
19641 << getOpenMPDirectiveName(OMPD_threadprivate);
19642 continue;
19643 }
19644
19645 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19646 // A variable of class type (or array thereof) that appears in a
19647 // copyin clause requires an accessible, unambiguous copy assignment
19648 // operator for the class type.
19649 QualType ElemType =
19651 VarDecl *SrcVD =
19652 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
19653 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19654 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
19655 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
19656 VarDecl *DstVD =
19657 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
19658 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19659 DeclRefExpr *PseudoDstExpr =
19660 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
19661 // For arrays generate assignment operation for single element and replace
19662 // it by the original array element in CodeGen.
19663 ExprResult AssignmentOp =
19664 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
19665 PseudoDstExpr, PseudoSrcExpr);
19666 if (AssignmentOp.isInvalid())
19667 continue;
19668 AssignmentOp =
19669 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
19670 /*DiscardedValue=*/false);
19671 if (AssignmentOp.isInvalid())
19672 continue;
19673
19674 DSAStack->addDSA(VD, DE, OMPC_copyin);
19675 Vars.push_back(DE);
19676 SrcExprs.push_back(PseudoSrcExpr);
19677 DstExprs.push_back(PseudoDstExpr);
19678 AssignmentOps.push_back(AssignmentOp.get());
19679 }
19680
19681 if (Vars.empty())
19682 return nullptr;
19683
19684 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19685 Vars, SrcExprs, DstExprs, AssignmentOps);
19686}
19687
19689 SourceLocation StartLoc,
19690 SourceLocation LParenLoc,
19691 SourceLocation EndLoc) {
19693 SmallVector<Expr *, 8> SrcExprs;
19694 SmallVector<Expr *, 8> DstExprs;
19695 SmallVector<Expr *, 8> AssignmentOps;
19696 for (Expr *RefExpr : VarList) {
19697 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19698 SourceLocation ELoc;
19699 SourceRange ERange;
19700 Expr *SimpleRefExpr = RefExpr;
19701 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19702 if (Res.second) {
19703 // It will be analyzed later.
19704 Vars.push_back(RefExpr);
19705 SrcExprs.push_back(nullptr);
19706 DstExprs.push_back(nullptr);
19707 AssignmentOps.push_back(nullptr);
19708 }
19709 ValueDecl *D = Res.first;
19710 if (!D)
19711 continue;
19712
19713 QualType Type = D->getType();
19714 auto *VD = dyn_cast<VarDecl>(D);
19715
19716 // OpenMP [2.14.4.2, Restrictions, p.2]
19717 // A list item that appears in a copyprivate clause may not appear in a
19718 // private or firstprivate clause on the single construct.
19719 if (!VD || !DSAStack->isThreadPrivate(VD)) {
19720 DSAStackTy::DSAVarData DVar =
19721 DSAStack->getTopDSA(D, /*FromParent=*/false);
19722 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19723 DVar.RefExpr) {
19724 Diag(ELoc, diag::err_omp_wrong_dsa)
19725 << getOpenMPClauseName(DVar.CKind)
19726 << getOpenMPClauseName(OMPC_copyprivate);
19728 continue;
19729 }
19730
19731 // OpenMP [2.11.4.2, Restrictions, p.1]
19732 // All list items that appear in a copyprivate clause must be either
19733 // threadprivate or private in the enclosing context.
19734 if (DVar.CKind == OMPC_unknown) {
19735 DVar = DSAStack->getImplicitDSA(D, false);
19736 if (DVar.CKind == OMPC_shared) {
19737 Diag(ELoc, diag::err_omp_required_access)
19738 << getOpenMPClauseName(OMPC_copyprivate)
19739 << "threadprivate or private in the enclosing context";
19741 continue;
19742 }
19743 }
19744 }
19745
19746 // Variably modified types are not supported.
19748 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19749 << getOpenMPClauseName(OMPC_copyprivate) << Type
19750 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
19751 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19753 Diag(D->getLocation(),
19754 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19755 << D;
19756 continue;
19757 }
19758
19759 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19760 // A variable of class type (or array thereof) that appears in a
19761 // copyin clause requires an accessible, unambiguous copy assignment
19762 // operator for the class type.
19764 .getBaseElementType(Type.getNonReferenceType())
19766 VarDecl *SrcVD =
19767 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
19768 D->hasAttrs() ? &D->getAttrs() : nullptr);
19769 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
19770 VarDecl *DstVD =
19771 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
19772 D->hasAttrs() ? &D->getAttrs() : nullptr);
19773 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19774 ExprResult AssignmentOp = SemaRef.BuildBinOp(
19775 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19776 if (AssignmentOp.isInvalid())
19777 continue;
19778 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19779 /*DiscardedValue=*/false);
19780 if (AssignmentOp.isInvalid())
19781 continue;
19782
19783 // No need to mark vars as copyprivate, they are already threadprivate or
19784 // implicitly private.
19785 assert(VD || isOpenMPCapturedDecl(D));
19786 Vars.push_back(
19787 VD ? RefExpr->IgnoreParens()
19788 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
19789 SrcExprs.push_back(PseudoSrcExpr);
19790 DstExprs.push_back(PseudoDstExpr);
19791 AssignmentOps.push_back(AssignmentOp.get());
19792 }
19793
19794 if (Vars.empty())
19795 return nullptr;
19796
19797 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
19798 EndLoc, Vars, SrcExprs, DstExprs,
19799 AssignmentOps);
19800}
19801
19803 SourceLocation StartLoc,
19804 SourceLocation LParenLoc,
19805 SourceLocation EndLoc) {
19806 if (VarList.empty())
19807 return nullptr;
19808
19809 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19810 VarList);
19811}
19812
19813/// Tries to find omp_depend_t. type.
19814static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
19815 bool Diagnose = true) {
19816 QualType OMPDependT = Stack->getOMPDependT();
19817 if (!OMPDependT.isNull())
19818 return true;
19819 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
19820 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
19821 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
19822 if (Diagnose)
19823 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
19824 return false;
19825 }
19826 Stack->setOMPDependT(PT.get());
19827 return true;
19828}
19829
19831 SourceLocation StartLoc,
19832 SourceLocation LParenLoc,
19833 SourceLocation EndLoc) {
19834 if (!Depobj)
19835 return nullptr;
19836
19837 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
19838
19839 // OpenMP 5.0, 2.17.10.1 depobj Construct
19840 // depobj is an lvalue expression of type omp_depend_t.
19841 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
19842 !Depobj->isInstantiationDependent() &&
19844 (OMPDependTFound && !getASTContext().typesAreCompatible(
19845 DSAStack->getOMPDependT(), Depobj->getType(),
19846 /*CompareUnqualified=*/true))) {
19847 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19848 << 0 << Depobj->getType() << Depobj->getSourceRange();
19849 }
19850
19851 if (!Depobj->isLValue()) {
19852 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19853 << 1 << Depobj->getSourceRange();
19854 }
19855
19856 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19857 Depobj);
19858}
19859
19860namespace {
19861// Utility struct that gathers the related info for doacross clause.
19862struct DoacrossDataInfoTy {
19863 // The list of expressions.
19865 // The OperatorOffset for doacross loop.
19867 // The depended loop count.
19868 llvm::APSInt TotalDepCount;
19869};
19870} // namespace
19871static DoacrossDataInfoTy
19873 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
19874 SourceLocation EndLoc) {
19875
19878 llvm::APSInt DepCounter(/*BitWidth=*/32);
19879 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19880
19881 if (const Expr *OrderedCountExpr =
19882 Stack->getParentOrderedRegionParam().first) {
19883 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
19884 TotalDepCount.setIsUnsigned(/*Val=*/true);
19885 }
19886
19887 for (Expr *RefExpr : VarList) {
19888 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
19889 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19890 // It will be analyzed later.
19891 Vars.push_back(RefExpr);
19892 continue;
19893 }
19894
19895 SourceLocation ELoc = RefExpr->getExprLoc();
19896 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19897 if (!IsSource) {
19898 if (Stack->getParentOrderedRegionParam().first &&
19899 DepCounter >= TotalDepCount) {
19900 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19901 continue;
19902 }
19903 ++DepCounter;
19904 // OpenMP [2.13.9, Summary]
19905 // depend(dependence-type : vec), where dependence-type is:
19906 // 'sink' and where vec is the iteration vector, which has the form:
19907 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
19908 // where n is the value specified by the ordered clause in the loop
19909 // directive, xi denotes the loop iteration variable of the i-th nested
19910 // loop associated with the loop directive, and di is a constant
19911 // non-negative integer.
19912 if (SemaRef.CurContext->isDependentContext()) {
19913 // It will be analyzed later.
19914 Vars.push_back(RefExpr);
19915 continue;
19916 }
19917 SimpleExpr = SimpleExpr->IgnoreImplicit();
19919 SourceLocation OOLoc;
19920 Expr *LHS = SimpleExpr;
19921 Expr *RHS = nullptr;
19922 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19923 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
19924 OOLoc = BO->getOperatorLoc();
19925 LHS = BO->getLHS()->IgnoreParenImpCasts();
19926 RHS = BO->getRHS()->IgnoreParenImpCasts();
19927 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19928 OOK = OCE->getOperator();
19929 OOLoc = OCE->getOperatorLoc();
19930 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19931 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
19932 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19933 OOK = MCE->getMethodDecl()
19934 ->getNameInfo()
19935 .getName()
19936 .getCXXOverloadedOperator();
19937 OOLoc = MCE->getCallee()->getExprLoc();
19938 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
19939 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19940 }
19941 SourceLocation ELoc;
19942 SourceRange ERange;
19943 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
19944 if (Res.second) {
19945 // It will be analyzed later.
19946 Vars.push_back(RefExpr);
19947 }
19948 ValueDecl *D = Res.first;
19949 if (!D)
19950 continue;
19951
19952 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
19953 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19954 continue;
19955 }
19956 if (RHS) {
19957 ExprResult RHSRes =
19959 RHS, OMPC_depend, /*StrictlyPositive=*/false);
19960 if (RHSRes.isInvalid())
19961 continue;
19962 }
19963 if (!SemaRef.CurContext->isDependentContext() &&
19964 Stack->getParentOrderedRegionParam().first &&
19965 DepCounter != Stack->isParentLoopControlVariable(D).first) {
19966 const ValueDecl *VD =
19967 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19968 if (VD)
19969 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19970 << 1 << VD;
19971 else
19972 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19973 << 0;
19974 continue;
19975 }
19976 OpsOffs.emplace_back(RHS, OOK);
19977 }
19978 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19979 }
19980 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
19981 TotalDepCount > VarList.size() &&
19982 Stack->getParentOrderedRegionParam().first &&
19983 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19984 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19985 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19986 }
19987 return {Vars, OpsOffs, TotalDepCount};
19988}
19989
19991 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
19992 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19993 SourceLocation EndLoc) {
19994 OpenMPDependClauseKind DepKind = Data.DepKind;
19995 SourceLocation DepLoc = Data.DepLoc;
19996 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
19997 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19998 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19999 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
20000 return nullptr;
20001 }
20002 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20003 DepKind == OMPC_DEPEND_mutexinoutset) {
20004 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20005 return nullptr;
20006 }
20007 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20008 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20009 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20010 DepKind == OMPC_DEPEND_sink ||
20011 ((getLangOpts().OpenMP < 50 ||
20012 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20013 DepKind == OMPC_DEPEND_depobj))) {
20014 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20015 OMPC_DEPEND_outallmemory,
20016 OMPC_DEPEND_inoutallmemory};
20017 if (getLangOpts().OpenMP < 50 ||
20018 DSAStack->getCurrentDirective() == OMPD_depobj)
20019 Except.push_back(OMPC_DEPEND_depobj);
20020 if (getLangOpts().OpenMP < 51)
20021 Except.push_back(OMPC_DEPEND_inoutset);
20022 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
20023 ? "depend modifier(iterator) or "
20024 : "";
20025 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20026 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20027 /*Last=*/OMPC_DEPEND_unknown,
20028 Except)
20029 << getOpenMPClauseName(OMPC_depend);
20030 return nullptr;
20031 }
20032 if (DepModifier &&
20033 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20034 Diag(DepModifier->getExprLoc(),
20035 diag::err_omp_depend_sink_source_with_modifier);
20036 return nullptr;
20037 }
20038 if (DepModifier &&
20039 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20040 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20041
20044 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20045
20046 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20047 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20048 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20049 Vars = VarOffset.Vars;
20050 OpsOffs = VarOffset.OpsOffs;
20051 TotalDepCount = VarOffset.TotalDepCount;
20052 } else {
20053 for (Expr *RefExpr : VarList) {
20054 assert(RefExpr && "NULL expr in OpenMP shared clause.");
20055 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20056 // It will be analyzed later.
20057 Vars.push_back(RefExpr);
20058 continue;
20059 }
20060
20061 SourceLocation ELoc = RefExpr->getExprLoc();
20062 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20063 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20064 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
20065 if (OMPDependTFound)
20066 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
20067 DepKind == OMPC_DEPEND_depobj);
20068 if (DepKind == OMPC_DEPEND_depobj) {
20069 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20070 // List items used in depend clauses with the depobj dependence type
20071 // must be expressions of the omp_depend_t type.
20072 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20073 !RefExpr->isInstantiationDependent() &&
20074 !RefExpr->containsUnexpandedParameterPack() &&
20075 (OMPDependTFound &&
20076 !getASTContext().hasSameUnqualifiedType(
20077 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20078 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20079 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20080 continue;
20081 }
20082 if (!RefExpr->isLValue()) {
20083 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20084 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20085 continue;
20086 }
20087 } else {
20088 // OpenMP 5.0 [2.17.11, Restrictions]
20089 // List items used in depend clauses cannot be zero-length array
20090 // sections.
20091 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20092 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
20093 if (OASE) {
20094 QualType BaseType =
20096 if (BaseType.isNull())
20097 return nullptr;
20098 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20099 ExprTy = ATy->getElementType();
20100 else
20101 ExprTy = BaseType->getPointeeType();
20102 if (BaseType.isNull() || ExprTy.isNull())
20103 return nullptr;
20104 ExprTy = ExprTy.getNonReferenceType();
20105 const Expr *Length = OASE->getLength();
20107 if (Length && !Length->isValueDependent() &&
20108 Length->EvaluateAsInt(Result, getASTContext()) &&
20109 Result.Val.getInt().isZero()) {
20110 Diag(ELoc,
20111 diag::err_omp_depend_zero_length_array_section_not_allowed)
20112 << SimpleExpr->getSourceRange();
20113 continue;
20114 }
20115 }
20116
20117 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20118 // List items used in depend clauses with the in, out, inout,
20119 // inoutset, or mutexinoutset dependence types cannot be
20120 // expressions of the omp_depend_t type.
20121 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20122 !RefExpr->isInstantiationDependent() &&
20123 !RefExpr->containsUnexpandedParameterPack() &&
20124 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20125 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20126 ExprTy.getTypePtr()))) {
20127 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20128 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20129 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20130 << RefExpr->getSourceRange();
20131 continue;
20132 }
20133
20134 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20135 if (ASE && !ASE->getBase()->isTypeDependent() &&
20136 !ASE->getBase()
20137 ->getType()
20138 .getNonReferenceType()
20139 ->isPointerType() &&
20140 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20141 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20142 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20143 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20144 << RefExpr->getSourceRange();
20145 continue;
20146 }
20147
20148 ExprResult Res;
20149 {
20151 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20152 RefExpr->IgnoreParenImpCasts());
20153 }
20154 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20155 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20156 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20157 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20158 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20159 << RefExpr->getSourceRange();
20160 continue;
20161 }
20162 }
20163 }
20164 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20165 }
20166 }
20167
20168 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20169 DepKind != OMPC_DEPEND_outallmemory &&
20170 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20171 return nullptr;
20172
20173 auto *C = OMPDependClause::Create(
20174 getASTContext(), StartLoc, LParenLoc, EndLoc,
20175 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20176 TotalDepCount.getZExtValue());
20177 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20178 DSAStack->isParentOrderedRegion())
20179 DSAStack->addDoacrossDependClause(C, OpsOffs);
20180 return C;
20181}
20182
20185 SourceLocation LParenLoc, SourceLocation ModifierLoc,
20186 SourceLocation EndLoc) {
20187 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20188 "Unexpected device modifier in OpenMP < 50.");
20189
20190 bool ErrorFound = false;
20191 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20192 std::string Values =
20193 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20194 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20195 << Values << getOpenMPClauseName(OMPC_device);
20196 ErrorFound = true;
20197 }
20198
20199 Expr *ValExpr = Device;
20200 Stmt *HelperValStmt = nullptr;
20201
20202 // OpenMP [2.9.1, Restrictions]
20203 // The device expression must evaluate to a non-negative integer value.
20204 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20205 /*StrictlyPositive=*/false) ||
20206 ErrorFound;
20207 if (ErrorFound)
20208 return nullptr;
20209
20210 // OpenMP 5.0 [2.12.5, Restrictions]
20211 // In case of ancestor device-modifier, a requires directive with
20212 // the reverse_offload clause must be specified.
20213 if (Modifier == OMPC_DEVICE_ancestor) {
20214 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20216 StartLoc,
20217 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20218 ErrorFound = true;
20219 }
20220 }
20221
20222 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20223 OpenMPDirectiveKind CaptureRegion =
20224 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20225 if (CaptureRegion != OMPD_unknown &&
20227 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20228 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20229 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20230 HelperValStmt = buildPreInits(getASTContext(), Captures);
20231 }
20232
20233 return new (getASTContext())
20234 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20235 LParenLoc, ModifierLoc, EndLoc);
20236}
20237
20239 DSAStackTy *Stack, QualType QTy,
20240 bool FullCheck = true) {
20241 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20242 return false;
20243 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20244 !QTy.isTriviallyCopyableType(SemaRef.Context))
20245 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20246 return true;
20247}
20248
20249/// Return true if it can be proven that the provided array expression
20250/// (array section or array subscript) does NOT specify the whole size of the
20251/// array whose base type is \a BaseQTy.
20253 const Expr *E,
20254 QualType BaseQTy) {
20255 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20256
20257 // If this is an array subscript, it refers to the whole size if the size of
20258 // the dimension is constant and equals 1. Also, an array section assumes the
20259 // format of an array subscript if no colon is used.
20260 if (isa<ArraySubscriptExpr>(E) ||
20261 (OASE && OASE->getColonLocFirst().isInvalid())) {
20262 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20263 return ATy->getSExtSize() != 1;
20264 // Size can't be evaluated statically.
20265 return false;
20266 }
20267
20268 assert(OASE && "Expecting array section if not an array subscript.");
20269 const Expr *LowerBound = OASE->getLowerBound();
20270 const Expr *Length = OASE->getLength();
20271
20272 // If there is a lower bound that does not evaluates to zero, we are not
20273 // covering the whole dimension.
20274 if (LowerBound) {
20276 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20277 return false; // Can't get the integer value as a constant.
20278
20279 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20280 if (ConstLowerBound.getSExtValue())
20281 return true;
20282 }
20283
20284 // If we don't have a length we covering the whole dimension.
20285 if (!Length)
20286 return false;
20287
20288 // If the base is a pointer, we don't have a way to get the size of the
20289 // pointee.
20290 if (BaseQTy->isPointerType())
20291 return false;
20292
20293 // We can only check if the length is the same as the size of the dimension
20294 // if we have a constant array.
20295 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20296 if (!CATy)
20297 return false;
20298
20300 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20301 return false; // Can't get the integer value as a constant.
20302
20303 llvm::APSInt ConstLength = Result.Val.getInt();
20304 return CATy->getSExtSize() != ConstLength.getSExtValue();
20305}
20306
20307// Return true if it can be proven that the provided array expression (array
20308// section or array subscript) does NOT specify a single element of the array
20309// whose base type is \a BaseQTy.
20311 const Expr *E,
20312 QualType BaseQTy) {
20313 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20314
20315 // An array subscript always refer to a single element. Also, an array section
20316 // assumes the format of an array subscript if no colon is used.
20317 if (isa<ArraySubscriptExpr>(E) ||
20318 (OASE && OASE->getColonLocFirst().isInvalid()))
20319 return false;
20320
20321 assert(OASE && "Expecting array section if not an array subscript.");
20322 const Expr *Length = OASE->getLength();
20323
20324 // If we don't have a length we have to check if the array has unitary size
20325 // for this dimension. Also, we should always expect a length if the base type
20326 // is pointer.
20327 if (!Length) {
20328 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20329 return ATy->getSExtSize() != 1;
20330 // We cannot assume anything.
20331 return false;
20332 }
20333
20334 // Check if the length evaluates to 1.
20336 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20337 return false; // Can't get the integer value as a constant.
20338
20339 llvm::APSInt ConstLength = Result.Val.getInt();
20340 return ConstLength.getSExtValue() != 1;
20341}
20342
20343// The base of elements of list in a map clause have to be either:
20344// - a reference to variable or field.
20345// - a member expression.
20346// - an array expression.
20347//
20348// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20349// reference to 'r'.
20350//
20351// If we have:
20352//
20353// struct SS {
20354// Bla S;
20355// foo() {
20356// #pragma omp target map (S.Arr[:12]);
20357// }
20358// }
20359//
20360// We want to retrieve the member expression 'this->S';
20361
20362// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20363// If a list item is an array section, it must specify contiguous storage.
20364//
20365// For this restriction it is sufficient that we make sure only references
20366// to variables or fields and array expressions, and that no array sections
20367// exist except in the rightmost expression (unless they cover the whole
20368// dimension of the array). E.g. these would be invalid:
20369//
20370// r.ArrS[3:5].Arr[6:7]
20371//
20372// r.ArrS[3:5].x
20373//
20374// but these would be valid:
20375// r.ArrS[3].Arr[6:7]
20376//
20377// r.ArrS[3].x
20378namespace {
20379class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20380 Sema &SemaRef;
20381 OpenMPClauseKind CKind = OMPC_unknown;
20382 OpenMPDirectiveKind DKind = OMPD_unknown;
20384 bool IsNonContiguous = false;
20385 bool NoDiagnose = false;
20386 const Expr *RelevantExpr = nullptr;
20387 bool AllowUnitySizeArraySection = true;
20388 bool AllowWholeSizeArraySection = true;
20389 bool AllowAnotherPtr = true;
20390 SourceLocation ELoc;
20391 SourceRange ERange;
20392
20393 void emitErrorMsg() {
20394 // If nothing else worked, this is not a valid map clause expression.
20395 if (SemaRef.getLangOpts().OpenMP < 50) {
20396 SemaRef.Diag(ELoc,
20397 diag::err_omp_expected_named_var_member_or_array_expression)
20398 << ERange;
20399 } else {
20400 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20401 << getOpenMPClauseName(CKind) << ERange;
20402 }
20403 }
20404
20405public:
20406 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20407 if (!isa<VarDecl>(DRE->getDecl())) {
20408 emitErrorMsg();
20409 return false;
20410 }
20411 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20412 RelevantExpr = DRE;
20413 // Record the component.
20414 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20415 return true;
20416 }
20417
20418 bool VisitMemberExpr(MemberExpr *ME) {
20419 Expr *E = ME;
20420 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20421
20422 if (isa<CXXThisExpr>(BaseE)) {
20423 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20424 // We found a base expression: this->Val.
20425 RelevantExpr = ME;
20426 } else {
20427 E = BaseE;
20428 }
20429
20430 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20431 if (!NoDiagnose) {
20432 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20433 << ME->getSourceRange();
20434 return false;
20435 }
20436 if (RelevantExpr)
20437 return false;
20438 return Visit(E);
20439 }
20440
20441 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20442
20443 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20444 // A bit-field cannot appear in a map clause.
20445 //
20446 if (FD->isBitField()) {
20447 if (!NoDiagnose) {
20448 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20449 << ME->getSourceRange() << getOpenMPClauseName(CKind);
20450 return false;
20451 }
20452 if (RelevantExpr)
20453 return false;
20454 return Visit(E);
20455 }
20456
20457 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20458 // If the type of a list item is a reference to a type T then the type
20459 // will be considered to be T for all purposes of this clause.
20460 QualType CurType = BaseE->getType().getNonReferenceType();
20461
20462 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20463 // A list item cannot be a variable that is a member of a structure with
20464 // a union type.
20465 //
20466 if (CurType->isUnionType()) {
20467 if (!NoDiagnose) {
20468 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20469 << ME->getSourceRange();
20470 return false;
20471 }
20472 return RelevantExpr || Visit(E);
20473 }
20474
20475 // If we got a member expression, we should not expect any array section
20476 // before that:
20477 //
20478 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20479 // If a list item is an element of a structure, only the rightmost symbol
20480 // of the variable reference can be an array section.
20481 //
20482 AllowUnitySizeArraySection = false;
20483 AllowWholeSizeArraySection = false;
20484
20485 // Record the component.
20486 Components.emplace_back(ME, FD, IsNonContiguous);
20487 return RelevantExpr || Visit(E);
20488 }
20489
20490 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20491 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20492
20493 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20494 if (!NoDiagnose) {
20495 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20496 << 0 << AE->getSourceRange();
20497 return false;
20498 }
20499 return RelevantExpr || Visit(E);
20500 }
20501
20502 // If we got an array subscript that express the whole dimension we
20503 // can have any array expressions before. If it only expressing part of
20504 // the dimension, we can only have unitary-size array expressions.
20506 AllowWholeSizeArraySection = false;
20507
20508 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20509 Expr::EvalResult Result;
20510 if (!AE->getIdx()->isValueDependent() &&
20511 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20512 !Result.Val.getInt().isZero()) {
20513 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20514 diag::err_omp_invalid_map_this_expr);
20515 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20516 diag::note_omp_invalid_subscript_on_this_ptr_map);
20517 }
20518 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20519 RelevantExpr = TE;
20520 }
20521
20522 // Record the component - we don't have any declaration associated.
20523 Components.emplace_back(AE, nullptr, IsNonContiguous);
20524
20525 return RelevantExpr || Visit(E);
20526 }
20527
20528 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
20529 // After OMP 5.0 Array section in reduction clause will be implicitly
20530 // mapped
20531 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20532 "Array sections cannot be implicitly mapped.");
20533 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20534 QualType CurType =
20536
20537 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20538 // If the type of a list item is a reference to a type T then the type
20539 // will be considered to be T for all purposes of this clause.
20540 if (CurType->isReferenceType())
20541 CurType = CurType->getPointeeType();
20542
20543 bool IsPointer = CurType->isAnyPointerType();
20544
20545 if (!IsPointer && !CurType->isArrayType()) {
20546 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20547 << 0 << OASE->getSourceRange();
20548 return false;
20549 }
20550
20551 bool NotWhole =
20552 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20553 bool NotUnity =
20554 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20555
20556 if (AllowWholeSizeArraySection) {
20557 // Any array section is currently allowed. Allowing a whole size array
20558 // section implies allowing a unity array section as well.
20559 //
20560 // If this array section refers to the whole dimension we can still
20561 // accept other array sections before this one, except if the base is a
20562 // pointer. Otherwise, only unitary sections are accepted.
20563 if (NotWhole || IsPointer)
20564 AllowWholeSizeArraySection = false;
20565 } else if (DKind == OMPD_target_update &&
20566 SemaRef.getLangOpts().OpenMP >= 50) {
20567 if (IsPointer && !AllowAnotherPtr)
20568 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20569 << /*array of unknown bound */ 1;
20570 else
20571 IsNonContiguous = true;
20572 } else if (AllowUnitySizeArraySection && NotUnity) {
20573 // A unity or whole array section is not allowed and that is not
20574 // compatible with the properties of the current array section.
20575 if (NoDiagnose)
20576 return false;
20577 SemaRef.Diag(ELoc,
20578 diag::err_array_section_does_not_specify_contiguous_storage)
20579 << OASE->getSourceRange();
20580 return false;
20581 }
20582
20583 if (IsPointer)
20584 AllowAnotherPtr = false;
20585
20586 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20587 Expr::EvalResult ResultR;
20588 Expr::EvalResult ResultL;
20589 if (!OASE->getLength()->isValueDependent() &&
20590 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20591 !ResultR.Val.getInt().isOne()) {
20592 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20593 diag::err_omp_invalid_map_this_expr);
20594 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20595 diag::note_omp_invalid_length_on_this_ptr_mapping);
20596 }
20597 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20598 OASE->getLowerBound()->EvaluateAsInt(ResultL,
20599 SemaRef.getASTContext()) &&
20600 !ResultL.Val.getInt().isZero()) {
20601 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20602 diag::err_omp_invalid_map_this_expr);
20603 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20604 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20605 }
20606 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20607 RelevantExpr = TE;
20608 }
20609
20610 // Record the component - we don't have any declaration associated.
20611 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20612 return RelevantExpr || Visit(E);
20613 }
20614 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20615 Expr *Base = E->getBase();
20616
20617 // Record the component - we don't have any declaration associated.
20618 Components.emplace_back(E, nullptr, IsNonContiguous);
20619
20620 return Visit(Base->IgnoreParenImpCasts());
20621 }
20622
20623 bool VisitUnaryOperator(UnaryOperator *UO) {
20624 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20625 UO->getOpcode() != UO_Deref) {
20626 emitErrorMsg();
20627 return false;
20628 }
20629 if (!RelevantExpr) {
20630 // Record the component if haven't found base decl.
20631 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20632 }
20633 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20634 }
20635 bool VisitBinaryOperator(BinaryOperator *BO) {
20636 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20637 emitErrorMsg();
20638 return false;
20639 }
20640
20641 // Pointer arithmetic is the only thing we expect to happen here so after we
20642 // make sure the binary operator is a pointer type, the only thing we need
20643 // to do is to visit the subtree that has the same type as root (so that we
20644 // know the other subtree is just an offset)
20645 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20646 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20647 Components.emplace_back(BO, nullptr, false);
20648 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20649 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20650 "Either LHS or RHS have base decl inside");
20651 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20652 return RelevantExpr || Visit(LE);
20653 return RelevantExpr || Visit(RE);
20654 }
20655 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20656 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20657 RelevantExpr = CTE;
20658 Components.emplace_back(CTE, nullptr, IsNonContiguous);
20659 return true;
20660 }
20661 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20662 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20663 Components.emplace_back(COCE, nullptr, IsNonContiguous);
20664 return true;
20665 }
20666 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20667 Expr *Source = E->getSourceExpr();
20668 if (!Source) {
20669 emitErrorMsg();
20670 return false;
20671 }
20672 return Visit(Source);
20673 }
20674 bool VisitStmt(Stmt *) {
20675 emitErrorMsg();
20676 return false;
20677 }
20678 const Expr *getFoundBase() const { return RelevantExpr; }
20679 explicit MapBaseChecker(
20680 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20682 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20683 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20684 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20685};
20686} // namespace
20687
20688/// Return the expression of the base of the mappable expression or null if it
20689/// cannot be determined and do all the necessary checks to see if the
20690/// expression is valid as a standalone mappable expression. In the process,
20691/// record all the components of the expression.
20693 Sema &SemaRef, Expr *E,
20695 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20696 SourceLocation ELoc = E->getExprLoc();
20697 SourceRange ERange = E->getSourceRange();
20698 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20699 ERange);
20700 if (Checker.Visit(E->IgnoreParens())) {
20701 // Check if the highest dimension array section has length specified
20702 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20703 (CKind == OMPC_to || CKind == OMPC_from)) {
20704 auto CI = CurComponents.rbegin();
20705 auto CE = CurComponents.rend();
20706 for (; CI != CE; ++CI) {
20707 const auto *OASE =
20708 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20709 if (!OASE)
20710 continue;
20711 if (OASE && OASE->getLength())
20712 break;
20713 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
20714 << ERange;
20715 }
20716 }
20717 return Checker.getFoundBase();
20718 }
20719 return nullptr;
20720}
20721
20722// Return true if expression E associated with value VD has conflicts with other
20723// map information.
20725 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
20726 bool CurrentRegionOnly,
20728 OpenMPClauseKind CKind) {
20729 assert(VD && E);
20730 SourceLocation ELoc = E->getExprLoc();
20731 SourceRange ERange = E->getSourceRange();
20732
20733 // In order to easily check the conflicts we need to match each component of
20734 // the expression under test with the components of the expressions that are
20735 // already in the stack.
20736
20737 assert(!CurComponents.empty() && "Map clause expression with no components!");
20738 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20739 "Map clause expression with unexpected base!");
20740
20741 // Variables to help detecting enclosing problems in data environment nests.
20742 bool IsEnclosedByDataEnvironmentExpr = false;
20743 const Expr *EnclosingExpr = nullptr;
20744
20745 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20746 VD, CurrentRegionOnly,
20747 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20748 ERange, CKind, &EnclosingExpr,
20750 StackComponents,
20751 OpenMPClauseKind Kind) {
20752 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
20753 return false;
20754 assert(!StackComponents.empty() &&
20755 "Map clause expression with no components!");
20756 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20757 "Map clause expression with unexpected base!");
20758 (void)VD;
20759
20760 // The whole expression in the stack.
20761 const Expr *RE = StackComponents.front().getAssociatedExpression();
20762
20763 // Expressions must start from the same base. Here we detect at which
20764 // point both expressions diverge from each other and see if we can
20765 // detect if the memory referred to both expressions is contiguous and
20766 // do not overlap.
20767 auto CI = CurComponents.rbegin();
20768 auto CE = CurComponents.rend();
20769 auto SI = StackComponents.rbegin();
20770 auto SE = StackComponents.rend();
20771 for (; CI != CE && SI != SE; ++CI, ++SI) {
20772
20773 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
20774 // At most one list item can be an array item derived from a given
20775 // variable in map clauses of the same construct.
20776 if (CurrentRegionOnly &&
20777 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20778 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20779 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20780 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20781 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20782 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20783 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20784 diag::err_omp_multiple_array_items_in_map_clause)
20785 << CI->getAssociatedExpression()->getSourceRange();
20786 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20787 diag::note_used_here)
20788 << SI->getAssociatedExpression()->getSourceRange();
20789 return true;
20790 }
20791
20792 // Do both expressions have the same kind?
20793 if (CI->getAssociatedExpression()->getStmtClass() !=
20794 SI->getAssociatedExpression()->getStmtClass())
20795 break;
20796
20797 // Are we dealing with different variables/fields?
20798 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20799 break;
20800 }
20801 // Check if the extra components of the expressions in the enclosing
20802 // data environment are redundant for the current base declaration.
20803 // If they are, the maps completely overlap, which is legal.
20804 for (; SI != SE; ++SI) {
20805 QualType Type;
20806 if (const auto *ASE =
20807 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20808 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20809 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
20810 SI->getAssociatedExpression())) {
20811 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20812 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20813 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20814 SI->getAssociatedExpression())) {
20815 Type = OASE->getBase()->getType()->getPointeeType();
20816 }
20817 if (Type.isNull() || Type->isAnyPointerType() ||
20819 SemaRef, SI->getAssociatedExpression(), Type))
20820 break;
20821 }
20822
20823 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20824 // List items of map clauses in the same construct must not share
20825 // original storage.
20826 //
20827 // If the expressions are exactly the same or one is a subset of the
20828 // other, it means they are sharing storage.
20829 if (CI == CE && SI == SE) {
20830 if (CurrentRegionOnly) {
20831 if (CKind == OMPC_map) {
20832 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20833 } else {
20834 assert(CKind == OMPC_to || CKind == OMPC_from);
20835 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20836 << ERange;
20837 }
20838 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20839 << RE->getSourceRange();
20840 return true;
20841 }
20842 // If we find the same expression in the enclosing data environment,
20843 // that is legal.
20844 IsEnclosedByDataEnvironmentExpr = true;
20845 return false;
20846 }
20847
20848 QualType DerivedType =
20849 std::prev(CI)->getAssociatedDeclaration()->getType();
20850 SourceLocation DerivedLoc =
20851 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20852
20853 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20854 // If the type of a list item is a reference to a type T then the type
20855 // will be considered to be T for all purposes of this clause.
20856 DerivedType = DerivedType.getNonReferenceType();
20857
20858 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
20859 // A variable for which the type is pointer and an array section
20860 // derived from that variable must not appear as list items of map
20861 // clauses of the same construct.
20862 //
20863 // Also, cover one of the cases in:
20864 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20865 // If any part of the original storage of a list item has corresponding
20866 // storage in the device data environment, all of the original storage
20867 // must have corresponding storage in the device data environment.
20868 //
20869 if (DerivedType->isAnyPointerType()) {
20870 if (CI == CE || SI == SE) {
20871 SemaRef.Diag(
20872 DerivedLoc,
20873 diag::err_omp_pointer_mapped_along_with_derived_section)
20874 << DerivedLoc;
20875 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20876 << RE->getSourceRange();
20877 return true;
20878 }
20879 if (CI->getAssociatedExpression()->getStmtClass() !=
20880 SI->getAssociatedExpression()->getStmtClass() ||
20881 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20882 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20883 assert(CI != CE && SI != SE);
20884 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20885 << DerivedLoc;
20886 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20887 << RE->getSourceRange();
20888 return true;
20889 }
20890 }
20891
20892 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20893 // List items of map clauses in the same construct must not share
20894 // original storage.
20895 //
20896 // An expression is a subset of the other.
20897 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20898 if (CKind == OMPC_map) {
20899 if (CI != CE || SI != SE) {
20900 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
20901 // a pointer.
20902 auto Begin =
20903 CI != CE ? CurComponents.begin() : StackComponents.begin();
20904 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20905 auto It = Begin;
20906 while (It != End && !It->getAssociatedDeclaration())
20907 std::advance(It, 1);
20908 assert(It != End &&
20909 "Expected at least one component with the declaration.");
20910 if (It != Begin && It->getAssociatedDeclaration()
20911 ->getType()
20912 .getCanonicalType()
20913 ->isAnyPointerType()) {
20914 IsEnclosedByDataEnvironmentExpr = false;
20915 EnclosingExpr = nullptr;
20916 return false;
20917 }
20918 }
20919 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20920 } else {
20921 assert(CKind == OMPC_to || CKind == OMPC_from);
20922 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20923 << ERange;
20924 }
20925 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20926 << RE->getSourceRange();
20927 return true;
20928 }
20929
20930 // The current expression uses the same base as other expression in the
20931 // data environment but does not contain it completely.
20932 if (!CurrentRegionOnly && SI != SE)
20933 EnclosingExpr = RE;
20934
20935 // The current expression is a subset of the expression in the data
20936 // environment.
20937 IsEnclosedByDataEnvironmentExpr |=
20938 (!CurrentRegionOnly && CI != CE && SI == SE);
20939
20940 return false;
20941 });
20942
20943 if (CurrentRegionOnly)
20944 return FoundError;
20945
20946 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20947 // If any part of the original storage of a list item has corresponding
20948 // storage in the device data environment, all of the original storage must
20949 // have corresponding storage in the device data environment.
20950 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
20951 // If a list item is an element of a structure, and a different element of
20952 // the structure has a corresponding list item in the device data environment
20953 // prior to a task encountering the construct associated with the map clause,
20954 // then the list item must also have a corresponding list item in the device
20955 // data environment prior to the task encountering the construct.
20956 //
20957 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20958 SemaRef.Diag(ELoc,
20959 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20960 << ERange;
20961 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
20962 << EnclosingExpr->getSourceRange();
20963 return true;
20964 }
20965
20966 return FoundError;
20967}
20968
20969// Look up the user-defined mapper given the mapper name and mapped type, and
20970// build a reference to it.
20972 CXXScopeSpec &MapperIdScopeSpec,
20973 const DeclarationNameInfo &MapperId,
20974 QualType Type,
20975 Expr *UnresolvedMapper) {
20976 if (MapperIdScopeSpec.isInvalid())
20977 return ExprError();
20978 // Get the actual type for the array type.
20979 if (Type->isArrayType()) {
20980 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
20982 }
20983 // Find all user-defined mappers with the given MapperId.
20984 SmallVector<UnresolvedSet<8>, 4> Lookups;
20985 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
20986 Lookup.suppressDiagnostics();
20987 if (S) {
20988 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
20989 /*ObjectType=*/QualType())) {
20990 NamedDecl *D = Lookup.getRepresentativeDecl();
20991 while (S && !S->isDeclScope(D))
20992 S = S->getParent();
20993 if (S)
20994 S = S->getParent();
20995 Lookups.emplace_back();
20996 Lookups.back().append(Lookup.begin(), Lookup.end());
20997 Lookup.clear();
20998 }
20999 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21000 // Extract the user-defined mappers with the given MapperId.
21001 Lookups.push_back(UnresolvedSet<8>());
21002 for (NamedDecl *D : ULE->decls()) {
21003 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21004 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21005 Lookups.back().addDecl(DMD);
21006 }
21007 }
21008 // Defer the lookup for dependent types. The results will be passed through
21009 // UnresolvedMapper on instantiation.
21010 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21013 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21014 return !D->isInvalidDecl() &&
21015 (D->getType()->isDependentType() ||
21016 D->getType()->isInstantiationDependentType() ||
21017 D->getType()->containsUnexpandedParameterPack());
21018 })) {
21019 UnresolvedSet<8> URS;
21020 for (const UnresolvedSet<8> &Set : Lookups) {
21021 if (Set.empty())
21022 continue;
21023 URS.append(Set.begin(), Set.end());
21024 }
21026 SemaRef.Context, /*NamingClass=*/nullptr,
21027 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21028 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
21029 /*KnownInstantiationDependent=*/false);
21030 }
21031 SourceLocation Loc = MapperId.getLoc();
21032 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21033 // The type must be of struct, union or class type in C and C++
21035 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21036 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21037 return ExprError();
21038 }
21039 // Perform argument dependent lookup.
21040 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21041 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21042 // Return the first user-defined mapper with the desired type.
21043 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21044 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21045 if (!D->isInvalidDecl() &&
21046 SemaRef.Context.hasSameType(D->getType(), Type))
21047 return D;
21048 return nullptr;
21049 }))
21050 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21051 // Find the first user-defined mapper with a type derived from the desired
21052 // type.
21053 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21054 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21055 if (!D->isInvalidDecl() &&
21056 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21057 !Type.isMoreQualifiedThan(D->getType(),
21058 SemaRef.getASTContext()))
21059 return D;
21060 return nullptr;
21061 })) {
21062 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21063 /*DetectVirtual=*/false);
21064 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21065 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21066 VD->getType().getUnqualifiedType()))) {
21067 if (SemaRef.CheckBaseClassAccess(
21068 Loc, VD->getType(), Type, Paths.front(),
21069 /*DiagID=*/0) != Sema::AR_inaccessible) {
21070 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21071 }
21072 }
21073 }
21074 }
21075 // Report error if a mapper is specified, but cannot be found.
21076 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21077 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21078 << Type << MapperId.getName();
21079 return ExprError();
21080 }
21081 return ExprEmpty();
21082}
21083
21084namespace {
21085// Utility struct that gathers all the related lists associated with a mappable
21086// expression.
21087struct MappableVarListInfo {
21088 // The list of expressions.
21089 ArrayRef<Expr *> VarList;
21090 // The list of processed expressions.
21091 SmallVector<Expr *, 16> ProcessedVarList;
21092 // The mappble components for each expression.
21094 // The base declaration of the variable.
21095 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21096 // The reference to the user-defined mapper associated with every expression.
21097 SmallVector<Expr *, 16> UDMapperList;
21098
21099 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21100 // We have a list of components and base declarations for each entry in the
21101 // variable list.
21102 VarComponents.reserve(VarList.size());
21103 VarBaseDeclarations.reserve(VarList.size());
21104 }
21105};
21106} // namespace
21107
21109 DSAStackTy *Stack,
21111
21112 const RecordDecl *RD = BaseType->getAsRecordDecl();
21114 DeclarationNameInfo ImplicitName;
21115 // Dummy variable _s for Mapper.
21116 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
21117 DeclRefExpr *MapperVarRef =
21118 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
21119
21120 // Create implicit map clause for mapper.
21122 for (auto *FD : RD->fields()) {
21123 Expr *BE = S.BuildMemberExpr(
21124 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
21127 /*HadMultipleCandidates=*/false,
21129 FD->getType(), VK_LValue, OK_Ordinary);
21130 SExprs.push_back(BE);
21131 }
21132 CXXScopeSpec MapperIdScopeSpec;
21133 DeclarationNameInfo MapperId;
21134 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21135
21136 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21137 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
21138 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21139 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
21140 OMPVarListLocTy());
21141 Maps.push_back(MapClause);
21142 return MapperVarRef;
21143}
21144
21146 DSAStackTy *Stack) {
21147
21148 // Build impilicit map for mapper
21150 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21151
21152 const RecordDecl *RD = BaseType->getAsRecordDecl();
21153 // AST context is RD's ParentASTContext().
21154 ASTContext &Ctx = RD->getParentASTContext();
21155 // DeclContext is RD's DeclContext.
21156 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21157
21158 // Create implicit default mapper for "RD".
21159 DeclarationName MapperId;
21160 auto &DeclNames = Ctx.DeclarationNames;
21161 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
21162 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
21163 BaseType, MapperId, Maps, nullptr);
21164 Scope *Scope = S.getScopeForContext(DCT);
21165 if (Scope)
21166 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
21167 DCT->addDecl(DMD);
21168 DMD->setAccess(clang::AS_none);
21169 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21170 VD->setDeclContext(DMD);
21171 VD->setLexicalDeclContext(DMD);
21172 DMD->addDecl(VD);
21173 DMD->setMapperVarRef(MapperVarRef);
21174 FieldDecl *FD = *RD->field_begin();
21175 // create mapper refence.
21177 DMD, false, SourceLocation(), BaseType, VK_LValue);
21178}
21179
21180// Look up the user-defined mapper given the mapper name and mapper type,
21181// return true if found one.
21182static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21183 CXXScopeSpec &MapperIdScopeSpec,
21184 const DeclarationNameInfo &MapperId,
21185 QualType Type) {
21186 // Find all user-defined mappers with the given MapperId.
21187 SmallVector<UnresolvedSet<8>, 4> Lookups;
21188 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21189 Lookup.suppressDiagnostics();
21190 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21191 /*ObjectType=*/QualType())) {
21192 NamedDecl *D = Lookup.getRepresentativeDecl();
21193 while (S && !S->isDeclScope(D))
21194 S = S->getParent();
21195 if (S)
21196 S = S->getParent();
21197 Lookups.emplace_back();
21198 Lookups.back().append(Lookup.begin(), Lookup.end());
21199 Lookup.clear();
21200 }
21201 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21204 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21205 return !D->isInvalidDecl() &&
21206 (D->getType()->isDependentType() ||
21207 D->getType()->isInstantiationDependentType() ||
21208 D->getType()->containsUnexpandedParameterPack());
21209 }))
21210 return false;
21211 // Perform argument dependent lookup.
21212 SourceLocation Loc = MapperId.getLoc();
21213 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21214 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21215 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21216 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21217 if (!D->isInvalidDecl() &&
21218 SemaRef.Context.hasSameType(D->getType(), Type))
21219 return D;
21220 return nullptr;
21221 }))
21222 return true;
21223 // Find the first user-defined mapper with a type derived from the desired
21224 // type.
21225 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21226 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21227 if (!D->isInvalidDecl() &&
21228 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21229 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
21230 return D;
21231 return nullptr;
21232 });
21233 if (!VD)
21234 return false;
21235 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21236 /*DetectVirtual=*/false);
21237 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21238 bool IsAmbiguous = !Paths.isAmbiguous(
21240 if (IsAmbiguous)
21241 return false;
21242 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
21243 /*DiagID=*/0) != Sema::AR_inaccessible)
21244 return true;
21245 }
21246 return false;
21247}
21248
21249static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21250 QualType CanonType, const Expr *E) {
21251
21252 // DFS over data members in structures/classes.
21254 {CanonType, nullptr});
21255 llvm::DenseMap<const Type *, bool> Visited;
21256 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21257 while (!Types.empty()) {
21258 auto [BaseType, CurFD] = Types.pop_back_val();
21259 while (ParentChain.back().second == 0)
21260 ParentChain.pop_back();
21261 --ParentChain.back().second;
21262 if (BaseType.isNull())
21263 continue;
21264 // Only structs/classes are allowed to have mappers.
21265 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21266 if (!RD)
21267 continue;
21268 auto It = Visited.find(BaseType.getTypePtr());
21269 if (It == Visited.end()) {
21270 // Try to find the associated user-defined mapper.
21271 CXXScopeSpec MapperIdScopeSpec;
21272 DeclarationNameInfo DefaultMapperId;
21274 &S.Context.Idents.get("default")));
21275 DefaultMapperId.setLoc(E->getExprLoc());
21276 bool HasUDMapper =
21277 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
21278 DefaultMapperId, BaseType);
21279 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21280 }
21281 // Found default mapper.
21282 if (It->second)
21283 return true;
21284 // Check for the "default" mapper for data members.
21285 bool FirstIter = true;
21286 for (FieldDecl *FD : RD->fields()) {
21287 if (!FD)
21288 continue;
21289 QualType FieldTy = FD->getType();
21290 if (FieldTy.isNull() ||
21291 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21292 continue;
21293 if (FirstIter) {
21294 FirstIter = false;
21295 ParentChain.emplace_back(CurFD, 1);
21296 } else {
21297 ++ParentChain.back().second;
21298 }
21299 Types.emplace_back(FieldTy, FD);
21300 }
21301 }
21302 return false;
21303}
21304
21305// Check the validity of the provided variable list for the provided clause kind
21306// \a CKind. In the check process the valid expressions, mappable expression
21307// components, variables, and user-defined mappers are extracted and used to
21308// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21309// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21310// and \a MapperId are expected to be valid if the clause kind is 'map'.
21312 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21313 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21314 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21315 ArrayRef<Expr *> UnresolvedMappers,
21317 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
21318 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21319 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21320 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21321 "Unexpected clause kind with mappable expressions!");
21322
21323 // If the identifier of user-defined mapper is not specified, it is "default".
21324 // We do not change the actual name in this clause to distinguish whether a
21325 // mapper is specified explicitly, i.e., it is not explicitly specified when
21326 // MapperId.getName() is empty.
21327 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21328 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21329 MapperId.setName(DeclNames.getIdentifier(
21330 &SemaRef.getASTContext().Idents.get("default")));
21331 MapperId.setLoc(StartLoc);
21332 }
21333
21334 // Iterators to find the current unresolved mapper expression.
21335 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21336 bool UpdateUMIt = false;
21337 Expr *UnresolvedMapper = nullptr;
21338
21339 bool HasHoldModifier =
21340 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21341
21342 // Keep track of the mappable components and base declarations in this clause.
21343 // Each entry in the list is going to have a list of components associated. We
21344 // record each set of the components so that we can build the clause later on.
21345 // In the end we should have the same amount of declarations and component
21346 // lists.
21347
21348 for (Expr *RE : MVLI.VarList) {
21349 assert(RE && "Null expr in omp to/from/map clause");
21350 SourceLocation ELoc = RE->getExprLoc();
21351
21352 // Find the current unresolved mapper expression.
21353 if (UpdateUMIt && UMIt != UMEnd) {
21354 UMIt++;
21355 assert(
21356 UMIt != UMEnd &&
21357 "Expect the size of UnresolvedMappers to match with that of VarList");
21358 }
21359 UpdateUMIt = true;
21360 if (UMIt != UMEnd)
21361 UnresolvedMapper = *UMIt;
21362
21363 const Expr *VE = RE->IgnoreParenLValueCasts();
21364
21365 if (VE->isValueDependent() || VE->isTypeDependent() ||
21368 // Try to find the associated user-defined mapper.
21370 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21371 VE->getType().getCanonicalType(), UnresolvedMapper);
21372 if (ER.isInvalid())
21373 continue;
21374 MVLI.UDMapperList.push_back(ER.get());
21375 // We can only analyze this information once the missing information is
21376 // resolved.
21377 MVLI.ProcessedVarList.push_back(RE);
21378 continue;
21379 }
21380
21381 Expr *SimpleExpr = RE->IgnoreParenCasts();
21382
21383 if (!RE->isLValue()) {
21384 if (SemaRef.getLangOpts().OpenMP < 50) {
21385 SemaRef.Diag(
21386 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21387 << RE->getSourceRange();
21388 } else {
21389 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21390 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21391 }
21392 continue;
21393 }
21394
21396 ValueDecl *CurDeclaration = nullptr;
21397
21398 // Obtain the array or member expression bases if required. Also, fill the
21399 // components array with all the components identified in the process.
21400 const Expr *BE =
21401 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21402 DSAS->getCurrentDirective(), NoDiagnose);
21403 if (!BE)
21404 continue;
21405
21406 assert(!CurComponents.empty() &&
21407 "Invalid mappable expression information.");
21408
21409 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21410 // Add store "this" pointer to class in DSAStackTy for future checking
21411 DSAS->addMappedClassesQualTypes(TE->getType());
21412 // Try to find the associated user-defined mapper.
21414 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21415 VE->getType().getCanonicalType(), UnresolvedMapper);
21416 if (ER.isInvalid())
21417 continue;
21418 MVLI.UDMapperList.push_back(ER.get());
21419 // Skip restriction checking for variable or field declarations
21420 MVLI.ProcessedVarList.push_back(RE);
21421 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21422 MVLI.VarComponents.back().append(CurComponents.begin(),
21423 CurComponents.end());
21424 MVLI.VarBaseDeclarations.push_back(nullptr);
21425 continue;
21426 }
21427
21428 // For the following checks, we rely on the base declaration which is
21429 // expected to be associated with the last component. The declaration is
21430 // expected to be a variable or a field (if 'this' is being mapped).
21431 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21432 assert(CurDeclaration && "Null decl on map clause.");
21433 assert(
21434 CurDeclaration->isCanonicalDecl() &&
21435 "Expecting components to have associated only canonical declarations.");
21436
21437 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21438 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21439
21440 assert((VD || FD) && "Only variables or fields are expected here!");
21441 (void)FD;
21442
21443 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21444 // threadprivate variables cannot appear in a map clause.
21445 // OpenMP 4.5 [2.10.5, target update Construct]
21446 // threadprivate variables cannot appear in a from clause.
21447 if (VD && DSAS->isThreadPrivate(VD)) {
21448 if (NoDiagnose)
21449 continue;
21450 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21451 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21452 << getOpenMPClauseName(CKind);
21453 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21454 continue;
21455 }
21456
21457 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21458 // A list item cannot appear in both a map clause and a data-sharing
21459 // attribute clause on the same construct.
21460
21461 // Check conflicts with other map clause expressions. We check the conflicts
21462 // with the current construct separately from the enclosing data
21463 // environment, because the restrictions are different. We only have to
21464 // check conflicts across regions for the map clauses.
21465 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21466 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21467 break;
21468 if (CKind == OMPC_map &&
21469 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21470 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21471 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21472 break;
21473
21474 // OpenMP 4.5 [2.10.5, target update Construct]
21475 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21476 // If the type of a list item is a reference to a type T then the type will
21477 // be considered to be T for all purposes of this clause.
21478 auto I = llvm::find_if(
21479 CurComponents,
21481 return MC.getAssociatedDeclaration();
21482 });
21483 assert(I != CurComponents.end() && "Null decl on map clause.");
21484 (void)I;
21485 QualType Type;
21486 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21487 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
21488 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21489 if (ASE) {
21490 Type = ASE->getType().getNonReferenceType();
21491 } else if (OASE) {
21492 QualType BaseType =
21494 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21495 Type = ATy->getElementType();
21496 else
21497 Type = BaseType->getPointeeType();
21498 Type = Type.getNonReferenceType();
21499 } else if (OAShE) {
21500 Type = OAShE->getBase()->getType()->getPointeeType();
21501 } else {
21502 Type = VE->getType();
21503 }
21504
21505 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21506 // A list item in a to or from clause must have a mappable type.
21507 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21508 // A list item must have a mappable type.
21509 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21510 DSAS, Type, /*FullCheck=*/true))
21511 continue;
21512
21513 if (CKind == OMPC_map) {
21514 // target enter data
21515 // OpenMP [2.10.2, Restrictions, p. 99]
21516 // A map-type must be specified in all map clauses and must be either
21517 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21518 // no map type is present.
21519 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21520 if (DKind == OMPD_target_enter_data &&
21521 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21522 SemaRef.getLangOpts().OpenMP >= 52)) {
21523 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21524 << (IsMapTypeImplicit ? 1 : 0)
21525 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21526 << getOpenMPDirectiveName(DKind);
21527 continue;
21528 }
21529
21530 // target exit_data
21531 // OpenMP [2.10.3, Restrictions, p. 102]
21532 // A map-type must be specified in all map clauses and must be either
21533 // from, release, or delete. Starting with OpenMP 5.2 the default map
21534 // type is `from` if no map type is present.
21535 if (DKind == OMPD_target_exit_data &&
21536 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21537 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21538 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21539 << (IsMapTypeImplicit ? 1 : 0)
21540 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21541 << getOpenMPDirectiveName(DKind);
21542 continue;
21543 }
21544
21545 // The 'ompx_hold' modifier is specifically intended to be used on a
21546 // 'target' or 'target data' directive to prevent data from being unmapped
21547 // during the associated statement. It is not permitted on a 'target
21548 // enter data' or 'target exit data' directive, which have no associated
21549 // statement.
21550 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21551 HasHoldModifier) {
21552 SemaRef.Diag(StartLoc,
21553 diag::err_omp_invalid_map_type_modifier_for_directive)
21555 OMPC_MAP_MODIFIER_ompx_hold)
21556 << getOpenMPDirectiveName(DKind);
21557 continue;
21558 }
21559
21560 // target, target data
21561 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21562 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21563 // A map-type in a map clause must be to, from, tofrom or alloc
21564 if ((DKind == OMPD_target_data ||
21566 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21567 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21568 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21569 << (IsMapTypeImplicit ? 1 : 0)
21570 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21571 << getOpenMPDirectiveName(DKind);
21572 continue;
21573 }
21574
21575 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21576 // A list item cannot appear in both a map clause and a data-sharing
21577 // attribute clause on the same construct
21578 //
21579 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21580 // A list item cannot appear in both a map clause and a data-sharing
21581 // attribute clause on the same construct unless the construct is a
21582 // combined construct.
21583 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21585 DKind == OMPD_target)) {
21586 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21587 if (isOpenMPPrivate(DVar.CKind)) {
21588 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21589 << getOpenMPClauseName(DVar.CKind)
21590 << getOpenMPClauseName(OMPC_map)
21591 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21592 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21593 continue;
21594 }
21595 }
21596 }
21597
21598 // Try to find the associated user-defined mapper.
21600 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21601 Type.getCanonicalType(), UnresolvedMapper);
21602 if (ER.isInvalid())
21603 continue;
21604 if (!ER.get() && isa<ArraySectionExpr>(VE)) {
21605 // Create implicit mapper as needed.
21606 QualType BaseType = VE->getType().getCanonicalType();
21607 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
21608 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
21610 QualType ElemType;
21611 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
21612 ElemType = ATy->getElementType();
21613 else
21614 ElemType = BType->getPointeeType();
21615 BaseType = ElemType.getCanonicalType();
21616 }
21617 if (BaseType->getAsRecordDecl() &&
21618 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
21619 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
21620 }
21621 }
21622 MVLI.UDMapperList.push_back(ER.get());
21623
21624 // Save the current expression.
21625 MVLI.ProcessedVarList.push_back(RE);
21626
21627 // Store the components in the stack so that they can be used to check
21628 // against other clauses later on.
21629 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21630 /*WhereFoundClauseKind=*/OMPC_map);
21631
21632 // Save the components and declaration to create the clause. For purposes of
21633 // the clause creation, any component list that has base 'this' uses
21634 // null as base declaration.
21635 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21636 MVLI.VarComponents.back().append(CurComponents.begin(),
21637 CurComponents.end());
21638 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21639 : CurDeclaration);
21640 }
21641}
21642
21644 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21645 ArrayRef<SourceLocation> MapTypeModifiersLoc,
21646 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21647 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21648 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21649 const OMPVarListLocTy &Locs, bool NoDiagnose,
21650 ArrayRef<Expr *> UnresolvedMappers) {
21651 OpenMPMapModifierKind Modifiers[] = {
21656
21657 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
21658 BuiltinType::OMPIterator))
21659 Diag(IteratorModifier->getExprLoc(),
21660 diag::err_omp_map_modifier_not_iterator);
21661
21662 // Process map-type-modifiers, flag errors for duplicate modifiers.
21663 unsigned Count = 0;
21664 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21665 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21666 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21667 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21668 continue;
21669 }
21670 assert(Count < NumberOfOMPMapClauseModifiers &&
21671 "Modifiers exceed the allowed number of map type modifiers");
21672 Modifiers[Count] = MapTypeModifiers[I];
21673 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21674 ++Count;
21675 }
21676
21677 MappableVarListInfo MVLI(VarList);
21679 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21680 MapType, Modifiers, IsMapTypeImplicit,
21681 NoDiagnose);
21682
21683 // We need to produce a map clause even if we don't have variables so that
21684 // other diagnostics related with non-existing map clauses are accurate.
21685 return OMPMapClause::Create(
21686 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21687 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21688 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
21689 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21690}
21691
21694 assert(ParsedType.isUsable());
21695
21696 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
21697 if (ReductionType.isNull())
21698 return QualType();
21699
21700 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21701 // A type name in a declare reduction directive cannot be a function type, an
21702 // array type, a reference type, or a type qualified with const, volatile or
21703 // restrict.
21704 if (ReductionType.hasQualifiers()) {
21705 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21706 return QualType();
21707 }
21708
21709 if (ReductionType->isFunctionType()) {
21710 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21711 return QualType();
21712 }
21713 if (ReductionType->isReferenceType()) {
21714 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21715 return QualType();
21716 }
21717 if (ReductionType->isArrayType()) {
21718 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21719 return QualType();
21720 }
21721 return ReductionType;
21722}
21723
21726 Scope *S, DeclContext *DC, DeclarationName Name,
21727 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21728 AccessSpecifier AS, Decl *PrevDeclInScope) {
21730 Decls.reserve(ReductionTypes.size());
21731
21732 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21735 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21736 // A reduction-identifier may not be re-declared in the current scope for the
21737 // same type or for a type that is compatible according to the base language
21738 // rules.
21739 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21740 OMPDeclareReductionDecl *PrevDRD = nullptr;
21741 bool InCompoundScope = true;
21742 if (S != nullptr) {
21743 // Find previous declaration with the same name not referenced in other
21744 // declarations.
21746 InCompoundScope =
21747 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21748 SemaRef.LookupName(Lookup, S);
21749 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21750 /*AllowInlineNamespace=*/false);
21751 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21752 LookupResult::Filter Filter = Lookup.makeFilter();
21753 while (Filter.hasNext()) {
21754 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21755 if (InCompoundScope) {
21756 UsedAsPrevious.try_emplace(PrevDecl, false);
21757 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21758 UsedAsPrevious[D] = true;
21759 }
21760 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21761 PrevDecl->getLocation();
21762 }
21763 Filter.done();
21764 if (InCompoundScope) {
21765 for (const auto &PrevData : UsedAsPrevious) {
21766 if (!PrevData.second) {
21767 PrevDRD = PrevData.first;
21768 break;
21769 }
21770 }
21771 }
21772 } else if (PrevDeclInScope != nullptr) {
21773 auto *PrevDRDInScope = PrevDRD =
21774 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21775 do {
21776 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21777 PrevDRDInScope->getLocation();
21778 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21779 } while (PrevDRDInScope != nullptr);
21780 }
21781 for (const auto &TyData : ReductionTypes) {
21782 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21783 bool Invalid = false;
21784 if (I != PreviousRedeclTypes.end()) {
21785 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21786 << TyData.first;
21787 Diag(I->second, diag::note_previous_definition);
21788 Invalid = true;
21789 }
21790 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21792 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21793 DC->addDecl(DRD);
21794 DRD->setAccess(AS);
21795 Decls.push_back(DRD);
21796 if (Invalid)
21797 DRD->setInvalidDecl();
21798 else
21799 PrevDRD = DRD;
21800 }
21801
21802 return DeclGroupPtrTy::make(
21803 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
21804}
21805
21807 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21808
21809 // Enter new function scope.
21813
21814 if (S != nullptr)
21815 SemaRef.PushDeclContext(S, DRD);
21816 else
21817 SemaRef.CurContext = DRD;
21818
21821
21822 QualType ReductionType = DRD->getType();
21823 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21824 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21825 // uses semantics of argument handles by value, but it should be passed by
21826 // reference. C lang does not support references, so pass all parameters as
21827 // pointers.
21828 // Create 'T omp_in;' variable.
21829 VarDecl *OmpInParm =
21830 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
21831 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21832 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21833 // uses semantics of argument handles by value, but it should be passed by
21834 // reference. C lang does not support references, so pass all parameters as
21835 // pointers.
21836 // Create 'T omp_out;' variable.
21837 VarDecl *OmpOutParm =
21838 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
21839 if (S != nullptr) {
21840 SemaRef.PushOnScopeChains(OmpInParm, S);
21841 SemaRef.PushOnScopeChains(OmpOutParm, S);
21842 } else {
21843 DRD->addDecl(OmpInParm);
21844 DRD->addDecl(OmpOutParm);
21845 }
21846 Expr *InE =
21847 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
21848 Expr *OutE =
21849 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
21850 DRD->setCombinerData(InE, OutE);
21851}
21852
21854 Expr *Combiner) {
21855 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21858
21861
21862 if (Combiner != nullptr)
21863 DRD->setCombiner(Combiner);
21864 else
21865 DRD->setInvalidDecl();
21866}
21867
21869 Decl *D) {
21870 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21871
21872 // Enter new function scope.
21875
21876 if (S != nullptr)
21877 SemaRef.PushDeclContext(S, DRD);
21878 else
21879 SemaRef.CurContext = DRD;
21880
21883
21884 QualType ReductionType = DRD->getType();
21885 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21886 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21887 // uses semantics of argument handles by value, but it should be passed by
21888 // reference. C lang does not support references, so pass all parameters as
21889 // pointers.
21890 // Create 'T omp_priv;' variable.
21891 VarDecl *OmpPrivParm =
21892 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
21893 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21894 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21895 // uses semantics of argument handles by value, but it should be passed by
21896 // reference. C lang does not support references, so pass all parameters as
21897 // pointers.
21898 // Create 'T omp_orig;' variable.
21899 VarDecl *OmpOrigParm =
21900 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
21901 if (S != nullptr) {
21902 SemaRef.PushOnScopeChains(OmpPrivParm, S);
21903 SemaRef.PushOnScopeChains(OmpOrigParm, S);
21904 } else {
21905 DRD->addDecl(OmpPrivParm);
21906 DRD->addDecl(OmpOrigParm);
21907 }
21908 Expr *OrigE =
21909 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
21910 Expr *PrivE =
21911 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
21912 DRD->setInitializerData(OrigE, PrivE);
21913 return OmpPrivParm;
21914}
21915
21917 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
21918 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21921
21924
21925 if (Initializer != nullptr) {
21926 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
21927 } else if (OmpPrivParm->hasInit()) {
21928 DRD->setInitializer(OmpPrivParm->getInit(),
21929 OmpPrivParm->isDirectInit()
21932 } else {
21933 DRD->setInvalidDecl();
21934 }
21935}
21936
21938 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
21939 for (Decl *D : DeclReductions.get()) {
21940 if (IsValid) {
21941 if (S)
21942 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
21943 /*AddToContext=*/false);
21944 } else {
21945 D->setInvalidDecl();
21946 }
21947 }
21948 return DeclReductions;
21949}
21950
21952 Declarator &D) {
21954 QualType T = TInfo->getType();
21955 if (D.isInvalidType())
21956 return true;
21957
21958 if (getLangOpts().CPlusPlus) {
21959 // Check that there are no default arguments (C++ only).
21961 }
21962
21963 return SemaRef.CreateParsedType(T, TInfo);
21964}
21965
21968 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
21969
21971 assert(!MapperType.isNull() && "Expect valid mapper type");
21972
21973 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21974 // The type must be of struct, union or class type in C and C++
21975 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
21976 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21977 return QualType();
21978 }
21979 return MapperType;
21980}
21981
21983 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
21985 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
21986 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21989 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21990 // A mapper-identifier may not be redeclared in the current scope for the
21991 // same type or for a type that is compatible according to the base language
21992 // rules.
21993 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21994 OMPDeclareMapperDecl *PrevDMD = nullptr;
21995 bool InCompoundScope = true;
21996 if (S != nullptr) {
21997 // Find previous declaration with the same name not referenced in other
21998 // declarations.
22000 InCompoundScope =
22001 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22002 SemaRef.LookupName(Lookup, S);
22003 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22004 /*AllowInlineNamespace=*/false);
22005 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22006 LookupResult::Filter Filter = Lookup.makeFilter();
22007 while (Filter.hasNext()) {
22008 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22009 if (InCompoundScope) {
22010 UsedAsPrevious.try_emplace(PrevDecl, false);
22011 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22012 UsedAsPrevious[D] = true;
22013 }
22014 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22015 PrevDecl->getLocation();
22016 }
22017 Filter.done();
22018 if (InCompoundScope) {
22019 for (const auto &PrevData : UsedAsPrevious) {
22020 if (!PrevData.second) {
22021 PrevDMD = PrevData.first;
22022 break;
22023 }
22024 }
22025 }
22026 } else if (PrevDeclInScope) {
22027 auto *PrevDMDInScope = PrevDMD =
22028 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22029 do {
22030 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22031 PrevDMDInScope->getLocation();
22032 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22033 } while (PrevDMDInScope != nullptr);
22034 }
22035 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22036 bool Invalid = false;
22037 if (I != PreviousRedeclTypes.end()) {
22038 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22039 << MapperType << Name;
22040 Diag(I->second, diag::note_previous_definition);
22041 Invalid = true;
22042 }
22043 // Build expressions for implicit maps of data members with 'default'
22044 // mappers.
22045 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
22046 if (getLangOpts().OpenMP >= 50)
22048 ClausesWithImplicit);
22049 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
22050 MapperType, VN, ClausesWithImplicit,
22051 PrevDMD);
22052 if (S)
22053 SemaRef.PushOnScopeChains(DMD, S);
22054 else
22055 DC->addDecl(DMD);
22056 DMD->setAccess(AS);
22057 if (Invalid)
22058 DMD->setInvalidDecl();
22059
22060 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22061 VD->setDeclContext(DMD);
22062 VD->setLexicalDeclContext(DMD);
22063 DMD->addDecl(VD);
22064 DMD->setMapperVarRef(MapperVarRef);
22065
22067}
22068
22070 Scope *S, QualType MapperType, SourceLocation StartLoc,
22071 DeclarationName VN) {
22072 TypeSourceInfo *TInfo =
22073 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
22074 auto *VD = VarDecl::Create(
22075 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
22076 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
22077 if (S)
22078 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
22079 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
22080 DSAStack->addDeclareMapperVarRef(E);
22081 return E;
22082}
22083
22085 if (DSAStack->getDeclareMapperVarRef())
22086 DSAStack->addIteratorVarDecl(VD);
22087}
22088
22090 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22091 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22092 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22093 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22094 return true;
22096 return true;
22097 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22098 return true;
22099 return false;
22100 }
22101 return true;
22102}
22103
22105 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22106 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22107}
22108
22110 SourceLocation StartLoc,
22111 SourceLocation LParenLoc,
22112 SourceLocation EndLoc) {
22113 if (VarList.empty())
22114 return nullptr;
22115
22116 for (Expr *ValExpr : VarList) {
22117 // OpenMP [teams Constrcut, Restrictions]
22118 // The num_teams expression must evaluate to a positive integer value.
22119 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
22120 /*StrictlyPositive=*/true))
22121 return nullptr;
22122 }
22123
22124 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22126 DKind, OMPC_num_teams, getLangOpts().OpenMP);
22127 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22128 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22129 LParenLoc, EndLoc, VarList,
22130 /*PreInit=*/nullptr);
22131
22132 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22134 for (Expr *ValExpr : VarList) {
22135 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22136 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22137 Vars.push_back(ValExpr);
22138 }
22139
22140 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22141 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22142 LParenLoc, EndLoc, Vars, PreInit);
22143}
22144
22146 SourceLocation StartLoc,
22147 SourceLocation LParenLoc,
22148 SourceLocation EndLoc) {
22149 if (VarList.empty())
22150 return nullptr;
22151
22152 for (Expr *ValExpr : VarList) {
22153 // OpenMP [teams Constrcut, Restrictions]
22154 // The thread_limit expression must evaluate to a positive integer value.
22155 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
22156 /*StrictlyPositive=*/true))
22157 return nullptr;
22158 }
22159
22160 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22162 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
22163 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22164 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
22165 StartLoc, LParenLoc, EndLoc, VarList,
22166 /*PreInit=*/nullptr);
22167
22168 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22170 for (Expr *ValExpr : VarList) {
22171 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22172 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22173 Vars.push_back(ValExpr);
22174 }
22175
22176 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22177 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
22178 LParenLoc, EndLoc, Vars, PreInit);
22179}
22180
22182 SourceLocation StartLoc,
22183 SourceLocation LParenLoc,
22184 SourceLocation EndLoc) {
22185 Expr *ValExpr = Priority;
22186 Stmt *HelperValStmt = nullptr;
22187 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22188
22189 // OpenMP [2.9.1, task Constrcut]
22190 // The priority-value is a non-negative numerical scalar expression.
22192 ValExpr, SemaRef, OMPC_priority,
22193 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22194 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22195 return nullptr;
22196
22197 return new (getASTContext()) OMPPriorityClause(
22198 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22199}
22200
22202 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22203 SourceLocation StartLoc, SourceLocation LParenLoc,
22204 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22205 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22206 "Unexpected grainsize modifier in OpenMP < 51.");
22207
22208 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22209 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22211 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22212 << Values << getOpenMPClauseName(OMPC_grainsize);
22213 return nullptr;
22214 }
22215
22216 Expr *ValExpr = Grainsize;
22217 Stmt *HelperValStmt = nullptr;
22218 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22219
22220 // OpenMP [2.9.2, taskloop Constrcut]
22221 // The parameter of the grainsize clause must be a positive integer
22222 // expression.
22223 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22224 /*StrictlyPositive=*/true,
22225 /*BuildCapture=*/true,
22226 DSAStack->getCurrentDirective(),
22227 &CaptureRegion, &HelperValStmt))
22228 return nullptr;
22229
22230 return new (getASTContext())
22231 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22232 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22233}
22234
22236 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22237 SourceLocation StartLoc, SourceLocation LParenLoc,
22238 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22239 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22240 "Unexpected num_tasks modifier in OpenMP < 51.");
22241
22242 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22243 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22245 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22246 << Values << getOpenMPClauseName(OMPC_num_tasks);
22247 return nullptr;
22248 }
22249
22250 Expr *ValExpr = NumTasks;
22251 Stmt *HelperValStmt = nullptr;
22252 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22253
22254 // OpenMP [2.9.2, taskloop Constrcut]
22255 // The parameter of the num_tasks clause must be a positive integer
22256 // expression.
22258 ValExpr, SemaRef, OMPC_num_tasks,
22259 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22260 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22261 return nullptr;
22262
22263 return new (getASTContext())
22264 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22265 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22266}
22267
22269 SourceLocation StartLoc,
22270 SourceLocation LParenLoc,
22271 SourceLocation EndLoc) {
22272 // OpenMP [2.13.2, critical construct, Description]
22273 // ... where hint-expression is an integer constant expression that evaluates
22274 // to a valid lock hint.
22275 ExprResult HintExpr =
22276 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22277 if (HintExpr.isInvalid())
22278 return nullptr;
22279 return new (getASTContext())
22280 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22281}
22282
22283/// Tries to find omp_event_handle_t type.
22285 DSAStackTy *Stack) {
22286 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22287 if (!OMPEventHandleT.isNull())
22288 return true;
22289 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22290 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22291 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22292 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22293 return false;
22294 }
22295 Stack->setOMPEventHandleT(PT.get());
22296 return true;
22297}
22298
22300 SourceLocation StartLoc,
22301 SourceLocation LParenLoc,
22302 SourceLocation EndLoc) {
22303 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22304 !Evt->isInstantiationDependent() &&
22307 return nullptr;
22308 // OpenMP 5.0, 2.10.1 task Construct.
22309 // event-handle is a variable of the omp_event_handle_t type.
22310 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22311 if (!Ref) {
22312 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22313 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22314 return nullptr;
22315 }
22316 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22317 if (!VD) {
22318 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22319 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22320 return nullptr;
22321 }
22322 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22323 VD->getType()) ||
22324 VD->getType().isConstant(getASTContext())) {
22325 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22326 << "omp_event_handle_t" << 1 << VD->getType()
22327 << Evt->getSourceRange();
22328 return nullptr;
22329 }
22330 // OpenMP 5.0, 2.10.1 task Construct
22331 // [detach clause]... The event-handle will be considered as if it was
22332 // specified on a firstprivate clause.
22333 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22334 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22335 DVar.RefExpr) {
22336 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22337 << getOpenMPClauseName(DVar.CKind)
22338 << getOpenMPClauseName(OMPC_firstprivate);
22340 return nullptr;
22341 }
22342 }
22343
22344 return new (getASTContext())
22345 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22346}
22347
22349 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22350 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22351 SourceLocation EndLoc) {
22352 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22353 std::string Values;
22354 Values += "'";
22355 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22356 Values += "'";
22357 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22358 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22359 return nullptr;
22360 }
22361 Expr *ValExpr = ChunkSize;
22362 Stmt *HelperValStmt = nullptr;
22363 if (ChunkSize) {
22364 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22365 !ChunkSize->isInstantiationDependent() &&
22366 !ChunkSize->containsUnexpandedParameterPack()) {
22367 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22368 ExprResult Val =
22369 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22370 if (Val.isInvalid())
22371 return nullptr;
22372
22373 ValExpr = Val.get();
22374
22375 // OpenMP [2.7.1, Restrictions]
22376 // chunk_size must be a loop invariant integer expression with a positive
22377 // value.
22378 if (std::optional<llvm::APSInt> Result =
22380 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22381 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22382 << "dist_schedule" << ChunkSize->getSourceRange();
22383 return nullptr;
22384 }
22386 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22387 getLangOpts().OpenMP) != OMPD_unknown &&
22389 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22390 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22391 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22392 HelperValStmt = buildPreInits(getASTContext(), Captures);
22393 }
22394 }
22395 }
22396
22397 return new (getASTContext())
22398 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22399 Kind, ValExpr, HelperValStmt);
22400}
22401
22404 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22405 SourceLocation KindLoc, SourceLocation EndLoc) {
22406 if (getLangOpts().OpenMP < 50) {
22407 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22408 Kind != OMPC_DEFAULTMAP_scalar) {
22409 std::string Value;
22411 Value += "'";
22412 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22413 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22414 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22415 Loc = MLoc;
22416 } else {
22417 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22418 OMPC_DEFAULTMAP_scalar);
22419 Loc = KindLoc;
22420 }
22421 Value += "'";
22422 Diag(Loc, diag::err_omp_unexpected_clause_value)
22423 << Value << getOpenMPClauseName(OMPC_defaultmap);
22424 return nullptr;
22425 }
22426 } else {
22427 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22428 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22429 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22430 if (!isDefaultmapKind || !isDefaultmapModifier) {
22431 StringRef KindValue = getLangOpts().OpenMP < 52
22432 ? "'scalar', 'aggregate', 'pointer'"
22433 : "'scalar', 'aggregate', 'pointer', 'all'";
22434 if (getLangOpts().OpenMP == 50) {
22435 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22436 "'firstprivate', 'none', 'default'";
22437 if (!isDefaultmapKind && isDefaultmapModifier) {
22438 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22439 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22440 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22441 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22442 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22443 } else {
22444 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22445 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22446 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22447 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22448 }
22449 } else {
22450 StringRef ModifierValue =
22451 "'alloc', 'from', 'to', 'tofrom', "
22452 "'firstprivate', 'none', 'default', 'present'";
22453 if (!isDefaultmapKind && isDefaultmapModifier) {
22454 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22455 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22456 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22457 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22458 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22459 } else {
22460 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22461 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22462 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22463 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22464 }
22465 }
22466 return nullptr;
22467 }
22468
22469 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22470 // At most one defaultmap clause for each category can appear on the
22471 // directive.
22472 if (DSAStack->checkDefaultmapCategory(Kind)) {
22473 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22474 return nullptr;
22475 }
22476 }
22477 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
22478 // Variable category is not specified - mark all categories.
22479 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22480 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22481 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22482 } else {
22483 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22484 }
22485
22486 return new (getASTContext())
22487 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22488}
22489
22492 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22493 if (!CurLexicalContext->isFileContext() &&
22494 !CurLexicalContext->isExternCContext() &&
22495 !CurLexicalContext->isExternCXXContext() &&
22496 !isa<CXXRecordDecl>(CurLexicalContext) &&
22497 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22498 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22499 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22500 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22501 return false;
22502 }
22503
22504 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22505 if (getLangOpts().HIP)
22506 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
22507
22508 DeclareTargetNesting.push_back(DTCI);
22509 return true;
22510}
22511
22514 assert(!DeclareTargetNesting.empty() &&
22515 "check isInOpenMPDeclareTargetContext() first!");
22516 return DeclareTargetNesting.pop_back_val();
22517}
22518
22521 for (auto &It : DTCI.ExplicitlyMapped)
22522 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22523}
22524
22526 if (DeclareTargetNesting.empty())
22527 return;
22528 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22529 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22530 << getOpenMPDirectiveName(DTCI.Kind);
22531}
22532
22534 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
22536 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
22537 /*ObjectType=*/QualType(),
22538 /*AllowBuiltinCreation=*/true);
22539
22540 if (Lookup.isAmbiguous())
22541 return nullptr;
22542 Lookup.suppressDiagnostics();
22543
22544 if (!Lookup.isSingleResult()) {
22545 VarOrFuncDeclFilterCCC CCC(SemaRef);
22546 if (TypoCorrection Corrected =
22547 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
22549 SemaRef.diagnoseTypo(Corrected,
22550 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
22551 << Id.getName());
22552 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22553 return nullptr;
22554 }
22555
22556 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22557 return nullptr;
22558 }
22559
22560 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22561 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22562 !isa<FunctionTemplateDecl>(ND)) {
22563 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22564 return nullptr;
22565 }
22566 return ND;
22567}
22568
22570 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
22572 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22573 isa<FunctionTemplateDecl>(ND)) &&
22574 "Expected variable, function or function template.");
22575
22576 if (auto *VD = dyn_cast<VarDecl>(ND)) {
22577 // Only global variables can be marked as declare target.
22578 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22579 !VD->isStaticDataMember()) {
22580 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
22581 << VD->getNameAsString();
22582 return;
22583 }
22584 }
22585 // Diagnose marking after use as it may lead to incorrect diagnosis and
22586 // codegen.
22587 if (getLangOpts().OpenMP >= 50 &&
22588 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22589 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22590
22591 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22592 if (getLangOpts().HIP)
22593 Diag(Loc, diag::warn_hip_omp_target_directives);
22594
22595 // Explicit declare target lists have precedence.
22596 const unsigned Level = -1;
22597
22598 auto *VD = cast<ValueDecl>(ND);
22599 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22600 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22601 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22602 (*ActiveAttr)->getLevel() == Level) {
22603 Diag(Loc, diag::err_omp_device_type_mismatch)
22604 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22605 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22606 (*ActiveAttr)->getDevType());
22607 return;
22608 }
22609 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22610 (*ActiveAttr)->getLevel() == Level) {
22611 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22612 return;
22613 }
22614
22615 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22616 return;
22617
22618 Expr *IndirectE = nullptr;
22619 bool IsIndirect = false;
22620 if (DTCI.Indirect) {
22621 IndirectE = *DTCI.Indirect;
22622 if (!IndirectE)
22623 IsIndirect = true;
22624 }
22625 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22626 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
22627 SourceRange(Loc, Loc));
22628 ND->addAttr(A);
22629 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22630 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22632 if (auto *VD = dyn_cast<VarDecl>(ND);
22633 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
22634 VD->hasGlobalStorage())
22636}
22637
22639 Sema &SemaRef, Decl *D) {
22640 if (!D || !isa<VarDecl>(D))
22641 return;
22642 auto *VD = cast<VarDecl>(D);
22643 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22644 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22645 if (SemaRef.LangOpts.OpenMP >= 50 &&
22646 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22647 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22648 VD->hasGlobalStorage()) {
22649 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22650 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22651 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22652 // If a lambda declaration and definition appears between a
22653 // declare target directive and the matching end declare target
22654 // directive, all variables that are captured by the lambda
22655 // expression must also appear in a to clause.
22656 SemaRef.Diag(VD->getLocation(),
22657 diag::err_omp_lambda_capture_in_declare_target_not_to);
22658 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22659 << VD << 0 << SR;
22660 return;
22661 }
22662 }
22663 if (MapTy)
22664 return;
22665 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22666 SemaRef.Diag(SL, diag::note_used_here) << SR;
22667}
22668
22670 Sema &SemaRef, DSAStackTy *Stack,
22671 ValueDecl *VD) {
22672 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22673 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22674 /*FullCheck=*/false);
22675}
22676
22678 SourceLocation IdLoc) {
22679 if (!D || D->isInvalidDecl())
22680 return;
22682 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22683 if (auto *VD = dyn_cast<VarDecl>(D)) {
22684 // Only global variables can be marked as declare target.
22685 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22686 !VD->isStaticDataMember())
22687 return;
22688 // 2.10.6: threadprivate variable cannot appear in a declare target
22689 // directive.
22690 if (DSAStack->isThreadPrivate(VD)) {
22691 Diag(SL, diag::err_omp_threadprivate_in_target);
22692 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22693 return;
22694 }
22695 }
22696 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22697 D = FTD->getTemplatedDecl();
22698 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22699 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22700 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22701 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22702 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22703 Diag(FD->getLocation(), diag::note_defined_here) << FD;
22704 return;
22705 }
22706 }
22707 if (auto *VD = dyn_cast<ValueDecl>(D)) {
22708 // Problem if any with var declared with incomplete type will be reported
22709 // as normal, so no need to check it here.
22710 if ((E || !VD->getType()->isIncompleteType()) &&
22712 return;
22714 // Checking declaration inside declare target region.
22715 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22716 isa<FunctionTemplateDecl>(D)) {
22717 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22718 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22719 unsigned Level = DeclareTargetNesting.size();
22720 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22721 return;
22722 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22723 Expr *IndirectE = nullptr;
22724 bool IsIndirect = false;
22725 if (DTCI.Indirect) {
22726 IndirectE = *DTCI.Indirect;
22727 if (!IndirectE)
22728 IsIndirect = true;
22729 }
22730 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22731 getASTContext(),
22732 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22733 : OMPDeclareTargetDeclAttr::MT_To,
22734 DTCI.DT, IndirectE, IsIndirect, Level,
22735 SourceRange(DTCI.Loc, DTCI.Loc));
22736 D->addAttr(A);
22737 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22738 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22739 }
22740 return;
22741 }
22742 }
22743 if (!E)
22744 return;
22746}
22747
22748/// This class visits every VarDecl that the initializer references and adds
22749/// OMPDeclareTargetDeclAttr to each of them.
22750class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
22751 SmallVector<VarDecl *> DeclVector;
22752 Attr *A;
22753
22754public:
22755 /// A StmtVisitor class function that visits all DeclRefExpr and adds
22756 /// OMPDeclareTargetDeclAttr to them.
22758 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
22759 VD->addAttr(A);
22760 DeclVector.push_back(VD);
22761 }
22762 }
22763 /// A function that iterates across each of the Expr's children.
22764 void VisitExpr(Expr *Ex) {
22765 for (auto *Child : Ex->children()) {
22766 Visit(Child);
22767 }
22768 }
22769 /// A function that keeps a record of all the Decls that are variables, has
22770 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
22771 /// each Decl one at a time and use the inherited 'visit' functions to look
22772 /// for DeclRefExpr.
22774 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
22775 DeclVector.push_back(cast<VarDecl>(TD));
22776 while (!DeclVector.empty()) {
22777 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22778 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
22779 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
22780 if (Expr *Ex = TargetVarDecl->getInit())
22781 Visit(Ex);
22782 }
22783 }
22784 }
22785};
22786
22787/// Adding OMPDeclareTargetDeclAttr to variables with static storage
22788/// duration that are referenced in the initializer expression list of
22789/// variables with static storage duration in declare target directive.
22791 GlobalDeclRefChecker Checker;
22792 if (isa<VarDecl>(TargetDecl))
22793 Checker.declareTargetInitializer(TargetDecl);
22794}
22795
22797 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22798 ArrayRef<SourceLocation> MotionModifiersLoc,
22799 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22800 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22801 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22805
22806 // Process motion-modifiers, flag errors for duplicate modifiers.
22807 unsigned Count = 0;
22808 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22809 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22810 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22811 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22812 continue;
22813 }
22814 assert(Count < NumberOfOMPMotionModifiers &&
22815 "Modifiers exceed the allowed number of motion modifiers");
22816 Modifiers[Count] = MotionModifiers[I];
22817 ModifiersLoc[Count] = MotionModifiersLoc[I];
22818 ++Count;
22819 }
22820
22821 MappableVarListInfo MVLI(VarList);
22823 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22824 if (MVLI.ProcessedVarList.empty())
22825 return nullptr;
22826
22827 return OMPToClause::Create(
22828 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22829 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22830 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22831}
22832
22834 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22835 ArrayRef<SourceLocation> MotionModifiersLoc,
22836 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22837 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22838 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22842
22843 // Process motion-modifiers, flag errors for duplicate modifiers.
22844 unsigned Count = 0;
22845 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22846 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22847 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22848 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22849 continue;
22850 }
22851 assert(Count < NumberOfOMPMotionModifiers &&
22852 "Modifiers exceed the allowed number of motion modifiers");
22853 Modifiers[Count] = MotionModifiers[I];
22854 ModifiersLoc[Count] = MotionModifiersLoc[I];
22855 ++Count;
22856 }
22857
22858 MappableVarListInfo MVLI(VarList);
22859 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22860 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22861 if (MVLI.ProcessedVarList.empty())
22862 return nullptr;
22863
22864 return OMPFromClause::Create(
22865 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22866 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22867 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22868}
22869
22870OMPClause *
22872 const OMPVarListLocTy &Locs) {
22873 MappableVarListInfo MVLI(VarList);
22874 SmallVector<Expr *, 8> PrivateCopies;
22876
22877 for (Expr *RefExpr : VarList) {
22878 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22879 SourceLocation ELoc;
22880 SourceRange ERange;
22881 Expr *SimpleRefExpr = RefExpr;
22882 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22883 if (Res.second) {
22884 // It will be analyzed later.
22885 MVLI.ProcessedVarList.push_back(RefExpr);
22886 PrivateCopies.push_back(nullptr);
22887 Inits.push_back(nullptr);
22888 }
22889 ValueDecl *D = Res.first;
22890 if (!D)
22891 continue;
22892
22893 QualType Type = D->getType();
22894 Type = Type.getNonReferenceType().getUnqualifiedType();
22895
22896 auto *VD = dyn_cast<VarDecl>(D);
22897
22898 // Item should be a pointer or reference to pointer.
22899 if (!Type->isPointerType()) {
22900 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22901 << 0 << RefExpr->getSourceRange();
22902 continue;
22903 }
22904
22905 // Build the private variable and the expression that refers to it.
22906 auto VDPrivate =
22907 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
22908 D->hasAttrs() ? &D->getAttrs() : nullptr,
22909 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22910 if (VDPrivate->isInvalidDecl())
22911 continue;
22912
22913 SemaRef.CurContext->addDecl(VDPrivate);
22914 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22915 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22916
22917 // Add temporary variable to initialize the private copy of the pointer.
22918 VarDecl *VDInit =
22919 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
22920 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22921 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22923 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
22924 /*DirectInit=*/false);
22925
22926 // If required, build a capture to implement the privatization initialized
22927 // with the current list item value.
22928 DeclRefExpr *Ref = nullptr;
22929 if (!VD)
22930 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22931 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22932 PrivateCopies.push_back(VDPrivateRefExpr);
22933 Inits.push_back(VDInitRefExpr);
22934
22935 // We need to add a data sharing attribute for this variable to make sure it
22936 // is correctly captured. A variable that shows up in a use_device_ptr has
22937 // similar properties of a first private variable.
22938 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22939
22940 // Create a mappable component for the list item. List items in this clause
22941 // only need a component.
22942 MVLI.VarBaseDeclarations.push_back(D);
22943 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22944 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22945 /*IsNonContiguous=*/false);
22946 }
22947
22948 if (MVLI.ProcessedVarList.empty())
22949 return nullptr;
22950
22952 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22953 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22954}
22955
22956OMPClause *
22958 const OMPVarListLocTy &Locs) {
22959 MappableVarListInfo MVLI(VarList);
22960
22961 for (Expr *RefExpr : VarList) {
22962 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22963 SourceLocation ELoc;
22964 SourceRange ERange;
22965 Expr *SimpleRefExpr = RefExpr;
22966 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22967 /*AllowArraySection=*/true);
22968 if (Res.second) {
22969 // It will be analyzed later.
22970 MVLI.ProcessedVarList.push_back(RefExpr);
22971 }
22972 ValueDecl *D = Res.first;
22973 if (!D)
22974 continue;
22975 auto *VD = dyn_cast<VarDecl>(D);
22976
22977 // If required, build a capture to implement the privatization initialized
22978 // with the current list item value.
22979 DeclRefExpr *Ref = nullptr;
22980 if (!VD)
22981 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22982 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22983
22984 // We need to add a data sharing attribute for this variable to make sure it
22985 // is correctly captured. A variable that shows up in a use_device_addr has
22986 // similar properties of a first private variable.
22987 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22988
22989 // Create a mappable component for the list item. List items in this clause
22990 // only need a component.
22991 MVLI.VarBaseDeclarations.push_back(D);
22992 MVLI.VarComponents.emplace_back();
22993 Expr *Component = SimpleRefExpr;
22994 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22995 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22996 Component =
22998 MVLI.VarComponents.back().emplace_back(Component, D,
22999 /*IsNonContiguous=*/false);
23000 }
23001
23002 if (MVLI.ProcessedVarList.empty())
23003 return nullptr;
23004
23006 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23007 MVLI.VarComponents);
23008}
23009
23010OMPClause *
23012 const OMPVarListLocTy &Locs) {
23013 MappableVarListInfo MVLI(VarList);
23014 for (Expr *RefExpr : VarList) {
23015 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23016 SourceLocation ELoc;
23017 SourceRange ERange;
23018 Expr *SimpleRefExpr = RefExpr;
23019 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23020 if (Res.second) {
23021 // It will be analyzed later.
23022 MVLI.ProcessedVarList.push_back(RefExpr);
23023 }
23024 ValueDecl *D = Res.first;
23025 if (!D)
23026 continue;
23027
23028 QualType Type = D->getType();
23029 // item should be a pointer or array or reference to pointer or array
23030 if (!Type.getNonReferenceType()->isPointerType() &&
23031 !Type.getNonReferenceType()->isArrayType()) {
23032 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23033 << 0 << RefExpr->getSourceRange();
23034 continue;
23035 }
23036
23037 // Check if the declaration in the clause does not show up in any data
23038 // sharing attribute.
23039 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23040 if (isOpenMPPrivate(DVar.CKind)) {
23041 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23042 << getOpenMPClauseName(DVar.CKind)
23043 << getOpenMPClauseName(OMPC_is_device_ptr)
23044 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23046 continue;
23047 }
23048
23049 const Expr *ConflictExpr;
23050 if (DSAStack->checkMappableExprComponentListsForDecl(
23051 D, /*CurrentRegionOnly=*/true,
23052 [&ConflictExpr](
23054 OpenMPClauseKind) -> bool {
23055 ConflictExpr = R.front().getAssociatedExpression();
23056 return true;
23057 })) {
23058 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23059 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23060 << ConflictExpr->getSourceRange();
23061 continue;
23062 }
23063
23064 // Store the components in the stack so that they can be used to check
23065 // against other clauses later on.
23067 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23068 DSAStack->addMappableExpressionComponents(
23069 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23070
23071 // Record the expression we've just processed.
23072 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23073
23074 // Create a mappable component for the list item. List items in this clause
23075 // only need a component. We use a null declaration to signal fields in
23076 // 'this'.
23077 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23078 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23079 "Unexpected device pointer expression!");
23080 MVLI.VarBaseDeclarations.push_back(
23081 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23082 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23083 MVLI.VarComponents.back().push_back(MC);
23084 }
23085
23086 if (MVLI.ProcessedVarList.empty())
23087 return nullptr;
23088
23090 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23091 MVLI.VarComponents);
23092}
23093
23094OMPClause *
23096 const OMPVarListLocTy &Locs) {
23097 MappableVarListInfo MVLI(VarList);
23098 for (Expr *RefExpr : VarList) {
23099 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23100 SourceLocation ELoc;
23101 SourceRange ERange;
23102 Expr *SimpleRefExpr = RefExpr;
23103 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23104 /*AllowArraySection=*/true);
23105 if (Res.second) {
23106 // It will be analyzed later.
23107 MVLI.ProcessedVarList.push_back(RefExpr);
23108 }
23109 ValueDecl *D = Res.first;
23110 if (!D)
23111 continue;
23112
23113 // Check if the declaration in the clause does not show up in any data
23114 // sharing attribute.
23115 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23116 if (isOpenMPPrivate(DVar.CKind)) {
23117 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23118 << getOpenMPClauseName(DVar.CKind)
23119 << getOpenMPClauseName(OMPC_has_device_addr)
23120 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23122 continue;
23123 }
23124
23125 const Expr *ConflictExpr;
23126 if (DSAStack->checkMappableExprComponentListsForDecl(
23127 D, /*CurrentRegionOnly=*/true,
23128 [&ConflictExpr](
23130 OpenMPClauseKind) -> bool {
23131 ConflictExpr = R.front().getAssociatedExpression();
23132 return true;
23133 })) {
23134 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23135 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23136 << ConflictExpr->getSourceRange();
23137 continue;
23138 }
23139
23140 // Store the components in the stack so that they can be used to check
23141 // against other clauses later on.
23142 Expr *Component = SimpleRefExpr;
23143 auto *VD = dyn_cast<VarDecl>(D);
23144 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23145 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23146 Component =
23149 Component, D, /*IsNonContiguous=*/false);
23150 DSAStack->addMappableExpressionComponents(
23151 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23152
23153 // Record the expression we've just processed.
23154 if (!VD && !SemaRef.CurContext->isDependentContext()) {
23155 DeclRefExpr *Ref =
23156 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23157 assert(Ref && "has_device_addr capture failed");
23158 MVLI.ProcessedVarList.push_back(Ref);
23159 } else
23160 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23161
23162 // Create a mappable component for the list item. List items in this clause
23163 // only need a component. We use a null declaration to signal fields in
23164 // 'this'.
23165 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23166 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23167 "Unexpected device pointer expression!");
23168 MVLI.VarBaseDeclarations.push_back(
23169 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23170 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23171 MVLI.VarComponents.back().push_back(MC);
23172 }
23173
23174 if (MVLI.ProcessedVarList.empty())
23175 return nullptr;
23176
23178 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23179 MVLI.VarComponents);
23180}
23181
23183 Expr *Allocator, Expr *Alignment,
23184 OpenMPAllocateClauseModifier FirstAllocateModifier,
23185 SourceLocation FirstAllocateModifierLoc,
23186 OpenMPAllocateClauseModifier SecondAllocateModifier,
23187 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
23188 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23189 SourceLocation EndLoc) {
23190 if (Allocator) {
23191 // Allocator expression is dependent - skip it for now and build the
23192 // allocator when instantiated.
23193 bool AllocDependent =
23194 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23195 Allocator->isInstantiationDependent() ||
23196 Allocator->containsUnexpandedParameterPack());
23197 if (!AllocDependent) {
23198 // OpenMP [2.11.4 allocate Clause, Description]
23199 // allocator is an expression of omp_allocator_handle_t type.
23200 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
23201 return nullptr;
23202
23203 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
23204 if (AllocatorRes.isInvalid())
23205 return nullptr;
23206 AllocatorRes = SemaRef.PerformImplicitConversion(
23207 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23209 /*AllowExplicit=*/true);
23210 if (AllocatorRes.isInvalid())
23211 return nullptr;
23212 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
23213 }
23214 } else {
23215 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23216 // allocate clauses that appear on a target construct or on constructs in a
23217 // target region must specify an allocator expression unless a requires
23218 // directive with the dynamic_allocators clause is present in the same
23219 // compilation unit.
23220 if (getLangOpts().OpenMPIsTargetDevice &&
23221 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23222 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
23223 }
23224 if (Alignment) {
23225 bool AlignmentDependent = Alignment->isTypeDependent() ||
23226 Alignment->isValueDependent() ||
23227 Alignment->isInstantiationDependent() ||
23229 if (!AlignmentDependent) {
23230 ExprResult AlignResult =
23231 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
23232 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
23233 }
23234 }
23235 // Analyze and build list of variables.
23237 for (Expr *RefExpr : VarList) {
23238 assert(RefExpr && "NULL expr in OpenMP private clause.");
23239 SourceLocation ELoc;
23240 SourceRange ERange;
23241 Expr *SimpleRefExpr = RefExpr;
23242 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23243 if (Res.second) {
23244 // It will be analyzed later.
23245 Vars.push_back(RefExpr);
23246 }
23247 ValueDecl *D = Res.first;
23248 if (!D)
23249 continue;
23250
23251 auto *VD = dyn_cast<VarDecl>(D);
23252 DeclRefExpr *Ref = nullptr;
23253 if (!VD && !SemaRef.CurContext->isDependentContext())
23254 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
23255 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
23256 ? RefExpr->IgnoreParens()
23257 : Ref);
23258 }
23259
23260 if (Vars.empty())
23261 return nullptr;
23262
23263 if (Allocator)
23264 DSAStack->addInnerAllocatorExpr(Allocator);
23265
23267 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
23268 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
23269 SecondAllocateModifierLoc, EndLoc, Vars);
23270}
23271
23273 SourceLocation StartLoc,
23274 SourceLocation LParenLoc,
23275 SourceLocation EndLoc) {
23277 for (Expr *RefExpr : VarList) {
23278 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23279 SourceLocation ELoc;
23280 SourceRange ERange;
23281 Expr *SimpleRefExpr = RefExpr;
23282 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23283 if (Res.second)
23284 // It will be analyzed later.
23285 Vars.push_back(RefExpr);
23286 ValueDecl *D = Res.first;
23287 if (!D)
23288 continue;
23289
23290 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23291 // A list-item cannot appear in more than one nontemporal clause.
23292 if (const Expr *PrevRef =
23293 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23294 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23295 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23296 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23297 << getOpenMPClauseName(OMPC_nontemporal);
23298 continue;
23299 }
23300
23301 Vars.push_back(RefExpr);
23302 }
23303
23304 if (Vars.empty())
23305 return nullptr;
23306
23307 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
23308 EndLoc, Vars);
23309}
23310
23312 Stmt *AStmt,
23313 SourceLocation StartLoc,
23314 SourceLocation EndLoc) {
23315 if (!AStmt)
23316 return StmtError();
23317
23319
23320 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
23321 AStmt);
23322}
23323
23325 SourceLocation StartLoc,
23326 SourceLocation LParenLoc,
23327 SourceLocation EndLoc) {
23329 for (Expr *RefExpr : VarList) {
23330 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23331 SourceLocation ELoc;
23332 SourceRange ERange;
23333 Expr *SimpleRefExpr = RefExpr;
23334 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23335 /*AllowArraySection=*/true);
23336 if (Res.second)
23337 // It will be analyzed later.
23338 Vars.push_back(RefExpr);
23339 ValueDecl *D = Res.first;
23340 if (!D)
23341 continue;
23342
23343 const DSAStackTy::DSAVarData DVar =
23344 DSAStack->getTopDSA(D, /*FromParent=*/true);
23345 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23346 // A list item that appears in the inclusive or exclusive clause must appear
23347 // in a reduction clause with the inscan modifier on the enclosing
23348 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23349 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23350 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23351 << RefExpr->getSourceRange();
23352
23353 if (DSAStack->getParentDirective() != OMPD_unknown)
23354 DSAStack->markDeclAsUsedInScanDirective(D);
23355 Vars.push_back(RefExpr);
23356 }
23357
23358 if (Vars.empty())
23359 return nullptr;
23360
23361 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23362 EndLoc, Vars);
23363}
23364
23366 SourceLocation StartLoc,
23367 SourceLocation LParenLoc,
23368 SourceLocation EndLoc) {
23370 for (Expr *RefExpr : VarList) {
23371 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23372 SourceLocation ELoc;
23373 SourceRange ERange;
23374 Expr *SimpleRefExpr = RefExpr;
23375 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23376 /*AllowArraySection=*/true);
23377 if (Res.second)
23378 // It will be analyzed later.
23379 Vars.push_back(RefExpr);
23380 ValueDecl *D = Res.first;
23381 if (!D)
23382 continue;
23383
23384 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23385 DSAStackTy::DSAVarData DVar;
23386 if (ParentDirective != OMPD_unknown)
23387 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23388 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23389 // A list item that appears in the inclusive or exclusive clause must appear
23390 // in a reduction clause with the inscan modifier on the enclosing
23391 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23392 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23393 DVar.Modifier != OMPC_REDUCTION_inscan) {
23394 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23395 << RefExpr->getSourceRange();
23396 } else {
23397 DSAStack->markDeclAsUsedInScanDirective(D);
23398 }
23399 Vars.push_back(RefExpr);
23400 }
23401
23402 if (Vars.empty())
23403 return nullptr;
23404
23405 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23406 EndLoc, Vars);
23407}
23408
23409/// Tries to find omp_alloctrait_t type.
23410static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23411 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23412 if (!OMPAlloctraitT.isNull())
23413 return true;
23414 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23415 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23416 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23417 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23418 return false;
23419 }
23420 Stack->setOMPAlloctraitT(PT.get());
23421 return true;
23422}
23423
23425 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23427 ASTContext &Context = getASTContext();
23428 // OpenMP [2.12.5, target Construct]
23429 // allocator is an identifier of omp_allocator_handle_t type.
23430 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
23431 return nullptr;
23432 // OpenMP [2.12.5, target Construct]
23433 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23434 if (llvm::any_of(
23435 Data,
23436 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23437 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
23438 return nullptr;
23439 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23440 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23441 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23442 StringRef Allocator =
23443 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23444 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23445 PredefinedAllocators.insert(SemaRef.LookupSingleName(
23446 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23447 }
23448
23450 for (const UsesAllocatorsData &D : Data) {
23451 Expr *AllocatorExpr = nullptr;
23452 // Check allocator expression.
23453 if (D.Allocator->isTypeDependent()) {
23454 AllocatorExpr = D.Allocator;
23455 } else {
23456 // Traits were specified - need to assign new allocator to the specified
23457 // allocator, so it must be an lvalue.
23458 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23459 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23460 bool IsPredefinedAllocator = false;
23461 if (DRE) {
23462 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23463 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
23464 IsPredefinedAllocator =
23465 AllocatorTy !=
23466 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23467 }
23468 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23469 QualType AllocatorExprType = AllocatorExpr->getType();
23470 bool IsTypeCompatible = IsPredefinedAllocator;
23471 IsTypeCompatible = IsTypeCompatible ||
23472 Context.hasSameUnqualifiedType(AllocatorExprType,
23473 OMPAllocatorHandleT);
23474 IsTypeCompatible =
23475 IsTypeCompatible ||
23476 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23477 bool IsNonConstantLValue =
23478 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23479 if (!DRE || !IsTypeCompatible ||
23480 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23481 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23482 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23483 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23484 continue;
23485 }
23486 // OpenMP [2.12.5, target Construct]
23487 // Predefined allocators appearing in a uses_allocators clause cannot have
23488 // traits specified.
23489 if (IsPredefinedAllocator && D.AllocatorTraits) {
23490 Diag(D.AllocatorTraits->getExprLoc(),
23491 diag::err_omp_predefined_allocator_with_traits)
23492 << D.AllocatorTraits->getSourceRange();
23493 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23494 << cast<NamedDecl>(DRE->getDecl())->getName()
23495 << D.Allocator->getSourceRange();
23496 continue;
23497 }
23498 // OpenMP [2.12.5, target Construct]
23499 // Non-predefined allocators appearing in a uses_allocators clause must
23500 // have traits specified.
23501 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23502 Diag(D.Allocator->getExprLoc(),
23503 diag::err_omp_nonpredefined_allocator_without_traits);
23504 continue;
23505 }
23506 // No allocator traits - just convert it to rvalue.
23507 if (!D.AllocatorTraits)
23508 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
23509 DSAStack->addUsesAllocatorsDecl(
23510 DRE->getDecl(),
23511 IsPredefinedAllocator
23512 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23513 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23514 }
23515 Expr *AllocatorTraitsExpr = nullptr;
23516 if (D.AllocatorTraits) {
23517 if (D.AllocatorTraits->isTypeDependent()) {
23518 AllocatorTraitsExpr = D.AllocatorTraits;
23519 } else {
23520 // OpenMP [2.12.5, target Construct]
23521 // Arrays that contain allocator traits that appear in a uses_allocators
23522 // clause must be constant arrays, have constant values and be defined
23523 // in the same scope as the construct in which the clause appears.
23524 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23525 // Check that traits expr is a constant array.
23526 QualType TraitTy;
23527 if (const ArrayType *Ty =
23528 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23529 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23530 TraitTy = ConstArrayTy->getElementType();
23531 if (TraitTy.isNull() ||
23532 !(Context.hasSameUnqualifiedType(TraitTy,
23533 DSAStack->getOMPAlloctraitT()) ||
23534 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23535 /*CompareUnqualified=*/true))) {
23536 Diag(D.AllocatorTraits->getExprLoc(),
23537 diag::err_omp_expected_array_alloctraits)
23538 << AllocatorTraitsExpr->getType();
23539 continue;
23540 }
23541 // Do not map by default allocator traits if it is a standalone
23542 // variable.
23543 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23544 DSAStack->addUsesAllocatorsDecl(
23545 DRE->getDecl(),
23546 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23547 }
23548 }
23549 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23550 NewD.Allocator = AllocatorExpr;
23551 NewD.AllocatorTraits = AllocatorTraitsExpr;
23552 NewD.LParenLoc = D.LParenLoc;
23553 NewD.RParenLoc = D.RParenLoc;
23554 }
23555 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
23556 EndLoc, NewData);
23557}
23558
23560 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23561 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23563 for (Expr *RefExpr : Locators) {
23564 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23565 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23566 // It will be analyzed later.
23567 Vars.push_back(RefExpr);
23568 continue;
23569 }
23570
23571 SourceLocation ELoc = RefExpr->getExprLoc();
23572 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23573
23574 if (!SimpleExpr->isLValue()) {
23575 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23576 << 1 << 0 << RefExpr->getSourceRange();
23577 continue;
23578 }
23579
23580 ExprResult Res;
23581 {
23583 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23584 }
23585 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23586 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23587 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23588 << 1 << 0 << RefExpr->getSourceRange();
23589 continue;
23590 }
23591 Vars.push_back(SimpleExpr);
23592 }
23593
23594 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
23595 ColonLoc, EndLoc, Modifier, Vars);
23596}
23597
23599 SourceLocation KindLoc,
23600 SourceLocation StartLoc,
23601 SourceLocation LParenLoc,
23602 SourceLocation EndLoc) {
23603 if (Kind == OMPC_BIND_unknown) {
23604 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23605 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23606 /*Last=*/unsigned(OMPC_BIND_unknown))
23607 << getOpenMPClauseName(OMPC_bind);
23608 return nullptr;
23609 }
23610
23611 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
23612 LParenLoc, EndLoc);
23613}
23614
23616 SourceLocation StartLoc,
23617 SourceLocation LParenLoc,
23618 SourceLocation EndLoc) {
23619 Expr *ValExpr = Size;
23620 Stmt *HelperValStmt = nullptr;
23621
23622 // OpenMP [2.5, Restrictions]
23623 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23624 // value.
23625 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
23626 /*StrictlyPositive=*/false))
23627 return nullptr;
23628
23629 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23631 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
23632 if (CaptureRegion != OMPD_unknown &&
23634 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23635 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23636 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23637 HelperValStmt = buildPreInits(getASTContext(), Captures);
23638 }
23639
23641 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23642}
23643
23646 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23647 SourceLocation LParenLoc, SourceLocation EndLoc) {
23648
23649 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
23650 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23651 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23652 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23653 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23654 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23655 return nullptr;
23656 }
23657
23660 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23661 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
23662 SemaRef,
23663 DepType == OMPC_DOACROSS_source ||
23664 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23665 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23666 VarList, DSAStack, EndLoc);
23667 Vars = VarOffset.Vars;
23668 OpsOffs = VarOffset.OpsOffs;
23669 TotalDepCount = VarOffset.TotalDepCount;
23670 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
23671 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23672 TotalDepCount.getZExtValue());
23673 if (DSAStack->isParentOrderedRegion())
23674 DSAStack->addDoacrossDependClause(C, OpsOffs);
23675 return C;
23676}
23677
23679 SourceLocation StartLoc,
23680 SourceLocation LParenLoc,
23681 SourceLocation EndLoc) {
23682 return new (getASTContext())
23683 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
23684}
23685
23687 SourceLocation EndLoc) {
23688 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
23689}
23690
23692 SourceLocation LParenLoc,
23693 SourceLocation EndLoc) {
23694 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
23695}
23696
23700 switch (CK) {
23701 case OMPC_absent:
23702 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23703 case OMPC_contains:
23704 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23705 default:
23706 llvm_unreachable("Unexpected OpenMP clause");
23707 }
23708}
23709
23712 SourceLocation RLoc) {
23713 switch (CK) {
23714 case OMPC_no_openmp:
23715 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
23716 case OMPC_no_openmp_routines:
23717 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
23718 case OMPC_no_parallelism:
23719 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
23720 default:
23721 llvm_unreachable("Unexpected OpenMP clause");
23722 }
23723}
23724
23726 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
23727 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
23728 Expr *Stride, SourceLocation RBLoc) {
23729 ASTContext &Context = getASTContext();
23730 if (Base->hasPlaceholderType() &&
23731 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23733 if (Result.isInvalid())
23734 return ExprError();
23735 Base = Result.get();
23736 }
23737 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
23739 if (Result.isInvalid())
23740 return ExprError();
23742 if (Result.isInvalid())
23743 return ExprError();
23744 LowerBound = Result.get();
23745 }
23746 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23748 if (Result.isInvalid())
23749 return ExprError();
23751 if (Result.isInvalid())
23752 return ExprError();
23753 Length = Result.get();
23754 }
23755 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
23757 if (Result.isInvalid())
23758 return ExprError();
23760 if (Result.isInvalid())
23761 return ExprError();
23762 Stride = Result.get();
23763 }
23764
23765 // Build an unanalyzed expression if either operand is type-dependent.
23766 if (Base->isTypeDependent() ||
23767 (LowerBound &&
23768 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
23769 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23770 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
23771 return new (Context) ArraySectionExpr(
23772 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
23773 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23774 }
23775
23776 // Perform default conversions.
23778 QualType ResultTy;
23779 if (OriginalTy->isAnyPointerType()) {
23780 ResultTy = OriginalTy->getPointeeType();
23781 } else if (OriginalTy->isArrayType()) {
23782 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
23783 } else {
23784 return ExprError(
23785 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23786 << Base->getSourceRange());
23787 }
23788 // C99 6.5.2.1p1
23789 if (LowerBound) {
23790 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
23791 LowerBound);
23792 if (Res.isInvalid())
23793 return ExprError(Diag(LowerBound->getExprLoc(),
23794 diag::err_omp_typecheck_section_not_integer)
23795 << 0 << LowerBound->getSourceRange());
23796 LowerBound = Res.get();
23797
23798 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23799 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23800 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
23801 << 0 << LowerBound->getSourceRange();
23802 }
23803 if (Length) {
23804 auto Res =
23805 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
23806 if (Res.isInvalid())
23807 return ExprError(Diag(Length->getExprLoc(),
23808 diag::err_omp_typecheck_section_not_integer)
23809 << 1 << Length->getSourceRange());
23810 Length = Res.get();
23811
23812 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23813 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23814 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23815 << 1 << Length->getSourceRange();
23816 }
23817 if (Stride) {
23818 ExprResult Res =
23820 if (Res.isInvalid())
23821 return ExprError(Diag(Stride->getExprLoc(),
23822 diag::err_omp_typecheck_section_not_integer)
23823 << 1 << Stride->getSourceRange());
23824 Stride = Res.get();
23825
23826 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23827 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23828 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
23829 << 1 << Stride->getSourceRange();
23830 }
23831
23832 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
23833 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
23834 // type. Note that functions are not objects, and that (in C99 parlance)
23835 // incomplete types are not object types.
23836 if (ResultTy->isFunctionType()) {
23837 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
23838 << ResultTy << Base->getSourceRange();
23839 return ExprError();
23840 }
23841
23842 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
23843 diag::err_omp_section_incomplete_type, Base))
23844 return ExprError();
23845
23846 if (LowerBound && !OriginalTy->isAnyPointerType()) {
23848 if (LowerBound->EvaluateAsInt(Result, Context)) {
23849 // OpenMP 5.0, [2.1.5 Array Sections]
23850 // The array section must be a subset of the original array.
23851 llvm::APSInt LowerBoundValue = Result.Val.getInt();
23852 if (LowerBoundValue.isNegative()) {
23853 Diag(LowerBound->getExprLoc(),
23854 diag::err_omp_section_not_subset_of_array)
23855 << LowerBound->getSourceRange();
23856 return ExprError();
23857 }
23858 }
23859 }
23860
23861 if (Length) {
23863 if (Length->EvaluateAsInt(Result, Context)) {
23864 // OpenMP 5.0, [2.1.5 Array Sections]
23865 // The length must evaluate to non-negative integers.
23866 llvm::APSInt LengthValue = Result.Val.getInt();
23867 if (LengthValue.isNegative()) {
23868 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23869 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
23870 << Length->getSourceRange();
23871 return ExprError();
23872 }
23873 }
23874 } else if (ColonLocFirst.isValid() &&
23875 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
23876 !OriginalTy->isVariableArrayType()))) {
23877 // OpenMP 5.0, [2.1.5 Array Sections]
23878 // When the size of the array dimension is not known, the length must be
23879 // specified explicitly.
23880 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23881 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
23882 return ExprError();
23883 }
23884
23885 if (Stride) {
23887 if (Stride->EvaluateAsInt(Result, Context)) {
23888 // OpenMP 5.0, [2.1.5 Array Sections]
23889 // The stride must evaluate to a positive integer.
23890 llvm::APSInt StrideValue = Result.Val.getInt();
23891 if (!StrideValue.isStrictlyPositive()) {
23892 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
23893 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
23894 << Stride->getSourceRange();
23895 return ExprError();
23896 }
23897 }
23898 }
23899
23900 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23902 if (Result.isInvalid())
23903 return ExprError();
23904 Base = Result.get();
23905 }
23906 return new (Context) ArraySectionExpr(
23907 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
23908 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23909}
23910
23912 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
23913 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
23914 ASTContext &Context = getASTContext();
23915 if (Base->hasPlaceholderType()) {
23917 if (Result.isInvalid())
23918 return ExprError();
23920 if (Result.isInvalid())
23921 return ExprError();
23922 Base = Result.get();
23923 }
23924 QualType BaseTy = Base->getType();
23925 // Delay analysis of the types/expressions if instantiation/specialization is
23926 // required.
23927 if (!BaseTy->isPointerType() && Base->isTypeDependent())
23928 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
23929 LParenLoc, RParenLoc, Dims, Brackets);
23930 if (!BaseTy->isPointerType() ||
23931 (!Base->isTypeDependent() &&
23932 BaseTy->getPointeeType()->isIncompleteType()))
23933 return ExprError(Diag(Base->getExprLoc(),
23934 diag::err_omp_non_pointer_type_array_shaping_base)
23935 << Base->getSourceRange());
23936
23937 SmallVector<Expr *, 4> NewDims;
23938 bool ErrorFound = false;
23939 for (Expr *Dim : Dims) {
23940 if (Dim->hasPlaceholderType()) {
23942 if (Result.isInvalid()) {
23943 ErrorFound = true;
23944 continue;
23945 }
23947 if (Result.isInvalid()) {
23948 ErrorFound = true;
23949 continue;
23950 }
23951 Dim = Result.get();
23952 }
23953 if (!Dim->isTypeDependent()) {
23956 if (Result.isInvalid()) {
23957 ErrorFound = true;
23958 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23959 << Dim->getSourceRange();
23960 continue;
23961 }
23962 Dim = Result.get();
23963 Expr::EvalResult EvResult;
23964 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23965 // OpenMP 5.0, [2.1.4 Array Shaping]
23966 // Each si is an integral type expression that must evaluate to a
23967 // positive integer.
23968 llvm::APSInt Value = EvResult.Val.getInt();
23969 if (!Value.isStrictlyPositive()) {
23970 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23971 << toString(Value, /*Radix=*/10, /*Signed=*/true)
23972 << Dim->getSourceRange();
23973 ErrorFound = true;
23974 continue;
23975 }
23976 }
23977 }
23978 NewDims.push_back(Dim);
23979 }
23980 if (ErrorFound)
23981 return ExprError();
23982 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
23983 LParenLoc, RParenLoc, NewDims, Brackets);
23984}
23985
23987 SourceLocation IteratorKwLoc,
23988 SourceLocation LLoc,
23989 SourceLocation RLoc,
23991 ASTContext &Context = getASTContext();
23993 bool IsCorrect = true;
23994 for (const OMPIteratorData &D : Data) {
23995 TypeSourceInfo *TInfo = nullptr;
23996 SourceLocation StartLoc;
23997 QualType DeclTy;
23998 if (!D.Type.getAsOpaquePtr()) {
23999 // OpenMP 5.0, 2.1.6 Iterators
24000 // In an iterator-specifier, if the iterator-type is not specified then
24001 // the type of that iterator is of int type.
24002 DeclTy = Context.IntTy;
24003 StartLoc = D.DeclIdentLoc;
24004 } else {
24005 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
24006 StartLoc = TInfo->getTypeLoc().getBeginLoc();
24007 }
24008
24009 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24010 DeclTy->containsUnexpandedParameterPack() ||
24011 DeclTy->isInstantiationDependentType();
24012 if (!IsDeclTyDependent) {
24013 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24014 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24015 // The iterator-type must be an integral or pointer type.
24016 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24017 << DeclTy;
24018 IsCorrect = false;
24019 continue;
24020 }
24021 if (DeclTy.isConstant(Context)) {
24022 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24023 // The iterator-type must not be const qualified.
24024 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24025 << DeclTy;
24026 IsCorrect = false;
24027 continue;
24028 }
24029 }
24030
24031 // Iterator declaration.
24032 assert(D.DeclIdent && "Identifier expected.");
24033 // Always try to create iterator declarator to avoid extra error messages
24034 // about unknown declarations use.
24035 auto *VD =
24036 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
24037 D.DeclIdent, DeclTy, TInfo, SC_None);
24038 VD->setImplicit();
24039 if (S) {
24040 // Check for conflicting previous declaration.
24041 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24043 RedeclarationKind::ForVisibleRedeclaration);
24044 Previous.suppressDiagnostics();
24046
24048 /*ConsiderLinkage=*/false,
24049 /*AllowInlineNamespace=*/false);
24050 if (!Previous.empty()) {
24051 NamedDecl *Old = Previous.getRepresentativeDecl();
24052 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
24053 Diag(Old->getLocation(), diag::note_previous_definition);
24054 } else {
24056 }
24057 } else {
24059 }
24060
24061 /// Act on the iterator variable declaration.
24063
24064 Expr *Begin = D.Range.Begin;
24065 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24068 Begin = BeginRes.get();
24069 }
24070 Expr *End = D.Range.End;
24071 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24073 End, DeclTy, AssignmentAction::Converting);
24074 End = EndRes.get();
24075 }
24076 Expr *Step = D.Range.Step;
24077 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24078 if (!Step->getType()->isIntegralType(Context)) {
24079 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
24080 << Step << Step->getSourceRange();
24081 IsCorrect = false;
24082 continue;
24083 }
24084 std::optional<llvm::APSInt> Result =
24085 Step->getIntegerConstantExpr(Context);
24086 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24087 // If the step expression of a range-specification equals zero, the
24088 // behavior is unspecified.
24089 if (Result && Result->isZero()) {
24090 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24091 << Step << Step->getSourceRange();
24092 IsCorrect = false;
24093 continue;
24094 }
24095 }
24096 if (!Begin || !End || !IsCorrect) {
24097 IsCorrect = false;
24098 continue;
24099 }
24100 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
24101 IDElem.IteratorDecl = VD;
24102 IDElem.AssignmentLoc = D.AssignLoc;
24103 IDElem.Range.Begin = Begin;
24104 IDElem.Range.End = End;
24105 IDElem.Range.Step = Step;
24106 IDElem.ColonLoc = D.ColonLoc;
24107 IDElem.SecondColonLoc = D.SecColonLoc;
24108 }
24109 if (!IsCorrect) {
24110 // Invalidate all created iterator declarations if error is found.
24111 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24112 if (Decl *ID = D.IteratorDecl)
24113 ID->setInvalidDecl();
24114 }
24115 return ExprError();
24116 }
24119 // Build number of ityeration for each iteration range.
24120 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
24121 // ((Begini-Stepi-1-Endi) / -Stepi);
24123 // (Endi - Begini)
24124 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
24125 D.Range.End, D.Range.Begin);
24126 if (!Res.isUsable()) {
24127 IsCorrect = false;
24128 continue;
24129 }
24130 ExprResult St, St1;
24131 if (D.Range.Step) {
24132 St = D.Range.Step;
24133 // (Endi - Begini) + Stepi
24134 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
24135 St.get());
24136 if (!Res.isUsable()) {
24137 IsCorrect = false;
24138 continue;
24139 }
24140 // (Endi - Begini) + Stepi - 1
24142 D.AssignmentLoc, BO_Sub, Res.get(),
24143 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24144 if (!Res.isUsable()) {
24145 IsCorrect = false;
24146 continue;
24147 }
24148 // ((Endi - Begini) + Stepi - 1) / Stepi
24149 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
24150 St.get());
24151 if (!Res.isUsable()) {
24152 IsCorrect = false;
24153 continue;
24154 }
24155 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
24156 D.Range.Step);
24157 // (Begini - Endi)
24159 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
24160 if (!Res1.isUsable()) {
24161 IsCorrect = false;
24162 continue;
24163 }
24164 // (Begini - Endi) - Stepi
24165 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
24166 St1.get());
24167 if (!Res1.isUsable()) {
24168 IsCorrect = false;
24169 continue;
24170 }
24171 // (Begini - Endi) - Stepi - 1
24173 D.AssignmentLoc, BO_Sub, Res1.get(),
24174 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24175 if (!Res1.isUsable()) {
24176 IsCorrect = false;
24177 continue;
24178 }
24179 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24180 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
24181 St1.get());
24182 if (!Res1.isUsable()) {
24183 IsCorrect = false;
24184 continue;
24185 }
24186 // Stepi > 0.
24188 D.AssignmentLoc, BO_GT, D.Range.Step,
24189 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
24190 if (!CmpRes.isUsable()) {
24191 IsCorrect = false;
24192 continue;
24193 }
24194 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
24195 CmpRes.get(), Res.get(), Res1.get());
24196 if (!Res.isUsable()) {
24197 IsCorrect = false;
24198 continue;
24199 }
24200 }
24201 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
24202 if (!Res.isUsable()) {
24203 IsCorrect = false;
24204 continue;
24205 }
24206
24207 // Build counter update.
24208 // Build counter.
24209 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
24210 D.IteratorDecl->getBeginLoc(),
24211 D.IteratorDecl->getBeginLoc(), nullptr,
24212 Res.get()->getType(), nullptr, SC_None);
24213 CounterVD->setImplicit();
24214 ExprResult RefRes =
24215 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
24216 D.IteratorDecl->getBeginLoc());
24217 // Build counter update.
24218 // I = Begini + counter * Stepi;
24219 ExprResult UpdateRes;
24220 if (D.Range.Step) {
24221 UpdateRes = SemaRef.CreateBuiltinBinOp(
24222 D.AssignmentLoc, BO_Mul,
24223 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
24224 } else {
24225 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
24226 }
24227 if (!UpdateRes.isUsable()) {
24228 IsCorrect = false;
24229 continue;
24230 }
24231 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
24232 D.Range.Begin, UpdateRes.get());
24233 if (!UpdateRes.isUsable()) {
24234 IsCorrect = false;
24235 continue;
24236 }
24237 ExprResult VDRes =
24238 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
24239 cast<VarDecl>(D.IteratorDecl)->getType(),
24240 VK_LValue, D.IteratorDecl->getBeginLoc());
24241 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
24242 VDRes.get(), UpdateRes.get());
24243 if (!UpdateRes.isUsable()) {
24244 IsCorrect = false;
24245 continue;
24246 }
24247 UpdateRes =
24248 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
24249 if (!UpdateRes.isUsable()) {
24250 IsCorrect = false;
24251 continue;
24252 }
24253 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24254 D.AssignmentLoc, UO_PreInc, RefRes.get());
24255 if (!CounterUpdateRes.isUsable()) {
24256 IsCorrect = false;
24257 continue;
24258 }
24259 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
24260 /*DiscardedValue=*/true);
24261 if (!CounterUpdateRes.isUsable()) {
24262 IsCorrect = false;
24263 continue;
24264 }
24265 OMPIteratorHelperData &HD = Helpers.emplace_back();
24266 HD.CounterVD = CounterVD;
24267 HD.Upper = Res.get();
24268 HD.Update = UpdateRes.get();
24269 HD.CounterUpdate = CounterUpdateRes.get();
24270 }
24271 } else {
24272 Helpers.assign(ID.size(), {});
24273 }
24274 if (!IsCorrect) {
24275 // Invalidate all created iterator declarations if error is found.
24276 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24277 if (Decl *ID = D.IteratorDecl)
24278 ID->setInvalidDecl();
24279 }
24280 return ExprError();
24281 }
24282 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
24283 LLoc, RLoc, ID, Helpers);
24284}
24285
24286/// Check if \p AssumptionStr is a known assumption and warn if not.
24288 StringRef AssumptionStr) {
24289 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24290 return;
24291
24292 unsigned BestEditDistance = 3;
24293 StringRef Suggestion;
24294 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24295 unsigned EditDistance =
24296 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24297 if (EditDistance < BestEditDistance) {
24298 Suggestion = KnownAssumptionIt.getKey();
24299 BestEditDistance = EditDistance;
24300 }
24301 }
24302
24303 if (!Suggestion.empty())
24304 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24305 << AssumptionStr << Suggestion;
24306 else
24307 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
24308 << AssumptionStr;
24309}
24310
24312 // Handle the case where the attribute has a text message.
24313 StringRef Str;
24314 SourceLocation AttrStrLoc;
24315 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
24316 return;
24317
24318 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
24319
24320 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24321}
24322
24324 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3453
NodeId Parent
Definition: ASTDiff.cpp:191
DynTypedNode Node
StringRef P
const Decl * D
enum clang::sema::@1724::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:3055
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:5184
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:2107
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition: Stmt.cpp:432
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:2196
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:2158
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:2885
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:1499
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1645
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:4687
unsigned getNumParams() const
Definition: Decl.h:4729
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5469
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4731
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition: Stmt.h:3797
This captures a statement into a function.
Definition: Stmt.h:3784
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1414
SourceRange getSourceRange() const LLVM_READONLY
Definition: Stmt.h:3987
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3888
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition: Stmt.cpp:1438
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:3979
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:1628
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition: Stmt.cpp:390
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:550
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:487
ValueDecl * getDecl()
Definition: Expr.h:1333
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Expr.cpp:555
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1519
SourceLocation getEndLoc() const
Definition: Stmt.h:1542
const DeclGroupRef getDeclGroup() const
Definition: Stmt.h:1537
const Decl * getSingleDecl() const
Definition: Stmt.h:1534
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:1545
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:3102
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:3114
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3097
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3085
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:3093
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:3077
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:276
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:3136
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4678
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3275
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1081
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2808
Stmt * getBody()
Definition: Stmt.h:2852
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:5107
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:2165
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:2089
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:7579
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:980
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, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
Definition: OpenMPClause.h:670
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:5265
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:785
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:682
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:5394
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:831
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.
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:876
Expr * getSafelen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:896
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:911
Expr * getSimdlen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:931
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:4996
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:8025
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:7936
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:8139
QualType getCanonicalType() const
Definition: Type.h:7988
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:8030
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:8108
const Type * getTypePtrOrNull() const
Definition: Type.h:7940
Represents a struct/union/class.
Definition: Decl.h:4162
field_range fields() const
Definition: Decl.h:4368
field_iterator field_begin() const
Definition: Decl.cpp:5094
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:6077
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)
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.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
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:916
Expr * get() const
Definition: Sema.h:7280
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:12125
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:7229
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:464
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
Definition: SemaType.cpp:6395
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:732
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:1561
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15498
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:8990
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:9031
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:9033
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:9035
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
SemaOpenMP & OpenMP()
Definition: Sema.h:1126
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:20171
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition: Sema.h:4325
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17394
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:20387
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:849
@ AR_inaccessible
Definition: Sema.h:1269
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:2292
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition: Sema.cpp:2161
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:6257
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:17152
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1665
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:1570
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ASTContext & Context
Definition: Sema.h:909
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4660
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:72
@ AllowFold
Definition: Sema.h:7245
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1499
void CleanupVarDeclMarking()
Definition: SemaExpr.cpp:19667
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:752
ASTContext & getASTContext() const
Definition: Sema.h:532
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15777
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:18937
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:19915
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:17827
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:817
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:2180
const LangOptions & getLangOpts() const
Definition: Sema.h:525
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:908
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:6475
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:907
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2406
DeclContext * getCurLexicalContext() const
Definition: Sema.h:736
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:4571
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:940
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:14990
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20355
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2361
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1044
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4675
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4109
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:20971
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:13490
@ TryCapture_ExplicitByVal
Definition: Sema.h:6595
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:11234
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:8776
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:14945
@ CTK_ErrorRecovery
Definition: Sema.h:9384
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2346
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:10921
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:288
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5120
@ 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:5704
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:9119
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:872
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:17904
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1310
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
Definition: SemaExpr.cpp:3598
void PopDeclContext()
Definition: SemaDecl.cpp:1317
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:1581
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:13936
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13377
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition: Sema.cpp:1963
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
Definition: SemaExpr.cpp:15345
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:14768
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:2376
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2735
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:2751
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:451
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:7294
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:8268
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:357
child_range children()
Definition: Stmt.cpp:294
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:333
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:204
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:345
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4745
bool isTLSSupported() const
Whether the target supports thread-local storage.
Definition: TargetInfo.h:1583
bool isVLASupported() const
Whether target supports variable-length arrays.
Definition: TargetInfo.h:1594
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition: Decl.h:3384
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7907
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:7918
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:8267
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:8263
bool isArithmeticType() const
Definition: Type.cpp:2315
bool isPointerType() const
Definition: Type.h:8191
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8555
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8805
bool isReferenceType() const
Definition: Type.h:8209
bool isEnumeralType() const
Definition: Type.h:8295
bool isScalarType() const
Definition: Type.h:8614
bool isVariableArrayType() const
Definition: Type.h:8275
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:8509
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:8484
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:8299
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:8656
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:8791
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:8753
bool isFunctionType() const
Definition: Type.h:8187
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:8199
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8736
bool isRecordType() const
Definition: Type.h:8291
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:3414
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:5048
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
@ OMPC_ALLOCATE_unknown
Definition: OpenMPKinds.h:230
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:5192
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:244
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:1397
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1130
Data for list of allocators.
Definition: SemaOpenMP.h:1337
Clang specific specialization of the OMPContext to lookup target features.