clang 22.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
64
65namespace {
66/// Default data sharing attributes, which can be applied to directive.
67enum DefaultDataSharingAttributes {
68 DSA_unspecified = 0, /// Data sharing attribute not specified.
69 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
70 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
71 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
72 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
73};
74
75/// Stack for tracking declarations used in OpenMP directives and
76/// clauses and their data-sharing attributes.
77class DSAStackTy {
78public:
79 struct DSAVarData {
80 OpenMPDirectiveKind DKind = OMPD_unknown;
81 OpenMPClauseKind CKind = OMPC_unknown;
82 unsigned Modifier = 0;
83 const Expr *RefExpr = nullptr;
84 DeclRefExpr *PrivateCopy = nullptr;
85 SourceLocation ImplicitDSALoc;
86 bool AppliedToPointee = false;
87 DSAVarData() = default;
88 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
89 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
90 SourceLocation ImplicitDSALoc, unsigned Modifier,
91 bool AppliedToPointee)
92 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
93 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
94 AppliedToPointee(AppliedToPointee) {}
95 };
96 using OperatorOffsetTy =
98 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
99 /// Kind of the declaration used in the uses_allocators clauses.
100 enum class UsesAllocatorsDeclKind {
101 /// Predefined allocator
102 PredefinedAllocator,
103 /// User-defined allocator
104 UserDefinedAllocator,
105 /// The declaration that represent allocator trait
106 AllocatorTrait,
107 };
108
109private:
110 struct DSAInfo {
111 OpenMPClauseKind Attributes = OMPC_unknown;
112 unsigned Modifier = 0;
113 /// Pointer to a reference expression and a flag which shows that the
114 /// variable is marked as lastprivate(true) or not (false).
115 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
116 DeclRefExpr *PrivateCopy = nullptr;
117 /// true if the attribute is applied to the pointee, not the variable
118 /// itself.
119 bool AppliedToPointee = false;
120 };
121 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
122 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
123 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
124 using LoopControlVariablesMapTy =
125 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
126 /// Struct that associates a component with the clause kind where they are
127 /// found.
128 struct MappedExprComponentTy {
130 OpenMPClauseKind Kind = OMPC_unknown;
131 };
132 using MappedExprComponentsTy =
133 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
134 using CriticalsWithHintsTy =
135 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
136 struct ReductionData {
137 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
138 SourceRange ReductionRange;
139 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
140 ReductionData() = default;
141 void set(BinaryOperatorKind BO, SourceRange RR) {
142 ReductionRange = RR;
143 ReductionOp = BO;
144 }
145 void set(const Expr *RefExpr, SourceRange RR) {
146 ReductionRange = RR;
147 ReductionOp = RefExpr;
148 }
149 };
150 using DeclReductionMapTy =
151 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
152 struct DefaultmapInfo {
153 OpenMPDefaultmapClauseModifier ImplicitBehavior =
155 SourceLocation SLoc;
156 DefaultmapInfo() = default;
158 : ImplicitBehavior(M), SLoc(Loc) {}
159 };
160
161 struct SharingMapTy {
162 DeclSAMapTy SharingMap;
163 DeclReductionMapTy ReductionMap;
164 UsedRefMapTy AlignedMap;
165 UsedRefMapTy NontemporalMap;
166 MappedExprComponentsTy MappedExprComponents;
167 LoopControlVariablesMapTy LCVMap;
168 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
169 SourceLocation DefaultAttrLoc;
170 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
171 OpenMPDirectiveKind Directive = OMPD_unknown;
172 DeclarationNameInfo DirectiveName;
173 Scope *CurScope = nullptr;
174 DeclContext *Context = nullptr;
175 SourceLocation ConstructLoc;
176 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
177 /// get the data (loop counters etc.) about enclosing loop-based construct.
178 /// This data is required during codegen.
179 DoacrossClauseMapTy DoacrossDepends;
180 /// First argument (Expr *) contains optional argument of the
181 /// 'ordered' clause, the second one is true if the regions has 'ordered'
182 /// clause, false otherwise.
183 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
184 bool RegionHasOrderConcurrent = false;
185 unsigned AssociatedLoops = 1;
186 bool HasMutipleLoops = false;
187 const Decl *PossiblyLoopCounter = nullptr;
188 bool NowaitRegion = false;
189 bool UntiedRegion = false;
190 bool CancelRegion = false;
191 bool LoopStart = false;
192 bool BodyComplete = false;
193 SourceLocation PrevScanLocation;
194 SourceLocation PrevOrderedLocation;
195 SourceLocation InnerTeamsRegionLoc;
196 /// Reference to the taskgroup task_reduction reference expression.
197 Expr *TaskgroupReductionRef = nullptr;
198 llvm::DenseSet<QualType> MappedClassesQualTypes;
199 SmallVector<Expr *, 4> InnerUsedAllocators;
200 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
201 /// List of globals marked as declare target link in this target region
202 /// (isOpenMPTargetExecutionDirective(Directive) == true).
203 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
204 /// List of decls used in inclusive/exclusive clauses of the scan directive.
205 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
206 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
207 UsesAllocatorsDecls;
208 /// Data is required on creating capture fields for implicit
209 /// default first|private clause.
210 struct ImplicitDefaultFDInfoTy {
211 /// Field decl.
212 const FieldDecl *FD = nullptr;
213 /// Nesting stack level
214 size_t StackLevel = 0;
215 /// Capture variable decl.
216 VarDecl *VD = nullptr;
217 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
218 VarDecl *VD)
219 : FD(FD), StackLevel(StackLevel), VD(VD) {}
220 };
221 /// List of captured fields
223 ImplicitDefaultFirstprivateFDs;
224 Expr *DeclareMapperVar = nullptr;
225 SmallVector<VarDecl *, 16> IteratorVarDecls;
226 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
227 Scope *CurScope, SourceLocation Loc)
228 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
229 ConstructLoc(Loc) {}
230 SharingMapTy() = default;
231 };
232
233 using StackTy = SmallVector<SharingMapTy, 4>;
234
235 /// Stack of used declaration and their data-sharing attributes.
236 DeclSAMapTy Threadprivates;
237 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
239 /// true, if check for DSA must be from parent directive, false, if
240 /// from current directive.
241 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
242 Sema &SemaRef;
243 bool ForceCapturing = false;
244 /// true if all the variables in the target executable directives must be
245 /// captured by reference.
246 bool ForceCaptureByReferenceInTargetExecutable = false;
247 CriticalsWithHintsTy Criticals;
248 unsigned IgnoredStackElements = 0;
249
250 /// Iterators over the stack iterate in order from innermost to outermost
251 /// directive.
252 using const_iterator = StackTy::const_reverse_iterator;
253 const_iterator begin() const {
254 return Stack.empty() ? const_iterator()
255 : Stack.back().first.rbegin() + IgnoredStackElements;
256 }
257 const_iterator end() const {
258 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
259 }
260 using iterator = StackTy::reverse_iterator;
261 iterator begin() {
262 return Stack.empty() ? iterator()
263 : Stack.back().first.rbegin() + IgnoredStackElements;
264 }
265 iterator end() {
266 return Stack.empty() ? iterator() : Stack.back().first.rend();
267 }
268
269 // Convenience operations to get at the elements of the stack.
270
271 bool isStackEmpty() const {
272 return Stack.empty() ||
273 Stack.back().second != CurrentNonCapturingFunctionScope ||
274 Stack.back().first.size() <= IgnoredStackElements;
275 }
276 size_t getStackSize() const {
277 return isStackEmpty() ? 0
278 : Stack.back().first.size() - IgnoredStackElements;
279 }
280
281 SharingMapTy *getTopOfStackOrNull() {
282 size_t Size = getStackSize();
283 if (Size == 0)
284 return nullptr;
285 return &Stack.back().first[Size - 1];
286 }
287 const SharingMapTy *getTopOfStackOrNull() const {
288 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
289 }
290 SharingMapTy &getTopOfStack() {
291 assert(!isStackEmpty() && "no current directive");
292 return *getTopOfStackOrNull();
293 }
294 const SharingMapTy &getTopOfStack() const {
295 return const_cast<DSAStackTy &>(*this).getTopOfStack();
296 }
297
298 SharingMapTy *getSecondOnStackOrNull() {
299 size_t Size = getStackSize();
300 if (Size <= 1)
301 return nullptr;
302 return &Stack.back().first[Size - 2];
303 }
304 const SharingMapTy *getSecondOnStackOrNull() const {
305 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
306 }
307
308 /// Get the stack element at a certain level (previously returned by
309 /// \c getNestingLevel).
310 ///
311 /// Note that nesting levels count from outermost to innermost, and this is
312 /// the reverse of our iteration order where new inner levels are pushed at
313 /// the front of the stack.
314 SharingMapTy &getStackElemAtLevel(unsigned Level) {
315 assert(Level < getStackSize() && "no such stack element");
316 return Stack.back().first[Level];
317 }
318 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
319 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
320 }
321
322 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
323
324 /// Checks if the variable is a local for OpenMP region.
325 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
326
327 /// Vector of previously declared requires directives
329 /// omp_allocator_handle_t type.
330 QualType OMPAllocatorHandleT;
331 /// omp_depend_t type.
332 QualType OMPDependT;
333 /// omp_event_handle_t type.
334 QualType OMPEventHandleT;
335 /// omp_alloctrait_t type.
336 QualType OMPAlloctraitT;
337 /// Expression for the predefined allocators.
338 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
339 nullptr};
340 /// Vector of previously encountered target directives
341 SmallVector<SourceLocation, 2> TargetLocations;
342 SourceLocation AtomicLocation;
343 /// Vector of declare variant construct traits.
345
346public:
347 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
348
349 /// Sets omp_allocator_handle_t type.
350 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
351 /// Gets omp_allocator_handle_t type.
352 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
353 /// Sets omp_alloctrait_t type.
354 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
355 /// Gets omp_alloctrait_t type.
356 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
357 /// Sets the given default allocator.
358 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
359 Expr *Allocator) {
360 OMPPredefinedAllocators[AllocatorKind] = Allocator;
361 }
362 /// Returns the specified default allocator.
363 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
364 return OMPPredefinedAllocators[AllocatorKind];
365 }
366 /// Sets omp_depend_t type.
367 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
368 /// Gets omp_depend_t type.
369 QualType getOMPDependT() const { return OMPDependT; }
370
371 /// Sets omp_event_handle_t type.
372 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
373 /// Gets omp_event_handle_t type.
374 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
375
376 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
377 OpenMPClauseKind getClauseParsingMode() const {
378 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
379 return ClauseKindMode;
380 }
381 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
382
383 bool isBodyComplete() const {
384 const SharingMapTy *Top = getTopOfStackOrNull();
385 return Top && Top->BodyComplete;
386 }
387 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
388
389 bool isForceVarCapturing() const { return ForceCapturing; }
390 void setForceVarCapturing(bool V) { ForceCapturing = V; }
391
392 void setForceCaptureByReferenceInTargetExecutable(bool V) {
393 ForceCaptureByReferenceInTargetExecutable = V;
394 }
395 bool isForceCaptureByReferenceInTargetExecutable() const {
396 return ForceCaptureByReferenceInTargetExecutable;
397 }
398
399 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
400 Scope *CurScope, SourceLocation Loc) {
401 assert(!IgnoredStackElements &&
402 "cannot change stack while ignoring elements");
403 if (Stack.empty() ||
404 Stack.back().second != CurrentNonCapturingFunctionScope)
405 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
406 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
407 Stack.back().first.back().DefaultAttrLoc = Loc;
408 }
409
410 void pop() {
411 assert(!IgnoredStackElements &&
412 "cannot change stack while ignoring elements");
413 assert(!Stack.back().first.empty() &&
414 "Data-sharing attributes stack is empty!");
415 Stack.back().first.pop_back();
416 }
417
418 /// RAII object to temporarily leave the scope of a directive when we want to
419 /// logically operate in its parent.
420 class ParentDirectiveScope {
421 DSAStackTy &Self;
422 bool Active;
423
424 public:
425 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
426 : Self(Self), Active(false) {
427 if (Activate)
428 enable();
429 }
430 ~ParentDirectiveScope() { disable(); }
431 void disable() {
432 if (Active) {
433 --Self.IgnoredStackElements;
434 Active = false;
435 }
436 }
437 void enable() {
438 if (!Active) {
439 ++Self.IgnoredStackElements;
440 Active = true;
441 }
442 }
443 };
444
445 /// Marks that we're started loop parsing.
446 void loopInit() {
447 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
448 "Expected loop-based directive.");
449 getTopOfStack().LoopStart = true;
450 }
451 /// Start capturing of the variables in the loop context.
452 void loopStart() {
453 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
454 "Expected loop-based directive.");
455 getTopOfStack().LoopStart = false;
456 }
457 /// true, if variables are captured, false otherwise.
458 bool isLoopStarted() const {
459 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
460 "Expected loop-based directive.");
461 return !getTopOfStack().LoopStart;
462 }
463 /// Marks (or clears) declaration as possibly loop counter.
464 void resetPossibleLoopCounter(const Decl *D = nullptr) {
465 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
466 }
467 /// Gets the possible loop counter decl.
468 const Decl *getPossiblyLoopCounter() const {
469 return getTopOfStack().PossiblyLoopCounter;
470 }
471 /// Start new OpenMP region stack in new non-capturing function.
472 void pushFunction() {
473 assert(!IgnoredStackElements &&
474 "cannot change stack while ignoring elements");
475 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
476 assert(!isa<CapturingScopeInfo>(CurFnScope));
477 CurrentNonCapturingFunctionScope = CurFnScope;
478 }
479 /// Pop region stack for non-capturing function.
480 void popFunction(const FunctionScopeInfo *OldFSI) {
481 assert(!IgnoredStackElements &&
482 "cannot change stack while ignoring elements");
483 if (!Stack.empty() && Stack.back().second == OldFSI) {
484 assert(Stack.back().first.empty());
485 Stack.pop_back();
486 }
487 CurrentNonCapturingFunctionScope = nullptr;
488 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
489 if (!isa<CapturingScopeInfo>(FSI)) {
490 CurrentNonCapturingFunctionScope = FSI;
491 break;
492 }
493 }
494 }
495
496 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
497 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
498 }
499 std::pair<const OMPCriticalDirective *, llvm::APSInt>
500 getCriticalWithHint(const DeclarationNameInfo &Name) const {
501 auto I = Criticals.find(Name.getAsString());
502 if (I != Criticals.end())
503 return I->second;
504 return std::make_pair(nullptr, llvm::APSInt());
505 }
506 /// If 'aligned' declaration for given variable \a D was not seen yet,
507 /// add it and return NULL; otherwise return previous occurrence's expression
508 /// for diagnostics.
509 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
510 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
511 /// add it and return NULL; otherwise return previous occurrence's expression
512 /// for diagnostics.
513 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
514
515 /// Register specified variable as loop control variable.
516 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
517 /// Check if the specified variable is a loop control variable for
518 /// current region.
519 /// \return The index of the loop control variable in the list of associated
520 /// for-loops (from outer to inner).
521 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
522 /// Check if the specified variable is a loop control variable for
523 /// parent region.
524 /// \return The index of the loop control variable in the list of associated
525 /// for-loops (from outer to inner).
526 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
527 /// Check if the specified variable is a loop control variable for
528 /// current region.
529 /// \return The index of the loop control variable in the list of associated
530 /// for-loops (from outer to inner).
531 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
532 unsigned Level) const;
533 /// Get the loop control variable for the I-th loop (or nullptr) in
534 /// parent directive.
535 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
536
537 /// Marks the specified decl \p D as used in scan directive.
538 void markDeclAsUsedInScanDirective(ValueDecl *D) {
539 if (SharingMapTy *Stack = getSecondOnStackOrNull())
540 Stack->UsedInScanDirective.insert(D);
541 }
542
543 /// Checks if the specified declaration was used in the inner scan directive.
544 bool isUsedInScanDirective(ValueDecl *D) const {
545 if (const SharingMapTy *Stack = getTopOfStackOrNull())
546 return Stack->UsedInScanDirective.contains(D);
547 return false;
548 }
549
550 /// Adds explicit data sharing attribute to the specified declaration.
551 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
552 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
553 bool AppliedToPointee = false);
554
555 /// Adds additional information for the reduction items with the reduction id
556 /// represented as an operator.
557 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
559 /// Adds additional information for the reduction items with the reduction id
560 /// represented as reduction identifier.
561 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
562 const Expr *ReductionRef);
563 /// Returns the location and reduction operation from the innermost parent
564 /// region for the given \p D.
565 const DSAVarData
566 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
568 Expr *&TaskgroupDescriptor) const;
569 /// Returns the location and reduction operation from the innermost parent
570 /// region for the given \p D.
571 const DSAVarData
572 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
573 const Expr *&ReductionRef,
574 Expr *&TaskgroupDescriptor) const;
575 /// Return reduction reference expression for the current taskgroup or
576 /// parallel/worksharing directives with task reductions.
577 Expr *getTaskgroupReductionRef() const {
578 assert((getTopOfStack().Directive == OMPD_taskgroup ||
579 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
580 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
581 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
582 "taskgroup reference expression requested for non taskgroup or "
583 "parallel/worksharing directive.");
584 return getTopOfStack().TaskgroupReductionRef;
585 }
586 /// Checks if the given \p VD declaration is actually a taskgroup reduction
587 /// descriptor variable at the \p Level of OpenMP regions.
588 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
589 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
590 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
591 ->getDecl() == VD;
592 }
593
594 /// Returns data sharing attributes from top of the stack for the
595 /// specified declaration.
596 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
599 /// Returns data-sharing attributes for the specified declaration.
600 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
601 /// Checks if the specified variables has data-sharing attributes which
602 /// match specified \a CPred predicate in any directive which matches \a DPred
603 /// predicate.
604 const DSAVarData
605 hasDSA(ValueDecl *D,
606 const llvm::function_ref<bool(OpenMPClauseKind, bool,
607 DefaultDataSharingAttributes)>
608 CPred,
609 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
610 bool FromParent) const;
611 /// Checks if the specified variables has data-sharing attributes which
612 /// match specified \a CPred predicate in any innermost directive which
613 /// matches \a DPred predicate.
614 const DSAVarData
615 hasInnermostDSA(ValueDecl *D,
616 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
617 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
618 bool FromParent) const;
619 /// Checks if the specified variables has explicit data-sharing
620 /// attributes which match specified \a CPred predicate at the specified
621 /// OpenMP region.
622 bool
623 hasExplicitDSA(const ValueDecl *D,
624 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
625 unsigned Level, bool NotLastprivate = false) const;
626
627 /// Returns true if the directive at level \Level matches in the
628 /// specified \a DPred predicate.
629 bool hasExplicitDirective(
630 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
631 unsigned Level) const;
632
633 /// Finds a directive which matches specified \a DPred predicate.
634 bool hasDirective(
635 const llvm::function_ref<bool(
637 DPred,
638 bool FromParent) const;
639
640 /// Returns currently analyzed directive.
641 OpenMPDirectiveKind getCurrentDirective() const {
642 const SharingMapTy *Top = getTopOfStackOrNull();
643 return Top ? Top->Directive : OMPD_unknown;
644 }
645 /// Returns directive kind at specified level.
646 OpenMPDirectiveKind getDirective(unsigned Level) const {
647 assert(!isStackEmpty() && "No directive at specified level.");
648 return getStackElemAtLevel(Level).Directive;
649 }
650 /// Returns the capture region at the specified level.
651 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
652 unsigned OpenMPCaptureLevel) const {
654 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
655 return CaptureRegions[OpenMPCaptureLevel];
656 }
657 /// Returns parent directive.
658 OpenMPDirectiveKind getParentDirective() const {
659 const SharingMapTy *Parent = getSecondOnStackOrNull();
660 return Parent ? Parent->Directive : OMPD_unknown;
661 }
662
663 /// Add requires decl to internal vector
664 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
665
666 /// Checks if the defined 'requires' directive has specified type of clause.
667 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
668 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
669 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
670 return isa<ClauseType>(C);
671 });
672 });
673 }
674
675 /// Checks for a duplicate clause amongst previously declared requires
676 /// directives
677 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
678 bool IsDuplicate = false;
679 for (OMPClause *CNew : ClauseList) {
680 for (const OMPRequiresDecl *D : RequiresDecls) {
681 for (const OMPClause *CPrev : D->clauselists()) {
682 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
683 SemaRef.Diag(CNew->getBeginLoc(),
684 diag::err_omp_requires_clause_redeclaration)
685 << getOpenMPClauseNameForDiag(CNew->getClauseKind());
686 SemaRef.Diag(CPrev->getBeginLoc(),
687 diag::note_omp_requires_previous_clause)
688 << getOpenMPClauseNameForDiag(CPrev->getClauseKind());
689 IsDuplicate = true;
690 }
691 }
692 }
693 }
694 return IsDuplicate;
695 }
696
697 /// Add location of previously encountered target to internal vector
698 void addTargetDirLocation(SourceLocation LocStart) {
699 TargetLocations.push_back(LocStart);
700 }
701
702 /// Add location for the first encountered atomic directive.
703 void addAtomicDirectiveLoc(SourceLocation Loc) {
704 if (AtomicLocation.isInvalid())
705 AtomicLocation = Loc;
706 }
707
708 /// Returns the location of the first encountered atomic directive in the
709 /// module.
710 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
711
712 // Return previously encountered target region locations.
713 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
714 return TargetLocations;
715 }
716
717 /// Set default data sharing attribute to none.
718 void setDefaultDSANone(SourceLocation Loc) {
719 getTopOfStack().DefaultAttr = DSA_none;
720 getTopOfStack().DefaultAttrLoc = Loc;
721 }
722 /// Set default data sharing attribute to shared.
723 void setDefaultDSAShared(SourceLocation Loc) {
724 getTopOfStack().DefaultAttr = DSA_shared;
725 getTopOfStack().DefaultAttrLoc = Loc;
726 }
727 /// Set default data sharing attribute to private.
728 void setDefaultDSAPrivate(SourceLocation Loc) {
729 getTopOfStack().DefaultAttr = DSA_private;
730 getTopOfStack().DefaultAttrLoc = Loc;
731 }
732 /// Set default data sharing attribute to firstprivate.
733 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_firstprivate;
735 getTopOfStack().DefaultAttrLoc = Loc;
736 }
737 /// Set default data mapping attribute to Modifier:Kind
738 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
740 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
741 DMI.ImplicitBehavior = M;
742 DMI.SLoc = Loc;
743 }
744 /// Check whether the implicit-behavior has been set in defaultmap
745 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
746 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
747 return getTopOfStack()
748 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
749 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
750 getTopOfStack()
751 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
752 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
753 getTopOfStack()
754 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
755 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
756 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
758 }
759
760 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
761 return ConstructTraits;
762 }
763 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
764 bool ScopeEntry) {
765 if (ScopeEntry)
766 ConstructTraits.append(Traits.begin(), Traits.end());
767 else
768 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
769 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
770 assert(Top == Trait && "Something left a trait on the stack!");
771 (void)Trait;
772 (void)Top;
773 }
774 }
775
776 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
777 return getStackSize() <= Level ? DSA_unspecified
778 : getStackElemAtLevel(Level).DefaultAttr;
779 }
780 DefaultDataSharingAttributes getDefaultDSA() const {
781 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
782 }
783 SourceLocation getDefaultDSALocation() const {
784 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
785 }
787 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
788 return isStackEmpty()
790 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
791 }
793 getDefaultmapModifierAtLevel(unsigned Level,
794 OpenMPDefaultmapClauseKind Kind) const {
795 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
796 }
797 bool isDefaultmapCapturedByRef(unsigned Level,
798 OpenMPDefaultmapClauseKind Kind) const {
800 getDefaultmapModifierAtLevel(Level, Kind);
801 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
802 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
806 (M == OMPC_DEFAULTMAP_MODIFIER_present);
807 }
808 return true;
809 }
810 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
812 switch (Kind) {
813 case OMPC_DEFAULTMAP_scalar:
814 case OMPC_DEFAULTMAP_pointer:
815 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
816 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
817 (M == OMPC_DEFAULTMAP_MODIFIER_default);
818 case OMPC_DEFAULTMAP_aggregate:
819 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
820 default:
821 break;
822 }
823 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
824 }
825 bool mustBeFirstprivateAtLevel(unsigned Level,
826 OpenMPDefaultmapClauseKind Kind) const {
828 getDefaultmapModifierAtLevel(Level, Kind);
829 return mustBeFirstprivateBase(M, Kind);
830 }
831 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
832 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
833 return mustBeFirstprivateBase(M, Kind);
834 }
835
836 /// Checks if the specified variable is a threadprivate.
837 bool isThreadPrivate(VarDecl *D) {
838 const DSAVarData DVar = getTopDSA(D, false);
839 return isOpenMPThreadPrivate(DVar.CKind);
840 }
841
842 /// Marks current region as ordered (it has an 'ordered' clause).
843 void setOrderedRegion(bool IsOrdered, const Expr *Param,
844 OMPOrderedClause *Clause) {
845 if (IsOrdered)
846 getTopOfStack().OrderedRegion.emplace(Param, Clause);
847 else
848 getTopOfStack().OrderedRegion.reset();
849 }
850 /// Returns true, if region is ordered (has associated 'ordered' clause),
851 /// false - otherwise.
852 bool isOrderedRegion() const {
853 if (const SharingMapTy *Top = getTopOfStackOrNull())
854 return Top->OrderedRegion.has_value();
855 return false;
856 }
857 /// Returns optional parameter for the ordered region.
858 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
859 if (const SharingMapTy *Top = getTopOfStackOrNull())
860 if (Top->OrderedRegion)
861 return *Top->OrderedRegion;
862 return std::make_pair(nullptr, nullptr);
863 }
864 /// Returns true, if parent region is ordered (has associated
865 /// 'ordered' clause), false - otherwise.
866 bool isParentOrderedRegion() const {
867 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
868 return Parent->OrderedRegion.has_value();
869 return false;
870 }
871 /// Returns optional parameter for the ordered region.
872 std::pair<const Expr *, OMPOrderedClause *>
873 getParentOrderedRegionParam() const {
874 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
875 if (Parent->OrderedRegion)
876 return *Parent->OrderedRegion;
877 return std::make_pair(nullptr, nullptr);
878 }
879 /// Marks current region as having an 'order' clause.
880 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
881 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
882 }
883 /// Returns true, if parent region is order (has associated
884 /// 'order' clause), false - otherwise.
885 bool isParentOrderConcurrent() const {
886 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
887 return Parent->RegionHasOrderConcurrent;
888 return false;
889 }
890 /// Marks current region as nowait (it has a 'nowait' clause).
891 void setNowaitRegion(bool IsNowait = true) {
892 getTopOfStack().NowaitRegion = IsNowait;
893 }
894 /// Returns true, if parent region is nowait (has associated
895 /// 'nowait' clause), false - otherwise.
896 bool isParentNowaitRegion() const {
897 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
898 return Parent->NowaitRegion;
899 return false;
900 }
901 /// Marks current region as untied (it has a 'untied' clause).
902 void setUntiedRegion(bool IsUntied = true) {
903 getTopOfStack().UntiedRegion = IsUntied;
904 }
905 /// Return true if current region is untied.
906 bool isUntiedRegion() const {
907 const SharingMapTy *Top = getTopOfStackOrNull();
908 return Top ? Top->UntiedRegion : false;
909 }
910 /// Marks parent region as cancel region.
911 void setParentCancelRegion(bool Cancel = true) {
912 if (SharingMapTy *Parent = getSecondOnStackOrNull())
913 Parent->CancelRegion |= Cancel;
914 }
915 /// Return true if current region has inner cancel construct.
916 bool isCancelRegion() const {
917 const SharingMapTy *Top = getTopOfStackOrNull();
918 return Top ? Top->CancelRegion : false;
919 }
920
921 /// Mark that parent region already has scan directive.
922 void setParentHasScanDirective(SourceLocation Loc) {
923 if (SharingMapTy *Parent = getSecondOnStackOrNull())
924 Parent->PrevScanLocation = Loc;
925 }
926 /// Return true if current region has inner cancel construct.
927 bool doesParentHasScanDirective() const {
928 const SharingMapTy *Top = getSecondOnStackOrNull();
929 return Top ? Top->PrevScanLocation.isValid() : false;
930 }
931 /// Return true if current region has inner cancel construct.
932 SourceLocation getParentScanDirectiveLoc() const {
933 const SharingMapTy *Top = getSecondOnStackOrNull();
934 return Top ? Top->PrevScanLocation : SourceLocation();
935 }
936 /// Mark that parent region already has ordered directive.
937 void setParentHasOrderedDirective(SourceLocation Loc) {
938 if (SharingMapTy *Parent = getSecondOnStackOrNull())
939 Parent->PrevOrderedLocation = Loc;
940 }
941 /// Return true if current region has inner ordered construct.
942 bool doesParentHasOrderedDirective() const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevOrderedLocation.isValid() : false;
945 }
946 /// Returns the location of the previously specified ordered directive.
947 SourceLocation getParentOrderedDirectiveLoc() const {
948 const SharingMapTy *Top = getSecondOnStackOrNull();
949 return Top ? Top->PrevOrderedLocation : SourceLocation();
950 }
951
952 /// Set collapse value for the region.
953 void setAssociatedLoops(unsigned Val) {
954 getTopOfStack().AssociatedLoops = Val;
955 if (Val > 1)
956 getTopOfStack().HasMutipleLoops = true;
957 }
958 /// Return collapse value for region.
959 unsigned getAssociatedLoops() const {
960 const SharingMapTy *Top = getTopOfStackOrNull();
961 return Top ? Top->AssociatedLoops : 0;
962 }
963 /// Returns true if the construct is associated with multiple loops.
964 bool hasMutipleLoops() const {
965 const SharingMapTy *Top = getTopOfStackOrNull();
966 return Top ? Top->HasMutipleLoops : false;
967 }
968
969 /// Marks current target region as one with closely nested teams
970 /// region.
971 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
972 if (SharingMapTy *Parent = getSecondOnStackOrNull())
973 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
974 }
975 /// Returns true, if current region has closely nested teams region.
976 bool hasInnerTeamsRegion() const {
977 return getInnerTeamsRegionLoc().isValid();
978 }
979 /// Returns location of the nested teams region (if any).
980 SourceLocation getInnerTeamsRegionLoc() const {
981 const SharingMapTy *Top = getTopOfStackOrNull();
982 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
983 }
984
985 Scope *getCurScope() const {
986 const SharingMapTy *Top = getTopOfStackOrNull();
987 return Top ? Top->CurScope : nullptr;
988 }
989 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
990 SourceLocation getConstructLoc() const {
991 const SharingMapTy *Top = getTopOfStackOrNull();
992 return Top ? Top->ConstructLoc : SourceLocation();
993 }
994
995 /// Do the check specified in \a Check to all component lists and return true
996 /// if any issue is found.
997 bool checkMappableExprComponentListsForDecl(
998 const ValueDecl *VD, bool CurrentRegionOnly,
999 const llvm::function_ref<
1002 Check) const {
1003 if (isStackEmpty())
1004 return false;
1005 auto SI = begin();
1006 auto SE = end();
1007
1008 if (SI == SE)
1009 return false;
1010
1011 if (CurrentRegionOnly)
1012 SE = std::next(SI);
1013 else
1014 std::advance(SI, 1);
1015
1016 for (; SI != SE; ++SI) {
1017 auto MI = SI->MappedExprComponents.find(VD);
1018 if (MI != SI->MappedExprComponents.end())
1020 MI->second.Components)
1021 if (Check(L, MI->second.Kind))
1022 return true;
1023 }
1024 return false;
1025 }
1026
1027 /// Do the check specified in \a Check to all component lists at a given level
1028 /// and return true if any issue is found.
1029 bool checkMappableExprComponentListsForDeclAtLevel(
1030 const ValueDecl *VD, unsigned Level,
1031 const llvm::function_ref<
1034 Check) const {
1035 if (getStackSize() <= Level)
1036 return false;
1037
1038 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1039 auto MI = StackElem.MappedExprComponents.find(VD);
1040 if (MI != StackElem.MappedExprComponents.end())
1042 MI->second.Components)
1043 if (Check(L, MI->second.Kind))
1044 return true;
1045 return false;
1046 }
1047
1048 /// Create a new mappable expression component list associated with a given
1049 /// declaration and initialize it with the provided list of components.
1050 void addMappableExpressionComponents(
1051 const ValueDecl *VD,
1053 OpenMPClauseKind WhereFoundClauseKind) {
1054 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1055 // Create new entry and append the new components there.
1056 MEC.Components.resize(MEC.Components.size() + 1);
1057 MEC.Components.back().append(Components.begin(), Components.end());
1058 MEC.Kind = WhereFoundClauseKind;
1059 }
1060
1061 unsigned getNestingLevel() const {
1062 assert(!isStackEmpty());
1063 return getStackSize() - 1;
1064 }
1065 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1066 SharingMapTy *Parent = getSecondOnStackOrNull();
1067 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1068 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1069 }
1070 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1071 getDoacrossDependClauses() const {
1072 const SharingMapTy &StackElem = getTopOfStack();
1073 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1074 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1075 return llvm::make_range(Ref.begin(), Ref.end());
1076 }
1077 return llvm::make_range(StackElem.DoacrossDepends.end(),
1078 StackElem.DoacrossDepends.end());
1079 }
1080
1081 // Store types of classes which have been explicitly mapped
1082 void addMappedClassesQualTypes(QualType QT) {
1083 SharingMapTy &StackElem = getTopOfStack();
1084 StackElem.MappedClassesQualTypes.insert(QT);
1085 }
1086
1087 // Return set of mapped classes types
1088 bool isClassPreviouslyMapped(QualType QT) const {
1089 const SharingMapTy &StackElem = getTopOfStack();
1090 return StackElem.MappedClassesQualTypes.contains(QT);
1091 }
1092
1093 /// Adds global declare target to the parent target region.
1094 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1095 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1096 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1097 "Expected declare target link global.");
1098 for (auto &Elem : *this) {
1099 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1100 Elem.DeclareTargetLinkVarDecls.push_back(E);
1101 return;
1102 }
1103 }
1104 }
1105
1106 /// Returns the list of globals with declare target link if current directive
1107 /// is target.
1108 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1109 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1110 "Expected target executable directive.");
1111 return getTopOfStack().DeclareTargetLinkVarDecls;
1112 }
1113
1114 /// Adds list of allocators expressions.
1115 void addInnerAllocatorExpr(Expr *E) {
1116 getTopOfStack().InnerUsedAllocators.push_back(E);
1117 }
1118 /// Return list of used allocators.
1119 ArrayRef<Expr *> getInnerAllocators() const {
1120 return getTopOfStack().InnerUsedAllocators;
1121 }
1122 /// Marks the declaration as implicitly firstprivate nin the task-based
1123 /// regions.
1124 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1125 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1126 }
1127 /// Checks if the decl is implicitly firstprivate in the task-based region.
1128 bool isImplicitTaskFirstprivate(Decl *D) const {
1129 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1130 }
1131
1132 /// Marks decl as used in uses_allocators clause as the allocator.
1133 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1134 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1135 }
1136 /// Checks if specified decl is used in uses allocator clause as the
1137 /// allocator.
1138 std::optional<UsesAllocatorsDeclKind>
1139 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1140 const SharingMapTy &StackElem = getTopOfStack();
1141 auto I = StackElem.UsesAllocatorsDecls.find(D);
1142 if (I == StackElem.UsesAllocatorsDecls.end())
1143 return std::nullopt;
1144 return I->getSecond();
1145 }
1146 std::optional<UsesAllocatorsDeclKind>
1147 isUsesAllocatorsDecl(const Decl *D) const {
1148 const SharingMapTy &StackElem = getTopOfStack();
1149 auto I = StackElem.UsesAllocatorsDecls.find(D);
1150 if (I == StackElem.UsesAllocatorsDecls.end())
1151 return std::nullopt;
1152 return I->getSecond();
1153 }
1154
1155 void addDeclareMapperVarRef(Expr *Ref) {
1156 SharingMapTy &StackElem = getTopOfStack();
1157 StackElem.DeclareMapperVar = Ref;
1158 }
1159 const Expr *getDeclareMapperVarRef() const {
1160 const SharingMapTy *Top = getTopOfStackOrNull();
1161 return Top ? Top->DeclareMapperVar : nullptr;
1162 }
1163
1164 /// Add a new iterator variable.
1165 void addIteratorVarDecl(VarDecl *VD) {
1166 SharingMapTy &StackElem = getTopOfStack();
1167 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1168 }
1169 /// Check if variable declaration is an iterator VarDecl.
1170 bool isIteratorVarDecl(const VarDecl *VD) const {
1171 const SharingMapTy *Top = getTopOfStackOrNull();
1172 if (!Top)
1173 return false;
1174
1175 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1176 }
1177 /// get captured field from ImplicitDefaultFirstprivateFDs
1178 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1179 const_iterator I = begin();
1180 const_iterator EndI = end();
1181 size_t StackLevel = getStackSize();
1182 for (; I != EndI; ++I) {
1183 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1184 break;
1185 StackLevel--;
1186 }
1187 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1188 if (I == EndI)
1189 return nullptr;
1190 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1191 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1192 return IFD.VD;
1193 return nullptr;
1194 }
1195 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1196 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1197 const_iterator I = begin();
1198 const_iterator EndI = end();
1199 for (; I != EndI; ++I)
1200 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1201 break;
1202 if (I == EndI)
1203 return false;
1204 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1205 if (IFD.VD == VD)
1206 return true;
1207 return false;
1208 }
1209 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1210 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1211 iterator I = begin();
1212 const_iterator EndI = end();
1213 size_t StackLevel = getStackSize();
1214 for (; I != EndI; ++I) {
1215 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1216 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1217 break;
1218 }
1219 StackLevel--;
1220 }
1221 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1222 }
1223};
1224
1225bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1226 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1227}
1228
1229bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1230 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1231 DKind == OMPD_unknown;
1232}
1233
1234} // namespace
1235
1236static const Expr *getExprAsWritten(const Expr *E) {
1237 if (const auto *FE = dyn_cast<FullExpr>(E))
1238 E = FE->getSubExpr();
1239
1240 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1241 E = MTE->getSubExpr();
1242
1243 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1244 E = Binder->getSubExpr();
1245
1246 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1247 E = ICE->getSubExprAsWritten();
1248 return E->IgnoreParens();
1249}
1250
1252 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1253}
1254
1255static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1256 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1257 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1258 D = ME->getMemberDecl();
1259
1260 D = cast<ValueDecl>(D->getCanonicalDecl());
1261 return D;
1262}
1263
1265 return const_cast<ValueDecl *>(
1266 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1267}
1268
1270 if (C == OMPC_threadprivate)
1271 return getOpenMPClauseName(C).str() + " or thread local";
1272 return getOpenMPClauseName(C).str();
1273}
1274
1275DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1276 ValueDecl *D) const {
1277 D = getCanonicalDecl(D);
1278 auto *VD = dyn_cast<VarDecl>(D);
1279 const auto *FD = dyn_cast<FieldDecl>(D);
1280 DSAVarData DVar;
1281 if (Iter == end()) {
1282 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1283 // in a region but not in construct]
1284 // File-scope or namespace-scope variables referenced in called routines
1285 // in the region are shared unless they appear in a threadprivate
1286 // directive.
1287 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1288 DVar.CKind = OMPC_shared;
1289
1290 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1291 // in a region but not in construct]
1292 // Variables with static storage duration that are declared in called
1293 // routines in the region are shared.
1294 if (VD && VD->hasGlobalStorage())
1295 DVar.CKind = OMPC_shared;
1296
1297 // Non-static data members are shared by default.
1298 if (FD)
1299 DVar.CKind = OMPC_shared;
1300
1301 return DVar;
1302 }
1303
1304 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1305 // in a Construct, C/C++, predetermined, p.1]
1306 // Variables with automatic storage duration that are declared in a scope
1307 // inside the construct are private.
1308 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1309 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1310 DVar.CKind = OMPC_private;
1311 return DVar;
1312 }
1313
1314 DVar.DKind = Iter->Directive;
1315 // Explicitly specified attributes and local variables with predetermined
1316 // attributes.
1317 if (Iter->SharingMap.count(D)) {
1318 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1319 DVar.RefExpr = Data.RefExpr.getPointer();
1320 DVar.PrivateCopy = Data.PrivateCopy;
1321 DVar.CKind = Data.Attributes;
1322 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1323 DVar.Modifier = Data.Modifier;
1324 DVar.AppliedToPointee = Data.AppliedToPointee;
1325 return DVar;
1326 }
1327
1328 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1329 // in a Construct, C/C++, implicitly determined, p.1]
1330 // In a parallel or task construct, the data-sharing attributes of these
1331 // variables are determined by the default clause, if present.
1332 switch (Iter->DefaultAttr) {
1333 case DSA_shared:
1334 DVar.CKind = OMPC_shared;
1335 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1336 return DVar;
1337 case DSA_none:
1338 return DVar;
1339 case DSA_firstprivate:
1340 if (VD && VD->getStorageDuration() == SD_Static &&
1341 VD->getDeclContext()->isFileContext()) {
1342 DVar.CKind = OMPC_unknown;
1343 } else {
1344 DVar.CKind = OMPC_firstprivate;
1345 }
1346 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1347 return DVar;
1348 case DSA_private:
1349 // each variable with static storage duration that is declared
1350 // in a namespace or global scope and referenced in the construct,
1351 // and that does not have a predetermined data-sharing attribute
1352 if (VD && VD->getStorageDuration() == SD_Static &&
1353 VD->getDeclContext()->isFileContext()) {
1354 DVar.CKind = OMPC_unknown;
1355 } else {
1356 DVar.CKind = OMPC_private;
1357 }
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 return DVar;
1360 case DSA_unspecified:
1361 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1362 // in a Construct, implicitly determined, p.2]
1363 // In a parallel construct, if no default clause is present, these
1364 // variables are shared.
1365 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1366 if ((isOpenMPParallelDirective(DVar.DKind) &&
1367 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1368 isOpenMPTeamsDirective(DVar.DKind)) {
1369 DVar.CKind = OMPC_shared;
1370 return DVar;
1371 }
1372
1373 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1374 // in a Construct, implicitly determined, p.4]
1375 // In a task construct, if no default clause is present, a variable that in
1376 // the enclosing context is determined to be shared by all implicit tasks
1377 // bound to the current team is shared.
1378 if (isOpenMPTaskingDirective(DVar.DKind)) {
1379 DSAVarData DVarTemp;
1380 const_iterator I = Iter, E = end();
1381 do {
1382 ++I;
1383 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1384 // Referenced in a Construct, implicitly determined, p.6]
1385 // In a task construct, if no default clause is present, a variable
1386 // whose data-sharing attribute is not determined by the rules above is
1387 // firstprivate.
1388 DVarTemp = getDSA(I, D);
1389 if (DVarTemp.CKind != OMPC_shared) {
1390 DVar.RefExpr = nullptr;
1391 DVar.CKind = OMPC_firstprivate;
1392 return DVar;
1393 }
1394 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1395 DVar.CKind =
1396 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1397 return DVar;
1398 }
1399 }
1400 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1401 // in a Construct, implicitly determined, p.3]
1402 // For constructs other than task, if no default clause is present, these
1403 // variables inherit their data-sharing attributes from the enclosing
1404 // context.
1405 return getDSA(++Iter, D);
1406}
1407
1408const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1409 const Expr *NewDE) {
1410 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1411 D = getCanonicalDecl(D);
1412 SharingMapTy &StackElem = getTopOfStack();
1413 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1414 if (Inserted) {
1415 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1416 return nullptr;
1417 }
1418 assert(It->second && "Unexpected nullptr expr in the aligned map");
1419 return It->second;
1420}
1421
1422const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1423 const Expr *NewDE) {
1424 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1425 D = getCanonicalDecl(D);
1426 SharingMapTy &StackElem = getTopOfStack();
1427 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1428 if (Inserted) {
1429 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1430 return nullptr;
1431 }
1432 assert(It->second && "Unexpected nullptr expr in the aligned map");
1433 return It->second;
1434}
1435
1436void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1437 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1438 D = getCanonicalDecl(D);
1439 SharingMapTy &StackElem = getTopOfStack();
1440 StackElem.LCVMap.try_emplace(
1441 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1442}
1443
1444const DSAStackTy::LCDeclInfo
1445DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1446 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1447 D = getCanonicalDecl(D);
1448 const SharingMapTy &StackElem = getTopOfStack();
1449 auto It = StackElem.LCVMap.find(D);
1450 if (It != StackElem.LCVMap.end())
1451 return It->second;
1452 return {0, nullptr};
1453}
1454
1455const DSAStackTy::LCDeclInfo
1456DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1457 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1458 D = getCanonicalDecl(D);
1459 for (unsigned I = Level + 1; I > 0; --I) {
1460 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1461 auto It = StackElem.LCVMap.find(D);
1462 if (It != StackElem.LCVMap.end())
1463 return It->second;
1464 }
1465 return {0, nullptr};
1466}
1467
1468const DSAStackTy::LCDeclInfo
1469DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1470 const SharingMapTy *Parent = getSecondOnStackOrNull();
1471 assert(Parent && "Data-sharing attributes stack is empty");
1472 D = getCanonicalDecl(D);
1473 auto It = Parent->LCVMap.find(D);
1474 if (It != Parent->LCVMap.end())
1475 return It->second;
1476 return {0, nullptr};
1477}
1478
1479const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1480 const SharingMapTy *Parent = getSecondOnStackOrNull();
1481 assert(Parent && "Data-sharing attributes stack is empty");
1482 if (Parent->LCVMap.size() < I)
1483 return nullptr;
1484 for (const auto &Pair : Parent->LCVMap)
1485 if (Pair.second.first == I)
1486 return Pair.first;
1487 return nullptr;
1488}
1489
1490void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1491 DeclRefExpr *PrivateCopy, unsigned Modifier,
1492 bool AppliedToPointee) {
1493 D = getCanonicalDecl(D);
1494 if (A == OMPC_threadprivate) {
1495 DSAInfo &Data = Threadprivates[D];
1496 Data.Attributes = A;
1497 Data.RefExpr.setPointer(E);
1498 Data.PrivateCopy = nullptr;
1499 Data.Modifier = Modifier;
1500 } else {
1501 DSAInfo &Data = getTopOfStack().SharingMap[D];
1502 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1503 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1504 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1505 (isLoopControlVariable(D).first && A == OMPC_private));
1506 Data.Modifier = Modifier;
1507 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1508 Data.RefExpr.setInt(/*IntVal=*/true);
1509 return;
1510 }
1511 const bool IsLastprivate =
1512 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1513 Data.Attributes = A;
1514 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1515 Data.PrivateCopy = PrivateCopy;
1516 Data.AppliedToPointee = AppliedToPointee;
1517 if (PrivateCopy) {
1518 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1519 Data.Modifier = Modifier;
1520 Data.Attributes = A;
1521 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1522 Data.PrivateCopy = nullptr;
1523 Data.AppliedToPointee = AppliedToPointee;
1524 }
1525 }
1526}
1527
1528/// Build a variable declaration for OpenMP loop iteration variable.
1530 StringRef Name, const AttrVec *Attrs = nullptr,
1531 DeclRefExpr *OrigRef = nullptr) {
1532 DeclContext *DC = SemaRef.CurContext;
1533 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1535 auto *Decl =
1536 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1537 if (Attrs) {
1538 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1539 I != E; ++I)
1540 Decl->addAttr(*I);
1541 }
1542 Decl->setImplicit();
1543 if (OrigRef) {
1544 Decl->addAttr(
1545 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1546 }
1547 return Decl;
1548}
1549
1552 bool RefersToCapture = false) {
1553 D->setReferenced();
1554 D->markUsed(S.Context);
1556 SourceLocation(), D, RefersToCapture, Loc, Ty,
1557 VK_LValue);
1558}
1559
1560void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1561 BinaryOperatorKind BOK) {
1562 D = getCanonicalDecl(D);
1563 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1564 assert(
1565 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1566 "Additional reduction info may be specified only for reduction items.");
1567 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1568 assert(ReductionData.ReductionRange.isInvalid() &&
1569 (getTopOfStack().Directive == OMPD_taskgroup ||
1570 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1571 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1572 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1573 "Additional reduction info may be specified only once for reduction "
1574 "items.");
1575 ReductionData.set(BOK, SR);
1576 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1577 if (!TaskgroupReductionRef) {
1578 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1579 SemaRef.Context.VoidPtrTy, ".task_red.");
1580 TaskgroupReductionRef =
1581 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1582 }
1583}
1584
1585void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1586 const Expr *ReductionRef) {
1587 D = getCanonicalDecl(D);
1588 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1589 assert(
1590 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1591 "Additional reduction info may be specified only for reduction items.");
1592 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1593 assert(ReductionData.ReductionRange.isInvalid() &&
1594 (getTopOfStack().Directive == OMPD_taskgroup ||
1595 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1596 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1597 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1598 "Additional reduction info may be specified only once for reduction "
1599 "items.");
1600 ReductionData.set(ReductionRef, SR);
1601 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1602 if (!TaskgroupReductionRef) {
1603 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1604 SemaRef.Context.VoidPtrTy, ".task_red.");
1605 TaskgroupReductionRef =
1606 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1607 }
1608}
1609
1610const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1611 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1612 Expr *&TaskgroupDescriptor) const {
1613 D = getCanonicalDecl(D);
1614 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1615 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1616 const DSAInfo &Data = I->SharingMap.lookup(D);
1617 if (Data.Attributes != OMPC_reduction ||
1618 Data.Modifier != OMPC_REDUCTION_task)
1619 continue;
1620 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1621 if (!ReductionData.ReductionOp ||
1622 isa<const Expr *>(ReductionData.ReductionOp))
1623 return DSAVarData();
1624 SR = ReductionData.ReductionRange;
1625 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1626 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1627 "expression for the descriptor is not "
1628 "set.");
1629 TaskgroupDescriptor = I->TaskgroupReductionRef;
1630 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1631 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1632 /*AppliedToPointee=*/false);
1633 }
1634 return DSAVarData();
1635}
1636
1637const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1638 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1639 Expr *&TaskgroupDescriptor) const {
1640 D = getCanonicalDecl(D);
1641 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1642 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1643 const DSAInfo &Data = I->SharingMap.lookup(D);
1644 if (Data.Attributes != OMPC_reduction ||
1645 Data.Modifier != OMPC_REDUCTION_task)
1646 continue;
1647 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1648 if (!ReductionData.ReductionOp ||
1649 !isa<const Expr *>(ReductionData.ReductionOp))
1650 return DSAVarData();
1651 SR = ReductionData.ReductionRange;
1652 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1653 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1654 "expression for the descriptor is not "
1655 "set.");
1656 TaskgroupDescriptor = I->TaskgroupReductionRef;
1657 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1658 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1659 /*AppliedToPointee=*/false);
1660 }
1661 return DSAVarData();
1662}
1663
1664bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1665 D = D->getCanonicalDecl();
1666 for (const_iterator E = end(); I != E; ++I) {
1667 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1668 isOpenMPTargetExecutionDirective(I->Directive)) {
1669 if (I->CurScope) {
1670 Scope *TopScope = I->CurScope->getParent();
1671 Scope *CurScope = getCurScope();
1672 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1673 CurScope = CurScope->getParent();
1674 return CurScope != TopScope;
1675 }
1676 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1677 if (I->Context == DC)
1678 return true;
1679 return false;
1680 }
1681 }
1682 return false;
1683}
1684
1686 bool AcceptIfMutable = true,
1687 bool *IsClassType = nullptr) {
1688 ASTContext &Context = SemaRef.getASTContext();
1689 Type = Type.getNonReferenceType().getCanonicalType();
1690 bool IsConstant = Type.isConstant(Context);
1691 Type = Context.getBaseElementType(Type);
1692 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1694 : nullptr;
1695 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1696 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1697 RD = CTD->getTemplatedDecl();
1698 if (IsClassType)
1699 *IsClassType = RD;
1700 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1701 RD->hasDefinition() && RD->hasMutableFields());
1702}
1703
1704static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1706 SourceLocation ELoc,
1707 bool AcceptIfMutable = true,
1708 bool ListItemNotVar = false) {
1709 ASTContext &Context = SemaRef.getASTContext();
1710 bool IsClassType;
1711 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1712 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1713 : IsClassType ? diag::err_omp_const_not_mutable_variable
1714 : diag::err_omp_const_variable;
1715 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseNameForDiag(CKind);
1716 if (!ListItemNotVar && D) {
1717 const VarDecl *VD = dyn_cast<VarDecl>(D);
1718 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1720 SemaRef.Diag(D->getLocation(),
1721 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1722 << D;
1723 }
1724 return true;
1725 }
1726 return false;
1727}
1728
1729const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1730 bool FromParent) {
1731 D = getCanonicalDecl(D);
1732 DSAVarData DVar;
1733
1734 auto *VD = dyn_cast<VarDecl>(D);
1735 auto TI = Threadprivates.find(D);
1736 if (TI != Threadprivates.end()) {
1737 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1738 DVar.CKind = OMPC_threadprivate;
1739 DVar.Modifier = TI->getSecond().Modifier;
1740 return DVar;
1741 }
1742 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1743 DVar.RefExpr = buildDeclRefExpr(
1744 SemaRef, VD, D->getType().getNonReferenceType(),
1745 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1746 DVar.CKind = OMPC_threadprivate;
1747 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1748 return DVar;
1749 }
1750 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1751 // in a Construct, C/C++, predetermined, p.1]
1752 // Variables appearing in threadprivate directives are threadprivate.
1753 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1754 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1755 SemaRef.getLangOpts().OpenMPUseTLS &&
1756 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1757 (VD && VD->getStorageClass() == SC_Register &&
1758 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1759 DVar.RefExpr = buildDeclRefExpr(
1760 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1761 DVar.CKind = OMPC_threadprivate;
1762 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1763 return DVar;
1764 }
1765 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1766 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1767 !isLoopControlVariable(D).first) {
1768 const_iterator IterTarget =
1769 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1770 return isOpenMPTargetExecutionDirective(Data.Directive);
1771 });
1772 if (IterTarget != end()) {
1773 const_iterator ParentIterTarget = IterTarget + 1;
1774 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1775 if (isOpenMPLocal(VD, Iter)) {
1776 DVar.RefExpr =
1777 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1778 D->getLocation());
1779 DVar.CKind = OMPC_threadprivate;
1780 return DVar;
1781 }
1782 }
1783 if (!isClauseParsingMode() || IterTarget != begin()) {
1784 auto DSAIter = IterTarget->SharingMap.find(D);
1785 if (DSAIter != IterTarget->SharingMap.end() &&
1786 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1787 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1788 DVar.CKind = OMPC_threadprivate;
1789 return DVar;
1790 }
1791 const_iterator End = end();
1792 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1793 D, std::distance(ParentIterTarget, End),
1794 /*OpenMPCaptureLevel=*/0)) {
1795 DVar.RefExpr =
1796 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1797 IterTarget->ConstructLoc);
1798 DVar.CKind = OMPC_threadprivate;
1799 return DVar;
1800 }
1801 }
1802 }
1803 }
1804
1805 if (isStackEmpty())
1806 // Not in OpenMP execution region and top scope was already checked.
1807 return DVar;
1808
1809 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1810 // in a Construct, C/C++, predetermined, p.4]
1811 // Static data members are shared.
1812 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1813 // in a Construct, C/C++, predetermined, p.7]
1814 // Variables with static storage duration that are declared in a scope
1815 // inside the construct are shared.
1816 if (VD && VD->isStaticDataMember()) {
1817 // Check for explicitly specified attributes.
1818 const_iterator I = begin();
1819 const_iterator EndI = end();
1820 if (FromParent && I != EndI)
1821 ++I;
1822 if (I != EndI) {
1823 auto It = I->SharingMap.find(D);
1824 if (It != I->SharingMap.end()) {
1825 const DSAInfo &Data = It->getSecond();
1826 DVar.RefExpr = Data.RefExpr.getPointer();
1827 DVar.PrivateCopy = Data.PrivateCopy;
1828 DVar.CKind = Data.Attributes;
1829 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1830 DVar.DKind = I->Directive;
1831 DVar.Modifier = Data.Modifier;
1832 DVar.AppliedToPointee = Data.AppliedToPointee;
1833 return DVar;
1834 }
1835 }
1836
1837 DVar.CKind = OMPC_shared;
1838 return DVar;
1839 }
1840
1841 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1842 // The predetermined shared attribute for const-qualified types having no
1843 // mutable members was removed after OpenMP 3.1.
1844 if (SemaRef.LangOpts.OpenMP <= 31) {
1845 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1846 // in a Construct, C/C++, predetermined, p.6]
1847 // Variables with const qualified type having no mutable member are
1848 // shared.
1849 if (isConstNotMutableType(SemaRef, D->getType())) {
1850 // Variables with const-qualified type having no mutable member may be
1851 // listed in a firstprivate clause, even if they are static data members.
1852 DSAVarData DVarTemp = hasInnermostDSA(
1853 D,
1854 [](OpenMPClauseKind C, bool) {
1855 return C == OMPC_firstprivate || C == OMPC_shared;
1856 },
1857 MatchesAlways, FromParent);
1858 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1859 return DVarTemp;
1860
1861 DVar.CKind = OMPC_shared;
1862 return DVar;
1863 }
1864 }
1865
1866 // Explicitly specified attributes and local variables with predetermined
1867 // attributes.
1868 const_iterator I = begin();
1869 const_iterator EndI = end();
1870 if (FromParent && I != EndI)
1871 ++I;
1872 if (I == EndI)
1873 return DVar;
1874 auto It = I->SharingMap.find(D);
1875 if (It != I->SharingMap.end()) {
1876 const DSAInfo &Data = It->getSecond();
1877 DVar.RefExpr = Data.RefExpr.getPointer();
1878 DVar.PrivateCopy = Data.PrivateCopy;
1879 DVar.CKind = Data.Attributes;
1880 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1881 DVar.DKind = I->Directive;
1882 DVar.Modifier = Data.Modifier;
1883 DVar.AppliedToPointee = Data.AppliedToPointee;
1884 }
1885
1886 return DVar;
1887}
1888
1889const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1890 bool FromParent) const {
1891 if (isStackEmpty()) {
1892 const_iterator I;
1893 return getDSA(I, D);
1894 }
1895 D = getCanonicalDecl(D);
1896 const_iterator StartI = begin();
1897 const_iterator EndI = end();
1898 if (FromParent && StartI != EndI)
1899 ++StartI;
1900 return getDSA(StartI, D);
1901}
1902
1903const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1904 unsigned Level) const {
1905 if (getStackSize() <= Level)
1906 return DSAVarData();
1907 D = getCanonicalDecl(D);
1908 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1909 return getDSA(StartI, D);
1910}
1911
1912const DSAStackTy::DSAVarData
1913DSAStackTy::hasDSA(ValueDecl *D,
1914 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1915 DefaultDataSharingAttributes)>
1916 CPred,
1917 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1918 bool FromParent) const {
1919 if (isStackEmpty())
1920 return {};
1921 D = getCanonicalDecl(D);
1922 const_iterator I = begin();
1923 const_iterator EndI = end();
1924 if (FromParent && I != EndI)
1925 ++I;
1926 for (; I != EndI; ++I) {
1927 if (!DPred(I->Directive) &&
1928 !isImplicitOrExplicitTaskingRegion(I->Directive))
1929 continue;
1930 const_iterator NewI = I;
1931 DSAVarData DVar = getDSA(NewI, D);
1932 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1933 return DVar;
1934 }
1935 return {};
1936}
1937
1938const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1939 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1940 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1941 bool FromParent) const {
1942 if (isStackEmpty())
1943 return {};
1944 D = getCanonicalDecl(D);
1945 const_iterator StartI = begin();
1946 const_iterator EndI = end();
1947 if (FromParent && StartI != EndI)
1948 ++StartI;
1949 if (StartI == EndI || !DPred(StartI->Directive))
1950 return {};
1951 const_iterator NewI = StartI;
1952 DSAVarData DVar = getDSA(NewI, D);
1953 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1954 ? DVar
1955 : DSAVarData();
1956}
1957
1958bool DSAStackTy::hasExplicitDSA(
1959 const ValueDecl *D,
1960 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1961 unsigned Level, bool NotLastprivate) const {
1962 if (getStackSize() <= Level)
1963 return false;
1964 D = getCanonicalDecl(D);
1965 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1966 auto I = StackElem.SharingMap.find(D);
1967 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1968 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1969 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1970 return true;
1971 // Check predetermined rules for the loop control variables.
1972 auto LI = StackElem.LCVMap.find(D);
1973 if (LI != StackElem.LCVMap.end())
1974 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1975 return false;
1976}
1977
1978bool DSAStackTy::hasExplicitDirective(
1979 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1980 unsigned Level) const {
1981 if (getStackSize() <= Level)
1982 return false;
1983 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1984 return DPred(StackElem.Directive);
1985}
1986
1987bool DSAStackTy::hasDirective(
1988 const llvm::function_ref<bool(OpenMPDirectiveKind,
1990 DPred,
1991 bool FromParent) const {
1992 // We look only in the enclosing region.
1993 size_t Skip = FromParent ? 2 : 1;
1994 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1995 I != E; ++I) {
1996 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1997 return true;
1998 }
1999 return false;
2000}
2001
2002void SemaOpenMP::InitDataSharingAttributesStack() {
2003 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2004}
2005
2006#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2007
2008void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2009
2010void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2011 DSAStack->popFunction(OldFSI);
2012}
2013
2015 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2016 "Expected OpenMP device compilation.");
2018}
2019
2020namespace {
2021/// Status of the function emission on the host/device.
2022enum class FunctionEmissionStatus {
2023 Emitted,
2024 Discarded,
2025 Unknown,
2026};
2027} // anonymous namespace
2028
2031 const FunctionDecl *FD) {
2032 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2033 "Expected OpenMP device compilation.");
2034
2035 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2036 if (FD) {
2038 switch (FES) {
2040 Kind = SemaDiagnosticBuilder::K_Immediate;
2041 break;
2043 // TODO: We should always delay diagnostics here in case a target
2044 // region is in a function we do not emit. However, as the
2045 // current diagnostics are associated with the function containing
2046 // the target region and we do not emit that one, we would miss out
2047 // on diagnostics for the target region itself. We need to anchor
2048 // the diagnostics with the new generated function *or* ensure we
2049 // emit diagnostics associated with the surrounding function.
2051 ? SemaDiagnosticBuilder::K_Deferred
2052 : SemaDiagnosticBuilder::K_Immediate;
2053 break;
2056 Kind = SemaDiagnosticBuilder::K_Nop;
2057 break;
2059 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2060 break;
2061 }
2062 }
2063
2064 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2065}
2066
2069 const FunctionDecl *FD) {
2070 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2071 "Expected OpenMP host compilation.");
2072
2073 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2074 if (FD) {
2076 switch (FES) {
2078 Kind = SemaDiagnosticBuilder::K_Immediate;
2079 break;
2081 Kind = SemaDiagnosticBuilder::K_Deferred;
2082 break;
2086 Kind = SemaDiagnosticBuilder::K_Nop;
2087 break;
2088 }
2089 }
2090
2091 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2092}
2093
2096 if (LO.OpenMP <= 45) {
2098 return OMPC_DEFAULTMAP_scalar;
2099 return OMPC_DEFAULTMAP_aggregate;
2100 }
2102 return OMPC_DEFAULTMAP_pointer;
2104 return OMPC_DEFAULTMAP_scalar;
2105 return OMPC_DEFAULTMAP_aggregate;
2106}
2107
2109 unsigned OpenMPCaptureLevel) const {
2110 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2111
2112 ASTContext &Ctx = getASTContext();
2113 bool IsByRef = true;
2114
2115 // Find the directive that is associated with the provided scope.
2116 D = cast<ValueDecl>(D->getCanonicalDecl());
2117 QualType Ty = D->getType();
2118
2119 bool IsVariableUsedInMapClause = false;
2120 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2121 // This table summarizes how a given variable should be passed to the device
2122 // given its type and the clauses where it appears. This table is based on
2123 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2124 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2125 //
2126 // =========================================================================
2127 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2128 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2129 // =========================================================================
2130 // | scl | | | | - | | bycopy|
2131 // | scl | | - | x | - | - | bycopy|
2132 // | scl | | x | - | - | - | null |
2133 // | scl | x | | | - | | byref |
2134 // | scl | x | - | x | - | - | bycopy|
2135 // | scl | x | x | - | - | - | null |
2136 // | scl | | - | - | - | x | byref |
2137 // | scl | x | - | - | - | x | byref |
2138 //
2139 // | agg | n.a. | | | - | | byref |
2140 // | agg | n.a. | - | x | - | - | byref |
2141 // | agg | n.a. | x | - | - | - | null |
2142 // | agg | n.a. | - | - | - | x | byref |
2143 // | agg | n.a. | - | - | - | x[] | byref |
2144 //
2145 // | ptr | n.a. | | | - | | bycopy|
2146 // | ptr | n.a. | - | x | - | - | bycopy|
2147 // | ptr | n.a. | x | - | - | - | null |
2148 // | ptr | n.a. | - | - | - | x | byref |
2149 // | ptr | n.a. | - | - | - | x[] | bycopy|
2150 // | ptr | n.a. | - | - | x | | bycopy|
2151 // | ptr | n.a. | - | - | x | x | bycopy|
2152 // | ptr | n.a. | - | - | x | x[] | bycopy|
2153 // =========================================================================
2154 // Legend:
2155 // scl - scalar
2156 // ptr - pointer
2157 // agg - aggregate
2158 // x - applies
2159 // - - invalid in this combination
2160 // [] - mapped with an array section
2161 // byref - should be mapped by reference
2162 // byval - should be mapped by value
2163 // null - initialize a local variable to null on the device
2164 //
2165 // Observations:
2166 // - All scalar declarations that show up in a map clause have to be passed
2167 // by reference, because they may have been mapped in the enclosing data
2168 // environment.
2169 // - If the scalar value does not fit the size of uintptr, it has to be
2170 // passed by reference, regardless the result in the table above.
2171 // - For pointers mapped by value that have either an implicit map or an
2172 // array section, the runtime library may pass the NULL value to the
2173 // device instead of the value passed to it by the compiler.
2174
2175 if (Ty->isReferenceType())
2176 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2177
2178 // Locate map clauses and see if the variable being captured is referred to
2179 // in any of those clauses. Here we only care about variables, not fields,
2180 // because fields are part of aggregates.
2181 bool IsVariableAssociatedWithSection = false;
2182
2183 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2184 D, Level,
2185 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2187 MapExprComponents,
2188 OpenMPClauseKind WhereFoundClauseKind) {
2189 // Both map and has_device_addr clauses information influences how a
2190 // variable is captured. E.g. is_device_ptr does not require changing
2191 // the default behavior.
2192 if (WhereFoundClauseKind != OMPC_map &&
2193 WhereFoundClauseKind != OMPC_has_device_addr)
2194 return false;
2195
2196 auto EI = MapExprComponents.rbegin();
2197 auto EE = MapExprComponents.rend();
2198
2199 assert(EI != EE && "Invalid map expression!");
2200
2201 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2202 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2203
2204 ++EI;
2205 if (EI == EE)
2206 return false;
2207 auto Last = std::prev(EE);
2208 const auto *UO =
2209 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2210 if ((UO && UO->getOpcode() == UO_Deref) ||
2211 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2212 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2213 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2214 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2215 IsVariableAssociatedWithSection = true;
2216 // There is nothing more we need to know about this variable.
2217 return true;
2218 }
2219
2220 // Keep looking for more map info.
2221 return false;
2222 });
2223
2224 if (IsVariableUsedInMapClause) {
2225 // If variable is identified in a map clause it is always captured by
2226 // reference except if it is a pointer that is dereferenced somehow.
2227 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2228 } else {
2229 // By default, all the data that has a scalar type is mapped by copy
2230 // (except for reduction variables).
2231 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2232 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2233 !Ty->isAnyPointerType()) ||
2234 !Ty->isScalarType() ||
2235 DSAStack->isDefaultmapCapturedByRef(
2237 DSAStack->hasExplicitDSA(
2238 D,
2239 [](OpenMPClauseKind K, bool AppliedToPointee) {
2240 return K == OMPC_reduction && !AppliedToPointee;
2241 },
2242 Level);
2243 }
2244 }
2245
2246 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2247 IsByRef =
2248 ((IsVariableUsedInMapClause &&
2249 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2250 OMPD_target) ||
2251 !(DSAStack->hasExplicitDSA(
2252 D,
2253 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2254 return K == OMPC_firstprivate ||
2255 (K == OMPC_reduction && AppliedToPointee);
2256 },
2257 Level, /*NotLastprivate=*/true) ||
2258 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2259 // If the variable is artificial and must be captured by value - try to
2260 // capture by value.
2261 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2262 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2263 // If the variable is implicitly firstprivate and scalar - capture by
2264 // copy
2265 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2266 DSAStack->getDefaultDSA() == DSA_private) &&
2267 !DSAStack->hasExplicitDSA(
2268 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2269 Level) &&
2270 !DSAStack->isLoopControlVariable(D, Level).first);
2271 }
2272
2273 // When passing data by copy, we need to make sure it fits the uintptr size
2274 // and alignment, because the runtime library only deals with uintptr types.
2275 // If it does not fit the uintptr size, we need to pass the data by reference
2276 // instead.
2277 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2279 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2280 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2281 IsByRef = true;
2282 }
2283
2284 return IsByRef;
2285}
2286
2287unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2288 assert(getLangOpts().OpenMP);
2289 return DSAStack->getNestingLevel();
2290}
2291
2293 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2294 DSAStack->isUntiedRegion();
2295}
2296
2298 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2299 !DSAStack->isClauseParsingMode()) ||
2300 DSAStack->hasDirective(
2302 SourceLocation) -> bool {
2304 },
2305 false);
2306}
2307
2309 // Only rebuild for Field.
2310 if (!isa<FieldDecl>(D))
2311 return false;
2312 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2313 D,
2314 [](OpenMPClauseKind C, bool AppliedToPointee,
2315 DefaultDataSharingAttributes DefaultAttr) {
2316 return isOpenMPPrivate(C) && !AppliedToPointee &&
2317 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2318 },
2319 [](OpenMPDirectiveKind) { return true; },
2320 DSAStack->isClauseParsingMode());
2321 if (DVarPrivate.CKind != OMPC_unknown)
2322 return true;
2323 return false;
2324}
2325
2327 Expr *CaptureExpr, bool WithInit,
2328 DeclContext *CurContext,
2329 bool AsExpression);
2330
2332 unsigned StopAt) {
2333 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2334 D = getCanonicalDecl(D);
2335
2336 auto *VD = dyn_cast<VarDecl>(D);
2337 // Do not capture constexpr variables.
2338 if (VD && VD->isConstexpr())
2339 return nullptr;
2340
2341 // If we want to determine whether the variable should be captured from the
2342 // perspective of the current capturing scope, and we've already left all the
2343 // capturing scopes of the top directive on the stack, check from the
2344 // perspective of its parent directive (if any) instead.
2345 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2346 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2347
2348 // If we are attempting to capture a global variable in a directive with
2349 // 'target' we return true so that this global is also mapped to the device.
2350 //
2351 if (VD && !VD->hasLocalStorage() &&
2353 SemaRef.getCurLambda())) {
2355 DSAStackTy::DSAVarData DVarTop =
2356 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2357 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2358 return VD;
2359 // If the declaration is enclosed in a 'declare target' directive,
2360 // then it should not be captured.
2361 //
2362 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2363 return nullptr;
2364 CapturedRegionScopeInfo *CSI = nullptr;
2365 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2366 llvm::reverse(SemaRef.FunctionScopes),
2367 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2368 : 0)) {
2369 if (!isa<CapturingScopeInfo>(FSI))
2370 return nullptr;
2371 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2372 if (RSI->CapRegionKind == CR_OpenMP) {
2373 CSI = RSI;
2374 break;
2375 }
2376 }
2377 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2380 DSAStack->getDirective(CSI->OpenMPLevel));
2381 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2382 return VD;
2383 }
2385 // Try to mark variable as declare target if it is used in capturing
2386 // regions.
2387 if (getLangOpts().OpenMP <= 45 &&
2388 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2390 return nullptr;
2391 }
2392 }
2393
2394 if (CheckScopeInfo) {
2395 bool OpenMPFound = false;
2396 for (unsigned I = StopAt + 1; I > 0; --I) {
2398 if (!isa<CapturingScopeInfo>(FSI))
2399 return nullptr;
2400 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2401 if (RSI->CapRegionKind == CR_OpenMP) {
2402 OpenMPFound = true;
2403 break;
2404 }
2405 }
2406 if (!OpenMPFound)
2407 return nullptr;
2408 }
2409
2410 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2411 (!DSAStack->isClauseParsingMode() ||
2412 DSAStack->getParentDirective() != OMPD_unknown)) {
2413 auto &&Info = DSAStack->isLoopControlVariable(D);
2414 if (Info.first ||
2415 (VD && VD->hasLocalStorage() &&
2416 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2417 (VD && DSAStack->isForceVarCapturing()))
2418 return VD ? VD : Info.second;
2419 DSAStackTy::DSAVarData DVarTop =
2420 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2421 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2422 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2423 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2424 // Threadprivate variables must not be captured.
2425 if (isOpenMPThreadPrivate(DVarTop.CKind))
2426 return nullptr;
2427 // The variable is not private or it is the variable in the directive with
2428 // default(none) clause and not used in any clause.
2429 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2430 D,
2431 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2432 return isOpenMPPrivate(C) && !AppliedToPointee;
2433 },
2434 [](OpenMPDirectiveKind) { return true; },
2435 DSAStack->isClauseParsingMode());
2436 // Global shared must not be captured.
2437 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2438 ((DSAStack->getDefaultDSA() != DSA_none &&
2439 DSAStack->getDefaultDSA() != DSA_private &&
2440 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2441 DVarTop.CKind == OMPC_shared))
2442 return nullptr;
2443 auto *FD = dyn_cast<FieldDecl>(D);
2444 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2445 !DVarPrivate.PrivateCopy) {
2446 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2447 D,
2448 [](OpenMPClauseKind C, bool AppliedToPointee,
2449 DefaultDataSharingAttributes DefaultAttr) {
2450 return isOpenMPPrivate(C) && !AppliedToPointee &&
2451 (DefaultAttr == DSA_firstprivate ||
2452 DefaultAttr == DSA_private);
2453 },
2454 [](OpenMPDirectiveKind) { return true; },
2455 DSAStack->isClauseParsingMode());
2456 if (DVarPrivate.CKind == OMPC_unknown)
2457 return nullptr;
2458
2459 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2460 if (VD)
2461 return VD;
2463 return nullptr;
2466 /*IsImplicit=*/true);
2467 const CXXScopeSpec CS = CXXScopeSpec();
2469 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2472 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2475 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2476 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2477 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2479 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2480 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2481 return VD;
2482 }
2483 if (DVarPrivate.CKind != OMPC_unknown ||
2484 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2485 DSAStack->getDefaultDSA() == DSA_private ||
2486 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2487 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2488 }
2489 return nullptr;
2490}
2491
2492void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2493 unsigned Level) const {
2494 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2495}
2496
2498 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2499 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2500 DSAStack->loopInit();
2501}
2502
2504 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2505 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2506 DSAStack->resetPossibleLoopCounter();
2507 DSAStack->loopStart();
2508 }
2509}
2510
2512 unsigned CapLevel) const {
2513 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2514 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2515 (!DSAStack->isClauseParsingMode() ||
2516 DSAStack->getParentDirective() != OMPD_unknown)) {
2517 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2518 D,
2519 [](OpenMPClauseKind C, bool AppliedToPointee,
2520 DefaultDataSharingAttributes DefaultAttr) {
2521 return isOpenMPPrivate(C) && !AppliedToPointee &&
2522 DefaultAttr == DSA_private;
2523 },
2524 [](OpenMPDirectiveKind) { return true; },
2525 DSAStack->isClauseParsingMode());
2526 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2527 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2528 !DSAStack->isLoopControlVariable(D).first)
2529 return OMPC_private;
2530 }
2531 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2532 bool IsTriviallyCopyable =
2533 D->getType().getNonReferenceType().isTriviallyCopyableType(
2534 getASTContext()) &&
2535 !D->getType()
2536 .getNonReferenceType()
2537 .getCanonicalType()
2538 ->getAsCXXRecordDecl();
2539 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2541 getOpenMPCaptureRegions(CaptureRegions, DKind);
2542 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2543 (IsTriviallyCopyable ||
2544 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2545 if (DSAStack->hasExplicitDSA(
2546 D,
2547 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2548 Level, /*NotLastprivate=*/true))
2549 return OMPC_firstprivate;
2550 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2551 if (DVar.CKind != OMPC_shared &&
2552 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2553 DSAStack->addImplicitTaskFirstprivate(Level, D);
2554 return OMPC_firstprivate;
2555 }
2556 }
2557 }
2558 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2559 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2560 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2561 DSAStack->resetPossibleLoopCounter(D);
2562 DSAStack->loopStart();
2563 return OMPC_private;
2564 }
2565 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2566 DSAStack->isLoopControlVariable(D).first) &&
2567 !DSAStack->hasExplicitDSA(
2568 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2569 Level) &&
2570 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2571 return OMPC_private;
2572 }
2573 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2574 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2575 DSAStack->isForceVarCapturing() &&
2576 !DSAStack->hasExplicitDSA(
2577 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2578 Level))
2579 return OMPC_private;
2580 }
2581 // User-defined allocators are private since they must be defined in the
2582 // context of target region.
2583 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2584 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2585 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2586 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2587 return OMPC_private;
2588 return (DSAStack->hasExplicitDSA(
2589 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2590 Level) ||
2591 (DSAStack->isClauseParsingMode() &&
2592 DSAStack->getClauseParsingMode() == OMPC_private) ||
2593 // Consider taskgroup reduction descriptor variable a private
2594 // to avoid possible capture in the region.
2595 (DSAStack->hasExplicitDirective(
2596 [](OpenMPDirectiveKind K) {
2597 return K == OMPD_taskgroup ||
2598 ((isOpenMPParallelDirective(K) ||
2599 isOpenMPWorksharingDirective(K)) &&
2600 !isOpenMPSimdDirective(K));
2601 },
2602 Level) &&
2603 DSAStack->isTaskgroupReductionRef(D, Level)))
2604 ? OMPC_private
2605 : OMPC_unknown;
2606}
2607
2609 unsigned Level) {
2610 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2611 D = getCanonicalDecl(D);
2612 OpenMPClauseKind OMPC = OMPC_unknown;
2613 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2614 const unsigned NewLevel = I - 1;
2615 if (DSAStack->hasExplicitDSA(
2616 D,
2617 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2618 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2619 OMPC = K;
2620 return true;
2621 }
2622 return false;
2623 },
2624 NewLevel))
2625 break;
2626 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2627 D, NewLevel,
2629 OpenMPClauseKind) { return true; })) {
2630 OMPC = OMPC_map;
2631 break;
2632 }
2633 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2634 NewLevel)) {
2635 OMPC = OMPC_map;
2636 if (DSAStack->mustBeFirstprivateAtLevel(
2638 OMPC = OMPC_firstprivate;
2639 break;
2640 }
2641 }
2642 if (OMPC != OMPC_unknown)
2643 FD->addAttr(
2644 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2645}
2646
2648 unsigned CaptureLevel) const {
2649 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2650 // Return true if the current level is no longer enclosed in a target region.
2651
2653 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2654 const auto *VD = dyn_cast<VarDecl>(D);
2655 return VD && !VD->hasLocalStorage() &&
2656 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2657 Level) &&
2658 Regions[CaptureLevel] != OMPD_task;
2659}
2660
2662 unsigned CaptureLevel) const {
2663 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2664 // Return true if the current level is no longer enclosed in a target region.
2665
2666 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2667 if (!VD->hasLocalStorage()) {
2669 return true;
2670 DSAStackTy::DSAVarData TopDVar =
2671 DSAStack->getTopDSA(D, /*FromParent=*/false);
2672 unsigned NumLevels =
2673 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2674 if (Level == 0)
2675 // non-file scope static variable with default(firstprivate)
2676 // should be global captured.
2677 return (NumLevels == CaptureLevel + 1 &&
2678 (TopDVar.CKind != OMPC_shared ||
2679 DSAStack->getDefaultDSA() == DSA_firstprivate));
2680 do {
2681 --Level;
2682 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2683 if (DVar.CKind != OMPC_shared)
2684 return true;
2685 } while (Level > 0);
2686 }
2687 }
2688 return true;
2689}
2690
2691void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2692
2694 OMPTraitInfo &TI) {
2695 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2696}
2697
2700 "Not in OpenMP declare variant scope!");
2701
2702 OMPDeclareVariantScopes.pop_back();
2703}
2704
2706 const FunctionDecl *Callee,
2708 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2709 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2710 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2711 // Ignore host functions during device analysis.
2712 if (getLangOpts().OpenMPIsTargetDevice &&
2713 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2714 return;
2715 // Ignore nohost functions during host analysis.
2716 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2717 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2718 return;
2719 const FunctionDecl *FD = Callee->getMostRecentDecl();
2720 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2721 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2722 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2723 // Diagnose host function called during device codegen.
2724 StringRef HostDevTy =
2725 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2726 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2727 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2728 diag::note_omp_marked_device_type_here)
2729 << HostDevTy;
2730 return;
2731 }
2732 if (!getLangOpts().OpenMPIsTargetDevice &&
2733 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2734 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2735 // In OpenMP 5.2 or later, if the function has a host variant then allow
2736 // that to be called instead
2737 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2738 for (OMPDeclareVariantAttr *A :
2739 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2740 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2741 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2742 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2743 OMPDeclareTargetDeclAttr::getDeviceType(
2744 VariantFD->getMostRecentDecl());
2745 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2746 return true;
2747 }
2748 return false;
2749 };
2750 if (getLangOpts().OpenMP >= 52 &&
2751 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2752 return;
2753 // Diagnose nohost function called during host codegen.
2754 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2755 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2756 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2757 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2758 diag::note_omp_marked_device_type_here)
2759 << NoHostDevTy;
2760 }
2761}
2762
2764 const DeclarationNameInfo &DirName,
2765 Scope *CurScope, SourceLocation Loc) {
2766 DSAStack->push(DKind, DirName, CurScope, Loc);
2769}
2770
2772 DSAStack->setClauseParsingMode(K);
2773}
2774
2776 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2778}
2779
2780static std::pair<ValueDecl *, bool>
2781getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2782 SourceRange &ERange, bool AllowArraySection = false,
2783 StringRef DiagType = "");
2784
2785/// Check consistency of the reduction clauses.
2786static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2787 ArrayRef<OMPClause *> Clauses) {
2788 bool InscanFound = false;
2789 SourceLocation InscanLoc;
2790 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2791 // A reduction clause without the inscan reduction-modifier may not appear on
2792 // a construct on which a reduction clause with the inscan reduction-modifier
2793 // appears.
2794 for (OMPClause *C : Clauses) {
2795 if (C->getClauseKind() != OMPC_reduction)
2796 continue;
2797 auto *RC = cast<OMPReductionClause>(C);
2798 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2799 InscanFound = true;
2800 InscanLoc = RC->getModifierLoc();
2801 continue;
2802 }
2803 if (RC->getModifier() == OMPC_REDUCTION_task) {
2804 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2805 // A reduction clause with the task reduction-modifier may only appear on
2806 // a parallel construct, a worksharing construct or a combined or
2807 // composite construct for which any of the aforementioned constructs is a
2808 // constituent construct and simd or loop are not constituent constructs.
2809 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2810 if (!(isOpenMPParallelDirective(CurDir) ||
2812 isOpenMPSimdDirective(CurDir))
2813 S.Diag(RC->getModifierLoc(),
2814 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2815 continue;
2816 }
2817 }
2818 if (InscanFound) {
2819 for (OMPClause *C : Clauses) {
2820 if (C->getClauseKind() != OMPC_reduction)
2821 continue;
2822 auto *RC = cast<OMPReductionClause>(C);
2823 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2824 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2825 ? RC->getBeginLoc()
2826 : RC->getModifierLoc(),
2827 diag::err_omp_inscan_reduction_expected);
2828 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2829 continue;
2830 }
2831 for (Expr *Ref : RC->varlist()) {
2832 assert(Ref && "NULL expr in OpenMP reduction clause.");
2833 SourceLocation ELoc;
2834 SourceRange ERange;
2835 Expr *SimpleRefExpr = Ref;
2836 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2837 /*AllowArraySection=*/true);
2838 ValueDecl *D = Res.first;
2839 if (!D)
2840 continue;
2841 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2842 S.Diag(Ref->getExprLoc(),
2843 diag::err_omp_reduction_not_inclusive_exclusive)
2844 << Ref->getSourceRange();
2845 }
2846 }
2847 }
2848 }
2849}
2850
2851static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2852 ArrayRef<OMPClause *> Clauses);
2853static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2854 bool WithInit);
2855
2856static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2857 const ValueDecl *D,
2858 const DSAStackTy::DSAVarData &DVar,
2859 bool IsLoopIterVar = false);
2860
2862 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2863 // A variable of class type (or array thereof) that appears in a lastprivate
2864 // clause requires an accessible, unambiguous default constructor for the
2865 // class type, unless the list item is also specified in a firstprivate
2866 // clause.
2867
2868 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2869 SmallVector<Expr *, 8> PrivateCopies;
2870 for (Expr *DE : Clause->varlist()) {
2871 if (DE->isValueDependent() || DE->isTypeDependent()) {
2872 PrivateCopies.push_back(nullptr);
2873 continue;
2874 }
2875 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2876 auto *VD = cast<VarDecl>(DRE->getDecl());
2878 const DSAStackTy::DSAVarData DVar =
2879 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2880 if (DVar.CKind != OMPC_lastprivate) {
2881 // The variable is also a firstprivate, so initialization sequence
2882 // for private copy is generated already.
2883 PrivateCopies.push_back(nullptr);
2884 continue;
2885 }
2886 // Generate helper private variable and initialize it with the
2887 // default value. The address of the original variable is replaced
2888 // by the address of the new private variable in CodeGen. This new
2889 // variable is not added to IdResolver, so the code in the OpenMP
2890 // region uses original variable for proper diagnostics.
2891 VarDecl *VDPrivate = buildVarDecl(
2892 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2893 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2895 if (VDPrivate->isInvalidDecl()) {
2896 PrivateCopies.push_back(nullptr);
2897 continue;
2898 }
2899 PrivateCopies.push_back(buildDeclRefExpr(
2900 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2901 }
2902 Clause->setPrivateCopies(PrivateCopies);
2903 };
2904
2905 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
2906 // Finalize nontemporal clause by handling private copies, if any.
2907 SmallVector<Expr *, 8> PrivateRefs;
2908 for (Expr *RefExpr : Clause->varlist()) {
2909 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2910 SourceLocation ELoc;
2911 SourceRange ERange;
2912 Expr *SimpleRefExpr = RefExpr;
2913 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2914 if (Res.second)
2915 // It will be analyzed later.
2916 PrivateRefs.push_back(RefExpr);
2917 ValueDecl *D = Res.first;
2918 if (!D)
2919 continue;
2920
2921 const DSAStackTy::DSAVarData DVar =
2922 DSAStack->getTopDSA(D, /*FromParent=*/false);
2923 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2924 : SimpleRefExpr);
2925 }
2926 Clause->setPrivateRefs(PrivateRefs);
2927 };
2928
2929 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
2930 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2931 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2932 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2933 if (!DRE)
2934 continue;
2935 ValueDecl *VD = DRE->getDecl();
2936 if (!VD || !isa<VarDecl>(VD))
2937 continue;
2938 DSAStackTy::DSAVarData DVar =
2939 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2940 // OpenMP [2.12.5, target Construct]
2941 // Memory allocators that appear in a uses_allocators clause cannot
2942 // appear in other data-sharing attribute clauses or data-mapping
2943 // attribute clauses in the same construct.
2944 Expr *MapExpr = nullptr;
2945 if (DVar.RefExpr ||
2946 DSAStack->checkMappableExprComponentListsForDecl(
2947 VD, /*CurrentRegionOnly=*/true,
2948 [VD, &MapExpr](
2950 MapExprComponents,
2952 auto MI = MapExprComponents.rbegin();
2953 auto ME = MapExprComponents.rend();
2954 if (MI != ME &&
2955 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2956 VD->getCanonicalDecl()) {
2957 MapExpr = MI->getAssociatedExpression();
2958 return true;
2959 }
2960 return false;
2961 })) {
2962 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
2963 << D.Allocator->getSourceRange();
2964 if (DVar.RefExpr)
2966 else
2967 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2968 << MapExpr->getSourceRange();
2969 }
2970 }
2971 };
2972
2973 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2974 for (OMPClause *C : D->clauses()) {
2975 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2976 FinalizeLastprivate(Clause);
2977 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2978 FinalizeNontemporal(Clause);
2979 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2980 FinalizeAllocators(Clause);
2981 }
2982 }
2983 // Check allocate clauses.
2984 if (!SemaRef.CurContext->isDependentContext())
2985 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
2986 checkReductionClauses(SemaRef, DSAStack, D->clauses());
2987 }
2988
2989 DSAStack->pop();
2992}
2993
2995 Expr *NumIterations, Sema &SemaRef,
2996 Scope *S, DSAStackTy *Stack);
2997
2998static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3000 DSAStackTy *Stack) {
3001 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3002 "loop exprs were not built");
3003
3004 if (SemaRef.CurContext->isDependentContext())
3005 return false;
3006
3007 // Finalize the clauses that need pre-built expressions for CodeGen.
3008 for (OMPClause *C : Clauses) {
3009 auto *LC = dyn_cast<OMPLinearClause>(C);
3010 if (!LC)
3011 continue;
3012 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3013 B.NumIterations, SemaRef,
3014 SemaRef.getCurScope(), Stack))
3015 return true;
3016 }
3017
3018 return false;
3019}
3020
3021namespace {
3022
3023class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3024private:
3025 Sema &SemaRef;
3026
3027public:
3028 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3029 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3030 NamedDecl *ND = Candidate.getCorrectionDecl();
3031 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3032 return VD->hasGlobalStorage() &&
3033 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3034 SemaRef.getCurScope());
3035 }
3036 return false;
3037 }
3038
3039 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3040 return std::make_unique<VarDeclFilterCCC>(*this);
3041 }
3042};
3043
3044class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3045private:
3046 Sema &SemaRef;
3047
3048public:
3049 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3050 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3051 NamedDecl *ND = Candidate.getCorrectionDecl();
3052 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3053 isa<FunctionDecl>(ND))) {
3054 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3055 SemaRef.getCurScope());
3056 }
3057 return false;
3058 }
3059
3060 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3061 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3062 }
3063};
3064
3065} // namespace
3066
3068 CXXScopeSpec &ScopeSpec,
3069 const DeclarationNameInfo &Id,
3070 OpenMPDirectiveKind Kind) {
3071 ASTContext &Context = getASTContext();
3072 unsigned OMPVersion = getLangOpts().OpenMP;
3074 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3075 /*ObjectType=*/QualType(),
3076 /*AllowBuiltinCreation=*/true);
3077
3078 if (Lookup.isAmbiguous())
3079 return ExprError();
3080
3081 VarDecl *VD;
3082 if (!Lookup.isSingleResult()) {
3083 VarDeclFilterCCC CCC(SemaRef);
3084 if (TypoCorrection Corrected =
3085 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3088 Corrected,
3089 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3090 : diag::err_omp_expected_var_arg_suggest)
3091 << Id.getName());
3092 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3093 } else {
3094 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3095 : diag::err_omp_expected_var_arg)
3096 << Id.getName();
3097 return ExprError();
3098 }
3099 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3100 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3101 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3102 return ExprError();
3103 }
3104 Lookup.suppressDiagnostics();
3105
3106 // OpenMP [2.9.2, Syntax, C/C++]
3107 // Variables must be file-scope, namespace-scope, or static block-scope.
3108 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3109 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3110 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3111 bool IsDecl =
3113 Diag(VD->getLocation(),
3114 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3115 << VD;
3116 return ExprError();
3117 }
3118
3119 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3120 NamedDecl *ND = CanonicalVD;
3121 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3122 // A threadprivate directive for file-scope variables must appear outside
3123 // any definition or declaration.
3124 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3126 Diag(Id.getLoc(), diag::err_omp_var_scope)
3127 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3128 bool IsDecl =
3130 Diag(VD->getLocation(),
3131 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3132 << VD;
3133 return ExprError();
3134 }
3135 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3136 // A threadprivate directive for static class member variables must appear
3137 // in the class definition, in the same scope in which the member
3138 // variables are declared.
3139 if (CanonicalVD->isStaticDataMember() &&
3140 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3141 Diag(Id.getLoc(), diag::err_omp_var_scope)
3142 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3143 bool IsDecl =
3145 Diag(VD->getLocation(),
3146 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3147 << VD;
3148 return ExprError();
3149 }
3150 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3151 // A threadprivate directive for namespace-scope variables must appear
3152 // outside any definition or declaration other than the namespace
3153 // definition itself.
3154 if (CanonicalVD->getDeclContext()->isNamespace() &&
3157 CanonicalVD->getDeclContext()))) {
3158 Diag(Id.getLoc(), diag::err_omp_var_scope)
3159 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3160 bool IsDecl =
3162 Diag(VD->getLocation(),
3163 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3164 << VD;
3165 return ExprError();
3166 }
3167 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3168 // A threadprivate directive for static block-scope variables must appear
3169 // in the scope of the variable and not in a nested scope.
3170 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3172 Diag(Id.getLoc(), diag::err_omp_var_scope)
3173 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3174 bool IsDecl =
3176 Diag(VD->getLocation(),
3177 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3178 << VD;
3179 return ExprError();
3180 }
3181
3182 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3183 // A threadprivate directive must lexically precede all references to any
3184 // of the variables in its list.
3185 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3186 !DSAStack->isThreadPrivate(VD)) {
3187 Diag(Id.getLoc(), diag::err_omp_var_used)
3188 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3189 return ExprError();
3190 }
3191
3192 QualType ExprType = VD->getType().getNonReferenceType();
3194 SourceLocation(), VD,
3195 /*RefersToEnclosingVariableOrCapture=*/false,
3196 Id.getLoc(), ExprType, VK_LValue);
3197}
3198
3201 ArrayRef<Expr *> VarList) {
3205 }
3206 return nullptr;
3207}
3208
3209namespace {
3210class LocalVarRefChecker final
3211 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3212 Sema &SemaRef;
3213
3214public:
3215 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3216 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3217 if (VD->hasLocalStorage()) {
3218 SemaRef.Diag(E->getBeginLoc(),
3219 diag::err_omp_local_var_in_threadprivate_init)
3220 << E->getSourceRange();
3221 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3222 << VD << VD->getSourceRange();
3223 return true;
3224 }
3225 }
3226 return false;
3227 }
3228 bool VisitStmt(const Stmt *S) {
3229 for (const Stmt *Child : S->children()) {
3230 if (Child && Visit(Child))
3231 return true;
3232 }
3233 return false;
3234 }
3235 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3236};
3237} // namespace
3238
3241 ArrayRef<Expr *> VarList) {
3242 ASTContext &Context = getASTContext();
3244 for (Expr *RefExpr : VarList) {
3245 auto *DE = cast<DeclRefExpr>(RefExpr);
3246 auto *VD = cast<VarDecl>(DE->getDecl());
3247 SourceLocation ILoc = DE->getExprLoc();
3248
3249 // Mark variable as used.
3250 VD->setReferenced();
3251 VD->markUsed(Context);
3252
3253 QualType QType = VD->getType();
3254 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3255 // It will be analyzed later.
3256 Vars.push_back(DE);
3257 continue;
3258 }
3259
3260 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3261 // A threadprivate variable must not have an incomplete type.
3263 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3264 continue;
3265 }
3266
3267 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3268 // A threadprivate variable must not have a reference type.
3269 if (VD->getType()->isReferenceType()) {
3270 unsigned OMPVersion = getLangOpts().OpenMP;
3271 Diag(ILoc, diag::err_omp_ref_type_arg)
3272 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3273 << VD->getType();
3274 bool IsDecl =
3276 Diag(VD->getLocation(),
3277 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3278 << VD;
3279 continue;
3280 }
3281
3282 // Check if this is a TLS variable. If TLS is not being supported, produce
3283 // the corresponding diagnostic.
3284 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3285 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3286 getLangOpts().OpenMPUseTLS &&
3287 getASTContext().getTargetInfo().isTLSSupported())) ||
3288 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3289 !VD->isLocalVarDecl())) {
3290 Diag(ILoc, diag::err_omp_var_thread_local)
3291 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3292 bool IsDecl =
3294 Diag(VD->getLocation(),
3295 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3296 << VD;
3297 continue;
3298 }
3299
3300 // Check if initial value of threadprivate variable reference variable with
3301 // local storage (it is not supported by runtime).
3302 if (const Expr *Init = VD->getAnyInitializer()) {
3303 LocalVarRefChecker Checker(SemaRef);
3304 if (Checker.Visit(Init))
3305 continue;
3306 }
3307
3308 Vars.push_back(RefExpr);
3309 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3310 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3311 Context, SourceRange(Loc, Loc)));
3312 if (ASTMutationListener *ML = Context.getASTMutationListener())
3313 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3314 }
3315 OMPThreadPrivateDecl *D = nullptr;
3316 if (!Vars.empty()) {
3318 Loc, Vars);
3320 }
3321 return D;
3322}
3323
3324static OMPAllocateDeclAttr::AllocatorTypeTy
3325getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3326 if (!Allocator)
3327 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3328 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3329 Allocator->isInstantiationDependent() ||
3330 Allocator->containsUnexpandedParameterPack())
3331 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3332 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3333 llvm::FoldingSetNodeID AEId;
3334 const Expr *AE = Allocator->IgnoreParenImpCasts();
3335 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3336 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3337 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3338 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3339 llvm::FoldingSetNodeID DAEId;
3340 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3341 /*Canonical=*/true);
3342 if (AEId == DAEId) {
3343 AllocatorKindRes = AllocatorKind;
3344 break;
3345 }
3346 }
3347 return AllocatorKindRes;
3348}
3349
3351 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3352 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3353 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3354 return false;
3355 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3356 Expr *PrevAllocator = A->getAllocator();
3357 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3358 getAllocatorKind(S, Stack, PrevAllocator);
3359 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3360 if (AllocatorsMatch &&
3361 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3362 Allocator && PrevAllocator) {
3363 const Expr *AE = Allocator->IgnoreParenImpCasts();
3364 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3365 llvm::FoldingSetNodeID AEId, PAEId;
3366 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3367 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3368 AllocatorsMatch = AEId == PAEId;
3369 }
3370 if (!AllocatorsMatch) {
3371 SmallString<256> AllocatorBuffer;
3372 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3373 if (Allocator)
3374 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3375 SmallString<256> PrevAllocatorBuffer;
3376 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3377 if (PrevAllocator)
3378 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3379 S.getPrintingPolicy());
3380
3381 SourceLocation AllocatorLoc =
3382 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3383 SourceRange AllocatorRange =
3384 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3385 SourceLocation PrevAllocatorLoc =
3386 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3387 SourceRange PrevAllocatorRange =
3388 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3389 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3390 << (Allocator ? 1 : 0) << AllocatorStream.str()
3391 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3392 << AllocatorRange;
3393 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3394 << PrevAllocatorRange;
3395 return true;
3396 }
3397 return false;
3398}
3399
3400static void
3402 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3403 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3404 if (VD->hasAttr<OMPAllocateDeclAttr>())
3405 return;
3406 if (Alignment &&
3407 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3408 Alignment->isInstantiationDependent() ||
3409 Alignment->containsUnexpandedParameterPack()))
3410 // Apply later when we have a usable value.
3411 return;
3412 if (Allocator &&
3413 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3414 Allocator->isInstantiationDependent() ||
3415 Allocator->containsUnexpandedParameterPack()))
3416 return;
3417 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3418 Allocator, Alignment, SR);
3419 VD->addAttr(A);
3421 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3422}
3423
3426 DeclContext *Owner) {
3427 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3428 Expr *Alignment = nullptr;
3429 Expr *Allocator = nullptr;
3430 if (Clauses.empty()) {
3431 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3432 // allocate directives that appear in a target region must specify an
3433 // allocator clause unless a requires directive with the dynamic_allocators
3434 // clause is present in the same compilation unit.
3435 if (getLangOpts().OpenMPIsTargetDevice &&
3436 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3437 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3438 } else {
3439 for (const OMPClause *C : Clauses)
3440 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3441 Allocator = AC->getAllocator();
3442 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3443 Alignment = AC->getAlignment();
3444 else
3445 llvm_unreachable("Unexpected clause on allocate directive");
3446 }
3447 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3448 getAllocatorKind(SemaRef, DSAStack, Allocator);
3450 for (Expr *RefExpr : VarList) {
3451 auto *DE = cast<DeclRefExpr>(RefExpr);
3452 auto *VD = cast<VarDecl>(DE->getDecl());
3453
3454 // Check if this is a TLS variable or global register.
3455 if (VD->getTLSKind() != VarDecl::TLS_None ||
3456 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3457 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3458 !VD->isLocalVarDecl()))
3459 continue;
3460
3461 // If the used several times in the allocate directive, the same allocator
3462 // must be used.
3464 AllocatorKind, Allocator))
3465 continue;
3466
3467 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3468 // If a list item has a static storage type, the allocator expression in the
3469 // allocator clause must be a constant expression that evaluates to one of
3470 // the predefined memory allocator values.
3471 if (Allocator && VD->hasGlobalStorage()) {
3472 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3473 Diag(Allocator->getExprLoc(),
3474 diag::err_omp_expected_predefined_allocator)
3475 << Allocator->getSourceRange();
3476 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3478 Diag(VD->getLocation(),
3479 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3480 << VD;
3481 continue;
3482 }
3483 }
3484
3485 Vars.push_back(RefExpr);
3486 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3487 DE->getSourceRange());
3488 }
3489 if (Vars.empty())
3490 return nullptr;
3491 if (!Owner)
3492 Owner = SemaRef.getCurLexicalContext();
3493 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3495 Owner->addDecl(D);
3497}
3498
3501 ArrayRef<OMPClause *> ClauseList) {
3502 OMPRequiresDecl *D = nullptr;
3504 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3505 } else {
3506 D = CheckOMPRequiresDecl(Loc, ClauseList);
3507 if (D) {
3509 DSAStack->addRequiresDecl(D);
3510 }
3511 }
3513}
3514
3516 OpenMPDirectiveKind DKind,
3517 ArrayRef<std::string> Assumptions,
3518 bool SkippedClauses) {
3519 if (!SkippedClauses && Assumptions.empty()) {
3520 unsigned OMPVersion = getLangOpts().OpenMP;
3521 Diag(Loc, diag::err_omp_no_clause_for_directive)
3522 << llvm::omp::getAllAssumeClauseOptions()
3523 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3524 }
3525
3526 auto *AA =
3527 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3528 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3529 OMPAssumeScoped.push_back(AA);
3530 return;
3531 }
3532
3533 // Global assumes without assumption clauses are ignored.
3534 if (Assumptions.empty())
3535 return;
3536
3537 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3538 "Unexpected omp assumption directive!");
3539 OMPAssumeGlobal.push_back(AA);
3540
3541 // The OMPAssumeGlobal scope above will take care of new declarations but
3542 // we also want to apply the assumption to existing ones, e.g., to
3543 // declarations in included headers. To this end, we traverse all existing
3544 // declaration contexts and annotate function declarations here.
3545 SmallVector<DeclContext *, 8> DeclContexts;
3546 auto *Ctx = SemaRef.CurContext;
3547 while (Ctx->getLexicalParent())
3548 Ctx = Ctx->getLexicalParent();
3549 DeclContexts.push_back(Ctx);
3550 while (!DeclContexts.empty()) {
3551 DeclContext *DC = DeclContexts.pop_back_val();
3552 for (auto *SubDC : DC->decls()) {
3553 if (SubDC->isInvalidDecl())
3554 continue;
3555 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3556 DeclContexts.push_back(CTD->getTemplatedDecl());
3557 llvm::append_range(DeclContexts, CTD->specializations());
3558 continue;
3559 }
3560 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3561 DeclContexts.push_back(DC);
3562 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3563 F->addAttr(AA);
3564 continue;
3565 }
3566 }
3567 }
3568}
3569
3571 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3572 OMPAssumeScoped.pop_back();
3573}
3574
3576 Stmt *AStmt,
3577 SourceLocation StartLoc,
3578 SourceLocation EndLoc) {
3579 if (!AStmt)
3580 return StmtError();
3581
3582 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3583 AStmt);
3584}
3585
3588 ArrayRef<OMPClause *> ClauseList) {
3589 /// For target specific clauses, the requires directive cannot be
3590 /// specified after the handling of any of the target regions in the
3591 /// current compilation unit.
3592 ArrayRef<SourceLocation> TargetLocations =
3593 DSAStack->getEncounteredTargetLocs();
3594 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3595 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3596 for (const OMPClause *CNew : ClauseList) {
3597 // Check if any of the requires clauses affect target regions.
3598 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3599 isa<OMPUnifiedAddressClause>(CNew) ||
3600 isa<OMPReverseOffloadClause>(CNew) ||
3601 isa<OMPDynamicAllocatorsClause>(CNew)) {
3602 Diag(Loc, diag::err_omp_directive_before_requires)
3603 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3604 for (SourceLocation TargetLoc : TargetLocations) {
3605 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3606 << "target";
3607 }
3608 } else if (!AtomicLoc.isInvalid() &&
3609 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3610 Diag(Loc, diag::err_omp_directive_before_requires)
3611 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3612 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3613 << "atomic";
3614 }
3615 }
3616 }
3617
3618 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3620 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3621 return nullptr;
3622}
3623
3624static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3625 const ValueDecl *D,
3626 const DSAStackTy::DSAVarData &DVar,
3627 bool IsLoopIterVar) {
3628 if (DVar.RefExpr) {
3629 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3630 << getOpenMPClauseNameForDiag(DVar.CKind);
3631 return;
3632 }
3633 enum {
3634 PDSA_StaticMemberShared,
3635 PDSA_StaticLocalVarShared,
3636 PDSA_LoopIterVarPrivate,
3637 PDSA_LoopIterVarLinear,
3638 PDSA_LoopIterVarLastprivate,
3639 PDSA_ConstVarShared,
3640 PDSA_GlobalVarShared,
3641 PDSA_TaskVarFirstprivate,
3642 PDSA_LocalVarPrivate,
3643 PDSA_Implicit
3644 } Reason = PDSA_Implicit;
3645 bool ReportHint = false;
3646 auto ReportLoc = D->getLocation();
3647 auto *VD = dyn_cast<VarDecl>(D);
3648 if (IsLoopIterVar) {
3649 if (DVar.CKind == OMPC_private)
3650 Reason = PDSA_LoopIterVarPrivate;
3651 else if (DVar.CKind == OMPC_lastprivate)
3652 Reason = PDSA_LoopIterVarLastprivate;
3653 else
3654 Reason = PDSA_LoopIterVarLinear;
3655 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3656 DVar.CKind == OMPC_firstprivate) {
3657 Reason = PDSA_TaskVarFirstprivate;
3658 ReportLoc = DVar.ImplicitDSALoc;
3659 } else if (VD && VD->isStaticLocal())
3660 Reason = PDSA_StaticLocalVarShared;
3661 else if (VD && VD->isStaticDataMember())
3662 Reason = PDSA_StaticMemberShared;
3663 else if (VD && VD->isFileVarDecl())
3664 Reason = PDSA_GlobalVarShared;
3665 else if (D->getType().isConstant(SemaRef.getASTContext()))
3666 Reason = PDSA_ConstVarShared;
3667 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3668 ReportHint = true;
3669 Reason = PDSA_LocalVarPrivate;
3670 }
3671 if (Reason != PDSA_Implicit) {
3672 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3673 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3674 << Reason << ReportHint
3675 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3676 } else if (DVar.ImplicitDSALoc.isValid()) {
3677 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3678 << getOpenMPClauseNameForDiag(DVar.CKind);
3679 }
3680}
3681
3684 bool IsAggregateOrDeclareTarget) {
3686 switch (M) {
3687 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3688 Kind = OMPC_MAP_alloc;
3689 break;
3690 case OMPC_DEFAULTMAP_MODIFIER_to:
3691 Kind = OMPC_MAP_to;
3692 break;
3693 case OMPC_DEFAULTMAP_MODIFIER_from:
3694 Kind = OMPC_MAP_from;
3695 break;
3696 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3697 Kind = OMPC_MAP_tofrom;
3698 break;
3699 case OMPC_DEFAULTMAP_MODIFIER_present:
3700 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3701 // If implicit-behavior is present, each variable referenced in the
3702 // construct in the category specified by variable-category is treated as if
3703 // it had been listed in a map clause with the map-type of alloc and
3704 // map-type-modifier of present.
3705 Kind = OMPC_MAP_alloc;
3706 break;
3707 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3709 llvm_unreachable("Unexpected defaultmap implicit behavior");
3710 case OMPC_DEFAULTMAP_MODIFIER_none:
3711 case OMPC_DEFAULTMAP_MODIFIER_default:
3713 // IsAggregateOrDeclareTarget could be true if:
3714 // 1. the implicit behavior for aggregate is tofrom
3715 // 2. it's a declare target link
3716 if (IsAggregateOrDeclareTarget) {
3717 Kind = OMPC_MAP_tofrom;
3718 break;
3719 }
3720 llvm_unreachable("Unexpected defaultmap implicit behavior");
3721 }
3722 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3723 return Kind;
3724}
3725
3726namespace {
3727struct VariableImplicitInfo {
3728 static const unsigned MapKindNum = OMPC_MAP_unknown;
3729 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3730
3731 llvm::SetVector<Expr *> Privates;
3732 llvm::SetVector<Expr *> Firstprivates;
3733 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3735 MapModifiers[DefaultmapKindNum];
3736};
3737
3738class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3739 DSAStackTy *Stack;
3740 Sema &SemaRef;
3741 OpenMPDirectiveKind DKind = OMPD_unknown;
3742 bool ErrorFound = false;
3743 bool TryCaptureCXXThisMembers = false;
3744 CapturedStmt *CS = nullptr;
3745
3746 VariableImplicitInfo ImpInfo;
3747 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3748 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3749
3750 void VisitSubCaptures(OMPExecutableDirective *S) {
3751 // Check implicitly captured variables.
3752 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3753 return;
3754 if (S->getDirectiveKind() == OMPD_atomic ||
3755 S->getDirectiveKind() == OMPD_critical ||
3756 S->getDirectiveKind() == OMPD_section ||
3757 S->getDirectiveKind() == OMPD_master ||
3758 S->getDirectiveKind() == OMPD_masked ||
3759 S->getDirectiveKind() == OMPD_scope ||
3760 S->getDirectiveKind() == OMPD_assume ||
3761 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3762 Visit(S->getAssociatedStmt());
3763 return;
3764 }
3765 visitSubCaptures(S->getInnermostCapturedStmt());
3766 // Try to capture inner this->member references to generate correct mappings
3767 // and diagnostics.
3768 if (TryCaptureCXXThisMembers ||
3770 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3771 [](const CapturedStmt::Capture &C) {
3772 return C.capturesThis();
3773 }))) {
3774 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3775 TryCaptureCXXThisMembers = true;
3776 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3777 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3778 }
3779 // In tasks firstprivates are not captured anymore, need to analyze them
3780 // explicitly.
3781 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3782 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3783 for (OMPClause *C : S->clauses())
3784 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3785 for (Expr *Ref : FC->varlist())
3786 Visit(Ref);
3787 }
3788 }
3789 }
3790
3791public:
3792 void VisitDeclRefExpr(DeclRefExpr *E) {
3793 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3796 E->isNonOdrUse() == clang::NOUR_Unevaluated)
3797 return;
3798 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3799 // Check the datasharing rules for the expressions in the clauses.
3800 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3801 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3802 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3803 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3804 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3805 Visit(CED->getInit());
3806 return;
3807 }
3808 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3809 // Do not analyze internal variables and do not enclose them into
3810 // implicit clauses.
3811 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3812 return;
3813 VD = VD->getCanonicalDecl();
3814 // Skip internally declared variables.
3815 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3816 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3817 !Stack->isImplicitTaskFirstprivate(VD))
3818 return;
3819 // Skip allocators in uses_allocators clauses.
3820 if (Stack->isUsesAllocatorsDecl(VD))
3821 return;
3822
3823 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3824 // Check if the variable has explicit DSA set and stop analysis if it so.
3825 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3826 return;
3827
3828 // Skip internally declared static variables.
3829 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3830 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3831 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3832 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3833 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3834 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3835 !Stack->isImplicitTaskFirstprivate(VD))
3836 return;
3837
3838 SourceLocation ELoc = E->getExprLoc();
3839 // The default(none) clause requires that each variable that is referenced
3840 // in the construct, and does not have a predetermined data-sharing
3841 // attribute, must have its data-sharing attribute explicitly determined
3842 // by being listed in a data-sharing attribute clause.
3843 if (DVar.CKind == OMPC_unknown &&
3844 (Stack->getDefaultDSA() == DSA_none ||
3845 Stack->getDefaultDSA() == DSA_private ||
3846 Stack->getDefaultDSA() == DSA_firstprivate) &&
3847 isImplicitOrExplicitTaskingRegion(DKind) &&
3848 VarsWithInheritedDSA.count(VD) == 0) {
3849 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3850 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3851 Stack->getDefaultDSA() == DSA_private)) {
3852 DSAStackTy::DSAVarData DVar =
3853 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3854 InheritedDSA = DVar.CKind == OMPC_unknown;
3855 }
3856 if (InheritedDSA)
3857 VarsWithInheritedDSA[VD] = E;
3858 if (Stack->getDefaultDSA() == DSA_none)
3859 return;
3860 }
3861
3862 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3863 // If implicit-behavior is none, each variable referenced in the
3864 // construct that does not have a predetermined data-sharing attribute
3865 // and does not appear in a to or link clause on a declare target
3866 // directive must be listed in a data-mapping attribute clause, a
3867 // data-sharing attribute clause (including a data-sharing attribute
3868 // clause on a combined construct where target. is one of the
3869 // constituent constructs), or an is_device_ptr clause.
3870 OpenMPDefaultmapClauseKind ClauseKind =
3872 if (SemaRef.getLangOpts().OpenMP >= 50) {
3873 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3874 OMPC_DEFAULTMAP_MODIFIER_none;
3875 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3876 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3877 // Only check for data-mapping attribute and is_device_ptr here
3878 // since we have already make sure that the declaration does not
3879 // have a data-sharing attribute above
3880 if (!Stack->checkMappableExprComponentListsForDecl(
3881 VD, /*CurrentRegionOnly=*/true,
3883 MapExprComponents,
3885 auto MI = MapExprComponents.rbegin();
3886 auto ME = MapExprComponents.rend();
3887 return MI != ME && MI->getAssociatedDeclaration() == VD;
3888 })) {
3889 VarsWithInheritedDSA[VD] = E;
3890 return;
3891 }
3892 }
3893 }
3894 if (SemaRef.getLangOpts().OpenMP > 50) {
3895 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3896 OMPC_DEFAULTMAP_MODIFIER_present;
3897 if (IsModifierPresent) {
3898 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
3899 OMPC_MAP_MODIFIER_present)) {
3900 ImpInfo.MapModifiers[ClauseKind].push_back(
3901 OMPC_MAP_MODIFIER_present);
3902 }
3903 }
3904 }
3905
3907 !Stack->isLoopControlVariable(VD).first) {
3908 if (!Stack->checkMappableExprComponentListsForDecl(
3909 VD, /*CurrentRegionOnly=*/true,
3911 StackComponents,
3913 if (SemaRef.LangOpts.OpenMP >= 50)
3914 return !StackComponents.empty();
3915 // Variable is used if it has been marked as an array, array
3916 // section, array shaping or the variable itself.
3917 return StackComponents.size() == 1 ||
3918 llvm::all_of(
3919 llvm::drop_begin(llvm::reverse(StackComponents)),
3920 [](const OMPClauseMappableExprCommon::
3921 MappableComponent &MC) {
3922 return MC.getAssociatedDeclaration() ==
3923 nullptr &&
3924 (isa<ArraySectionExpr>(
3925 MC.getAssociatedExpression()) ||
3926 isa<OMPArrayShapingExpr>(
3927 MC.getAssociatedExpression()) ||
3928 isa<ArraySubscriptExpr>(
3929 MC.getAssociatedExpression()));
3930 });
3931 })) {
3932 bool IsFirstprivate = false;
3933 // By default lambdas are captured as firstprivates.
3934 if (const auto *RD =
3936 IsFirstprivate = RD->isLambda();
3937 IsFirstprivate =
3938 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3939 if (IsFirstprivate) {
3940 ImpInfo.Firstprivates.insert(E);
3941 } else {
3943 Stack->getDefaultmapModifier(ClauseKind);
3945 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3946 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
3947 }
3948 return;
3949 }
3950 }
3951
3952 // OpenMP [2.9.3.6, Restrictions, p.2]
3953 // A list item that appears in a reduction clause of the innermost
3954 // enclosing worksharing or parallel construct may not be accessed in an
3955 // explicit task.
3956 DVar = Stack->hasInnermostDSA(
3957 VD,
3958 [](OpenMPClauseKind C, bool AppliedToPointee) {
3959 return C == OMPC_reduction && !AppliedToPointee;
3960 },
3961 [](OpenMPDirectiveKind K) {
3962 return isOpenMPParallelDirective(K) ||
3964 },
3965 /*FromParent=*/true);
3966 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3967 ErrorFound = true;
3968 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3969 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3970 return;
3971 }
3972
3973 // Define implicit data-sharing attributes for task.
3974 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3975 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3976 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3977 DVar.CKind == OMPC_firstprivate) ||
3978 (Stack->getDefaultDSA() == DSA_private &&
3979 DVar.CKind == OMPC_private)) &&
3980 !DVar.RefExpr)) &&
3981 !Stack->isLoopControlVariable(VD).first) {
3982 if (Stack->getDefaultDSA() == DSA_private)
3983 ImpInfo.Privates.insert(E);
3984 else
3985 ImpInfo.Firstprivates.insert(E);
3986 return;
3987 }
3988
3989 // Store implicitly used globals with declare target link for parent
3990 // target.
3991 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3992 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3993 Stack->addToParentTargetRegionLinkGlobals(E);
3994 return;
3995 }
3996 }
3997 }
3998 void VisitMemberExpr(MemberExpr *E) {
3999 if (E->isTypeDependent() || E->isValueDependent() ||
4001 return;
4002 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4003 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4004 if (!FD)
4005 return;
4006 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4007 // Check if the variable has explicit DSA set and stop analysis if it
4008 // so.
4009 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4010 return;
4011
4013 !Stack->isLoopControlVariable(FD).first &&
4014 !Stack->checkMappableExprComponentListsForDecl(
4015 FD, /*CurrentRegionOnly=*/true,
4017 StackComponents,
4019 return isa<CXXThisExpr>(
4020 cast<MemberExpr>(
4021 StackComponents.back().getAssociatedExpression())
4022 ->getBase()
4023 ->IgnoreParens());
4024 })) {
4025 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4026 // A bit-field cannot appear in a map clause.
4027 //
4028 if (FD->isBitField())
4029 return;
4030
4031 // Check to see if the member expression is referencing a class that
4032 // has already been explicitly mapped
4033 if (Stack->isClassPreviouslyMapped(TE->getType()))
4034 return;
4035
4037 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4038 OpenMPDefaultmapClauseKind ClauseKind =
4041 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4042 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4043 return;
4044 }
4045
4046 SourceLocation ELoc = E->getExprLoc();
4047 // OpenMP [2.9.3.6, Restrictions, p.2]
4048 // A list item that appears in a reduction clause of the innermost
4049 // enclosing worksharing or parallel construct may not be accessed in
4050 // an explicit task.
4051 DVar = Stack->hasInnermostDSA(
4052 FD,
4053 [](OpenMPClauseKind C, bool AppliedToPointee) {
4054 return C == OMPC_reduction && !AppliedToPointee;
4055 },
4056 [](OpenMPDirectiveKind K) {
4057 return isOpenMPParallelDirective(K) ||
4059 },
4060 /*FromParent=*/true);
4061 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4062 ErrorFound = true;
4063 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4064 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4065 return;
4066 }
4067
4068 // Define implicit data-sharing attributes for task.
4069 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4070 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4071 !Stack->isLoopControlVariable(FD).first) {
4072 // Check if there is a captured expression for the current field in the
4073 // region. Do not mark it as firstprivate unless there is no captured
4074 // expression.
4075 // TODO: try to make it firstprivate.
4076 if (DVar.CKind != OMPC_unknown)
4077 ImpInfo.Firstprivates.insert(E);
4078 }
4079 return;
4080 }
4083 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4084 DKind, /*NoDiagnose=*/true))
4085 return;
4086 const auto *VD = cast<ValueDecl>(
4087 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4088 if (!Stack->checkMappableExprComponentListsForDecl(
4089 VD, /*CurrentRegionOnly=*/true,
4090 [&CurComponents](
4092 StackComponents,
4094 auto CCI = CurComponents.rbegin();
4095 auto CCE = CurComponents.rend();
4096 for (const auto &SC : llvm::reverse(StackComponents)) {
4097 // Do both expressions have the same kind?
4098 if (CCI->getAssociatedExpression()->getStmtClass() !=
4099 SC.getAssociatedExpression()->getStmtClass())
4100 if (!((isa<ArraySectionExpr>(
4101 SC.getAssociatedExpression()) ||
4102 isa<OMPArrayShapingExpr>(
4103 SC.getAssociatedExpression())) &&
4104 isa<ArraySubscriptExpr>(
4105 CCI->getAssociatedExpression())))
4106 return false;
4107
4108 const Decl *CCD = CCI->getAssociatedDeclaration();
4109 const Decl *SCD = SC.getAssociatedDeclaration();
4110 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4111 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4112 if (SCD != CCD)
4113 return false;
4114 std::advance(CCI, 1);
4115 if (CCI == CCE)
4116 break;
4117 }
4118 return true;
4119 })) {
4120 Visit(E->getBase());
4121 }
4122 } else if (!TryCaptureCXXThisMembers) {
4123 Visit(E->getBase());
4124 }
4125 }
4126 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4127 for (OMPClause *C : S->clauses()) {
4128 // Skip analysis of arguments of private clauses for task|target
4129 // directives.
4130 if (isa_and_nonnull<OMPPrivateClause>(C))
4131 continue;
4132 // Skip analysis of arguments of implicitly defined firstprivate clause
4133 // for task|target directives.
4134 // Skip analysis of arguments of implicitly defined map clause for target
4135 // directives.
4136 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4137 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4138 for (Stmt *CC : C->children()) {
4139 if (CC)
4140 Visit(CC);
4141 }
4142 }
4143 }
4144 // Check implicitly captured variables.
4145 VisitSubCaptures(S);
4146 }
4147
4148 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4149 // Loop transformation directives do not introduce data sharing
4150 VisitStmt(S);
4151 }
4152
4153 void VisitCallExpr(CallExpr *S) {
4154 for (Stmt *C : S->arguments()) {
4155 if (C) {
4156 // Check implicitly captured variables in the task-based directives to
4157 // check if they must be firstprivatized.
4158 Visit(C);
4159 }
4160 }
4161 if (Expr *Callee = S->getCallee()) {
4162 auto *CI = Callee->IgnoreParenImpCasts();
4163 if (auto *CE = dyn_cast<MemberExpr>(CI))
4164 Visit(CE->getBase());
4165 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4166 Visit(CE);
4167 }
4168 }
4169 void VisitStmt(Stmt *S) {
4170 for (Stmt *C : S->children()) {
4171 if (C) {
4172 // Check implicitly captured variables in the task-based directives to
4173 // check if they must be firstprivatized.
4174 Visit(C);
4175 }
4176 }
4177 }
4178
4179 void visitSubCaptures(CapturedStmt *S) {
4180 for (const CapturedStmt::Capture &Cap : S->captures()) {
4181 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4182 continue;
4183 VarDecl *VD = Cap.getCapturedVar();
4184 // Do not try to map the variable if it or its sub-component was mapped
4185 // already.
4187 Stack->checkMappableExprComponentListsForDecl(
4188 VD, /*CurrentRegionOnly=*/true,
4190 OpenMPClauseKind) { return true; }))
4191 continue;
4193 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4194 Cap.getLocation(), /*RefersToCapture=*/true);
4195 Visit(DRE);
4196 }
4197 }
4198 bool isErrorFound() const { return ErrorFound; }
4199 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4200 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4201 return VarsWithInheritedDSA;
4202 }
4203
4204 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4205 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4206 DKind = S->getCurrentDirective();
4207 // Process declare target link variables for the target directives.
4209 for (DeclRefExpr *E : Stack->getLinkGlobals())
4210 Visit(E);
4211 }
4212 }
4213};
4214} // namespace
4215
4216static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4217 OpenMPDirectiveKind DKind,
4218 bool ScopeEntry) {
4221 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4222 if (isOpenMPTeamsDirective(DKind))
4223 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4224 if (isOpenMPParallelDirective(DKind))
4225 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4227 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4228 if (isOpenMPSimdDirective(DKind))
4229 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4230 Stack->handleConstructTrait(Traits, ScopeEntry);
4231}
4232
4234getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4235 ASTContext &Context = SemaRef.getASTContext();
4236 QualType KmpInt32Ty =
4237 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4238 QualType KmpInt32PtrTy =
4239 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4241 std::make_pair(".global_tid.", KmpInt32PtrTy),
4242 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4243 };
4244 if (LoopBoundSharing) {
4245 QualType KmpSizeTy = Context.getSizeType().withConst();
4246 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4247 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4248 }
4249
4250 // __context with shared vars
4251 Params.push_back(std::make_pair(StringRef(), QualType()));
4252 return Params;
4253}
4254
4257 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4258}
4259
4262 ASTContext &Context = SemaRef.getASTContext();
4263 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4264 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4265 QualType KmpInt32PtrTy =
4266 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4267 QualType Args[] = {VoidPtrTy};
4269 EPI.Variadic = true;
4270 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4272 std::make_pair(".global_tid.", KmpInt32Ty),
4273 std::make_pair(".part_id.", KmpInt32PtrTy),
4274 std::make_pair(".privates.", VoidPtrTy),
4275 std::make_pair(
4276 ".copy_fn.",
4277 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4278 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4279 std::make_pair(StringRef(), QualType()) // __context with shared vars
4280 };
4281 return Params;
4282}
4283
4286 ASTContext &Context = SemaRef.getASTContext();
4288 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4289 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4290 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4291 }
4292 // __context with shared vars
4293 Params.push_back(std::make_pair(StringRef(), QualType()));
4294 return Params;
4295}
4296
4300 std::make_pair(StringRef(), QualType()) // __context with shared vars
4301 };
4302 return Params;
4303}
4304
4307 ASTContext &Context = SemaRef.getASTContext();
4308 QualType KmpInt32Ty =
4309 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4310 QualType KmpUInt64Ty =
4311 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4312 QualType KmpInt64Ty =
4313 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4314 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4315 QualType KmpInt32PtrTy =
4316 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4317 QualType Args[] = {VoidPtrTy};
4319 EPI.Variadic = true;
4320 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4322 std::make_pair(".global_tid.", KmpInt32Ty),
4323 std::make_pair(".part_id.", KmpInt32PtrTy),
4324 std::make_pair(".privates.", VoidPtrTy),
4325 std::make_pair(
4326 ".copy_fn.",
4327 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4328 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4329 std::make_pair(".lb.", KmpUInt64Ty),
4330 std::make_pair(".ub.", KmpUInt64Ty),
4331 std::make_pair(".st.", KmpInt64Ty),
4332 std::make_pair(".liter.", KmpInt32Ty),
4333 std::make_pair(".reductions.", VoidPtrTy),
4334 std::make_pair(StringRef(), QualType()) // __context with shared vars
4335 };
4336 return Params;
4337}
4338
4340 Scope *CurScope, SourceLocation Loc) {
4342 getOpenMPCaptureRegions(Regions, DKind);
4343
4344 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4345
4346 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4347 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4348 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4349 };
4350
4351 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4352 switch (RKind) {
4353 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4354 // are listed here.
4355 case OMPD_parallel:
4357 Loc, CurScope, CR_OpenMP,
4358 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4359 break;
4360 case OMPD_teams:
4361 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4362 getTeamsRegionParams(SemaRef), Level);
4363 break;
4364 case OMPD_task:
4365 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4366 getTaskRegionParams(SemaRef), Level);
4367 // Mark this captured region as inlined, because we don't use outlined
4368 // function directly.
4369 MarkAsInlined(SemaRef.getCurCapturedRegion());
4370 break;
4371 case OMPD_taskloop:
4372 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4373 getTaskloopRegionParams(SemaRef), Level);
4374 // Mark this captured region as inlined, because we don't use outlined
4375 // function directly.
4376 MarkAsInlined(SemaRef.getCurCapturedRegion());
4377 break;
4378 case OMPD_target:
4379 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4380 getTargetRegionParams(SemaRef), Level);
4381 break;
4382 case OMPD_unknown:
4383 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4384 getUnknownRegionParams(SemaRef));
4385 break;
4386 case OMPD_metadirective:
4387 case OMPD_nothing:
4388 default:
4389 llvm_unreachable("Unexpected capture region");
4390 }
4391 }
4392}
4393
4395 Scope *CurScope) {
4396 switch (DKind) {
4397 case OMPD_atomic:
4398 case OMPD_critical:
4399 case OMPD_masked:
4400 case OMPD_master:
4401 case OMPD_section:
4402 case OMPD_tile:
4403 case OMPD_stripe:
4404 case OMPD_unroll:
4405 case OMPD_reverse:
4406 case OMPD_interchange:
4407 case OMPD_assume:
4408 break;
4409 default:
4410 processCapturedRegions(SemaRef, DKind, CurScope,
4411 DSAStack->getConstructLoc());
4412 break;
4413 }
4414
4415 DSAStack->setContext(SemaRef.CurContext);
4416 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4417}
4418
4419int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4420 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4421}
4422
4425 getOpenMPCaptureRegions(CaptureRegions, DKind);
4426 return CaptureRegions.size();
4427}
4428
4430 Expr *CaptureExpr, bool WithInit,
4431 DeclContext *CurContext,
4432 bool AsExpression) {
4433 assert(CaptureExpr);
4434 ASTContext &C = S.getASTContext();
4435 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4436 QualType Ty = Init->getType();
4437 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4438 if (S.getLangOpts().CPlusPlus) {
4439 Ty = C.getLValueReferenceType(Ty);
4440 } else {
4441 Ty = C.getPointerType(Ty);
4442 ExprResult Res =
4443 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4444 if (!Res.isUsable())
4445 return nullptr;
4446 Init = Res.get();
4447 }
4448 WithInit = true;
4449 }
4450 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4451 CaptureExpr->getBeginLoc());
4452 if (!WithInit)
4453 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4454 CurContext->addHiddenDecl(CED);
4456 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4457 return CED;
4458}
4459
4460static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4461 bool WithInit) {
4463 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4464 CD = cast<OMPCapturedExprDecl>(VD);
4465 else
4466 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4467 S.CurContext,
4468 /*AsExpression=*/false);
4469 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4470 CaptureExpr->getExprLoc());
4471}
4472
4473static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4474 StringRef Name) {
4475 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4476 if (!Ref) {
4478 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4479 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4480 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4481 CaptureExpr->getExprLoc());
4482 }
4483 ExprResult Res = Ref;
4484 if (!S.getLangOpts().CPlusPlus &&
4485 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4486 Ref->getType()->isPointerType()) {
4487 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4488 if (!Res.isUsable())
4489 return ExprError();
4490 }
4491 return S.DefaultLvalueConversion(Res.get());
4492}
4493
4494namespace {
4495// OpenMP directives parsed in this section are represented as a
4496// CapturedStatement with an associated statement. If a syntax error
4497// is detected during the parsing of the associated statement, the
4498// compiler must abort processing and close the CapturedStatement.
4499//
4500// Combined directives such as 'target parallel' have more than one
4501// nested CapturedStatements. This RAII ensures that we unwind out
4502// of all the nested CapturedStatements when an error is found.
4503class CaptureRegionUnwinderRAII {
4504private:
4505 Sema &S;
4506 bool &ErrorFound;
4507 OpenMPDirectiveKind DKind = OMPD_unknown;
4508
4509public:
4510 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4511 OpenMPDirectiveKind DKind)
4512 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4513 ~CaptureRegionUnwinderRAII() {
4514 if (ErrorFound) {
4515 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4516 while (--ThisCaptureLevel >= 0)
4518 }
4519 }
4520};
4521} // namespace
4522
4524 // Capture variables captured by reference in lambdas for target-based
4525 // directives.
4527 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4529 DSAStack->getCurrentDirective()))) {
4530 QualType Type = V->getType();
4531 if (const auto *RD = Type.getCanonicalType()
4532 .getNonReferenceType()
4533 ->getAsCXXRecordDecl()) {
4534 bool SavedForceCaptureByReferenceInTargetExecutable =
4535 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4536 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4537 /*V=*/true);
4538 if (RD->isLambda()) {
4539 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4540 FieldDecl *ThisCapture;
4541 RD->getCaptureFields(Captures, ThisCapture);
4542 for (const LambdaCapture &LC : RD->captures()) {
4543 if (LC.getCaptureKind() == LCK_ByRef) {
4544 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4545 DeclContext *VDC = VD->getDeclContext();
4546 if (!VDC->Encloses(SemaRef.CurContext))
4547 continue;
4548 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4549 } else if (LC.getCaptureKind() == LCK_This) {
4551 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4552 ThisTy, ThisCapture->getType()))
4553 SemaRef.CheckCXXThisCapture(LC.getLocation());
4554 }
4555 }
4556 }
4557 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4558 SavedForceCaptureByReferenceInTargetExecutable);
4559 }
4560 }
4561}
4562
4564 const ArrayRef<OMPClause *> Clauses) {
4565 const OMPOrderedClause *Ordered = nullptr;
4566 const OMPOrderClause *Order = nullptr;
4567
4568 for (const OMPClause *Clause : Clauses) {
4569 if (Clause->getClauseKind() == OMPC_ordered)
4570 Ordered = cast<OMPOrderedClause>(Clause);
4571 else if (Clause->getClauseKind() == OMPC_order) {
4572 Order = cast<OMPOrderClause>(Clause);
4573 if (Order->getKind() != OMPC_ORDER_concurrent)
4574 Order = nullptr;
4575 }
4576 if (Ordered && Order)
4577 break;
4578 }
4579
4580 if (Ordered && Order) {
4581 S.Diag(Order->getKindKwLoc(),
4582 diag::err_omp_simple_clause_incompatible_with_ordered)
4583 << getOpenMPClauseNameForDiag(OMPC_order)
4584 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4585 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4586 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4587 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4588 return true;
4589 }
4590 return false;
4591}
4592
4594 ArrayRef<OMPClause *> Clauses) {
4596 /*ScopeEntry=*/false);
4597 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4598 return S;
4599
4600 bool ErrorFound = false;
4601 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4602 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4603 if (!S.isUsable()) {
4604 ErrorFound = true;
4605 return StmtError();
4606 }
4607
4609 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4610 OMPOrderedClause *OC = nullptr;
4611 OMPScheduleClause *SC = nullptr;
4614 // This is required for proper codegen.
4615 for (OMPClause *Clause : Clauses) {
4616 if (!getLangOpts().OpenMPSimd &&
4617 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4618 DSAStack->getCurrentDirective() == OMPD_target) &&
4619 Clause->getClauseKind() == OMPC_in_reduction) {
4620 // Capture taskgroup task_reduction descriptors inside the tasking regions
4621 // with the corresponding in_reduction items.
4622 auto *IRC = cast<OMPInReductionClause>(Clause);
4623 for (Expr *E : IRC->taskgroup_descriptors())
4624 if (E)
4626 }
4627 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4628 Clause->getClauseKind() == OMPC_copyprivate ||
4629 (getLangOpts().OpenMPUseTLS &&
4630 getASTContext().getTargetInfo().isTLSSupported() &&
4631 Clause->getClauseKind() == OMPC_copyin)) {
4632 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4633 // Mark all variables in private list clauses as used in inner region.
4634 for (Stmt *VarRef : Clause->children()) {
4635 if (auto *E = cast_or_null<Expr>(VarRef)) {
4637 }
4638 }
4639 DSAStack->setForceVarCapturing(/*V=*/false);
4640 } else if (CaptureRegions.size() > 1 ||
4641 CaptureRegions.back() != OMPD_unknown) {
4642 if (auto *C = OMPClauseWithPreInit::get(Clause))
4643 PICs.push_back(C);
4644 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4645 if (Expr *E = C->getPostUpdateExpr())
4647 }
4648 }
4649 if (Clause->getClauseKind() == OMPC_schedule)
4650 SC = cast<OMPScheduleClause>(Clause);
4651 else if (Clause->getClauseKind() == OMPC_ordered)
4652 OC = cast<OMPOrderedClause>(Clause);
4653 else if (Clause->getClauseKind() == OMPC_linear)
4654 LCs.push_back(cast<OMPLinearClause>(Clause));
4655 }
4656 // Capture allocator expressions if used.
4657 for (Expr *E : DSAStack->getInnerAllocators())
4659 // OpenMP, 2.7.1 Loop Construct, Restrictions
4660 // The nonmonotonic modifier cannot be specified if an ordered clause is
4661 // specified.
4662 if (SC &&
4663 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4665 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4666 OC) {
4667 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4670 diag::err_omp_simple_clause_incompatible_with_ordered)
4671 << getOpenMPClauseNameForDiag(OMPC_schedule)
4672 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4673 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4674 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4675 ErrorFound = true;
4676 }
4677 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4678 // If an order(concurrent) clause is present, an ordered clause may not appear
4679 // on the same directive.
4680 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4681 ErrorFound = true;
4682 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4683 for (const OMPLinearClause *C : LCs) {
4684 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4685 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4686 }
4687 ErrorFound = true;
4688 }
4689 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4690 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4691 OC->getNumForLoops()) {
4692 unsigned OMPVersion = getLangOpts().OpenMP;
4693 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4694 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4695 ErrorFound = true;
4696 }
4697 if (ErrorFound) {
4698 return StmtError();
4699 }
4700 StmtResult SR = S;
4701 unsigned CompletedRegions = 0;
4702 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4703 // Mark all variables in private list clauses as used in inner region.
4704 // Required for proper codegen of combined directives.
4705 // TODO: add processing for other clauses.
4706 if (ThisCaptureRegion != OMPD_unknown) {
4707 for (const clang::OMPClauseWithPreInit *C : PICs) {
4708 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4709 // Find the particular capture region for the clause if the
4710 // directive is a combined one with multiple capture regions.
4711 // If the directive is not a combined one, the capture region
4712 // associated with the clause is OMPD_unknown and is generated
4713 // only once.
4714 if (CaptureRegion == ThisCaptureRegion ||
4715 CaptureRegion == OMPD_unknown) {
4716 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4717 for (Decl *D : DS->decls())
4719 cast<VarDecl>(D));
4720 }
4721 }
4722 }
4723 }
4724 if (ThisCaptureRegion == OMPD_target) {
4725 // Capture allocator traits in the target region. They are used implicitly
4726 // and, thus, are not captured by default.
4727 for (OMPClause *C : Clauses) {
4728 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4729 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4730 ++I) {
4731 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4732 if (Expr *E = D.AllocatorTraits)
4734 }
4735 continue;
4736 }
4737 }
4738 }
4739 if (ThisCaptureRegion == OMPD_parallel) {
4740 // Capture temp arrays for inscan reductions and locals in aligned
4741 // clauses.
4742 for (OMPClause *C : Clauses) {
4743 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4744 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4745 continue;
4746 for (Expr *E : RC->copy_array_temps())
4747 if (E)
4749 }
4750 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4751 for (Expr *E : AC->varlist())
4753 }
4754 }
4755 }
4756 if (++CompletedRegions == CaptureRegions.size())
4757 DSAStack->setBodyComplete();
4759 }
4760 return SR;
4761}
4762
4763static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4764 OpenMPDirectiveKind CancelRegion,
4765 SourceLocation StartLoc) {
4766 // CancelRegion is only needed for cancel and cancellation_point.
4767 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4768 return false;
4769
4770 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4771 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4772 return false;
4773
4774 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4775 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4776 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4777 return true;
4778}
4779
4780static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4781 OpenMPDirectiveKind CurrentRegion,
4782 const DeclarationNameInfo &CurrentName,
4783 OpenMPDirectiveKind CancelRegion,
4784 OpenMPBindClauseKind BindKind,
4785 SourceLocation StartLoc) {
4786 if (!Stack->getCurScope())
4787 return false;
4788
4789 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4790 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4791 bool NestingProhibited = false;
4792 bool CloseNesting = true;
4793 bool OrphanSeen = false;
4794 enum {
4795 NoRecommend,
4796 ShouldBeInParallelRegion,
4797 ShouldBeInOrderedRegion,
4798 ShouldBeInTargetRegion,
4799 ShouldBeInTeamsRegion,
4800 ShouldBeInLoopSimdRegion,
4801 } Recommend = NoRecommend;
4802
4805 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4806 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4807 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4808
4809 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
4811 SemaRef.LangOpts)) {
4812 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4813 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4814 return true;
4815 }
4816 if (isOpenMPSimdDirective(ParentRegion) &&
4817 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
4818 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
4819 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4820 CurrentRegion != OMPD_scan))) {
4821 // OpenMP [2.16, Nesting of Regions]
4822 // OpenMP constructs may not be nested inside a simd region.
4823 // OpenMP [2.8.1,simd Construct, Restrictions]
4824 // An ordered construct with the simd clause is the only OpenMP
4825 // construct that can appear in the simd region.
4826 // Allowing a SIMD construct nested in another SIMD construct is an
4827 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4828 // message.
4829 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4830 // The only OpenMP constructs that can be encountered during execution of
4831 // a simd region are the atomic construct, the loop construct, the simd
4832 // construct and the ordered construct with the simd clause.
4833 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4834 ? diag::err_omp_prohibited_region_simd
4835 : diag::warn_omp_nesting_simd)
4836 << (OMPVersion >= 50 ? 1 : 0);
4837 return CurrentRegion != OMPD_simd;
4838 }
4839 if (EnclosingConstruct == OMPD_atomic) {
4840 // OpenMP [2.16, Nesting of Regions]
4841 // OpenMP constructs may not be nested inside an atomic region.
4842 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4843 return true;
4844 }
4845 if (CurrentRegion == OMPD_section) {
4846 // OpenMP [2.7.2, sections Construct, Restrictions]
4847 // Orphaned section directives are prohibited. That is, the section
4848 // directives must appear within the sections construct and must not be
4849 // encountered elsewhere in the sections region.
4850 if (EnclosingConstruct != OMPD_sections) {
4851 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4852 << (ParentRegion != OMPD_unknown)
4853 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
4854 return true;
4855 }
4856 return false;
4857 }
4858 // Allow some constructs (except teams and cancellation constructs) to be
4859 // orphaned (they could be used in functions, called from OpenMP regions
4860 // with the required preconditions).
4861 if (ParentRegion == OMPD_unknown &&
4862 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4863 CurrentRegion != OMPD_cancellation_point &&
4864 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4865 return false;
4866 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4867 // for a detailed explanation
4868 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
4869 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4870 (isOpenMPWorksharingDirective(ParentRegion) ||
4871 EnclosingConstruct == OMPD_loop)) {
4872 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4873 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4874 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
4875 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
4876 return true;
4877 }
4878 if (CurrentRegion == OMPD_cancellation_point ||
4879 CurrentRegion == OMPD_cancel) {
4880 // OpenMP [2.16, Nesting of Regions]
4881 // A cancellation point construct for which construct-type-clause is
4882 // taskgroup must be nested inside a task construct. A cancellation
4883 // point construct for which construct-type-clause is not taskgroup must
4884 // be closely nested inside an OpenMP construct that matches the type
4885 // specified in construct-type-clause.
4886 // A cancel construct for which construct-type-clause is taskgroup must be
4887 // nested inside a task construct. A cancel construct for which
4888 // construct-type-clause is not taskgroup must be closely nested inside an
4889 // OpenMP construct that matches the type specified in
4890 // construct-type-clause.
4891 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4892 if (CancelRegion == OMPD_taskgroup) {
4893 NestingProhibited =
4894 EnclosingConstruct != OMPD_task &&
4895 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
4896 } else if (CancelRegion == OMPD_sections) {
4897 NestingProhibited = EnclosingConstruct != OMPD_section &&
4898 EnclosingConstruct != OMPD_sections;
4899 } else {
4900 NestingProhibited = CancelRegion != Leafs.back();
4901 }
4902 OrphanSeen = ParentRegion == OMPD_unknown;
4903 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4904 // OpenMP 5.1 [2.22, Nesting of Regions]
4905 // A masked region may not be closely nested inside a worksharing, loop,
4906 // atomic, task, or taskloop region.
4907 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4908 isOpenMPGenericLoopDirective(ParentRegion) ||
4909 isOpenMPTaskingDirective(ParentRegion);
4910 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4911 // OpenMP [2.16, Nesting of Regions]
4912 // A critical region may not be nested (closely or otherwise) inside a
4913 // critical region with the same name. Note that this restriction is not
4914 // sufficient to prevent deadlock.
4915 SourceLocation PreviousCriticalLoc;
4916 bool DeadLock = Stack->hasDirective(
4917 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4918 const DeclarationNameInfo &DNI,
4920 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4921 PreviousCriticalLoc = Loc;
4922 return true;
4923 }
4924 return false;
4925 },
4926 false /* skip top directive */);
4927 if (DeadLock) {
4928 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4929 << CurrentName.getName();
4930 if (PreviousCriticalLoc.isValid())
4931 SemaRef.Diag(PreviousCriticalLoc,
4932 diag::note_omp_previous_critical_region);
4933 return true;
4934 }
4935 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4936 // OpenMP 5.1 [2.22, Nesting of Regions]
4937 // A scope region may not be closely nested inside a worksharing, loop,
4938 // task, taskloop, critical, ordered, atomic, or masked region.
4939 // OpenMP 5.1 [2.22, Nesting of Regions]
4940 // A barrier region may not be closely nested inside a worksharing, loop,
4941 // task, taskloop, critical, ordered, atomic, or masked region.
4942 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4943 isOpenMPGenericLoopDirective(ParentRegion) ||
4944 isOpenMPTaskingDirective(ParentRegion) ||
4945 llvm::is_contained({OMPD_masked, OMPD_master,
4946 OMPD_critical, OMPD_ordered},
4947 EnclosingConstruct);
4948 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4949 !isOpenMPParallelDirective(CurrentRegion) &&
4950 !isOpenMPTeamsDirective(CurrentRegion)) {
4951 // OpenMP 5.1 [2.22, Nesting of Regions]
4952 // A loop region that binds to a parallel region or a worksharing region
4953 // may not be closely nested inside a worksharing, loop, task, taskloop,
4954 // critical, ordered, atomic, or masked region.
4955 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4956 isOpenMPGenericLoopDirective(ParentRegion) ||
4957 isOpenMPTaskingDirective(ParentRegion) ||
4958 llvm::is_contained({OMPD_masked, OMPD_master,
4959 OMPD_critical, OMPD_ordered},
4960 EnclosingConstruct);
4961 Recommend = ShouldBeInParallelRegion;
4962 } else if (CurrentRegion == OMPD_ordered) {
4963 // OpenMP [2.16, Nesting of Regions]
4964 // An ordered region may not be closely nested inside a critical,
4965 // atomic, or explicit task region.
4966 // An ordered region must be closely nested inside a loop region (or
4967 // parallel loop region) with an ordered clause.
4968 // OpenMP [2.8.1,simd Construct, Restrictions]
4969 // An ordered construct with the simd clause is the only OpenMP construct
4970 // that can appear in the simd region.
4971 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4972 isOpenMPTaskingDirective(ParentRegion) ||
4973 !(isOpenMPSimdDirective(ParentRegion) ||
4974 Stack->isParentOrderedRegion());
4975 Recommend = ShouldBeInOrderedRegion;
4976 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4977 // OpenMP [2.16, Nesting of Regions]
4978 // If specified, a teams construct must be contained within a target
4979 // construct.
4980 NestingProhibited =
4981 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
4982 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
4983 EnclosingConstruct != OMPD_target);
4984 OrphanSeen = ParentRegion == OMPD_unknown;
4985 Recommend = ShouldBeInTargetRegion;
4986 } else if (CurrentRegion == OMPD_scan) {
4987 if (OMPVersion >= 50) {
4988 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4989 // simd, or for simd. This has to take into account combined directives.
4990 // In 5.2 this seems to be implied by the fact that the specified
4991 // separated constructs are do, for, and simd.
4992 NestingProhibited = !llvm::is_contained(
4993 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4994 } else {
4995 NestingProhibited = true;
4996 }
4997 OrphanSeen = ParentRegion == OMPD_unknown;
4998 Recommend = ShouldBeInLoopSimdRegion;
4999 }
5000 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5001 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5002 EnclosingConstruct == OMPD_teams) {
5003 // OpenMP [5.1, 2.22, Nesting of Regions]
5004 // distribute, distribute simd, distribute parallel worksharing-loop,
5005 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5006 // including any parallel regions arising from combined constructs,
5007 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5008 // only OpenMP regions that may be strictly nested inside the teams
5009 // region.
5010 //
5011 // As an extension, we permit atomic within teams as well.
5012 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5013 !isOpenMPDistributeDirective(CurrentRegion) &&
5014 CurrentRegion != OMPD_loop &&
5015 !(SemaRef.getLangOpts().OpenMPExtensions &&
5016 CurrentRegion == OMPD_atomic);
5017 Recommend = ShouldBeInParallelRegion;
5018 }
5019 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5020 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5021 // If the bind clause is present on the loop construct and binding is
5022 // teams then the corresponding loop region must be strictly nested inside
5023 // a teams region.
5024 NestingProhibited =
5025 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5026 Recommend = ShouldBeInTeamsRegion;
5027 }
5028 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5029 // OpenMP 4.5 [2.17 Nesting of Regions]
5030 // The region associated with the distribute construct must be strictly
5031 // nested inside a teams region
5032 NestingProhibited = EnclosingConstruct != OMPD_teams;
5033 Recommend = ShouldBeInTeamsRegion;
5034 }
5035 if (!NestingProhibited &&
5036 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5037 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5038 // OpenMP 4.5 [2.17 Nesting of Regions]
5039 // If a target, target update, target data, target enter data, or
5040 // target exit data construct is encountered during execution of a
5041 // target region, the behavior is unspecified.
5042 NestingProhibited = Stack->hasDirective(
5043 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5046 OffendingRegion = K;
5047 return true;
5048 }
5049 return false;
5050 },
5051 false /* don't skip top directive */);
5052 CloseNesting = false;
5053 }
5054 if (NestingProhibited) {
5055 if (OrphanSeen) {
5056 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5057 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5058 } else {
5059 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5060 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5061 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5062 }
5063 return true;
5064 }
5065 return false;
5066}
5067
5070 unsigned operator()(argument_type DK) { return unsigned(DK); }
5071};
5073 ArrayRef<OMPClause *> Clauses,
5074 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5075 bool ErrorFound = false;
5076 unsigned NamedModifiersNumber = 0;
5077 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5078 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5079 SmallVector<SourceLocation, 4> NameModifierLoc;
5080 unsigned OMPVersion = S.getLangOpts().OpenMP;
5081 for (const OMPClause *C : Clauses) {
5082 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5083 // At most one if clause without a directive-name-modifier can appear on
5084 // the directive.
5085 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5086 auto &FNM = FoundNameModifiers[CurNM];
5087 if (FNM) {
5088 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5089 << getOpenMPDirectiveName(Kind, OMPVersion)
5090 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5091 << getOpenMPDirectiveName(CurNM, OMPVersion);
5092 ErrorFound = true;
5093 } else if (CurNM != OMPD_unknown) {
5094 NameModifierLoc.push_back(IC->getNameModifierLoc());
5095 ++NamedModifiersNumber;
5096 }
5097 FNM = IC;
5098 if (CurNM == OMPD_unknown)
5099 continue;
5100 // Check if the specified name modifier is allowed for the current
5101 // directive.
5102 // At most one if clause with the particular directive-name-modifier can
5103 // appear on the directive.
5104 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5105 S.Diag(IC->getNameModifierLoc(),
5106 diag::err_omp_wrong_if_directive_name_modifier)
5107 << getOpenMPDirectiveName(CurNM, OMPVersion)
5108 << getOpenMPDirectiveName(Kind, OMPVersion);
5109 ErrorFound = true;
5110 }
5111 }
5112 }
5113 // If any if clause on the directive includes a directive-name-modifier then
5114 // all if clauses on the directive must include a directive-name-modifier.
5115 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5116 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5117 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5118 diag::err_omp_no_more_if_clause);
5119 } else {
5120 std::string Values;
5121 std::string Sep(", ");
5122 unsigned AllowedCnt = 0;
5123 unsigned TotalAllowedNum =
5124 AllowedNameModifiers.size() - NamedModifiersNumber;
5125 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5126 ++Cnt) {
5127 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5128 if (!FoundNameModifiers[NM]) {
5129 Values += "'";
5130 Values += getOpenMPDirectiveName(NM, OMPVersion);
5131 Values += "'";
5132 if (AllowedCnt + 2 == TotalAllowedNum)
5133 Values += " or ";
5134 else if (AllowedCnt + 1 != TotalAllowedNum)
5135 Values += Sep;
5136 ++AllowedCnt;
5137 }
5138 }
5139 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5140 diag::err_omp_unnamed_if_clause)
5141 << (TotalAllowedNum > 1) << Values;
5142 }
5143 for (SourceLocation Loc : NameModifierLoc) {
5144 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5145 }
5146 ErrorFound = true;
5147 }
5148 return ErrorFound;
5149}
5150
5151static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5152 SourceLocation &ELoc,
5153 SourceRange &ERange,
5154 bool AllowArraySection,
5155 StringRef DiagType) {
5156 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5158 return std::make_pair(nullptr, true);
5159
5160 // OpenMP [3.1, C/C++]
5161 // A list item is a variable name.
5162 // OpenMP [2.9.3.3, Restrictions, p.1]
5163 // A variable that is part of another variable (as an array or
5164 // structure element) cannot appear in a private clause.
5165 RefExpr = RefExpr->IgnoreParens();
5166 enum {
5167 NoArrayExpr = -1,
5168 ArraySubscript = 0,
5169 OMPArraySection = 1
5170 } IsArrayExpr = NoArrayExpr;
5171 if (AllowArraySection) {
5172 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5173 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5174 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5175 Base = TempASE->getBase()->IgnoreParenImpCasts();
5176 RefExpr = Base;
5177 IsArrayExpr = ArraySubscript;
5178 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5179 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5180 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5181 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5182 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5183 Base = TempASE->getBase()->IgnoreParenImpCasts();
5184 RefExpr = Base;
5185 IsArrayExpr = OMPArraySection;
5186 }
5187 }
5188 ELoc = RefExpr->getExprLoc();
5189 ERange = RefExpr->getSourceRange();
5190 RefExpr = RefExpr->IgnoreParenImpCasts();
5191 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5192 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5193 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5194 (S.getCurrentThisType().isNull() || !ME ||
5195 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5196 !isa<FieldDecl>(ME->getMemberDecl()))) {
5197 if (IsArrayExpr != NoArrayExpr) {
5198 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5199 << IsArrayExpr << ERange;
5200 } else if (!DiagType.empty()) {
5201 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5202 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5203 : 0;
5204 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5205 << DiagSelect << DiagType << ERange;
5206 } else {
5207 S.Diag(ELoc,
5208 AllowArraySection
5209 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5210 : diag::err_omp_expected_var_name_member_expr)
5211 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5212 }
5213 return std::make_pair(nullptr, false);
5214 }
5215 return std::make_pair(
5216 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5217}
5218
5219namespace {
5220/// Checks if the allocator is used in uses_allocators clause to be allowed in
5221/// target regions.
5222class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5223 DSAStackTy *S = nullptr;
5224
5225public:
5226 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5227 return S->isUsesAllocatorsDecl(E->getDecl())
5228 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5229 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5230 }
5231 bool VisitStmt(const Stmt *S) {
5232 for (const Stmt *Child : S->children()) {
5233 if (Child && Visit(Child))
5234 return true;
5235 }
5236 return false;
5237 }
5238 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5239};
5240} // namespace
5241
5242static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5243 ArrayRef<OMPClause *> Clauses) {
5244 assert(!S.CurContext->isDependentContext() &&
5245 "Expected non-dependent context.");
5246 auto AllocateRange =
5247 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5248 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5249 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5250 return isOpenMPPrivate(C->getClauseKind());
5251 });
5252 for (OMPClause *Cl : PrivateRange) {
5254 if (Cl->getClauseKind() == OMPC_private) {
5255 auto *PC = cast<OMPPrivateClause>(Cl);
5256 I = PC->private_copies().begin();
5257 It = PC->varlist_begin();
5258 Et = PC->varlist_end();
5259 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5260 auto *PC = cast<OMPFirstprivateClause>(Cl);
5261 I = PC->private_copies().begin();
5262 It = PC->varlist_begin();
5263 Et = PC->varlist_end();
5264 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5265 auto *PC = cast<OMPLastprivateClause>(Cl);
5266 I = PC->private_copies().begin();
5267 It = PC->varlist_begin();
5268 Et = PC->varlist_end();
5269 } else if (Cl->getClauseKind() == OMPC_linear) {
5270 auto *PC = cast<OMPLinearClause>(Cl);
5271 I = PC->privates().begin();
5272 It = PC->varlist_begin();
5273 Et = PC->varlist_end();
5274 } else if (Cl->getClauseKind() == OMPC_reduction) {
5275 auto *PC = cast<OMPReductionClause>(Cl);
5276 I = PC->privates().begin();
5277 It = PC->varlist_begin();
5278 Et = PC->varlist_end();
5279 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5280 auto *PC = cast<OMPTaskReductionClause>(Cl);
5281 I = PC->privates().begin();
5282 It = PC->varlist_begin();
5283 Et = PC->varlist_end();
5284 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5285 auto *PC = cast<OMPInReductionClause>(Cl);
5286 I = PC->privates().begin();
5287 It = PC->varlist_begin();
5288 Et = PC->varlist_end();
5289 } else {
5290 llvm_unreachable("Expected private clause.");
5291 }
5292 for (Expr *E : llvm::make_range(It, Et)) {
5293 if (!*I) {
5294 ++I;
5295 continue;
5296 }
5297 SourceLocation ELoc;
5298 SourceRange ERange;
5299 Expr *SimpleRefExpr = E;
5300 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5301 /*AllowArraySection=*/true);
5302 DeclToCopy.try_emplace(Res.first,
5303 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5304 ++I;
5305 }
5306 }
5307 for (OMPClause *C : AllocateRange) {
5308 auto *AC = cast<OMPAllocateClause>(C);
5309 if (S.getLangOpts().OpenMP >= 50 &&
5310 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5311 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5312 AC->getAllocator()) {
5313 Expr *Allocator = AC->getAllocator();
5314 // OpenMP, 2.12.5 target Construct
5315 // Memory allocators that do not appear in a uses_allocators clause cannot
5316 // appear as an allocator in an allocate clause or be used in the target
5317 // region unless a requires directive with the dynamic_allocators clause
5318 // is present in the same compilation unit.
5319 AllocatorChecker Checker(Stack);
5320 if (Checker.Visit(Allocator))
5321 S.Diag(Allocator->getExprLoc(),
5322 diag::err_omp_allocator_not_in_uses_allocators)
5323 << Allocator->getSourceRange();
5324 }
5325 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5326 getAllocatorKind(S, Stack, AC->getAllocator());
5327 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5328 // For task, taskloop or target directives, allocation requests to memory
5329 // allocators with the trait access set to thread result in unspecified
5330 // behavior.
5331 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5332 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5333 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5334 unsigned OMPVersion = S.getLangOpts().OpenMP;
5335 S.Diag(AC->getAllocator()->getExprLoc(),
5336 diag::warn_omp_allocate_thread_on_task_target_directive)
5337 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5338 }
5339 for (Expr *E : AC->varlist()) {
5340 SourceLocation ELoc;
5341 SourceRange ERange;
5342 Expr *SimpleRefExpr = E;
5343 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5344 ValueDecl *VD = Res.first;
5345 if (!VD)
5346 continue;
5347 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5348 if (!isOpenMPPrivate(Data.CKind)) {
5349 S.Diag(E->getExprLoc(),
5350 diag::err_omp_expected_private_copy_for_allocate);
5351 continue;
5352 }
5353 VarDecl *PrivateVD = DeclToCopy[VD];
5354 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5355 AllocatorKind, AC->getAllocator()))
5356 continue;
5357 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5358 AC->getAlignment(), E->getSourceRange());
5359 }
5360 }
5361}
5362
5363namespace {
5364/// Rewrite statements and expressions for Sema \p Actions CurContext.
5365///
5366/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5367/// context. DeclRefExpr used inside the new context are changed to refer to the
5368/// captured variable instead.
5369class CaptureVars : public TreeTransform<CaptureVars> {
5370 using BaseTransform = TreeTransform<CaptureVars>;
5371
5372public:
5373 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5374
5375 bool AlwaysRebuild() { return true; }
5376};
5377} // namespace
5378
5379static VarDecl *precomputeExpr(Sema &Actions,
5380 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5381 StringRef Name) {
5382 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5383 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5384 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5385 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5386 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5387 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5388 BodyStmts.push_back(NewDeclStmt);
5389 return NewVar;
5390}
5391
5392/// Create a closure that computes the number of iterations of a loop.
5393///
5394/// \param Actions The Sema object.
5395/// \param LogicalTy Type for the logical iteration number.
5396/// \param Rel Comparison operator of the loop condition.
5397/// \param StartExpr Value of the loop counter at the first iteration.
5398/// \param StopExpr Expression the loop counter is compared against in the loop
5399/// condition. \param StepExpr Amount of increment after each iteration.
5400///
5401/// \return Closure (CapturedStmt) of the distance calculation.
5402static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5404 Expr *StartExpr, Expr *StopExpr,
5405 Expr *StepExpr) {
5406 ASTContext &Ctx = Actions.getASTContext();
5407 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5408
5409 // Captured regions currently don't support return values, we use an
5410 // out-parameter instead. All inputs are implicit captures.
5411 // TODO: Instead of capturing each DeclRefExpr occurring in
5412 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5413 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5414 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5415 {StringRef(), QualType()}};
5416 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5417
5418 Stmt *Body;
5419 {
5420 Sema::CompoundScopeRAII CompoundScope(Actions);
5421 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5422
5423 // Get the LValue expression for the result.
5424 ImplicitParamDecl *DistParam = CS->getParam(0);
5425 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5426 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5427
5428 SmallVector<Stmt *, 4> BodyStmts;
5429
5430 // Capture all referenced variable references.
5431 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5432 // CapturedStmt, we could compute them before and capture the result, to be
5433 // used jointly with the LoopVar function.
5434 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5435 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5436 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5437 auto BuildVarRef = [&](VarDecl *VD) {
5438 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5439 };
5440
5442 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5444 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5445 Expr *Dist;
5446 if (Rel == BO_NE) {
5447 // When using a != comparison, the increment can be +1 or -1. This can be
5448 // dynamic at runtime, so we need to check for the direction.
5449 Expr *IsNegStep = AssertSuccess(
5450 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5451
5452 // Positive increment.
5453 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5454 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5455 ForwardRange = AssertSuccess(
5456 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5457 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5458 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5459
5460 // Negative increment.
5461 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5462 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5463 BackwardRange = AssertSuccess(
5464 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5465 Expr *NegIncAmount = AssertSuccess(
5466 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5467 Expr *BackwardDist = AssertSuccess(
5468 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5469
5470 // Use the appropriate case.
5471 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5472 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5473 } else {
5474 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5475 "Expected one of these relational operators");
5476
5477 // We can derive the direction from any other comparison operator. It is
5478 // non well-formed OpenMP if Step increments/decrements in the other
5479 // directions. Whether at least the first iteration passes the loop
5480 // condition.
5481 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5482 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5483
5484 // Compute the range between first and last counter value.
5485 Expr *Range;
5486 if (Rel == BO_GE || Rel == BO_GT)
5487 Range = AssertSuccess(Actions.BuildBinOp(
5488 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5489 else
5490 Range = AssertSuccess(Actions.BuildBinOp(
5491 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5492
5493 // Ensure unsigned range space.
5494 Range =
5495 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5496
5497 if (Rel == BO_LE || Rel == BO_GE) {
5498 // Add one to the range if the relational operator is inclusive.
5499 Range =
5500 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5501 }
5502
5503 // Divide by the absolute step amount. If the range is not a multiple of
5504 // the step size, rounding-up the effective upper bound ensures that the
5505 // last iteration is included.
5506 // Note that the rounding-up may cause an overflow in a temporary that
5507 // could be avoided, but would have occurred in a C-style for-loop as
5508 // well.
5509 Expr *Divisor = BuildVarRef(NewStep);
5510 if (Rel == BO_GE || Rel == BO_GT)
5511 Divisor =
5512 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5513 Expr *DivisorMinusOne =
5514 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5515 Expr *RangeRoundUp = AssertSuccess(
5516 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5517 Dist = AssertSuccess(
5518 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5519
5520 // If there is not at least one iteration, the range contains garbage. Fix
5521 // to zero in this case.
5522 Dist = AssertSuccess(
5523 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5524 }
5525
5526 // Assign the result to the out-parameter.
5527 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5528 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5529 BodyStmts.push_back(ResultAssign);
5530
5531 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5532 }
5533
5534 return cast<CapturedStmt>(
5535 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5536}
5537
5538/// Create a closure that computes the loop variable from the logical iteration
5539/// number.
5540///
5541/// \param Actions The Sema object.
5542/// \param LoopVarTy Type for the loop variable used for result value.
5543/// \param LogicalTy Type for the logical iteration number.
5544/// \param StartExpr Value of the loop counter at the first iteration.
5545/// \param Step Amount of increment after each iteration.
5546/// \param Deref Whether the loop variable is a dereference of the loop
5547/// counter variable.
5548///
5549/// \return Closure (CapturedStmt) of the loop value calculation.
5550static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5551 QualType LogicalTy,
5552 DeclRefExpr *StartExpr, Expr *Step,
5553 bool Deref) {
5554 ASTContext &Ctx = Actions.getASTContext();
5555
5556 // Pass the result as an out-parameter. Passing as return value would require
5557 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5558 // invoke a copy constructor.
5559 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5560 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5561 {"Logical", LogicalTy},
5562 {StringRef(), QualType()}};
5563 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5564
5565 // Capture the initial iterator which represents the LoopVar value at the
5566 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5567 // it in every iteration, capture it by value before it is modified.
5568 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5569 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5571 (void)Invalid;
5572 assert(!Invalid && "Expecting capture-by-value to work.");
5573
5574 Expr *Body;
5575 {
5576 Sema::CompoundScopeRAII CompoundScope(Actions);
5577 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5578
5579 ImplicitParamDecl *TargetParam = CS->getParam(0);
5580 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5581 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5582 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5583 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5584 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5585
5586 // Capture the Start expression.
5587 CaptureVars Recap(Actions);
5588 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5589 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5590
5592 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5593 // TODO: Explicitly cast to the iterator's difference_type instead of
5594 // relying on implicit conversion.
5595 Expr *Advanced =
5596 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5597
5598 if (Deref) {
5599 // For range-based for-loops convert the loop counter value to a concrete
5600 // loop variable value by dereferencing the iterator.
5601 Advanced =
5602 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5603 }
5604
5605 // Assign the result to the output parameter.
5606 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5607 BO_Assign, TargetRef, Advanced));
5608 }
5609 return cast<CapturedStmt>(
5610 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5611}
5612
5614 ASTContext &Ctx = getASTContext();
5615
5616 // Extract the common elements of ForStmt and CXXForRangeStmt:
5617 // Loop variable, repeat condition, increment
5618 Expr *Cond, *Inc;
5619 VarDecl *LIVDecl, *LUVDecl;
5620 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5621 Stmt *Init = For->getInit();
5622 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5623 // For statement declares loop variable.
5624 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5625 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5626 // For statement reuses variable.
5627 assert(LCAssign->getOpcode() == BO_Assign &&
5628 "init part must be a loop variable assignment");
5629 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5630 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5631 } else
5632 llvm_unreachable("Cannot determine loop variable");
5633 LUVDecl = LIVDecl;
5634
5635 Cond = For->getCond();
5636 Inc = For->getInc();
5637 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5638 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5639 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5640 LUVDecl = RangeFor->getLoopVariable();
5641
5642 Cond = RangeFor->getCond();
5643 Inc = RangeFor->getInc();
5644 } else
5645 llvm_unreachable("unhandled kind of loop");
5646
5647 QualType CounterTy = LIVDecl->getType();
5648 QualType LVTy = LUVDecl->getType();
5649
5650 // Analyze the loop condition.
5651 Expr *LHS, *RHS;
5652 BinaryOperator::Opcode CondRel;
5653 Cond = Cond->IgnoreImplicit();
5654 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5655 LHS = CondBinExpr->getLHS();
5656 RHS = CondBinExpr->getRHS();
5657 CondRel = CondBinExpr->getOpcode();
5658 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5659 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5660 LHS = CondCXXOp->getArg(0);
5661 RHS = CondCXXOp->getArg(1);
5662 switch (CondCXXOp->getOperator()) {
5663 case OO_ExclaimEqual:
5664 CondRel = BO_NE;
5665 break;
5666 case OO_Less:
5667 CondRel = BO_LT;
5668 break;
5669 case OO_LessEqual:
5670 CondRel = BO_LE;
5671 break;
5672 case OO_Greater:
5673 CondRel = BO_GT;
5674 break;
5675 case OO_GreaterEqual:
5676 CondRel = BO_GE;
5677 break;
5678 default:
5679 llvm_unreachable("unexpected iterator operator");
5680 }
5681 } else
5682 llvm_unreachable("unexpected loop condition");
5683
5684 // Normalize such that the loop counter is on the LHS.
5685 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5686 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5687 std::swap(LHS, RHS);
5688 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5689 }
5690 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5691
5692 // Decide the bit width for the logical iteration counter. By default use the
5693 // unsigned ptrdiff_t integer size (for iterators and pointers).
5694 // TODO: For iterators, use iterator::difference_type,
5695 // std::iterator_traits<>::difference_type or decltype(it - end).
5696 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5697 if (CounterTy->isIntegerType()) {
5698 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5699 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5700 }
5701
5702 // Analyze the loop increment.
5703 Expr *Step;
5704 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5705 int Direction;
5706 switch (IncUn->getOpcode()) {
5707 case UO_PreInc:
5708 case UO_PostInc:
5709 Direction = 1;
5710 break;
5711 case UO_PreDec:
5712 case UO_PostDec:
5713 Direction = -1;
5714 break;
5715 default:
5716 llvm_unreachable("unhandled unary increment operator");
5717 }
5719 Ctx,
5720 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5721 LogicalTy, {});
5722 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5723 if (IncBin->getOpcode() == BO_AddAssign) {
5724 Step = IncBin->getRHS();
5725 } else if (IncBin->getOpcode() == BO_SubAssign) {
5726 Step = AssertSuccess(
5727 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5728 } else
5729 llvm_unreachable("unhandled binary increment operator");
5730 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5731 switch (CondCXXOp->getOperator()) {
5732 case OO_PlusPlus:
5734 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5735 break;
5736 case OO_MinusMinus:
5738 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5739 break;
5740 case OO_PlusEqual:
5741 Step = CondCXXOp->getArg(1);
5742 break;
5743 case OO_MinusEqual:
5744 Step = AssertSuccess(
5745 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5746 break;
5747 default:
5748 llvm_unreachable("unhandled overloaded increment operator");
5749 }
5750 } else
5751 llvm_unreachable("unknown increment expression");
5752
5753 CapturedStmt *DistanceFunc =
5754 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5755 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5756 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5757 DeclRefExpr *LVRef =
5758 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5759 nullptr, nullptr, {}, nullptr);
5760 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5761 LoopVarFunc, LVRef);
5762}
5763
5765 // Handle a literal loop.
5766 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5767 return ActOnOpenMPCanonicalLoop(AStmt);
5768
5769 // If not a literal loop, it must be the result of a loop transformation.
5770 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5771 assert(
5773 "Loop transformation directive expected");
5774 return LoopTransform;
5775}
5776
5778 CXXScopeSpec &MapperIdScopeSpec,
5779 const DeclarationNameInfo &MapperId,
5780 QualType Type,
5781 Expr *UnresolvedMapper);
5782
5783/// Perform DFS through the structure/class data members trying to find
5784/// member(s) with user-defined 'default' mapper and generate implicit map
5785/// clauses for such members with the found 'default' mapper.
5786static void
5789 // Check for the default mapper for data members.
5790 if (S.getLangOpts().OpenMP < 50)
5791 return;
5792 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5793 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5794 if (!C)
5795 continue;
5796 SmallVector<Expr *, 4> SubExprs;
5797 auto *MI = C->mapperlist_begin();
5798 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5799 ++I, ++MI) {
5800 // Expression is mapped using mapper - skip it.
5801 if (*MI)
5802 continue;
5803 Expr *E = *I;
5804 // Expression is dependent - skip it, build the mapper when it gets
5805 // instantiated.
5806 if (E->isTypeDependent() || E->isValueDependent() ||
5808 continue;
5809 // Array section - need to check for the mapping of the array section
5810 // element.
5811 QualType CanonType = E->getType().getCanonicalType();
5812 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5813 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5814 QualType BaseType =
5816 QualType ElemType;
5817 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5818 ElemType = ATy->getElementType();
5819 else
5820 ElemType = BaseType->getPointeeType();
5821 CanonType = ElemType;
5822 }
5823
5824 // DFS over data members in structures/classes.
5826 1, {CanonType, nullptr});
5827 llvm::DenseMap<const Type *, Expr *> Visited;
5829 1, {nullptr, 1});
5830 while (!Types.empty()) {
5831 QualType BaseType;
5832 FieldDecl *CurFD;
5833 std::tie(BaseType, CurFD) = Types.pop_back_val();
5834 while (ParentChain.back().second == 0)
5835 ParentChain.pop_back();
5836 --ParentChain.back().second;
5837 if (BaseType.isNull())
5838 continue;
5839 // Only structs/classes are allowed to have mappers.
5840 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5841 if (!RD)
5842 continue;
5843 auto It = Visited.find(BaseType.getTypePtr());
5844 if (It == Visited.end()) {
5845 // Try to find the associated user-defined mapper.
5846 CXXScopeSpec MapperIdScopeSpec;
5847 DeclarationNameInfo DefaultMapperId;
5849 &S.Context.Idents.get("default")));
5850 DefaultMapperId.setLoc(E->getExprLoc());
5852 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5853 BaseType, /*UnresolvedMapper=*/nullptr);
5854 if (ER.isInvalid())
5855 continue;
5856 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5857 }
5858 // Found default mapper.
5859 if (It->second) {
5860 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5862 OE->setIsUnique(/*V=*/true);
5863 Expr *BaseExpr = OE;
5864 for (const auto &P : ParentChain) {
5865 if (P.first) {
5866 BaseExpr = S.BuildMemberExpr(
5867 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5869 DeclAccessPair::make(P.first, P.first->getAccess()),
5870 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5871 P.first->getType(), VK_LValue, OK_Ordinary);
5872 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5873 }
5874 }
5875 if (CurFD)
5876 BaseExpr = S.BuildMemberExpr(
5877 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5879 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5880 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5881 CurFD->getType(), VK_LValue, OK_Ordinary);
5882 SubExprs.push_back(BaseExpr);
5883 continue;
5884 }
5885 // Check for the "default" mapper for data members.
5886 bool FirstIter = true;
5887 for (FieldDecl *FD : RD->fields()) {
5888 if (!FD)
5889 continue;
5890 QualType FieldTy = FD->getType();
5891 if (FieldTy.isNull() ||
5892 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5893 continue;
5894 if (FirstIter) {
5895 FirstIter = false;
5896 ParentChain.emplace_back(CurFD, 1);
5897 } else {
5898 ++ParentChain.back().second;
5899 }
5900 Types.emplace_back(FieldTy, FD);
5901 }
5902 }
5903 }
5904 if (SubExprs.empty())
5905 continue;
5906 CXXScopeSpec MapperIdScopeSpec;
5907 DeclarationNameInfo MapperId;
5908 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5909 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
5910 MapperIdScopeSpec, MapperId, C->getMapType(),
5911 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
5912 SubExprs, OMPVarListLocTy()))
5913 Clauses.push_back(NewClause);
5914 }
5915}
5916
5917namespace {
5918/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5919/// call in the associated loop-nest cannot be a 'parallel for'.
5920class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5921 Sema &SemaRef;
5922
5923public:
5924 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5925
5926 // Is there a nested OpenMP loop bind(parallel)
5927 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5928 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5929 if (const auto *C = D->getSingleClause<OMPBindClause>())
5930 if (C->getBindKind() == OMPC_BIND_parallel) {
5931 TeamsLoopCanBeParallelFor = false;
5932 // No need to continue visiting any more
5933 return;
5934 }
5935 }
5936 for (const Stmt *Child : D->children())
5937 if (Child)
5938 Visit(Child);
5939 }
5940
5941 void VisitCallExpr(const CallExpr *C) {
5942 // Function calls inhibit parallel loop translation of 'target teams loop'
5943 // unless the assume-no-nested-parallelism flag has been specified.
5944 // OpenMP API runtime library calls do not inhibit parallel loop
5945 // translation, regardless of the assume-no-nested-parallelism.
5946 bool IsOpenMPAPI = false;
5947 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
5948 if (FD) {
5949 std::string Name = FD->getNameInfo().getAsString();
5950 IsOpenMPAPI = Name.find("omp_") == 0;
5951 }
5952 TeamsLoopCanBeParallelFor =
5953 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5954 if (!TeamsLoopCanBeParallelFor)
5955 return;
5956
5957 for (const Stmt *Child : C->children())
5958 if (Child)
5959 Visit(Child);
5960 }
5961
5962 void VisitCapturedStmt(const CapturedStmt *S) {
5963 if (!S)
5964 return;
5965 Visit(S->getCapturedDecl()->getBody());
5966 }
5967
5968 void VisitStmt(const Stmt *S) {
5969 if (!S)
5970 return;
5971 for (const Stmt *Child : S->children())
5972 if (Child)
5973 Visit(Child);
5974 }
5975 explicit TeamsLoopChecker(Sema &SemaRef)
5976 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5977
5978private:
5979 bool TeamsLoopCanBeParallelFor;
5980};
5981} // namespace
5982
5983static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5984 TeamsLoopChecker Checker(SemaRef);
5985 Checker.Visit(AStmt);
5986 return Checker.teamsLoopCanBeParallelFor();
5987}
5988
5990 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5991 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5992 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5993 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5994
5995 StmtResult Res = StmtError();
5997 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5998
5999 if (const OMPBindClause *BC =
6000 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6001 BindKind = BC->getBindKind();
6002
6003 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6004 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6005
6006 // Setting the enclosing teams or parallel construct for the loop
6007 // directive without bind clause.
6008 // [5.0:129:25-28] If the bind clause is not present on the construct and
6009 // the loop construct is closely nested inside a teams or parallel
6010 // construct, the binding region is the corresponding teams or parallel
6011 // region. If none of those conditions hold, the binding region is not
6012 // defined.
6013 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6014 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6015 getLeafConstructsOrSelf(ParentDirective);
6016
6017 if (ParentDirective == OMPD_unknown) {
6018 Diag(DSAStack->getDefaultDSALocation(),
6019 diag::err_omp_bind_required_on_loop);
6020 } else if (ParentLeafs.back() == OMPD_parallel) {
6021 BindKind = OMPC_BIND_parallel;
6022 } else if (ParentLeafs.back() == OMPD_teams) {
6023 BindKind = OMPC_BIND_teams;
6024 }
6025
6026 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6027
6028 OMPClause *C =
6031 ClausesWithImplicit.push_back(C);
6032 }
6033
6034 // Diagnose "loop bind(teams)" with "reduction".
6035 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6036 for (OMPClause *C : Clauses) {
6037 if (C->getClauseKind() == OMPC_reduction)
6038 Diag(DSAStack->getDefaultDSALocation(),
6039 diag::err_omp_loop_reduction_clause);
6040 }
6041 }
6042
6043 // First check CancelRegion which is then used in checkNestingOfRegions.
6044 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6045 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6046 BindKind, StartLoc)) {
6047 return StmtError();
6048 }
6049
6050 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6053 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6054
6055 VarsWithInheritedDSAType VarsWithInheritedDSA;
6056 bool ErrorFound = false;
6057 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6058
6059 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6061 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6062
6063 // Check default data sharing attributes for referenced variables.
6064 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6065 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6066 Stmt *S = AStmt;
6067 while (--ThisCaptureLevel >= 0)
6068 S = cast<CapturedStmt>(S)->getCapturedStmt();
6069 DSAChecker.Visit(S);
6071 !isOpenMPTaskingDirective(Kind)) {
6072 // Visit subcaptures to generate implicit clauses for captured vars.
6073 auto *CS = cast<CapturedStmt>(AStmt);
6075 getOpenMPCaptureRegions(CaptureRegions, Kind);
6076 // Ignore outer tasking regions for target directives.
6077 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6078 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6079 DSAChecker.visitSubCaptures(CS);
6080 }
6081 if (DSAChecker.isErrorFound())
6082 return StmtError();
6083 // Generate list of implicitly defined firstprivate variables.
6084 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6085 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6086
6088 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6089 // Get the original location of present modifier from Defaultmap clause.
6090 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6091 for (OMPClause *C : Clauses) {
6092 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6093 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6094 PresentModifierLocs[DMC->getDefaultmapKind()] =
6095 DMC->getDefaultmapModifierLoc();
6096 }
6097
6099 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6101 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6102 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6103 }
6104 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6105 for (OMPClause *C : Clauses) {
6106 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6107 for (Expr *E : IRC->taskgroup_descriptors())
6108 if (E)
6109 ImpInfo.Firstprivates.insert(E);
6110 }
6111 // OpenMP 5.0, 2.10.1 task Construct
6112 // [detach clause]... The event-handle will be considered as if it was
6113 // specified on a firstprivate clause.
6114 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6115 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6116 }
6117 if (!ImpInfo.Firstprivates.empty()) {
6119 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6121 ClausesWithImplicit.push_back(Implicit);
6122 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6123 ImpInfo.Firstprivates.size();
6124 } else {
6125 ErrorFound = true;
6126 }
6127 }
6128 if (!ImpInfo.Privates.empty()) {
6130 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6132 ClausesWithImplicit.push_back(Implicit);
6133 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6134 ImpInfo.Privates.size();
6135 } else {
6136 ErrorFound = true;
6137 }
6138 }
6139 // OpenMP 5.0 [2.19.7]
6140 // If a list item appears in a reduction, lastprivate or linear
6141 // clause on a combined target construct then it is treated as
6142 // if it also appears in a map clause with a map-type of tofrom
6143 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6145 SmallVector<Expr *, 4> ImplicitExprs;
6146 for (OMPClause *C : Clauses) {
6147 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6148 for (Expr *E : RC->varlist())
6149 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6150 ImplicitExprs.emplace_back(E);
6151 }
6152 if (!ImplicitExprs.empty()) {
6153 ArrayRef<Expr *> Exprs = ImplicitExprs;
6154 CXXScopeSpec MapperIdScopeSpec;
6155 DeclarationNameInfo MapperId;
6158 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6159 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6160 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6161 ClausesWithImplicit.emplace_back(Implicit);
6162 }
6163 }
6164 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6165 int ClauseKindCnt = -1;
6166 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6167 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6168 ++ClauseKindCnt;
6169 if (ImplicitMap.empty())
6170 continue;
6171 CXXScopeSpec MapperIdScopeSpec;
6172 DeclarationNameInfo MapperId;
6173 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6175 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6176 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6177 SourceLocation(), SourceLocation(), ImplicitMap,
6178 OMPVarListLocTy())) {
6179 ClausesWithImplicit.emplace_back(Implicit);
6180 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6181 ImplicitMap.size();
6182 } else {
6183 ErrorFound = true;
6184 }
6185 }
6186 }
6187 // Build expressions for implicit maps of data members with 'default'
6188 // mappers.
6189 if (getLangOpts().OpenMP >= 50)
6191 ClausesWithImplicit);
6192 }
6193
6194 switch (Kind) {
6195 case OMPD_parallel:
6196 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6197 EndLoc);
6198 break;
6199 case OMPD_simd:
6200 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6201 VarsWithInheritedDSA);
6202 break;
6203 case OMPD_tile:
6204 Res =
6205 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6206 break;
6207 case OMPD_stripe:
6208 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6209 EndLoc);
6210 break;
6211 case OMPD_unroll:
6212 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6213 EndLoc);
6214 break;
6215 case OMPD_reverse:
6216 assert(ClausesWithImplicit.empty() &&
6217 "reverse directive does not support any clauses");
6218 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6219 break;
6220 case OMPD_interchange:
6221 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6222 EndLoc);
6223 break;
6224 case OMPD_for:
6225 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6226 VarsWithInheritedDSA);
6227 break;
6228 case OMPD_for_simd:
6229 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6230 EndLoc, VarsWithInheritedDSA);
6231 break;
6232 case OMPD_sections:
6233 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6234 EndLoc);
6235 break;
6236 case OMPD_section:
6237 assert(ClausesWithImplicit.empty() &&
6238 "No clauses are allowed for 'omp section' directive");
6239 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6240 break;
6241 case OMPD_single:
6242 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6243 EndLoc);
6244 break;
6245 case OMPD_master:
6246 assert(ClausesWithImplicit.empty() &&
6247 "No clauses are allowed for 'omp master' directive");
6248 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6249 break;
6250 case OMPD_masked:
6251 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6252 EndLoc);
6253 break;
6254 case OMPD_critical:
6255 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6256 StartLoc, EndLoc);
6257 break;
6258 case OMPD_parallel_for:
6259 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6260 EndLoc, VarsWithInheritedDSA);
6261 break;
6262 case OMPD_parallel_for_simd:
6264 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6265 break;
6266 case OMPD_scope:
6267 Res =
6268 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6269 break;
6270 case OMPD_parallel_master:
6271 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6272 StartLoc, EndLoc);
6273 break;
6274 case OMPD_parallel_masked:
6275 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6276 StartLoc, EndLoc);
6277 break;
6278 case OMPD_parallel_sections:
6279 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6280 StartLoc, EndLoc);
6281 break;
6282 case OMPD_task:
6283 Res =
6284 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6285 break;
6286 case OMPD_taskyield:
6287 assert(ClausesWithImplicit.empty() &&
6288 "No clauses are allowed for 'omp taskyield' directive");
6289 assert(AStmt == nullptr &&
6290 "No associated statement allowed for 'omp taskyield' directive");
6291 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6292 break;
6293 case OMPD_error:
6294 assert(AStmt == nullptr &&
6295 "No associated statement allowed for 'omp error' directive");
6296 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6297 break;
6298 case OMPD_barrier:
6299 assert(ClausesWithImplicit.empty() &&
6300 "No clauses are allowed for 'omp barrier' directive");
6301 assert(AStmt == nullptr &&
6302 "No associated statement allowed for 'omp barrier' directive");
6303 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6304 break;
6305 case OMPD_taskwait:
6306 assert(AStmt == nullptr &&
6307 "No associated statement allowed for 'omp taskwait' directive");
6308 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6309 break;
6310 case OMPD_taskgroup:
6311 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6312 EndLoc);
6313 break;
6314 case OMPD_flush:
6315 assert(AStmt == nullptr &&
6316 "No associated statement allowed for 'omp flush' directive");
6317 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6318 break;
6319 case OMPD_depobj:
6320 assert(AStmt == nullptr &&
6321 "No associated statement allowed for 'omp depobj' directive");
6322 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6323 break;
6324 case OMPD_scan:
6325 assert(AStmt == nullptr &&
6326 "No associated statement allowed for 'omp scan' directive");
6327 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6328 break;
6329 case OMPD_ordered:
6330 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6331 EndLoc);
6332 break;
6333 case OMPD_atomic:
6334 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6335 EndLoc);
6336 break;
6337 case OMPD_teams:
6338 Res =
6339 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6340 break;
6341 case OMPD_target:
6342 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6343 EndLoc);
6344 break;
6345 case OMPD_target_parallel:
6346 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6347 StartLoc, EndLoc);
6348 break;
6349 case OMPD_target_parallel_for:
6351 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6352 break;
6353 case OMPD_cancellation_point:
6354 assert(ClausesWithImplicit.empty() &&
6355 "No clauses are allowed for 'omp cancellation point' directive");
6356 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6357 "cancellation point' directive");
6358 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6359 break;
6360 case OMPD_cancel:
6361 assert(AStmt == nullptr &&
6362 "No associated statement allowed for 'omp cancel' directive");
6363 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6364 CancelRegion);
6365 break;
6366 case OMPD_target_data:
6367 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6368 EndLoc);
6369 break;
6370 case OMPD_target_enter_data:
6371 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6372 EndLoc, AStmt);
6373 break;
6374 case OMPD_target_exit_data:
6375 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6376 EndLoc, AStmt);
6377 break;
6378 case OMPD_taskloop:
6379 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6380 EndLoc, VarsWithInheritedDSA);
6381 break;
6382 case OMPD_taskloop_simd:
6383 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6384 EndLoc, VarsWithInheritedDSA);
6385 break;
6386 case OMPD_master_taskloop:
6388 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6389 break;
6390 case OMPD_masked_taskloop:
6392 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6393 break;
6394 case OMPD_master_taskloop_simd:
6396 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6397 break;
6398 case OMPD_masked_taskloop_simd:
6400 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6401 break;
6402 case OMPD_parallel_master_taskloop:
6404 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6405 break;
6406 case OMPD_parallel_masked_taskloop:
6408 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6409 break;
6410 case OMPD_parallel_master_taskloop_simd:
6412 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6413 break;
6414 case OMPD_parallel_masked_taskloop_simd:
6416 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6417 break;
6418 case OMPD_distribute:
6419 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6420 EndLoc, VarsWithInheritedDSA);
6421 break;
6422 case OMPD_target_update:
6423 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6424 EndLoc, AStmt);
6425 break;
6426 case OMPD_distribute_parallel_for:
6428 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6429 break;
6430 case OMPD_distribute_parallel_for_simd:
6432 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6433 break;
6434 case OMPD_distribute_simd:
6436 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6437 break;
6438 case OMPD_target_parallel_for_simd:
6440 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6441 break;
6442 case OMPD_target_simd:
6443 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6444 EndLoc, VarsWithInheritedDSA);
6445 break;
6446 case OMPD_teams_distribute:
6448 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6449 break;
6450 case OMPD_teams_distribute_simd:
6452 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6453 break;
6454 case OMPD_teams_distribute_parallel_for_simd:
6456 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6457 break;
6458 case OMPD_teams_distribute_parallel_for:
6460 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6461 break;
6462 case OMPD_target_teams:
6463 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6464 EndLoc);
6465 break;
6466 case OMPD_target_teams_distribute:
6468 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6469 break;
6470 case OMPD_target_teams_distribute_parallel_for:
6472 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6473 break;
6474 case OMPD_target_teams_distribute_parallel_for_simd:
6476 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6477 break;
6478 case OMPD_target_teams_distribute_simd:
6480 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6481 break;
6482 case OMPD_interop:
6483 assert(AStmt == nullptr &&
6484 "No associated statement allowed for 'omp interop' directive");
6485 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6486 break;
6487 case OMPD_dispatch:
6488 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6489 EndLoc);
6490 break;
6491 case OMPD_loop:
6492 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6493 EndLoc, VarsWithInheritedDSA);
6494 break;
6495 case OMPD_teams_loop:
6497 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6498 break;
6499 case OMPD_target_teams_loop:
6501 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6502 break;
6503 case OMPD_parallel_loop:
6505 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6506 break;
6507 case OMPD_target_parallel_loop:
6509 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6510 break;
6511 case OMPD_declare_target:
6512 case OMPD_end_declare_target:
6513 case OMPD_threadprivate:
6514 case OMPD_allocate:
6515 case OMPD_declare_reduction:
6516 case OMPD_declare_mapper:
6517 case OMPD_declare_simd:
6518 case OMPD_requires:
6519 case OMPD_declare_variant:
6520 case OMPD_begin_declare_variant:
6521 case OMPD_end_declare_variant:
6522 llvm_unreachable("OpenMP Directive is not allowed");
6523 case OMPD_unknown:
6524 default:
6525 llvm_unreachable("Unknown OpenMP directive");
6526 }
6527
6528 ErrorFound = Res.isInvalid() || ErrorFound;
6529
6530 // Check variables in the clauses if default(none) or
6531 // default(firstprivate) was specified.
6532 if (DSAStack->getDefaultDSA() == DSA_none ||
6533 DSAStack->getDefaultDSA() == DSA_private ||
6534 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6535 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6536 for (OMPClause *C : Clauses) {
6537 switch (C->getClauseKind()) {
6538 case OMPC_num_threads:
6539 case OMPC_dist_schedule:
6540 // Do not analyze if no parent teams directive.
6541 if (isOpenMPTeamsDirective(Kind))
6542 break;
6543 continue;
6544 case OMPC_if:
6545 if (isOpenMPTeamsDirective(Kind) &&
6546 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6547 break;
6548 if (isOpenMPParallelDirective(Kind) &&
6550 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6551 break;
6552 continue;
6553 case OMPC_schedule:
6554 case OMPC_detach:
6555 break;
6556 case OMPC_grainsize:
6557 case OMPC_num_tasks:
6558 case OMPC_final:
6559 case OMPC_priority:
6560 case OMPC_novariants:
6561 case OMPC_nocontext:
6562 // Do not analyze if no parent parallel directive.
6563 if (isOpenMPParallelDirective(Kind))
6564 break;
6565 continue;
6566 case OMPC_ordered:
6567 case OMPC_device:
6568 case OMPC_num_teams:
6569 case OMPC_thread_limit:
6570 case OMPC_hint:
6571 case OMPC_collapse:
6572 case OMPC_safelen:
6573 case OMPC_simdlen:
6574 case OMPC_sizes:
6575 case OMPC_default:
6576 case OMPC_proc_bind:
6577 case OMPC_private:
6578 case OMPC_firstprivate:
6579 case OMPC_lastprivate:
6580 case OMPC_shared:
6581 case OMPC_reduction:
6582 case OMPC_task_reduction:
6583 case OMPC_in_reduction:
6584 case OMPC_linear:
6585 case OMPC_aligned:
6586 case OMPC_copyin:
6587 case OMPC_copyprivate:
6588 case OMPC_nowait:
6589 case OMPC_untied:
6590 case OMPC_mergeable:
6591 case OMPC_allocate:
6592 case OMPC_read:
6593 case OMPC_write:
6594 case OMPC_update:
6595 case OMPC_capture:
6596 case OMPC_compare:
6597 case OMPC_seq_cst:
6598 case OMPC_acq_rel:
6599 case OMPC_acquire:
6600 case OMPC_release:
6601 case OMPC_relaxed:
6602 case OMPC_depend:
6603 case OMPC_threads:
6604 case OMPC_simd:
6605 case OMPC_map:
6606 case OMPC_nogroup:
6607 case OMPC_defaultmap:
6608 case OMPC_to:
6609 case OMPC_from:
6610 case OMPC_use_device_ptr:
6611 case OMPC_use_device_addr:
6612 case OMPC_is_device_ptr:
6613 case OMPC_has_device_addr:
6614 case OMPC_nontemporal:
6615 case OMPC_order:
6616 case OMPC_destroy:
6617 case OMPC_inclusive:
6618 case OMPC_exclusive:
6619 case OMPC_uses_allocators:
6620 case OMPC_affinity:
6621 case OMPC_bind:
6622 case OMPC_filter:
6623 case OMPC_severity:
6624 case OMPC_message:
6625 continue;
6626 case OMPC_allocator:
6627 case OMPC_flush:
6628 case OMPC_depobj:
6629 case OMPC_threadprivate:
6630 case OMPC_uniform:
6631 case OMPC_unknown:
6632 case OMPC_unified_address:
6633 case OMPC_unified_shared_memory:
6634 case OMPC_reverse_offload:
6635 case OMPC_dynamic_allocators:
6636 case OMPC_atomic_default_mem_order:
6637 case OMPC_self_maps:
6638 case OMPC_device_type:
6639 case OMPC_match:
6640 case OMPC_when:
6641 case OMPC_at:
6642 default:
6643 llvm_unreachable("Unexpected clause");
6644 }
6645 for (Stmt *CC : C->children()) {
6646 if (CC)
6647 DSAChecker.Visit(CC);
6648 }
6649 }
6650 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6651 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6652 }
6653 for (const auto &P : VarsWithInheritedDSA) {
6654 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6655 continue;
6656 ErrorFound = true;
6657 if (DSAStack->getDefaultDSA() == DSA_none ||
6658 DSAStack->getDefaultDSA() == DSA_private ||
6659 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6660 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6661 << P.first << P.second->getSourceRange();
6662 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6663 } else if (getLangOpts().OpenMP >= 50) {
6664 Diag(P.second->getExprLoc(),
6665 diag::err_omp_defaultmap_no_attr_for_variable)
6666 << P.first << P.second->getSourceRange();
6667 Diag(DSAStack->getDefaultDSALocation(),
6668 diag::note_omp_defaultmap_attr_none);
6669 }
6670 }
6671
6672 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6673 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6674 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6675 AllowedNameModifiers.push_back(D);
6676 }
6677 if (!AllowedNameModifiers.empty())
6678 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6679 ErrorFound;
6680
6681 if (ErrorFound)
6682 return StmtError();
6683
6686 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6687 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6688 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6689 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6690 // Register target to DSA Stack.
6691 DSAStack->addTargetDirLocation(StartLoc);
6692 }
6693
6694 return Res;
6695}
6696
6698 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6699 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6700 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6701 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6702 assert(Aligneds.size() == Alignments.size());
6703 assert(Linears.size() == LinModifiers.size());
6704 assert(Linears.size() == Steps.size());
6705 if (!DG || DG.get().isNull())
6706 return DeclGroupPtrTy();
6707
6708 const int SimdId = 0;
6709 if (!DG.get().isSingleDecl()) {
6710 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6711 << SimdId;
6712 return DG;
6713 }
6714 Decl *ADecl = DG.get().getSingleDecl();
6715 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6716 ADecl = FTD->getTemplatedDecl();
6717
6718 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6719 if (!FD) {
6720 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6721 return DeclGroupPtrTy();
6722 }
6723
6724 // OpenMP [2.8.2, declare simd construct, Description]
6725 // The parameter of the simdlen clause must be a constant positive integer
6726 // expression.
6727 ExprResult SL;
6728 if (Simdlen)
6729 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6730 // OpenMP [2.8.2, declare simd construct, Description]
6731 // The special this pointer can be used as if was one of the arguments to the
6732 // function in any of the linear, aligned, or uniform clauses.
6733 // The uniform clause declares one or more arguments to have an invariant
6734 // value for all concurrent invocations of the function in the execution of a
6735 // single SIMD loop.
6736 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6737 const Expr *UniformedLinearThis = nullptr;
6738 for (const Expr *E : Uniforms) {
6739 E = E->IgnoreParenImpCasts();
6740 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6741 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6742 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6743 FD->getParamDecl(PVD->getFunctionScopeIndex())
6744 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6745 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6746 continue;
6747 }
6748 if (isa<CXXThisExpr>(E)) {
6749 UniformedLinearThis = E;
6750 continue;
6751 }
6752 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6753 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6754 }
6755 // OpenMP [2.8.2, declare simd construct, Description]
6756 // The aligned clause declares that the object to which each list item points
6757 // is aligned to the number of bytes expressed in the optional parameter of
6758 // the aligned clause.
6759 // The special this pointer can be used as if was one of the arguments to the
6760 // function in any of the linear, aligned, or uniform clauses.
6761 // The type of list items appearing in the aligned clause must be array,
6762 // pointer, reference to array, or reference to pointer.
6763 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6764 const Expr *AlignedThis = nullptr;
6765 for (const Expr *E : Aligneds) {
6766 E = E->IgnoreParenImpCasts();
6767 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6768 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6769 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6770 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6771 FD->getParamDecl(PVD->getFunctionScopeIndex())
6772 ->getCanonicalDecl() == CanonPVD) {
6773 // OpenMP [2.8.1, simd construct, Restrictions]
6774 // A list-item cannot appear in more than one aligned clause.
6775 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6776 if (!Inserted) {
6777 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6778 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6779 << E->getSourceRange();
6780 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6781 << getOpenMPClauseNameForDiag(OMPC_aligned);
6782 continue;
6783 }
6784 QualType QTy = PVD->getType()
6785 .getNonReferenceType()
6786 .getUnqualifiedType()
6787 .getCanonicalType();
6788 const Type *Ty = QTy.getTypePtrOrNull();
6789 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6790 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6791 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6792 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6793 }
6794 continue;
6795 }
6796 }
6797 if (isa<CXXThisExpr>(E)) {
6798 if (AlignedThis) {
6799 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6800 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
6801 << E->getSourceRange();
6802 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6803 << getOpenMPClauseNameForDiag(OMPC_aligned);
6804 }
6805 AlignedThis = E;
6806 continue;
6807 }
6808 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6809 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6810 }
6811 // The optional parameter of the aligned clause, alignment, must be a constant
6812 // positive integer expression. If no optional parameter is specified,
6813 // implementation-defined default alignments for SIMD instructions on the
6814 // target platforms are assumed.
6816 for (Expr *E : Alignments) {
6817 ExprResult Align;
6818 if (E)
6819 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6820 NewAligns.push_back(Align.get());
6821 }
6822 // OpenMP [2.8.2, declare simd construct, Description]
6823 // The linear clause declares one or more list items to be private to a SIMD
6824 // lane and to have a linear relationship with respect to the iteration space
6825 // of a loop.
6826 // The special this pointer can be used as if was one of the arguments to the
6827 // function in any of the linear, aligned, or uniform clauses.
6828 // When a linear-step expression is specified in a linear clause it must be
6829 // either a constant integer expression or an integer-typed parameter that is
6830 // specified in a uniform clause on the directive.
6831 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6832 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6833 auto MI = LinModifiers.begin();
6834 for (const Expr *E : Linears) {
6835 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6836 ++MI;
6837 E = E->IgnoreParenImpCasts();
6838 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6839 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6840 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6841 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6842 FD->getParamDecl(PVD->getFunctionScopeIndex())
6843 ->getCanonicalDecl() == CanonPVD) {
6844 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6845 // A list-item cannot appear in more than one linear clause.
6846 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
6847 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6848 << getOpenMPClauseNameForDiag(OMPC_linear)
6849 << getOpenMPClauseNameForDiag(OMPC_linear)
6850 << E->getSourceRange();
6851 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6852 << getOpenMPClauseNameForDiag(OMPC_linear);
6853 continue;
6854 }
6855 // Each argument can appear in at most one uniform or linear clause.
6856 if (auto It = UniformedArgs.find(CanonPVD);
6857 It != UniformedArgs.end()) {
6858 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6859 << getOpenMPClauseNameForDiag(OMPC_linear)
6860 << getOpenMPClauseNameForDiag(OMPC_uniform)
6861 << E->getSourceRange();
6862 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6863 << getOpenMPClauseNameForDiag(OMPC_uniform);
6864 continue;
6865 }
6866 LinearArgs[CanonPVD] = E;
6867 if (E->isValueDependent() || E->isTypeDependent() ||
6870 continue;
6871 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6872 PVD->getOriginalType(),
6873 /*IsDeclareSimd=*/true);
6874 continue;
6875 }
6876 }
6877 if (isa<CXXThisExpr>(E)) {
6878 if (UniformedLinearThis) {
6879 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6880 << getOpenMPClauseNameForDiag(OMPC_linear)
6881 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
6882 : OMPC_linear)
6883 << E->getSourceRange();
6884 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6885 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
6886 : OMPC_linear);
6887 continue;
6888 }
6889 UniformedLinearThis = E;
6890 if (E->isValueDependent() || E->isTypeDependent() ||
6892 continue;
6893 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6894 E->getType(), /*IsDeclareSimd=*/true);
6895 continue;
6896 }
6897 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6898 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6899 }
6900 Expr *Step = nullptr;
6901 Expr *NewStep = nullptr;
6902 SmallVector<Expr *, 4> NewSteps;
6903 for (Expr *E : Steps) {
6904 // Skip the same step expression, it was checked already.
6905 if (Step == E || !E) {
6906 NewSteps.push_back(E ? NewStep : nullptr);
6907 continue;
6908 }
6909 Step = E;
6910 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6911 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6912 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6913 if (UniformedArgs.count(CanonPVD) == 0) {
6914 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6915 << Step->getSourceRange();
6916 } else if (E->isValueDependent() || E->isTypeDependent() ||
6919 CanonPVD->getType()->hasIntegerRepresentation()) {
6920 NewSteps.push_back(Step);
6921 } else {
6922 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6923 << Step->getSourceRange();
6924 }
6925 continue;
6926 }
6927 NewStep = Step;
6928 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6929 !Step->isInstantiationDependent() &&
6931 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6932 .get();
6933 if (NewStep)
6934 NewStep = SemaRef
6936 NewStep, /*FIXME*/ AllowFoldKind::Allow)
6937 .get();
6938 }
6939 NewSteps.push_back(NewStep);
6940 }
6941 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6942 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
6943 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
6944 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
6945 const_cast<Expr **>(Linears.data()), Linears.size(),
6946 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
6947 NewSteps.data(), NewSteps.size(), SR);
6948 ADecl->addAttr(NewAttr);
6949 return DG;
6950}
6951
6953 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6954 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
6955 SourceLocation EndLoc) {
6956 assert(isOpenMPInformationalDirective(Kind) &&
6957 "Unexpected directive category");
6958
6959 StmtResult Res = StmtError();
6960
6961 switch (Kind) {
6962 case OMPD_assume:
6963 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
6964 break;
6965 default:
6966 llvm_unreachable("Unknown OpenMP directive");
6967 }
6968
6969 return Res;
6970}
6971
6972static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6973 QualType NewType) {
6974 assert(NewType->isFunctionProtoType() &&
6975 "Expected function type with prototype.");
6976 assert(FD->getType()->isFunctionNoProtoType() &&
6977 "Expected function with type with no prototype.");
6978 assert(FDWithProto->getType()->isFunctionProtoType() &&
6979 "Expected function with prototype.");
6980 // Synthesize parameters with the same types.
6981 FD->setType(NewType);
6983 for (const ParmVarDecl *P : FDWithProto->parameters()) {
6984 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
6985 SourceLocation(), nullptr, P->getType(),
6986 /*TInfo=*/nullptr, SC_None, nullptr);
6987 Param->setScopeInfo(0, Params.size());
6988 Param->setImplicit();
6989 Params.push_back(Param);
6990 }
6991
6992 FD->setParams(Params);
6993}
6994
6996 if (D->isInvalidDecl())
6997 return;
6998 FunctionDecl *FD = nullptr;
6999 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7000 FD = UTemplDecl->getTemplatedDecl();
7001 else
7002 FD = cast<FunctionDecl>(D);
7003 assert(FD && "Expected a function declaration!");
7004
7005 // If we are instantiating templates we do *not* apply scoped assumptions but
7006 // only global ones. We apply scoped assumption to the template definition
7007 // though.
7009 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7010 FD->addAttr(AA);
7011 }
7012 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7013 FD->addAttr(AA);
7014}
7015
7016SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7017 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7018
7020 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7022 if (!D.getIdentifier())
7023 return;
7024
7025 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7026
7027 // Template specialization is an extension, check if we do it.
7028 bool IsTemplated = !TemplateParamLists.empty();
7029 if (IsTemplated &&
7030 !DVScope.TI->isExtensionActive(
7031 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7032 return;
7033
7034 const IdentifierInfo *BaseII = D.getIdentifier();
7035 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7037 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7038 /*ObjectType=*/QualType());
7039
7041 QualType FType = TInfo->getType();
7042
7043 bool IsConstexpr =
7044 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7045 bool IsConsteval =
7046 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7047
7048 for (auto *Candidate : Lookup) {
7049 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7050 FunctionDecl *UDecl = nullptr;
7051 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7052 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7053 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7054 UDecl = FTD->getTemplatedDecl();
7055 } else if (!IsTemplated)
7056 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7057 if (!UDecl)
7058 continue;
7059
7060 // Don't specialize constexpr/consteval functions with
7061 // non-constexpr/consteval functions.
7062 if (UDecl->isConstexpr() && !IsConstexpr)
7063 continue;
7064 if (UDecl->isConsteval() && !IsConsteval)
7065 continue;
7066
7067 QualType UDeclTy = UDecl->getType();
7068 if (!UDeclTy->isDependentType()) {
7070 FType, UDeclTy, /*OfBlockPointer=*/false,
7071 /*Unqualified=*/false, /*AllowCXX=*/true);
7072 if (NewType.isNull())
7073 continue;
7074 }
7075
7076 // Found a base!
7077 Bases.push_back(UDecl);
7078 }
7079
7080 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7081 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7082 // If no base was found we create a declaration that we use as base.
7083 if (Bases.empty() && UseImplicitBase) {
7084 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7085 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7086 BaseD->setImplicit(true);
7087 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7088 Bases.push_back(BaseTemplD->getTemplatedDecl());
7089 else
7090 Bases.push_back(cast<FunctionDecl>(BaseD));
7091 }
7092
7093 std::string MangledName;
7094 MangledName += D.getIdentifier()->getName();
7095 MangledName += getOpenMPVariantManglingSeparatorStr();
7096 MangledName += DVScope.NameSuffix;
7097 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7098
7099 VariantII.setMangledOpenMPVariantName(true);
7100 D.SetIdentifier(&VariantII, D.getBeginLoc());
7101}
7102
7105 // Do not mark function as is used to prevent its emission if this is the
7106 // only place where it is used.
7109
7110 FunctionDecl *FD = nullptr;
7111 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7112 FD = UTemplDecl->getTemplatedDecl();
7113 else
7114 FD = cast<FunctionDecl>(D);
7115 auto *VariantFuncRef = DeclRefExpr::Create(
7117 /*RefersToEnclosingVariableOrCapture=*/false,
7118 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7119
7120 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7121 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7122 getASTContext(), VariantFuncRef, DVScope.TI,
7123 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7124 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7125 /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7126 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7127 for (FunctionDecl *BaseFD : Bases)
7128 BaseFD->addAttr(OMPDeclareVariantA);
7129}
7130
7132 SourceLocation LParenLoc,
7133 MultiExprArg ArgExprs,
7134 SourceLocation RParenLoc,
7135 Expr *ExecConfig) {
7136 // The common case is a regular call we do not want to specialize at all. Try
7137 // to make that case fast by bailing early.
7138 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7139 if (!CE)
7140 return Call;
7141
7142 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7143 if (!CalleeFnDecl)
7144 return Call;
7145
7146 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7147 CalleeFnDecl->getIdentifier() &&
7148 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7149 // checking for any calls inside an Order region
7151 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7152 }
7153
7154 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7155 return Call;
7156
7157 ASTContext &Context = getASTContext();
7158 std::function<void(StringRef)> DiagUnknownTrait = [this,
7159 CE](StringRef ISATrait) {
7160 // TODO Track the selector locations in a way that is accessible here to
7161 // improve the diagnostic location.
7162 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7163 << ISATrait;
7164 };
7165 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7167 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7168
7169 QualType CalleeFnType = CalleeFnDecl->getType();
7170
7173 while (CalleeFnDecl) {
7174 for (OMPDeclareVariantAttr *A :
7175 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7176 Expr *VariantRef = A->getVariantFuncRef();
7177
7178 VariantMatchInfo VMI;
7179 OMPTraitInfo &TI = A->getTraitInfo();
7180 TI.getAsVariantMatchInfo(Context, VMI);
7181 if (!isVariantApplicableInContext(VMI, OMPCtx,
7182 /*DeviceSetOnly=*/false))
7183 continue;
7184
7185 VMIs.push_back(VMI);
7186 Exprs.push_back(VariantRef);
7187 }
7188
7189 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7190 }
7191
7192 ExprResult NewCall;
7193 do {
7194 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7195 if (BestIdx < 0)
7196 return Call;
7197 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7198 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7199
7200 {
7201 // Try to build a (member) call expression for the current best applicable
7202 // variant expression. We allow this to fail in which case we continue
7203 // with the next best variant expression. The fail case is part of the
7204 // implementation defined behavior in the OpenMP standard when it talks
7205 // about what differences in the function prototypes: "Any differences
7206 // that the specific OpenMP context requires in the prototype of the
7207 // variant from the base function prototype are implementation defined."
7208 // This wording is there to allow the specialized variant to have a
7209 // different type than the base function. This is intended and OK but if
7210 // we cannot create a call the difference is not in the "implementation
7211 // defined range" we allow.
7213
7214 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7215 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7216 BestExpr = MemberExpr::CreateImplicit(
7217 Context, MemberCall->getImplicitObjectArgument(),
7218 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7219 MemberCall->getValueKind(), MemberCall->getObjectKind());
7220 }
7221 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7222 RParenLoc, ExecConfig);
7223 if (NewCall.isUsable()) {
7224 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7225 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7227 CalleeFnType, NewCalleeFnDecl->getType(),
7228 /*OfBlockPointer=*/false,
7229 /*Unqualified=*/false, /*AllowCXX=*/true);
7230 if (!NewType.isNull())
7231 break;
7232 // Don't use the call if the function type was not compatible.
7233 NewCall = nullptr;
7234 }
7235 }
7236 }
7237
7238 VMIs.erase(VMIs.begin() + BestIdx);
7239 Exprs.erase(Exprs.begin() + BestIdx);
7240 } while (!VMIs.empty());
7241
7242 if (!NewCall.isUsable())
7243 return Call;
7244 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7245}
7246
7247std::optional<std::pair<FunctionDecl *, Expr *>>
7249 Expr *VariantRef,
7250 OMPTraitInfo &TI,
7251 unsigned NumAppendArgs,
7252 SourceRange SR) {
7253 ASTContext &Context = getASTContext();
7254 if (!DG || DG.get().isNull())
7255 return std::nullopt;
7256
7257 const int VariantId = 1;
7258 // Must be applied only to single decl.
7259 if (!DG.get().isSingleDecl()) {
7260 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7261 << VariantId << SR;
7262 return std::nullopt;
7263 }
7264 Decl *ADecl = DG.get().getSingleDecl();
7265 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7266 ADecl = FTD->getTemplatedDecl();
7267
7268 // Decl must be a function.
7269 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7270 if (!FD) {
7271 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7272 << VariantId << SR;
7273 return std::nullopt;
7274 }
7275
7276 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7277 // The 'target' attribute needs to be separately checked because it does
7278 // not always signify a multiversion function declaration.
7279 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7280 };
7281 // OpenMP is not compatible with multiversion function attributes.
7282 if (HasMultiVersionAttributes(FD)) {
7283 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7284 << SR;
7285 return std::nullopt;
7286 }
7287
7288 // Allow #pragma omp declare variant only if the function is not used.
7289 if (FD->isUsed(false))
7290 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7291 << FD->getLocation();
7292
7293 // Check if the function was emitted already.
7294 const FunctionDecl *Definition;
7295 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7296 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7297 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7298 << FD->getLocation();
7299
7300 // The VariantRef must point to function.
7301 if (!VariantRef) {
7302 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7303 return std::nullopt;
7304 }
7305
7306 auto ShouldDelayChecks = [](Expr *&E, bool) {
7307 return E && (E->isTypeDependent() || E->isValueDependent() ||
7310 };
7311 // Do not check templates, wait until instantiation.
7312 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7313 TI.anyScoreOrCondition(ShouldDelayChecks))
7314 return std::make_pair(FD, VariantRef);
7315
7316 // Deal with non-constant score and user condition expressions.
7317 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7318 bool IsScore) -> bool {
7320 return false;
7321
7322 if (IsScore) {
7323 // We warn on non-constant scores and pretend they were not present.
7324 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7325 << E;
7326 E = nullptr;
7327 } else {
7328 // We could replace a non-constant user condition with "false" but we
7329 // will soon need to handle these anyway for the dynamic version of
7330 // OpenMP context selectors.
7331 Diag(E->getExprLoc(),
7332 diag::err_omp_declare_variant_user_condition_not_constant)
7333 << E;
7334 }
7335 return true;
7336 };
7337 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7338 return std::nullopt;
7339
7340 QualType AdjustedFnType = FD->getType();
7341 if (NumAppendArgs) {
7342 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7343 if (!PTy) {
7344 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7345 << SR;
7346 return std::nullopt;
7347 }
7348 // Adjust the function type to account for an extra omp_interop_t for each
7349 // specified in the append_args clause.
7350 const TypeDecl *TD = nullptr;
7351 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7354 NamedDecl *ND = Result.getFoundDecl();
7355 TD = dyn_cast_or_null<TypeDecl>(ND);
7356 }
7357 if (!TD) {
7358 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7359 return std::nullopt;
7360 }
7361 QualType InteropType =
7363 /*Qualifier=*/std::nullopt, TD);
7364 if (PTy->isVariadic()) {
7365 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7366 return std::nullopt;
7367 }
7369 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7370 Params.insert(Params.end(), NumAppendArgs, InteropType);
7371 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7372 PTy->getExtProtoInfo());
7373 }
7374
7375 // Convert VariantRef expression to the type of the original function to
7376 // resolve possible conflicts.
7377 ExprResult VariantRefCast = VariantRef;
7378 if (getLangOpts().CPlusPlus) {
7379 QualType FnPtrType;
7380 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7381 if (Method && !Method->isStatic()) {
7382 FnPtrType = Context.getMemberPointerType(
7383 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7384 ExprResult ER;
7385 {
7386 // Build addr_of unary op to correctly handle type checks for member
7387 // functions.
7389 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7390 VariantRef);
7391 }
7392 if (!ER.isUsable()) {
7393 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7394 << VariantId << VariantRef->getSourceRange();
7395 return std::nullopt;
7396 }
7397 VariantRef = ER.get();
7398 } else {
7399 FnPtrType = Context.getPointerType(AdjustedFnType);
7400 }
7401 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7402 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7404 VariantRef, FnPtrType.getUnqualifiedType(),
7405 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7406 /*InOverloadResolution=*/false,
7407 /*CStyle=*/false,
7408 /*AllowObjCWritebackConversion=*/false);
7409 if (ICS.isFailure()) {
7410 Diag(VariantRef->getExprLoc(),
7411 diag::err_omp_declare_variant_incompat_types)
7412 << VariantRef->getType()
7413 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7414 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7415 return std::nullopt;
7416 }
7417 VariantRefCast = SemaRef.PerformImplicitConversion(
7418 VariantRef, FnPtrType.getUnqualifiedType(),
7420 if (!VariantRefCast.isUsable())
7421 return std::nullopt;
7422 }
7423 // Drop previously built artificial addr_of unary op for member functions.
7424 if (Method && !Method->isStatic()) {
7425 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7426 if (auto *UO = dyn_cast<UnaryOperator>(
7427 PossibleAddrOfVariantRef->IgnoreImplicit()))
7428 VariantRefCast = UO->getSubExpr();
7429 }
7430 }
7431
7432 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7433 if (!ER.isUsable() ||
7435 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7436 << VariantId << VariantRef->getSourceRange();
7437 return std::nullopt;
7438 }
7439
7440 // The VariantRef must point to function.
7441 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7442 if (!DRE) {
7443 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7444 << VariantId << VariantRef->getSourceRange();
7445 return std::nullopt;
7446 }
7447 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7448 if (!NewFD) {
7449 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7450 << VariantId << VariantRef->getSourceRange();
7451 return std::nullopt;
7452 }
7453
7454 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7455 Diag(VariantRef->getExprLoc(),
7456 diag::err_omp_declare_variant_same_base_function)
7457 << VariantRef->getSourceRange();
7458 return std::nullopt;
7459 }
7460
7461 // Check if function types are compatible in C.
7462 if (!getLangOpts().CPlusPlus) {
7463 QualType NewType =
7464 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7465 if (NewType.isNull()) {
7466 Diag(VariantRef->getExprLoc(),
7467 diag::err_omp_declare_variant_incompat_types)
7468 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7469 << VariantRef->getSourceRange();
7470 return std::nullopt;
7471 }
7472 if (NewType->isFunctionProtoType()) {
7473 if (FD->getType()->isFunctionNoProtoType())
7474 setPrototype(SemaRef, FD, NewFD, NewType);
7475 else if (NewFD->getType()->isFunctionNoProtoType())
7476 setPrototype(SemaRef, NewFD, FD, NewType);
7477 }
7478 }
7479
7480 // Check if variant function is not marked with declare variant directive.
7481 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7482 Diag(VariantRef->getExprLoc(),
7483 diag::warn_omp_declare_variant_marked_as_declare_variant)
7484 << VariantRef->getSourceRange();
7485 SourceRange SR =
7486 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7487 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7488 return std::nullopt;
7489 }
7490
7491 enum DoesntSupport {
7492 VirtFuncs = 1,
7493 Constructors = 3,
7494 Destructors = 4,
7495 DeletedFuncs = 5,
7496 DefaultedFuncs = 6,
7497 ConstexprFuncs = 7,
7498 ConstevalFuncs = 8,
7499 };
7500 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7501 if (CXXFD->isVirtual()) {
7502 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7503 << VirtFuncs;
7504 return std::nullopt;
7505 }
7506
7507 if (isa<CXXConstructorDecl>(FD)) {
7508 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7509 << Constructors;
7510 return std::nullopt;
7511 }
7512
7513 if (isa<CXXDestructorDecl>(FD)) {
7514 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7515 << Destructors;
7516 return std::nullopt;
7517 }
7518 }
7519
7520 if (FD->isDeleted()) {
7521 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7522 << DeletedFuncs;
7523 return std::nullopt;
7524 }
7525
7526 if (FD->isDefaulted()) {
7527 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7528 << DefaultedFuncs;
7529 return std::nullopt;
7530 }
7531
7532 if (FD->isConstexpr()) {
7533 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7534 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7535 return std::nullopt;
7536 }
7537
7538 // Check general compatibility.
7544 VariantRef->getExprLoc(),
7545 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7546 PartialDiagnosticAt(VariantRef->getExprLoc(),
7547 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7548 << FD->getLocation()),
7549 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7550 /*CLinkageMayDiffer=*/true))
7551 return std::nullopt;
7552 return std::make_pair(FD, cast<Expr>(DRE));
7553}
7554
7556 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7557 ArrayRef<Expr *> AdjustArgsNothing,
7558 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7559 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7560 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7561 SourceLocation AppendArgsLoc, SourceRange SR) {
7562
7563 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7564 // An adjust_args clause or append_args clause can only be specified if the
7565 // dispatch selector of the construct selector set appears in the match
7566 // clause.
7567
7568 SmallVector<Expr *, 8> AllAdjustArgs;
7569 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7570 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7571 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7572
7573 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7574 VariantMatchInfo VMI;
7576 if (!llvm::is_contained(
7577 VMI.ConstructTraits,
7578 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7579 if (!AllAdjustArgs.empty())
7580 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7581 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7582 if (!AppendArgs.empty())
7583 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7584 << getOpenMPClauseNameForDiag(OMPC_append_args);
7585 return;
7586 }
7587 }
7588
7589 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7590 // Each argument can only appear in a single adjust_args clause for each
7591 // declare variant directive.
7593
7594 for (Expr *E : AllAdjustArgs) {
7595 E = E->IgnoreParenImpCasts();
7596 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7597 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7598 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7599 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7600 FD->getParamDecl(PVD->getFunctionScopeIndex())
7601 ->getCanonicalDecl() == CanonPVD) {
7602 // It's a parameter of the function, check duplicates.
7603 if (!AdjustVars.insert(CanonPVD).second) {
7604 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7605 << PVD;
7606 return;
7607 }
7608 continue;
7609 }
7610 }
7611 }
7612 // Anything that is not a function parameter is an error.
7613 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7614 return;
7615 }
7616
7617 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7618 // If the `need_device_addr` adjust-op modifier is present, each list item
7619 // that appears in the clause must refer to an argument in the declaration of
7620 // the function variant that has a reference type
7621 if (getLangOpts().OpenMP >= 60) {
7622 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7623 E = E->IgnoreParenImpCasts();
7624 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7625 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7626 if (!VD->getType()->isReferenceType())
7627 Diag(E->getExprLoc(),
7628 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7629 }
7630 }
7631 }
7632 }
7633
7634 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7635 getASTContext(), VariantRef, &TI,
7636 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7637 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7638 AdjustArgsNeedDevicePtr.size(),
7639 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7640 AdjustArgsNeedDeviceAddr.size(),
7641 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7642 FD->addAttr(NewAttr);
7643}
7644
7645static CapturedStmt *
7647 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7648 assert(CS && "Captured statement expected");
7649 // 1.2.2 OpenMP Language Terminology
7650 // Structured block - An executable statement with a single entry at the
7651 // top and a single exit at the bottom.
7652 // The point of exit cannot be a branch out of the structured block.
7653 // longjmp() and throw() must not violate the entry/exit criteria.
7654 CS->getCapturedDecl()->setNothrow();
7655
7656 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7657 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7658 CS = cast<CapturedStmt>(CS->getCapturedStmt());
7659 // 1.2.2 OpenMP Language Terminology
7660 // Structured block - An executable statement with a single entry at the
7661 // top and a single exit at the bottom.
7662 // The point of exit cannot be a branch out of the structured block.
7663 // longjmp() and throw() must not violate the entry/exit criteria.
7664 CS->getCapturedDecl()->setNothrow();
7665 }
7667 return CS;
7668}
7669
7672 Stmt *AStmt, SourceLocation StartLoc,
7673 SourceLocation EndLoc) {
7674 if (!AStmt)
7675 return StmtError();
7676
7677 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7678
7680 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7681 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7682}
7683
7684namespace {
7685/// Iteration space of a single for loop.
7686struct LoopIterationSpace final {
7687 /// True if the condition operator is the strict compare operator (<, > or
7688 /// !=).
7689 bool IsStrictCompare = false;
7690 /// Condition of the loop.
7691 Expr *PreCond = nullptr;
7692 /// This expression calculates the number of iterations in the loop.
7693 /// It is always possible to calculate it before starting the loop.
7694 Expr *NumIterations = nullptr;
7695 /// The loop counter variable.
7696 Expr *CounterVar = nullptr;
7697 /// Private loop counter variable.
7698 Expr *PrivateCounterVar = nullptr;
7699 /// This is initializer for the initial value of #CounterVar.
7700 Expr *CounterInit = nullptr;
7701 /// This is step for the #CounterVar used to generate its update:
7702 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7703 Expr *CounterStep = nullptr;
7704 /// Should step be subtracted?
7705 bool Subtract = false;
7706 /// Source range of the loop init.
7707 SourceRange InitSrcRange;
7708 /// Source range of the loop condition.
7709 SourceRange CondSrcRange;
7710 /// Source range of the loop increment.
7711 SourceRange IncSrcRange;
7712 /// Minimum value that can have the loop control variable. Used to support
7713 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7714 /// since only such variables can be used in non-loop invariant expressions.
7715 Expr *MinValue = nullptr;
7716 /// Maximum value that can have the loop control variable. Used to support
7717 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7718 /// since only such variables can be used in non-loop invariant expressions.
7719 Expr *MaxValue = nullptr;
7720 /// true, if the lower bound depends on the outer loop control var.
7721 bool IsNonRectangularLB = false;
7722 /// true, if the upper bound depends on the outer loop control var.
7723 bool IsNonRectangularUB = false;
7724 /// Index of the loop this loop depends on and forms non-rectangular loop
7725 /// nest.
7726 unsigned LoopDependentIdx = 0;
7727 /// Final condition for the non-rectangular loop nest support. It is used to
7728 /// check that the number of iterations for this particular counter must be
7729 /// finished.
7730 Expr *FinalCondition = nullptr;
7731};
7732
7733/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7734/// set are referenced. Used for verifying loop nest structure before
7735/// performing a loop collapse operation.
7736class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7737 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7738 VarDecl *ForbiddenVar = nullptr;
7739 SourceRange ErrLoc;
7740
7741public:
7742 explicit ForSubExprChecker(
7743 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7744 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7745 // We want to visit implicit code, i.e. synthetic initialisation statements
7746 // created during range-for lowering.
7747 ShouldVisitImplicitCode = true;
7748 }
7749
7750 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7751 ValueDecl *VD = E->getDecl();
7752 if (!isa<VarDecl, BindingDecl>(VD))
7753 return true;
7755 if (V->getType()->isReferenceType()) {
7756 VarDecl *VD = V->getDefinition();
7757 if (VD->hasInit()) {
7758 Expr *I = VD->getInit();
7759 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7760 if (!DRE)
7761 return true;
7763 }
7764 }
7765 Decl *Canon = V->getCanonicalDecl();
7766 if (CollapsedLoopVarDecls.contains(Canon)) {
7767 ForbiddenVar = V;
7768 ErrLoc = E->getSourceRange();
7769 return false;
7770 }
7771
7772 return true;
7773 }
7774
7775 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7776 SourceRange getErrRange() const { return ErrLoc; }
7777};
7778
7779/// Helper class for checking canonical form of the OpenMP loops and
7780/// extracting iteration space of each loop in the loop nest, that will be used
7781/// for IR generation.
7782class OpenMPIterationSpaceChecker {
7783 /// Reference to Sema.
7784 Sema &SemaRef;
7785 /// Does the loop associated directive support non-rectangular loops?
7786 bool SupportsNonRectangular;
7787 /// Data-sharing stack.
7788 DSAStackTy &Stack;
7789 /// A location for diagnostics (when there is no some better location).
7790 SourceLocation DefaultLoc;
7791 /// A location for diagnostics (when increment is not compatible).
7792 SourceLocation ConditionLoc;
7793 /// The set of variables declared within the (to be collapsed) loop nest.
7794 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7795 /// A source location for referring to loop init later.
7796 SourceRange InitSrcRange;
7797 /// A source location for referring to condition later.
7798 SourceRange ConditionSrcRange;
7799 /// A source location for referring to increment later.
7800 SourceRange IncrementSrcRange;
7801 /// Loop variable.
7802 ValueDecl *LCDecl = nullptr;
7803 /// Reference to loop variable.
7804 Expr *LCRef = nullptr;
7805 /// Lower bound (initializer for the var).
7806 Expr *LB = nullptr;
7807 /// Upper bound.
7808 Expr *UB = nullptr;
7809 /// Loop step (increment).
7810 Expr *Step = nullptr;
7811 /// This flag is true when condition is one of:
7812 /// Var < UB
7813 /// Var <= UB
7814 /// UB > Var
7815 /// UB >= Var
7816 /// This will have no value when the condition is !=
7817 std::optional<bool> TestIsLessOp;
7818 /// This flag is true when condition is strict ( < or > ).
7819 bool TestIsStrictOp = false;
7820 /// This flag is true when step is subtracted on each iteration.
7821 bool SubtractStep = false;
7822 /// The outer loop counter this loop depends on (if any).
7823 const ValueDecl *DepDecl = nullptr;
7824 /// Contains number of loop (starts from 1) on which loop counter init
7825 /// expression of this loop depends on.
7826 std::optional<unsigned> InitDependOnLC;
7827 /// Contains number of loop (starts from 1) on which loop counter condition
7828 /// expression of this loop depends on.
7829 std::optional<unsigned> CondDependOnLC;
7830 /// Checks if the provide statement depends on the loop counter.
7831 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7832 bool IsInitializer);
7833 /// Original condition required for checking of the exit condition for
7834 /// non-rectangular loop.
7835 Expr *Condition = nullptr;
7836
7837public:
7838 OpenMPIterationSpaceChecker(
7839 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
7840 SourceLocation DefaultLoc,
7841 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7842 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7843 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7844 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7845 /// Check init-expr for canonical loop form and save loop counter
7846 /// variable - #Var and its initialization value - #LB.
7847 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7848 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7849 /// for less/greater and for strict/non-strict comparison.
7850 bool checkAndSetCond(Expr *S);
7851 /// Check incr-expr for canonical loop form and return true if it
7852 /// does not conform, otherwise save loop step (#Step).
7853 bool checkAndSetInc(Expr *S);
7854 /// Return the loop counter variable.
7855 ValueDecl *getLoopDecl() const { return LCDecl; }
7856 /// Return the reference expression to loop counter variable.
7857 Expr *getLoopDeclRefExpr() const { return LCRef; }
7858 /// Source range of the loop init.
7859 SourceRange getInitSrcRange() const { return InitSrcRange; }
7860 /// Source range of the loop condition.
7861 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7862 /// Source range of the loop increment.
7863 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7864 /// True if the step should be subtracted.
7865 bool shouldSubtractStep() const { return SubtractStep; }
7866 /// True, if the compare operator is strict (<, > or !=).
7867 bool isStrictTestOp() const { return TestIsStrictOp; }
7868 /// Build the expression to calculate the number of iterations.
7869 Expr *buildNumIterations(
7870 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7871 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7872 /// Build the precondition expression for the loops.
7873 Expr *
7874 buildPreCond(Scope *S, Expr *Cond,
7875 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7876 /// Build reference expression to the counter be used for codegen.
7877 DeclRefExpr *
7878 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7879 DSAStackTy &DSA) const;
7880 /// Build reference expression to the private counter be used for
7881 /// codegen.
7882 Expr *buildPrivateCounterVar() const;
7883 /// Build initialization of the counter be used for codegen.
7884 Expr *buildCounterInit() const;
7885 /// Build step of the counter be used for codegen.
7886 Expr *buildCounterStep() const;
7887 /// Build loop data with counter value for depend clauses in ordered
7888 /// directives.
7889 Expr *
7890 buildOrderedLoopData(Scope *S, Expr *Counter,
7891 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7892 SourceLocation Loc, Expr *Inc = nullptr,
7893 OverloadedOperatorKind OOK = OO_Amp);
7894 /// Builds the minimum value for the loop counter.
7895 std::pair<Expr *, Expr *> buildMinMaxValues(
7896 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7897 /// Builds final condition for the non-rectangular loops.
7898 Expr *buildFinalCondition(Scope *S) const;
7899 /// Return true if any expression is dependent.
7900 bool dependent() const;
7901 /// Returns true if the initializer forms non-rectangular loop.
7902 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7903 /// Returns true if the condition forms non-rectangular loop.
7904 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7905 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7906 unsigned getLoopDependentIdx() const {
7907 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7908 }
7909
7910private:
7911 /// Check the right-hand side of an assignment in the increment
7912 /// expression.
7913 bool checkAndSetIncRHS(Expr *RHS);
7914 /// Helper to set loop counter variable and its initializer.
7915 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7916 bool EmitDiags);
7917 /// Helper to set upper bound.
7918 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7920 /// Helper to set loop increment.
7921 bool setStep(Expr *NewStep, bool Subtract);
7922};
7923
7924bool OpenMPIterationSpaceChecker::dependent() const {
7925 if (!LCDecl) {
7926 assert(!LB && !UB && !Step);
7927 return false;
7928 }
7929 return LCDecl->getType()->isDependentType() ||
7930 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7931 (Step && Step->isValueDependent());
7932}
7933
7934bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7935 Expr *NewLCRefExpr,
7936 Expr *NewLB, bool EmitDiags) {
7937 // State consistency checking to ensure correct usage.
7938 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7939 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7940 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7941 return true;
7942 LCDecl = getCanonicalDecl(NewLCDecl);
7943 LCRef = NewLCRefExpr;
7944 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7945 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7946 if ((Ctor->isCopyOrMoveConstructor() ||
7947 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7948 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7949 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7950 LB = NewLB;
7951 if (EmitDiags)
7952 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7953 return false;
7954}
7955
7956bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7957 bool StrictOp, SourceRange SR,
7958 SourceLocation SL) {
7959 // State consistency checking to ensure correct usage.
7960 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7961 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7962 if (!NewUB || NewUB->containsErrors())
7963 return true;
7964 UB = NewUB;
7965 if (LessOp)
7966 TestIsLessOp = LessOp;
7967 TestIsStrictOp = StrictOp;
7968 ConditionSrcRange = SR;
7969 ConditionLoc = SL;
7970 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7971 return false;
7972}
7973
7974bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7975 // State consistency checking to ensure correct usage.
7976 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7977 if (!NewStep || NewStep->containsErrors())
7978 return true;
7979 if (!NewStep->isValueDependent()) {
7980 // Check that the step is integer expression.
7981 SourceLocation StepLoc = NewStep->getBeginLoc();
7983 StepLoc, getExprAsWritten(NewStep));
7984 if (Val.isInvalid())
7985 return true;
7986 NewStep = Val.get();
7987
7988 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7989 // If test-expr is of form var relational-op b and relational-op is < or
7990 // <= then incr-expr must cause var to increase on each iteration of the
7991 // loop. If test-expr is of form var relational-op b and relational-op is
7992 // > or >= then incr-expr must cause var to decrease on each iteration of
7993 // the loop.
7994 // If test-expr is of form b relational-op var and relational-op is < or
7995 // <= then incr-expr must cause var to decrease on each iteration of the
7996 // loop. If test-expr is of form b relational-op var and relational-op is
7997 // > or >= then incr-expr must cause var to increase on each iteration of
7998 // the loop.
7999 std::optional<llvm::APSInt> Result =
8000 NewStep->getIntegerConstantExpr(SemaRef.Context);
8001 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8002 bool IsConstNeg =
8003 Result && Result->isSigned() && (Subtract != Result->isNegative());
8004 bool IsConstPos =
8005 Result && Result->isSigned() && (Subtract == Result->isNegative());
8006 bool IsConstZero = Result && !Result->getBoolValue();
8007
8008 // != with increment is treated as <; != with decrement is treated as >
8009 if (!TestIsLessOp)
8010 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8011 if (UB && (IsConstZero ||
8012 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8013 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8014 SemaRef.Diag(NewStep->getExprLoc(),
8015 diag::err_omp_loop_incr_not_compatible)
8016 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8017 SemaRef.Diag(ConditionLoc,
8018 diag::note_omp_loop_cond_requires_compatible_incr)
8019 << *TestIsLessOp << ConditionSrcRange;
8020 return true;
8021 }
8022 if (*TestIsLessOp == Subtract) {
8023 NewStep =
8024 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8025 .get();
8026 Subtract = !Subtract;
8027 }
8028 }
8029
8030 Step = NewStep;
8031 SubtractStep = Subtract;
8032 return false;
8033}
8034
8035namespace {
8036/// Checker for the non-rectangular loops. Checks if the initializer or
8037/// condition expression references loop counter variable.
8038class LoopCounterRefChecker final
8039 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8040 Sema &SemaRef;
8041 DSAStackTy &Stack;
8042 const ValueDecl *CurLCDecl = nullptr;
8043 const ValueDecl *DepDecl = nullptr;
8044 const ValueDecl *PrevDepDecl = nullptr;
8045 bool IsInitializer = true;
8046 bool SupportsNonRectangular;
8047 unsigned BaseLoopId = 0;
8048 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8049 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8050 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8051 << (IsInitializer ? 0 : 1);
8052 return false;
8053 }
8054 const auto &&Data = Stack.isLoopControlVariable(VD);
8055 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8056 // The type of the loop iterator on which we depend may not have a random
8057 // access iterator type.
8058 if (Data.first && VD->getType()->isRecordType()) {
8059 SmallString<128> Name;
8060 llvm::raw_svector_ostream OS(Name);
8061 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8062 /*Qualified=*/true);
8063 SemaRef.Diag(E->getExprLoc(),
8064 diag::err_omp_wrong_dependency_iterator_type)
8065 << OS.str();
8066 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8067 return false;
8068 }
8069 if (Data.first && !SupportsNonRectangular) {
8070 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8071 return false;
8072 }
8073 if (Data.first &&
8074 (DepDecl || (PrevDepDecl &&
8075 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8076 if (!DepDecl && PrevDepDecl)
8077 DepDecl = PrevDepDecl;
8078 SmallString<128> Name;
8079 llvm::raw_svector_ostream OS(Name);
8080 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8081 /*Qualified=*/true);
8082 SemaRef.Diag(E->getExprLoc(),
8083 diag::err_omp_invariant_or_linear_dependency)
8084 << OS.str();
8085 return false;
8086 }
8087 if (Data.first) {
8088 DepDecl = VD;
8089 BaseLoopId = Data.first;
8090 }
8091 return Data.first;
8092 }
8093
8094public:
8095 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8096 const ValueDecl *VD = E->getDecl();
8097 if (isa<VarDecl>(VD))
8098 return checkDecl(E, VD);
8099 return false;
8100 }
8101 bool VisitMemberExpr(const MemberExpr *E) {
8102 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8103 const ValueDecl *VD = E->getMemberDecl();
8104 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8105 return checkDecl(E, VD);
8106 }
8107 return false;
8108 }
8109 bool VisitStmt(const Stmt *S) {
8110 bool Res = false;
8111 for (const Stmt *Child : S->children())
8112 Res = (Child && Visit(Child)) || Res;
8113 return Res;
8114 }
8115 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8116 const ValueDecl *CurLCDecl, bool IsInitializer,
8117 const ValueDecl *PrevDepDecl = nullptr,
8118 bool SupportsNonRectangular = true)
8119 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8120 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8121 SupportsNonRectangular(SupportsNonRectangular) {}
8122 unsigned getBaseLoopId() const {
8123 assert(CurLCDecl && "Expected loop dependency.");
8124 return BaseLoopId;
8125 }
8126 const ValueDecl *getDepDecl() const {
8127 assert(CurLCDecl && "Expected loop dependency.");
8128 return DepDecl;
8129 }
8130};
8131} // namespace
8132
8133std::optional<unsigned>
8134OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8135 bool IsInitializer) {
8136 // Check for the non-rectangular loops.
8137 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8138 DepDecl, SupportsNonRectangular);
8139 if (LoopStmtChecker.Visit(S)) {
8140 DepDecl = LoopStmtChecker.getDepDecl();
8141 return LoopStmtChecker.getBaseLoopId();
8142 }
8143 return std::nullopt;
8144}
8145
8146bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8147 // Check init-expr for canonical loop form and save loop counter
8148 // variable - #Var and its initialization value - #LB.
8149 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8150 // var = lb
8151 // integer-type var = lb
8152 // random-access-iterator-type var = lb
8153 // pointer-type var = lb
8154 //
8155 if (!S) {
8156 if (EmitDiags) {
8157 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8158 }
8159 return true;
8160 }
8161 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8162 if (!ExprTemp->cleanupsHaveSideEffects())
8163 S = ExprTemp->getSubExpr();
8164
8165 if (!CollapsedLoopVarDecls.empty()) {
8166 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8167 if (!FSEC.TraverseStmt(S)) {
8168 SourceRange Range = FSEC.getErrRange();
8169 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8170 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8171 return true;
8172 }
8173 }
8174
8175 InitSrcRange = S->getSourceRange();
8176 if (Expr *E = dyn_cast<Expr>(S))
8177 S = E->IgnoreParens();
8178 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8179 if (BO->getOpcode() == BO_Assign) {
8180 Expr *LHS = BO->getLHS()->IgnoreParens();
8181 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8182 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8183 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8184 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8185 EmitDiags);
8186 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8187 }
8188 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8189 if (ME->isArrow() &&
8190 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8191 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8192 EmitDiags);
8193 }
8194 }
8195 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8196 if (DS->isSingleDecl()) {
8197 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8198 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8199 // Accept non-canonical init form here but emit ext. warning.
8200 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8201 SemaRef.Diag(S->getBeginLoc(),
8202 diag::ext_omp_loop_not_canonical_init)
8203 << S->getSourceRange();
8204 return setLCDeclAndLB(
8205 Var,
8206 buildDeclRefExpr(SemaRef, Var,
8207 Var->getType().getNonReferenceType(),
8208 DS->getBeginLoc()),
8209 Var->getInit(), EmitDiags);
8210 }
8211 }
8212 }
8213 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8214 if (CE->getOperator() == OO_Equal) {
8215 Expr *LHS = CE->getArg(0);
8216 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8217 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8218 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8219 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8220 EmitDiags);
8221 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8222 }
8223 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8224 if (ME->isArrow() &&
8225 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8226 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8227 EmitDiags);
8228 }
8229 }
8230 }
8231
8232 if (dependent() || SemaRef.CurContext->isDependentContext())
8233 return false;
8234 if (EmitDiags) {
8235 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8236 << S->getSourceRange();
8237 }
8238 return true;
8239}
8240
8241/// Ignore parenthesizes, implicit casts, copy constructor and return the
8242/// variable (which may be the loop variable) if possible.
8243static const ValueDecl *getInitLCDecl(const Expr *E) {
8244 if (!E)
8245 return nullptr;
8246 E = getExprAsWritten(E);
8247 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8248 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8249 if ((Ctor->isCopyOrMoveConstructor() ||
8250 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8251 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8252 E = CE->getArg(0)->IgnoreParenImpCasts();
8253 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8254 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8255 return getCanonicalDecl(VD);
8256 }
8257 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8258 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8259 return getCanonicalDecl(ME->getMemberDecl());
8260 return nullptr;
8261}
8262
8263bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8264 // Check test-expr for canonical form, save upper-bound UB, flags for
8265 // less/greater and for strict/non-strict comparison.
8266 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8267 // var relational-op b
8268 // b relational-op var
8269 //
8270 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8271 if (!S) {
8272 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8273 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8274 return true;
8275 }
8276 Condition = S;
8277 S = getExprAsWritten(S);
8278
8279 if (!CollapsedLoopVarDecls.empty()) {
8280 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8281 if (!FSEC.TraverseStmt(S)) {
8282 SourceRange Range = FSEC.getErrRange();
8283 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8284 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8285 return true;
8286 }
8287 }
8288
8289 SourceLocation CondLoc = S->getBeginLoc();
8290 auto &&CheckAndSetCond =
8291 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8292 const Expr *RHS, SourceRange SR,
8293 SourceLocation OpLoc) -> std::optional<bool> {
8294 if (BinaryOperator::isRelationalOp(Opcode)) {
8295 if (getInitLCDecl(LHS) == LCDecl)
8296 return setUB(const_cast<Expr *>(RHS),
8297 (Opcode == BO_LT || Opcode == BO_LE),
8298 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8299 if (getInitLCDecl(RHS) == LCDecl)
8300 return setUB(const_cast<Expr *>(LHS),
8301 (Opcode == BO_GT || Opcode == BO_GE),
8302 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8303 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8304 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8305 /*LessOp=*/std::nullopt,
8306 /*StrictOp=*/true, SR, OpLoc);
8307 }
8308 return std::nullopt;
8309 };
8310 std::optional<bool> Res;
8311 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8312 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8313 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8314 RBO->getOperatorLoc());
8315 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8316 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8317 BO->getSourceRange(), BO->getOperatorLoc());
8318 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8319 if (CE->getNumArgs() == 2) {
8320 Res = CheckAndSetCond(
8321 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8322 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8323 }
8324 }
8325 if (Res)
8326 return *Res;
8327 if (dependent() || SemaRef.CurContext->isDependentContext())
8328 return false;
8329 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8330 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8331 return true;
8332}
8333
8334bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8335 // RHS of canonical loop form increment can be:
8336 // var + incr
8337 // incr + var
8338 // var - incr
8339 //
8340 RHS = RHS->IgnoreParenImpCasts();
8341 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8342 if (BO->isAdditiveOp()) {
8343 bool IsAdd = BO->getOpcode() == BO_Add;
8344 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8345 return setStep(BO->getRHS(), !IsAdd);
8346 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8347 return setStep(BO->getLHS(), /*Subtract=*/false);
8348 }
8349 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8350 bool IsAdd = CE->getOperator() == OO_Plus;
8351 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8352 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8353 return setStep(CE->getArg(1), !IsAdd);
8354 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8355 return setStep(CE->getArg(0), /*Subtract=*/false);
8356 }
8357 }
8358 if (dependent() || SemaRef.CurContext->isDependentContext())
8359 return false;
8360 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8361 << RHS->getSourceRange() << LCDecl;
8362 return true;
8363}
8364
8365bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8366 // Check incr-expr for canonical loop form and return true if it
8367 // does not conform.
8368 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8369 // ++var
8370 // var++
8371 // --var
8372 // var--
8373 // var += incr
8374 // var -= incr
8375 // var = var + incr
8376 // var = incr + var
8377 // var = var - incr
8378 //
8379 if (!S) {
8380 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8381 return true;
8382 }
8383 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8384 if (!ExprTemp->cleanupsHaveSideEffects())
8385 S = ExprTemp->getSubExpr();
8386
8387 if (!CollapsedLoopVarDecls.empty()) {
8388 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8389 if (!FSEC.TraverseStmt(S)) {
8390 SourceRange Range = FSEC.getErrRange();
8391 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8392 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8393 return true;
8394 }
8395 }
8396
8397 IncrementSrcRange = S->getSourceRange();
8398 S = S->IgnoreParens();
8399 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8400 if (UO->isIncrementDecrementOp() &&
8401 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8402 return setStep(SemaRef
8403 .ActOnIntegerConstant(UO->getBeginLoc(),
8404 (UO->isDecrementOp() ? -1 : 1))
8405 .get(),
8406 /*Subtract=*/false);
8407 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8408 switch (BO->getOpcode()) {
8409 case BO_AddAssign:
8410 case BO_SubAssign:
8411 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8412 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8413 break;
8414 case BO_Assign:
8415 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8416 return checkAndSetIncRHS(BO->getRHS());
8417 break;
8418 default:
8419 break;
8420 }
8421 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8422 switch (CE->getOperator()) {
8423 case OO_PlusPlus:
8424 case OO_MinusMinus:
8425 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8426 return setStep(SemaRef
8427 .ActOnIntegerConstant(
8428 CE->getBeginLoc(),
8429 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8430 .get(),
8431 /*Subtract=*/false);
8432 break;
8433 case OO_PlusEqual:
8434 case OO_MinusEqual:
8435 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8436 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8437 break;
8438 case OO_Equal:
8439 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8440 return checkAndSetIncRHS(CE->getArg(1));
8441 break;
8442 default:
8443 break;
8444 }
8445 }
8446 if (dependent() || SemaRef.CurContext->isDependentContext())
8447 return false;
8448 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8449 << S->getSourceRange() << LCDecl;
8450 return true;
8451}
8452
8453static ExprResult
8454tryBuildCapture(Sema &SemaRef, Expr *Capture,
8455 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8456 StringRef Name = ".capture_expr.") {
8457 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8458 return Capture;
8459 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8460 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8461 Capture->getType(),
8463 /*AllowExplicit=*/true);
8464 auto I = Captures.find(Capture);
8465 if (I != Captures.end())
8466 return buildCapture(SemaRef, Capture, I->second, Name);
8467 DeclRefExpr *Ref = nullptr;
8468 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8469 Captures[Capture] = Ref;
8470 return Res;
8471}
8472
8473/// Calculate number of iterations, transforming to unsigned, if number of
8474/// iterations may be larger than the original type.
8475static Expr *
8476calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8477 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8478 bool TestIsStrictOp, bool RoundToStep,
8479 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8480 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8481 if (!NewStep.isUsable())
8482 return nullptr;
8483 llvm::APSInt LRes, SRes;
8484 bool IsLowerConst = false, IsStepConst = false;
8485 if (std::optional<llvm::APSInt> Res =
8486 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8487 LRes = *Res;
8488 IsLowerConst = true;
8489 }
8490 if (std::optional<llvm::APSInt> Res =
8491 Step->getIntegerConstantExpr(SemaRef.Context)) {
8492 SRes = *Res;
8493 IsStepConst = true;
8494 }
8495 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8496 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8497 (TestIsStrictOp && LRes.isStrictlyPositive()));
8498 bool NeedToReorganize = false;
8499 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8500 if (!NoNeedToConvert && IsLowerConst &&
8501 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8502 NoNeedToConvert = true;
8503 if (RoundToStep) {
8504 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8505 ? LRes.getBitWidth()
8506 : SRes.getBitWidth();
8507 LRes = LRes.extend(BW + 1);
8508 LRes.setIsSigned(true);
8509 SRes = SRes.extend(BW + 1);
8510 SRes.setIsSigned(true);
8511 LRes -= SRes;
8512 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8513 LRes = LRes.trunc(BW);
8514 }
8515 if (TestIsStrictOp) {
8516 unsigned BW = LRes.getBitWidth();
8517 LRes = LRes.extend(BW + 1);
8518 LRes.setIsSigned(true);
8519 ++LRes;
8520 NoNeedToConvert =
8521 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8522 // truncate to the original bitwidth.
8523 LRes = LRes.trunc(BW);
8524 }
8525 NeedToReorganize = NoNeedToConvert;
8526 }
8527 llvm::APSInt URes;
8528 bool IsUpperConst = false;
8529 if (std::optional<llvm::APSInt> Res =
8530 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8531 URes = *Res;
8532 IsUpperConst = true;
8533 }
8534 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8535 (!RoundToStep || IsStepConst)) {
8536 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8537 : URes.getBitWidth();
8538 LRes = LRes.extend(BW + 1);
8539 LRes.setIsSigned(true);
8540 URes = URes.extend(BW + 1);
8541 URes.setIsSigned(true);
8542 URes -= LRes;
8543 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8544 NeedToReorganize = NoNeedToConvert;
8545 }
8546 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8547 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8548 // unsigned.
8549 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8550 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8551 QualType LowerTy = Lower->getType();
8552 QualType UpperTy = Upper->getType();
8553 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8554 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8555 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8556 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8558 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8559 Upper =
8560 SemaRef
8562 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8564 .get();
8565 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8566 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8567 }
8568 }
8569 if (!Lower || !Upper || NewStep.isInvalid())
8570 return nullptr;
8571
8572 ExprResult Diff;
8573 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8574 // 1]).
8575 if (NeedToReorganize) {
8576 Diff = Lower;
8577
8578 if (RoundToStep) {
8579 // Lower - Step
8580 Diff =
8581 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8582 if (!Diff.isUsable())
8583 return nullptr;
8584 }
8585
8586 // Lower - Step [+ 1]
8587 if (TestIsStrictOp)
8588 Diff = SemaRef.BuildBinOp(
8589 S, DefaultLoc, BO_Add, Diff.get(),
8590 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8591 if (!Diff.isUsable())
8592 return nullptr;
8593
8594 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8595 if (!Diff.isUsable())
8596 return nullptr;
8597
8598 // Upper - (Lower - Step [+ 1]).
8599 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8600 if (!Diff.isUsable())
8601 return nullptr;
8602 } else {
8603 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8604
8605 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8606 // BuildBinOp already emitted error, this one is to point user to upper
8607 // and lower bound, and to tell what is passed to 'operator-'.
8608 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8609 << Upper->getSourceRange() << Lower->getSourceRange();
8610 return nullptr;
8611 }
8612
8613 if (!Diff.isUsable())
8614 return nullptr;
8615
8616 // Upper - Lower [- 1]
8617 if (TestIsStrictOp)
8618 Diff = SemaRef.BuildBinOp(
8619 S, DefaultLoc, BO_Sub, Diff.get(),
8620 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8621 if (!Diff.isUsable())
8622 return nullptr;
8623
8624 if (RoundToStep) {
8625 // Upper - Lower [- 1] + Step
8626 Diff =
8627 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8628 if (!Diff.isUsable())
8629 return nullptr;
8630 }
8631 }
8632
8633 // Parentheses (for dumping/debugging purposes only).
8634 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8635 if (!Diff.isUsable())
8636 return nullptr;
8637
8638 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8639 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8640 if (!Diff.isUsable())
8641 return nullptr;
8642
8643 return Diff.get();
8644}
8645
8646/// Build the expression to calculate the number of iterations.
8647Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8648 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8649 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8650 QualType VarType = LCDecl->getType().getNonReferenceType();
8651 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8652 !SemaRef.getLangOpts().CPlusPlus)
8653 return nullptr;
8654 Expr *LBVal = LB;
8655 Expr *UBVal = UB;
8656 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8657 // max(LB(MinVal), LB(MaxVal)))
8658 if (InitDependOnLC) {
8659 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8660 if (!IS.MinValue || !IS.MaxValue)
8661 return nullptr;
8662 // OuterVar = Min
8663 ExprResult MinValue =
8664 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8665 if (!MinValue.isUsable())
8666 return nullptr;
8667
8668 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8669 IS.CounterVar, MinValue.get());
8670 if (!LBMinVal.isUsable())
8671 return nullptr;
8672 // OuterVar = Min, LBVal
8673 LBMinVal =
8674 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8675 if (!LBMinVal.isUsable())
8676 return nullptr;
8677 // (OuterVar = Min, LBVal)
8678 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8679 if (!LBMinVal.isUsable())
8680 return nullptr;
8681
8682 // OuterVar = Max
8683 ExprResult MaxValue =
8684 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8685 if (!MaxValue.isUsable())
8686 return nullptr;
8687
8688 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8689 IS.CounterVar, MaxValue.get());
8690 if (!LBMaxVal.isUsable())
8691 return nullptr;
8692 // OuterVar = Max, LBVal
8693 LBMaxVal =
8694 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8695 if (!LBMaxVal.isUsable())
8696 return nullptr;
8697 // (OuterVar = Max, LBVal)
8698 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8699 if (!LBMaxVal.isUsable())
8700 return nullptr;
8701
8702 Expr *LBMin =
8703 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8704 Expr *LBMax =
8705 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8706 if (!LBMin || !LBMax)
8707 return nullptr;
8708 // LB(MinVal) < LB(MaxVal)
8709 ExprResult MinLessMaxRes =
8710 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8711 if (!MinLessMaxRes.isUsable())
8712 return nullptr;
8713 Expr *MinLessMax =
8714 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8715 .get();
8716 if (!MinLessMax)
8717 return nullptr;
8718 if (*TestIsLessOp) {
8719 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8720 // LB(MaxVal))
8721 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8722 MinLessMax, LBMin, LBMax);
8723 if (!MinLB.isUsable())
8724 return nullptr;
8725 LBVal = MinLB.get();
8726 } else {
8727 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8728 // LB(MaxVal))
8729 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8730 MinLessMax, LBMax, LBMin);
8731 if (!MaxLB.isUsable())
8732 return nullptr;
8733 LBVal = MaxLB.get();
8734 }
8735 // OuterVar = LB
8736 LBMinVal =
8737 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8738 if (!LBMinVal.isUsable())
8739 return nullptr;
8740 LBVal = LBMinVal.get();
8741 }
8742 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8743 // min(UB(MinVal), UB(MaxVal))
8744 if (CondDependOnLC) {
8745 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8746 if (!IS.MinValue || !IS.MaxValue)
8747 return nullptr;
8748 // OuterVar = Min
8749 ExprResult MinValue =
8750 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8751 if (!MinValue.isUsable())
8752 return nullptr;
8753
8754 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8755 IS.CounterVar, MinValue.get());
8756 if (!UBMinVal.isUsable())
8757 return nullptr;
8758 // OuterVar = Min, UBVal
8759 UBMinVal =
8760 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8761 if (!UBMinVal.isUsable())
8762 return nullptr;
8763 // (OuterVar = Min, UBVal)
8764 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8765 if (!UBMinVal.isUsable())
8766 return nullptr;
8767
8768 // OuterVar = Max
8769 ExprResult MaxValue =
8770 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8771 if (!MaxValue.isUsable())
8772 return nullptr;
8773
8774 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8775 IS.CounterVar, MaxValue.get());
8776 if (!UBMaxVal.isUsable())
8777 return nullptr;
8778 // OuterVar = Max, UBVal
8779 UBMaxVal =
8780 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8781 if (!UBMaxVal.isUsable())
8782 return nullptr;
8783 // (OuterVar = Max, UBVal)
8784 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8785 if (!UBMaxVal.isUsable())
8786 return nullptr;
8787
8788 Expr *UBMin =
8789 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8790 Expr *UBMax =
8791 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8792 if (!UBMin || !UBMax)
8793 return nullptr;
8794 // UB(MinVal) > UB(MaxVal)
8795 ExprResult MinGreaterMaxRes =
8796 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8797 if (!MinGreaterMaxRes.isUsable())
8798 return nullptr;
8799 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8800 Captures, ".min_greater_max")
8801 .get();
8802 if (!MinGreaterMax)
8803 return nullptr;
8804 if (*TestIsLessOp) {
8805 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8806 // UB(MaxVal))
8807 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8808 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8809 if (!MaxUB.isUsable())
8810 return nullptr;
8811 UBVal = MaxUB.get();
8812 } else {
8813 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8814 // UB(MaxVal))
8815 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8816 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8817 if (!MinUB.isUsable())
8818 return nullptr;
8819 UBVal = MinUB.get();
8820 }
8821 }
8822 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8823 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8824 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8825 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8826 if (!Upper || !Lower)
8827 return nullptr;
8828
8829 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8830 Step, VarType, TestIsStrictOp,
8831 /*RoundToStep=*/true, Captures);
8832 if (!Diff.isUsable())
8833 return nullptr;
8834
8835 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8836 QualType Type = Diff.get()->getType();
8837 ASTContext &C = SemaRef.Context;
8838 bool UseVarType = VarType->hasIntegerRepresentation() &&
8839 C.getTypeSize(Type) > C.getTypeSize(VarType);
8840 if (!Type->isIntegerType() || UseVarType) {
8841 unsigned NewSize =
8842 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8843 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8845 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8846 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8847 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
8849 /*AllowExplicit=*/true);
8850 if (!Diff.isUsable())
8851 return nullptr;
8852 }
8853 }
8854 if (LimitedType) {
8855 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8856 if (NewSize != C.getTypeSize(Type)) {
8857 if (NewSize < C.getTypeSize(Type)) {
8858 assert(NewSize == 64 && "incorrect loop var size");
8859 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8860 << InitSrcRange << ConditionSrcRange;
8861 }
8862 QualType NewType = C.getIntTypeForBitwidth(
8864 C.getTypeSize(Type) < NewSize);
8865 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8866 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8868 /*AllowExplicit=*/true);
8869 if (!Diff.isUsable())
8870 return nullptr;
8871 }
8872 }
8873 }
8874
8875 return Diff.get();
8876}
8877
8878std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8879 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8880 // Do not build for iterators, they cannot be used in non-rectangular loop
8881 // nests.
8882 if (LCDecl->getType()->isRecordType())
8883 return std::make_pair(nullptr, nullptr);
8884 // If we subtract, the min is in the condition, otherwise the min is in the
8885 // init value.
8886 Expr *MinExpr = nullptr;
8887 Expr *MaxExpr = nullptr;
8888 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8889 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8890 bool LBNonRect =
8891 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8892 bool UBNonRect =
8893 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8894 Expr *Lower =
8895 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8896 Expr *Upper =
8897 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8898 if (!Upper || !Lower)
8899 return std::make_pair(nullptr, nullptr);
8900
8901 if (*TestIsLessOp)
8902 MinExpr = Lower;
8903 else
8904 MaxExpr = Upper;
8905
8906 // Build minimum/maximum value based on number of iterations.
8907 QualType VarType = LCDecl->getType().getNonReferenceType();
8908
8909 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8910 Step, VarType, TestIsStrictOp,
8911 /*RoundToStep=*/false, Captures);
8912 if (!Diff.isUsable())
8913 return std::make_pair(nullptr, nullptr);
8914
8915 // ((Upper - Lower [- 1]) / Step) * Step
8916 // Parentheses (for dumping/debugging purposes only).
8917 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8918 if (!Diff.isUsable())
8919 return std::make_pair(nullptr, nullptr);
8920
8921 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8922 if (!NewStep.isUsable())
8923 return std::make_pair(nullptr, nullptr);
8924 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8925 if (!Diff.isUsable())
8926 return std::make_pair(nullptr, nullptr);
8927
8928 // Parentheses (for dumping/debugging purposes only).
8929 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8930 if (!Diff.isUsable())
8931 return std::make_pair(nullptr, nullptr);
8932
8933 // Convert to the ptrdiff_t, if original type is pointer.
8934 if (VarType->isAnyPointerType() &&
8935 !SemaRef.Context.hasSameType(
8936 Diff.get()->getType(),
8938 Diff = SemaRef.PerformImplicitConversion(
8939 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8940 AssignmentAction::Converting, /*AllowExplicit=*/true);
8941 }
8942 if (!Diff.isUsable())
8943 return std::make_pair(nullptr, nullptr);
8944
8945 if (*TestIsLessOp) {
8946 // MinExpr = Lower;
8947 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8948 Diff = SemaRef.BuildBinOp(
8949 S, DefaultLoc, BO_Add,
8950 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8951 Diff.get());
8952 if (!Diff.isUsable())
8953 return std::make_pair(nullptr, nullptr);
8954 } else {
8955 // MaxExpr = Upper;
8956 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8957 Diff = SemaRef.BuildBinOp(
8958 S, DefaultLoc, BO_Sub,
8959 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8960 Diff.get());
8961 if (!Diff.isUsable())
8962 return std::make_pair(nullptr, nullptr);
8963 }
8964
8965 // Convert to the original type.
8966 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8967 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8969 /*AllowExplicit=*/true);
8970 if (!Diff.isUsable())
8971 return std::make_pair(nullptr, nullptr);
8972
8973 Sema::TentativeAnalysisScope Trap(SemaRef);
8974 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8975 if (!Diff.isUsable())
8976 return std::make_pair(nullptr, nullptr);
8977
8978 if (*TestIsLessOp)
8979 MaxExpr = Diff.get();
8980 else
8981 MinExpr = Diff.get();
8982
8983 return std::make_pair(MinExpr, MaxExpr);
8984}
8985
8986Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8987 if (InitDependOnLC || CondDependOnLC)
8988 return Condition;
8989 return nullptr;
8990}
8991
8992Expr *OpenMPIterationSpaceChecker::buildPreCond(
8993 Scope *S, Expr *Cond,
8994 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8995 // Do not build a precondition when the condition/initialization is dependent
8996 // to prevent pessimistic early loop exit.
8997 // TODO: this can be improved by calculating min/max values but not sure that
8998 // it will be very effective.
8999 if (CondDependOnLC || InitDependOnLC)
9000 return SemaRef
9002 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9003 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9004 /*AllowExplicit=*/true)
9005 .get();
9006
9007 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9008 Sema::TentativeAnalysisScope Trap(SemaRef);
9009
9010 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9011 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9012 if (!NewLB.isUsable() || !NewUB.isUsable())
9013 return nullptr;
9014
9015 ExprResult CondExpr =
9016 SemaRef.BuildBinOp(S, DefaultLoc,
9017 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9018 : (TestIsStrictOp ? BO_GT : BO_GE),
9019 NewLB.get(), NewUB.get());
9020 if (CondExpr.isUsable()) {
9021 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9022 SemaRef.Context.BoolTy))
9023 CondExpr = SemaRef.PerformImplicitConversion(
9024 CondExpr.get(), SemaRef.Context.BoolTy,
9025 /*Action=*/AssignmentAction::Casting,
9026 /*AllowExplicit=*/true);
9027 }
9028
9029 // Otherwise use original loop condition and evaluate it in runtime.
9030 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9031}
9032
9033/// Build reference expression to the counter be used for codegen.
9034DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9035 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9036 DSAStackTy &DSA) const {
9037 auto *VD = dyn_cast<VarDecl>(LCDecl);
9038 if (!VD) {
9039 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9041 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9042 const DSAStackTy::DSAVarData Data =
9043 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9044 // If the loop control decl is explicitly marked as private, do not mark it
9045 // as captured again.
9046 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9047 Captures.insert(std::make_pair(LCRef, Ref));
9048 return Ref;
9049 }
9050 return cast<DeclRefExpr>(LCRef);
9051}
9052
9053Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9054 if (LCDecl && !LCDecl->isInvalidDecl()) {
9056 VarDecl *PrivateVar = buildVarDecl(
9057 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9058 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9059 isa<VarDecl>(LCDecl)
9060 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9061 : nullptr);
9062 if (PrivateVar->isInvalidDecl())
9063 return nullptr;
9064 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9065 }
9066 return nullptr;
9067}
9068
9069/// Build initialization of the counter to be used for codegen.
9070Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9071
9072/// Build step of the counter be used for codegen.
9073Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9074
9075Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9076 Scope *S, Expr *Counter,
9077 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9078 Expr *Inc, OverloadedOperatorKind OOK) {
9079 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9080 if (!Cnt)
9081 return nullptr;
9082 if (Inc) {
9083 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9084 "Expected only + or - operations for depend clauses.");
9085 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9086 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9087 if (!Cnt)
9088 return nullptr;
9089 }
9090 QualType VarType = LCDecl->getType().getNonReferenceType();
9091 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9092 !SemaRef.getLangOpts().CPlusPlus)
9093 return nullptr;
9094 // Upper - Lower
9095 Expr *Upper =
9096 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9097 Expr *Lower =
9098 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9099 if (!Upper || !Lower)
9100 return nullptr;
9101
9102 ExprResult Diff = calculateNumIters(
9103 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9104 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9105 if (!Diff.isUsable())
9106 return nullptr;
9107
9108 return Diff.get();
9109}
9110} // namespace
9111
9113 Stmt *Init) {
9114 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9115 assert(Init && "Expected loop in canonical form.");
9116 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9117 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9118 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9119 return;
9120
9121 DSAStack->loopStart();
9123 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9124 *DSAStack, ForLoc, EmptyDeclSet);
9125 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9126 if (ValueDecl *D = ISC.getLoopDecl()) {
9127 auto *VD = dyn_cast<VarDecl>(D);
9128 DeclRefExpr *PrivateRef = nullptr;
9129 if (!VD) {
9131 VD = Private;
9132 } else {
9133 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9134 /*WithInit=*/false);
9135 VD = cast<VarDecl>(PrivateRef->getDecl());
9136 }
9137 }
9138 DSAStack->addLoopControlVariable(D, VD);
9139 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9140 if (LD != D->getCanonicalDecl()) {
9141 DSAStack->resetPossibleLoopCounter();
9142 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9144 SemaRef, const_cast<VarDecl *>(Var),
9145 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9146 /*RefersToCapture=*/true));
9147 }
9148 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9149 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9150 // associated for-loop of a simd construct with just one associated
9151 // for-loop may be listed in a linear clause with a constant-linear-step
9152 // that is the increment of the associated for-loop. The loop iteration
9153 // variable(s) in the associated for-loop(s) of a for or parallel for
9154 // construct may be listed in a private or lastprivate clause.
9155 DSAStackTy::DSAVarData DVar =
9156 DSAStack->getTopDSA(D, /*FromParent=*/false);
9157 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9158 // is declared in the loop and it is predetermined as a private.
9159 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9160 OpenMPClauseKind PredeterminedCKind =
9162 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9163 : OMPC_private;
9164 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9165 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9166 };
9167 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9168 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9169 (getLangOpts().OpenMP <= 45 ||
9170 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9172 IsOpenMPTaskloopDirective(DKind) ||
9174 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9175 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9176 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9177 unsigned OMPVersion = getLangOpts().OpenMP;
9178 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9179 << getOpenMPClauseNameForDiag(DVar.CKind)
9180 << getOpenMPDirectiveName(DKind, OMPVersion)
9181 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9182 if (DVar.RefExpr == nullptr)
9183 DVar.CKind = PredeterminedCKind;
9184 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9185 } else if (LoopDeclRefExpr) {
9186 // Make the loop iteration variable private (for worksharing
9187 // constructs), linear (for simd directives with the only one
9188 // associated loop) or lastprivate (for simd directives with several
9189 // collapsed or ordered loops).
9190 if (DVar.CKind == OMPC_unknown)
9191 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9192 }
9193 }
9194 }
9195 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9196}
9197
9198namespace {
9199// Utility for OpenMP doacross clause kind
9200class OMPDoacrossKind {
9201public:
9202 bool isSource(const OMPDoacrossClause *C) {
9203 return C->getDependenceType() == OMPC_DOACROSS_source ||
9204 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9205 }
9206 bool isSink(const OMPDoacrossClause *C) {
9207 return C->getDependenceType() == OMPC_DOACROSS_sink;
9208 }
9209 bool isSinkIter(const OMPDoacrossClause *C) {
9210 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9211 }
9212};
9213} // namespace
9214/// Called on a for stmt to check and extract its iteration space
9215/// for further processing (such as collapsing).
9217 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9218 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9219 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9220 Expr *OrderedLoopCountExpr,
9221 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9223 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9224 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9225 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9226 // OpenMP [2.9.1, Canonical Loop Form]
9227 // for (init-expr; test-expr; incr-expr) structured-block
9228 // for (range-decl: range-expr) structured-block
9229 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9230 S = CanonLoop->getLoopStmt();
9231 auto *For = dyn_cast_or_null<ForStmt>(S);
9232 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9233 // Ranged for is supported only in OpenMP 5.0.
9234 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9235 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9236 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9237 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9238 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9239 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9240 if (TotalNestedLoopCount > 1) {
9241 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9242 SemaRef.Diag(DSA.getConstructLoc(),
9243 diag::note_omp_collapse_ordered_expr)
9244 << 2 << CollapseLoopCountExpr->getSourceRange()
9245 << OrderedLoopCountExpr->getSourceRange();
9246 else if (CollapseLoopCountExpr)
9247 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9248 diag::note_omp_collapse_ordered_expr)
9249 << 0 << CollapseLoopCountExpr->getSourceRange();
9250 else if (OrderedLoopCountExpr)
9251 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9252 diag::note_omp_collapse_ordered_expr)
9253 << 1 << OrderedLoopCountExpr->getSourceRange();
9254 }
9255 return true;
9256 }
9257 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9258 "No loop body.");
9259 // Postpone analysis in dependent contexts for ranged for loops.
9260 if (CXXFor && SemaRef.CurContext->isDependentContext())
9261 return false;
9262
9263 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9264 For ? For->getForLoc() : CXXFor->getForLoc(),
9265 CollapsedLoopVarDecls);
9266
9267 // Check init.
9268 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9269 if (ISC.checkAndSetInit(Init))
9270 return true;
9271
9272 bool HasErrors = false;
9273
9274 // Check loop variable's type.
9275 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9276 // OpenMP [2.6, Canonical Loop Form]
9277 // Var is one of the following:
9278 // A variable of signed or unsigned integer type.
9279 // For C++, a variable of a random access iterator type.
9280 // For C, a variable of a pointer type.
9281 QualType VarType = LCDecl->getType().getNonReferenceType();
9282 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9283 !VarType->isPointerType() &&
9284 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9285 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9286 << SemaRef.getLangOpts().CPlusPlus;
9287 HasErrors = true;
9288 }
9289
9290 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9291 // a Construct
9292 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9293 // parallel for construct is (are) private.
9294 // The loop iteration variable in the associated for-loop of a simd
9295 // construct with just one associated for-loop is linear with a
9296 // constant-linear-step that is the increment of the associated for-loop.
9297 // Exclude loop var from the list of variables with implicitly defined data
9298 // sharing attributes.
9299 VarsWithImplicitDSA.erase(LCDecl);
9300
9301 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9302
9303 // Check test-expr.
9304 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9305
9306 // Check incr-expr.
9307 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9308 }
9309
9310 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9311 return HasErrors;
9312
9313 // Build the loop's iteration space representation.
9314 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9315 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9316 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9317 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9323 Captures);
9324 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9325 ISC.buildCounterVar(Captures, DSA);
9326 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9327 ISC.buildPrivateCounterVar();
9328 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9329 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9330 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9331 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9332 ISC.getConditionSrcRange();
9333 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9334 ISC.getIncrementSrcRange();
9335 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9336 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9337 ISC.isStrictTestOp();
9338 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9339 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9340 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9341 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9342 ISC.buildFinalCondition(DSA.getCurScope());
9343 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9344 ISC.doesInitDependOnLC();
9345 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9346 ISC.doesCondDependOnLC();
9347 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9348 ISC.getLoopDependentIdx();
9349
9350 HasErrors |=
9351 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9352 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9353 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9354 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9355 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9356 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9357 if (!HasErrors && DSA.isOrderedRegion()) {
9358 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9359 if (CurrentNestedLoopCount <
9360 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9361 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9362 CurrentNestedLoopCount,
9363 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9364 DSA.getOrderedRegionParam().second->setLoopCounter(
9365 CurrentNestedLoopCount,
9366 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9367 }
9368 }
9369 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9370 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9371 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9372 unsigned NumLoops =
9373 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9374 if (CurrentNestedLoopCount >= NumLoops) {
9375 // Erroneous case - clause has some problems.
9376 continue;
9377 }
9378 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9379 Pair.second.size() <= CurrentNestedLoopCount) {
9380 // Erroneous case - clause has some problems.
9381 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9382 continue;
9383 }
9384 OMPDoacrossKind ODK;
9385 if (DoacrossC && ODK.isSink(DoacrossC) &&
9386 Pair.second.size() <= CurrentNestedLoopCount) {
9387 // Erroneous case - clause has some problems.
9388 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9389 continue;
9390 }
9391 Expr *CntValue;
9392 SourceLocation DepLoc =
9393 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9394 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9395 (DoacrossC && ODK.isSource(DoacrossC)))
9396 CntValue = ISC.buildOrderedLoopData(
9397 DSA.getCurScope(),
9398 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9399 DepLoc);
9400 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9401 Expr *Cnt = SemaRef
9403 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9404 .get();
9405 if (!Cnt)
9406 continue;
9407 // build CounterVar - 1
9408 Expr *Inc =
9409 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9410 .get();
9411 CntValue = ISC.buildOrderedLoopData(
9412 DSA.getCurScope(),
9413 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9414 DepLoc, Inc, clang::OO_Minus);
9415 } else
9416 CntValue = ISC.buildOrderedLoopData(
9417 DSA.getCurScope(),
9418 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9419 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9420 Pair.second[CurrentNestedLoopCount].second);
9421 if (DependC)
9422 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9423 else
9424 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9425 }
9426 }
9427
9428 return HasErrors;
9429}
9430
9431/// Build 'VarRef = Start.
9432static ExprResult
9434 ExprResult Start, bool IsNonRectangularLB,
9435 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9436 // Build 'VarRef = Start.
9437 ExprResult NewStart = IsNonRectangularLB
9438 ? Start.get()
9439 : tryBuildCapture(SemaRef, Start.get(), Captures);
9440 if (!NewStart.isUsable())
9441 return ExprError();
9442 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9443 VarRef.get()->getType())) {
9444 NewStart = SemaRef.PerformImplicitConversion(
9445 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9446 /*AllowExplicit=*/true);
9447 if (!NewStart.isUsable())
9448 return ExprError();
9449 }
9450
9452 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9453 return Init;
9454}
9455
9456/// Build 'VarRef = Start + Iter * Step'.
9458 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9459 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9460 bool IsNonRectangularLB,
9461 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9462 // Add parentheses (for debugging purposes only).
9463 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9464 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9465 !Step.isUsable())
9466 return ExprError();
9467
9468 ExprResult NewStep = Step;
9469 if (Captures)
9470 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9471 if (NewStep.isInvalid())
9472 return ExprError();
9474 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9475 if (!Update.isUsable())
9476 return ExprError();
9477
9478 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9479 // 'VarRef = Start (+|-) Iter * Step'.
9480 if (!Start.isUsable())
9481 return ExprError();
9482 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9483 if (!NewStart.isUsable())
9484 return ExprError();
9485 if (Captures && !IsNonRectangularLB)
9486 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9487 if (NewStart.isInvalid())
9488 return ExprError();
9489
9490 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9491 ExprResult SavedUpdate = Update;
9492 ExprResult UpdateVal;
9493 if (VarRef.get()->getType()->isOverloadableType() ||
9494 NewStart.get()->getType()->isOverloadableType() ||
9495 Update.get()->getType()->isOverloadableType()) {
9496 Sema::TentativeAnalysisScope Trap(SemaRef);
9497
9498 Update =
9499 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9500 if (Update.isUsable()) {
9501 UpdateVal =
9502 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9503 VarRef.get(), SavedUpdate.get());
9504 if (UpdateVal.isUsable()) {
9505 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9506 UpdateVal.get());
9507 }
9508 }
9509 }
9510
9511 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9512 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9513 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9514 NewStart.get(), SavedUpdate.get());
9515 if (!Update.isUsable())
9516 return ExprError();
9517
9518 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9519 VarRef.get()->getType())) {
9521 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9522 /*AllowExplicit=*/true);
9523 if (!Update.isUsable())
9524 return ExprError();
9525 }
9526
9527 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9528 }
9529 return Update;
9530}
9531
9532/// Convert integer expression \a E to make it have at least \a Bits
9533/// bits.
9534static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9535 if (E == nullptr)
9536 return ExprError();
9537 ASTContext &C = SemaRef.Context;
9538 QualType OldType = E->getType();
9539 unsigned HasBits = C.getTypeSize(OldType);
9540 if (HasBits >= Bits)
9541 return ExprResult(E);
9542 // OK to convert to signed, because new type has more bits than old.
9543 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9544 return SemaRef.PerformImplicitConversion(
9545 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9546}
9547
9548/// Check if the given expression \a E is a constant integer that fits
9549/// into \a Bits bits.
9550static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9551 if (E == nullptr)
9552 return false;
9553 if (std::optional<llvm::APSInt> Result =
9555 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9556 return false;
9557}
9558
9559/// Build preinits statement for the given declarations.
9561 MutableArrayRef<Decl *> PreInits) {
9562 if (!PreInits.empty()) {
9563 return new (Context) DeclStmt(
9564 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9566 }
9567 return nullptr;
9568}
9569
9570/// Append the \p Item or the content of a CompoundStmt to the list \p
9571/// TargetList.
9572///
9573/// A CompoundStmt is used as container in case multiple statements need to be
9574/// stored in lieu of using an explicit list. Flattening is necessary because
9575/// contained DeclStmts need to be visible after the execution of the list. Used
9576/// for OpenMP pre-init declarations/statements.
9578 Stmt *Item) {
9579 // nullptr represents an empty list.
9580 if (!Item)
9581 return;
9582
9583 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9584 llvm::append_range(TargetList, CS->body());
9585 else
9586 TargetList.push_back(Item);
9587}
9588
9589/// Build preinits statement for the given declarations.
9590static Stmt *
9592 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9593 if (!Captures.empty()) {
9594 SmallVector<Decl *, 16> PreInits;
9595 for (const auto &Pair : Captures)
9596 PreInits.push_back(Pair.second->getDecl());
9597 return buildPreInits(Context, PreInits);
9598 }
9599 return nullptr;
9600}
9601
9602/// Build pre-init statement for the given statements.
9603static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9604 if (PreInits.empty())
9605 return nullptr;
9606
9607 SmallVector<Stmt *> Stmts;
9608 for (Stmt *S : PreInits)
9609 appendFlattenedStmtList(Stmts, S);
9610 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9611}
9612
9613/// Build postupdate expression for the given list of postupdates expressions.
9614static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9615 Expr *PostUpdate = nullptr;
9616 if (!PostUpdates.empty()) {
9617 for (Expr *E : PostUpdates) {
9618 Expr *ConvE = S.BuildCStyleCastExpr(
9619 E->getExprLoc(),
9621 E->getExprLoc(), E)
9622 .get();
9623 PostUpdate = PostUpdate
9624 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9625 PostUpdate, ConvE)
9626 .get()
9627 : ConvE;
9628 }
9629 }
9630 return PostUpdate;
9631}
9632
9633/// Look for variables declared in the body parts of a for-loop nest. Used
9634/// for verifying loop nest structure before performing a loop collapse
9635/// operation.
9637 int NestingDepth = 0;
9638 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9639
9640public:
9641 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9642 : VarDecls(VD) {}
9643
9644 bool VisitForStmt(ForStmt *F) override {
9645 ++NestingDepth;
9646 TraverseStmt(F->getBody());
9647 --NestingDepth;
9648 return false;
9649 }
9650
9652 ++NestingDepth;
9653 TraverseStmt(RF->getBody());
9654 --NestingDepth;
9655 return false;
9656 }
9657
9658 bool VisitVarDecl(VarDecl *D) override {
9659 Decl *C = D->getCanonicalDecl();
9660 if (NestingDepth > 0)
9661 VarDecls.insert(C);
9662 return true;
9663 }
9664};
9665
9666/// Called on a for stmt to check itself and nested loops (if any).
9667/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9668/// number of collapsed loops otherwise.
9669static unsigned
9670checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9671 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9672 DSAStackTy &DSA,
9673 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9675 // If either of the loop expressions exist and contain errors, we bail out
9676 // early because diagnostics have already been emitted and we can't reliably
9677 // check more about the loop.
9678 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9679 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9680 return 0;
9681
9682 unsigned NestedLoopCount = 1;
9683 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9685 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9686
9687 if (CollapseLoopCountExpr) {
9688 // Found 'collapse' clause - calculate collapse number.
9690 if (!CollapseLoopCountExpr->isValueDependent() &&
9691 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9692 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9693
9694 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9695 FVDF.TraverseStmt(AStmt);
9696 } else {
9697 Built.clear(/*Size=*/1);
9698 return 1;
9699 }
9700 }
9701 unsigned OrderedLoopCount = 1;
9702 if (OrderedLoopCountExpr) {
9703 // Found 'ordered' clause - calculate collapse number.
9704 Expr::EvalResult EVResult;
9705 if (!OrderedLoopCountExpr->isValueDependent() &&
9706 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9707 SemaRef.getASTContext())) {
9708 llvm::APSInt Result = EVResult.Val.getInt();
9709 if (Result.getLimitedValue() < NestedLoopCount) {
9710 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9711 diag::err_omp_wrong_ordered_loop_count)
9712 << OrderedLoopCountExpr->getSourceRange();
9713 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9714 diag::note_collapse_loop_count)
9715 << CollapseLoopCountExpr->getSourceRange();
9716 }
9717 OrderedLoopCount = Result.getLimitedValue();
9718 } else {
9719 Built.clear(/*Size=*/1);
9720 return 1;
9721 }
9722 }
9723 // This is helper routine for loop directives (e.g., 'for', 'simd',
9724 // 'for simd', etc.).
9725 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9726 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9727 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9730 SupportsNonPerfectlyNested, NumLoops,
9731 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9732 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9733 &IterSpaces, &Captures,
9734 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9736 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9737 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9738 VarsWithImplicitDSA, IterSpaces, Captures,
9739 CollapsedLoopVarDecls))
9740 return true;
9741 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9742 IterSpaces[Cnt].CounterVar) {
9743 // Handle initialization of captured loop iterator variables.
9744 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9745 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9746 Captures[DRE] = DRE;
9747 }
9748 }
9749 return false;
9750 },
9751 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9752 Stmt *DependentPreInits = Transform->getPreInits();
9753 if (!DependentPreInits)
9754 return;
9755
9756 // Search for pre-init declared variables that need to be captured
9757 // to be referenceable inside the directive.
9758 SmallVector<Stmt *> Constituents;
9759 appendFlattenedStmtList(Constituents, DependentPreInits);
9760 for (Stmt *S : Constituents) {
9761 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9762 for (Decl *C : DC->decls()) {
9763 auto *D = cast<VarDecl>(C);
9765 SemaRef, D, D->getType().getNonReferenceType(),
9766 Transform->getBeginLoc());
9767 Captures[Ref] = Ref;
9768 }
9769 }
9770 }
9771 }))
9772 return 0;
9773
9774 Built.clear(/*size=*/NestedLoopCount);
9775
9776 if (SemaRef.CurContext->isDependentContext())
9777 return NestedLoopCount;
9778
9779 // An example of what is generated for the following code:
9780 //
9781 // #pragma omp simd collapse(2) ordered(2)
9782 // for (i = 0; i < NI; ++i)
9783 // for (k = 0; k < NK; ++k)
9784 // for (j = J0; j < NJ; j+=2) {
9785 // <loop body>
9786 // }
9787 //
9788 // We generate the code below.
9789 // Note: the loop body may be outlined in CodeGen.
9790 // Note: some counters may be C++ classes, operator- is used to find number of
9791 // iterations and operator+= to calculate counter value.
9792 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9793 // or i64 is currently supported).
9794 //
9795 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9796 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9797 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9798 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9799 // // similar updates for vars in clauses (e.g. 'linear')
9800 // <loop body (using local i and j)>
9801 // }
9802 // i = NI; // assign final values of counters
9803 // j = NJ;
9804 //
9805
9806 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9807 // the iteration counts of the collapsed for loops.
9808 // Precondition tests if there is at least one iteration (all conditions are
9809 // true).
9810 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9811 Expr *N0 = IterSpaces[0].NumIterations;
9812 ExprResult LastIteration32 = widenIterationCount(
9813 /*Bits=*/32,
9814 SemaRef
9815 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9817 /*AllowExplicit=*/true)
9818 .get(),
9819 SemaRef);
9820 ExprResult LastIteration64 = widenIterationCount(
9821 /*Bits=*/64,
9822 SemaRef
9823 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9825 /*AllowExplicit=*/true)
9826 .get(),
9827 SemaRef);
9828
9829 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9830 return NestedLoopCount;
9831
9832 ASTContext &C = SemaRef.Context;
9833 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9834
9835 Scope *CurScope = DSA.getCurScope();
9836 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9837 if (PreCond.isUsable()) {
9838 PreCond =
9839 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9840 PreCond.get(), IterSpaces[Cnt].PreCond);
9841 }
9842 Expr *N = IterSpaces[Cnt].NumIterations;
9844 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9845 if (LastIteration32.isUsable())
9846 LastIteration32 = SemaRef.BuildBinOp(
9847 CurScope, Loc, BO_Mul, LastIteration32.get(),
9848 SemaRef
9851 /*AllowExplicit=*/true)
9852 .get());
9853 if (LastIteration64.isUsable())
9854 LastIteration64 = SemaRef.BuildBinOp(
9855 CurScope, Loc, BO_Mul, LastIteration64.get(),
9856 SemaRef
9859 /*AllowExplicit=*/true)
9860 .get());
9861 }
9862
9863 // Choose either the 32-bit or 64-bit version.
9864 ExprResult LastIteration = LastIteration64;
9865 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9866 (LastIteration32.isUsable() &&
9867 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9868 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9869 fitsInto(
9870 /*Bits=*/32,
9871 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9872 LastIteration64.get(), SemaRef))))
9873 LastIteration = LastIteration32;
9874 QualType VType = LastIteration.get()->getType();
9875 QualType RealVType = VType;
9876 QualType StrideVType = VType;
9877 if (isOpenMPTaskLoopDirective(DKind)) {
9878 VType =
9879 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9880 StrideVType =
9881 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9882 }
9883
9884 if (!LastIteration.isUsable())
9885 return 0;
9886
9887 // Save the number of iterations.
9888 ExprResult NumIterations = LastIteration;
9889 {
9890 LastIteration = SemaRef.BuildBinOp(
9891 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9892 LastIteration.get(),
9893 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9894 if (!LastIteration.isUsable())
9895 return 0;
9896 }
9897
9898 // Calculate the last iteration number beforehand instead of doing this on
9899 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9900 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9901 ExprResult CalcLastIteration;
9902 if (!IsConstant) {
9903 ExprResult SaveRef =
9904 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9905 LastIteration = SaveRef;
9906
9907 // Prepare SaveRef + 1.
9908 NumIterations = SemaRef.BuildBinOp(
9909 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9910 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9911 if (!NumIterations.isUsable())
9912 return 0;
9913 }
9914
9915 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9916
9917 // Build variables passed into runtime, necessary for worksharing directives.
9918 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9923 // Lower bound variable, initialized with zero.
9924 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9925 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9926 SemaRef.AddInitializerToDecl(LBDecl,
9927 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9928 /*DirectInit=*/false);
9929
9930 // Upper bound variable, initialized with last iteration number.
9931 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9932 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9933 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9934 /*DirectInit=*/false);
9935
9936 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9937 // This will be used to implement clause 'lastprivate'.
9938 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9939 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9940 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9941 SemaRef.AddInitializerToDecl(ILDecl,
9942 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9943 /*DirectInit=*/false);
9944
9945 // Stride variable returned by runtime (we initialize it to 1 by default).
9946 VarDecl *STDecl =
9947 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9948 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9949 SemaRef.AddInitializerToDecl(STDecl,
9950 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9951 /*DirectInit=*/false);
9952
9953 // Build expression: UB = min(UB, LastIteration)
9954 // It is necessary for CodeGen of directives with static scheduling.
9955 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9956 UB.get(), LastIteration.get());
9957 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9958 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9959 LastIteration.get(), UB.get());
9960 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9961 CondOp.get());
9962 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
9963
9964 // If we have a combined directive that combines 'distribute', 'for' or
9965 // 'simd' we need to be able to access the bounds of the schedule of the
9966 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9967 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9969 // Lower bound variable, initialized with zero.
9970 VarDecl *CombLBDecl =
9971 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9972 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9973 SemaRef.AddInitializerToDecl(
9974 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9975 /*DirectInit=*/false);
9976
9977 // Upper bound variable, initialized with last iteration number.
9978 VarDecl *CombUBDecl =
9979 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9980 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9981 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9982 /*DirectInit=*/false);
9983
9984 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9985 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9986 ExprResult CombCondOp =
9987 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9988 LastIteration.get(), CombUB.get());
9989 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9990 CombCondOp.get());
9991 CombEUB =
9992 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
9993
9994 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9995 // We expect to have at least 2 more parameters than the 'parallel'
9996 // directive does - the lower and upper bounds of the previous schedule.
9997 assert(CD->getNumParams() >= 4 &&
9998 "Unexpected number of parameters in loop combined directive");
9999
10000 // Set the proper type for the bounds given what we learned from the
10001 // enclosed loops.
10002 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10003 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10004
10005 // Previous lower and upper bounds are obtained from the region
10006 // parameters.
10007 PrevLB =
10008 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10009 PrevUB =
10010 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10011 }
10012 }
10013
10014 // Build the iteration variable and its initialization before loop.
10015 ExprResult IV;
10016 ExprResult Init, CombInit;
10017 {
10018 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10019 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10020 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10025 ? LB.get()
10026 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10027 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10028 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10029
10031 Expr *CombRHS =
10036 ? CombLB.get()
10037 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10038 CombInit =
10039 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10040 CombInit =
10041 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10042 }
10043 }
10044
10045 bool UseStrictCompare =
10046 RealVType->hasUnsignedIntegerRepresentation() &&
10047 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10048 return LIS.IsStrictCompare;
10049 });
10050 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10051 // unsigned IV)) for worksharing loops.
10052 SourceLocation CondLoc = AStmt->getBeginLoc();
10053 Expr *BoundUB = UB.get();
10054 if (UseStrictCompare) {
10055 BoundUB =
10056 SemaRef
10057 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10058 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10059 .get();
10060 BoundUB =
10061 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10062 }
10063 ExprResult Cond =
10068 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10069 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10070 BoundUB)
10071 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10072 NumIterations.get());
10073 ExprResult CombDistCond;
10075 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10076 NumIterations.get());
10077 }
10078
10079 ExprResult CombCond;
10081 Expr *BoundCombUB = CombUB.get();
10082 if (UseStrictCompare) {
10083 BoundCombUB =
10084 SemaRef
10085 .BuildBinOp(
10086 CurScope, CondLoc, BO_Add, BoundCombUB,
10087 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10088 .get();
10089 BoundCombUB =
10090 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10091 .get();
10092 }
10093 CombCond =
10094 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10095 IV.get(), BoundCombUB);
10096 }
10097 // Loop increment (IV = IV + 1)
10098 SourceLocation IncLoc = AStmt->getBeginLoc();
10099 ExprResult Inc =
10100 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10101 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10102 if (!Inc.isUsable())
10103 return 0;
10104 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10105 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10106 if (!Inc.isUsable())
10107 return 0;
10108
10109 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10110 // Used for directives with static scheduling.
10111 // In combined construct, add combined version that use CombLB and CombUB
10112 // base variables for the update
10113 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10118 // LB + ST
10119 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10120 if (!NextLB.isUsable())
10121 return 0;
10122 // LB = LB + ST
10123 NextLB =
10124 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10125 NextLB =
10126 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10127 if (!NextLB.isUsable())
10128 return 0;
10129 // UB + ST
10130 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10131 if (!NextUB.isUsable())
10132 return 0;
10133 // UB = UB + ST
10134 NextUB =
10135 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10136 NextUB =
10137 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10138 if (!NextUB.isUsable())
10139 return 0;
10141 CombNextLB =
10142 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10143 if (!NextLB.isUsable())
10144 return 0;
10145 // LB = LB + ST
10146 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10147 CombNextLB.get());
10148 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10149 /*DiscardedValue=*/false);
10150 if (!CombNextLB.isUsable())
10151 return 0;
10152 // UB + ST
10153 CombNextUB =
10154 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10155 if (!CombNextUB.isUsable())
10156 return 0;
10157 // UB = UB + ST
10158 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10159 CombNextUB.get());
10160 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10161 /*DiscardedValue=*/false);
10162 if (!CombNextUB.isUsable())
10163 return 0;
10164 }
10165 }
10166
10167 // Create increment expression for distribute loop when combined in a same
10168 // directive with for as IV = IV + ST; ensure upper bound expression based
10169 // on PrevUB instead of NumIterations - used to implement 'for' when found
10170 // in combination with 'distribute', like in 'distribute parallel for'
10171 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10172 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10174 DistCond = SemaRef.BuildBinOp(
10175 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10176 assert(DistCond.isUsable() && "distribute cond expr was not built");
10177
10178 DistInc =
10179 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10180 assert(DistInc.isUsable() && "distribute inc expr was not built");
10181 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10182 DistInc.get());
10183 DistInc =
10184 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10185 assert(DistInc.isUsable() && "distribute inc expr was not built");
10186
10187 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10188 // construct
10189 ExprResult NewPrevUB = PrevUB;
10190 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10191 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10192 PrevUB.get()->getType())) {
10193 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10194 DistEUBLoc,
10196 DistEUBLoc, NewPrevUB.get());
10197 if (!NewPrevUB.isUsable())
10198 return 0;
10199 }
10200 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10201 UB.get(), NewPrevUB.get());
10202 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10203 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10204 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10205 CondOp.get());
10206 PrevEUB =
10207 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10208
10209 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10210 // parallel for is in combination with a distribute directive with
10211 // schedule(static, 1)
10212 Expr *BoundPrevUB = PrevUB.get();
10213 if (UseStrictCompare) {
10214 BoundPrevUB =
10215 SemaRef
10216 .BuildBinOp(
10217 CurScope, CondLoc, BO_Add, BoundPrevUB,
10218 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10219 .get();
10220 BoundPrevUB =
10221 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10222 .get();
10223 }
10224 ParForInDistCond =
10225 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10226 IV.get(), BoundPrevUB);
10227 }
10228
10229 // Build updates and final values of the loop counters.
10230 bool HasErrors = false;
10231 Built.Counters.resize(NestedLoopCount);
10232 Built.Inits.resize(NestedLoopCount);
10233 Built.Updates.resize(NestedLoopCount);
10234 Built.Finals.resize(NestedLoopCount);
10235 Built.DependentCounters.resize(NestedLoopCount);
10236 Built.DependentInits.resize(NestedLoopCount);
10237 Built.FinalsConditions.resize(NestedLoopCount);
10238 {
10239 // We implement the following algorithm for obtaining the
10240 // original loop iteration variable values based on the
10241 // value of the collapsed loop iteration variable IV.
10242 //
10243 // Let n+1 be the number of collapsed loops in the nest.
10244 // Iteration variables (I0, I1, .... In)
10245 // Iteration counts (N0, N1, ... Nn)
10246 //
10247 // Acc = IV;
10248 //
10249 // To compute Ik for loop k, 0 <= k <= n, generate:
10250 // Prod = N(k+1) * N(k+2) * ... * Nn;
10251 // Ik = Acc / Prod;
10252 // Acc -= Ik * Prod;
10253 //
10254 ExprResult Acc = IV;
10255 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10256 LoopIterationSpace &IS = IterSpaces[Cnt];
10257 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10259
10260 // Compute prod
10261 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10262 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10263 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10264 IterSpaces[K].NumIterations);
10265
10266 // Iter = Acc / Prod
10267 // If there is at least one more inner loop to avoid
10268 // multiplication by 1.
10269 if (Cnt + 1 < NestedLoopCount)
10270 Iter =
10271 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10272 else
10273 Iter = Acc;
10274 if (!Iter.isUsable()) {
10275 HasErrors = true;
10276 break;
10277 }
10278
10279 // Update Acc:
10280 // Acc -= Iter * Prod
10281 // Check if there is at least one more inner loop to avoid
10282 // multiplication by 1.
10283 if (Cnt + 1 < NestedLoopCount)
10284 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10285 Prod.get());
10286 else
10287 Prod = Iter;
10288 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10289
10290 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10291 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10292 DeclRefExpr *CounterVar = buildDeclRefExpr(
10293 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10294 /*RefersToCapture=*/true);
10296 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10297 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10298 if (!Init.isUsable()) {
10299 HasErrors = true;
10300 break;
10301 }
10303 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10304 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10305 if (!Update.isUsable()) {
10306 HasErrors = true;
10307 break;
10308 }
10309
10310 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10311 ExprResult Final =
10312 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10313 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10314 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10315 if (!Final.isUsable()) {
10316 HasErrors = true;
10317 break;
10318 }
10319
10320 if (!Update.isUsable() || !Final.isUsable()) {
10321 HasErrors = true;
10322 break;
10323 }
10324 // Save results
10325 Built.Counters[Cnt] = IS.CounterVar;
10326 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10327 Built.Inits[Cnt] = Init.get();
10328 Built.Updates[Cnt] = Update.get();
10329 Built.Finals[Cnt] = Final.get();
10330 Built.DependentCounters[Cnt] = nullptr;
10331 Built.DependentInits[Cnt] = nullptr;
10332 Built.FinalsConditions[Cnt] = nullptr;
10333 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10334 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10335 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10336 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10337 }
10338 }
10339 }
10340
10341 if (HasErrors)
10342 return 0;
10343
10344 // Save results
10345 Built.IterationVarRef = IV.get();
10346 Built.LastIteration = LastIteration.get();
10347 Built.NumIterations = NumIterations.get();
10348 Built.CalcLastIteration = SemaRef
10349 .ActOnFinishFullExpr(CalcLastIteration.get(),
10350 /*DiscardedValue=*/false)
10351 .get();
10352 Built.PreCond = PreCond.get();
10353 Built.PreInits = buildPreInits(C, Captures);
10354 Built.Cond = Cond.get();
10355 Built.Init = Init.get();
10356 Built.Inc = Inc.get();
10357 Built.LB = LB.get();
10358 Built.UB = UB.get();
10359 Built.IL = IL.get();
10360 Built.ST = ST.get();
10361 Built.EUB = EUB.get();
10362 Built.NLB = NextLB.get();
10363 Built.NUB = NextUB.get();
10364 Built.PrevLB = PrevLB.get();
10365 Built.PrevUB = PrevUB.get();
10366 Built.DistInc = DistInc.get();
10367 Built.PrevEUB = PrevEUB.get();
10368 Built.DistCombinedFields.LB = CombLB.get();
10369 Built.DistCombinedFields.UB = CombUB.get();
10370 Built.DistCombinedFields.EUB = CombEUB.get();
10371 Built.DistCombinedFields.Init = CombInit.get();
10372 Built.DistCombinedFields.Cond = CombCond.get();
10373 Built.DistCombinedFields.NLB = CombNextLB.get();
10374 Built.DistCombinedFields.NUB = CombNextUB.get();
10375 Built.DistCombinedFields.DistCond = CombDistCond.get();
10376 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10377
10378 return NestedLoopCount;
10379}
10380
10382 auto CollapseClauses =
10383 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10384 if (CollapseClauses.begin() != CollapseClauses.end())
10385 return (*CollapseClauses.begin())->getNumForLoops();
10386 return nullptr;
10387}
10388
10390 auto OrderedClauses =
10391 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10392 if (OrderedClauses.begin() != OrderedClauses.end())
10393 return (*OrderedClauses.begin())->getNumForLoops();
10394 return nullptr;
10395}
10396
10398 const ArrayRef<OMPClause *> Clauses) {
10399 const OMPSafelenClause *Safelen = nullptr;
10400 const OMPSimdlenClause *Simdlen = nullptr;
10401
10402 for (const OMPClause *Clause : Clauses) {
10403 if (Clause->getClauseKind() == OMPC_safelen)
10404 Safelen = cast<OMPSafelenClause>(Clause);
10405 else if (Clause->getClauseKind() == OMPC_simdlen)
10406 Simdlen = cast<OMPSimdlenClause>(Clause);
10407 if (Safelen && Simdlen)
10408 break;
10409 }
10410
10411 if (Simdlen && Safelen) {
10412 const Expr *SimdlenLength = Simdlen->getSimdlen();
10413 const Expr *SafelenLength = Safelen->getSafelen();
10414 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10415 SimdlenLength->isInstantiationDependent() ||
10416 SimdlenLength->containsUnexpandedParameterPack())
10417 return false;
10418 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10419 SafelenLength->isInstantiationDependent() ||
10420 SafelenLength->containsUnexpandedParameterPack())
10421 return false;
10422 Expr::EvalResult SimdlenResult, SafelenResult;
10423 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10424 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10425 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10426 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10427 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10428 // If both simdlen and safelen clauses are specified, the value of the
10429 // simdlen parameter must be less than or equal to the value of the safelen
10430 // parameter.
10431 if (SimdlenRes > SafelenRes) {
10432 S.Diag(SimdlenLength->getExprLoc(),
10433 diag::err_omp_wrong_simdlen_safelen_values)
10434 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10435 return true;
10436 }
10437 }
10438 return false;
10439}
10440
10442 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10443 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10444 if (!AStmt)
10445 return StmtError();
10446
10447 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10448
10449 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10451 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10452 // define the nested loops number.
10453 unsigned NestedLoopCount = checkOpenMPLoop(
10454 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10455 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10456 if (NestedLoopCount == 0)
10457 return StmtError();
10458
10459 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10460 return StmtError();
10461
10463 return StmtError();
10464
10465 auto *SimdDirective = OMPSimdDirective::Create(
10466 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10467 return SimdDirective;
10468}
10469
10471 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10472 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10473 if (!AStmt)
10474 return StmtError();
10475
10476 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10478 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10479 // define the nested loops number.
10480 unsigned NestedLoopCount = checkOpenMPLoop(
10481 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10482 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10483 if (NestedLoopCount == 0)
10484 return StmtError();
10485
10486 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10487 return StmtError();
10488
10489 auto *ForDirective = OMPForDirective::Create(
10490 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10491 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10492 return ForDirective;
10493}
10494
10496 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10497 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10498 if (!AStmt)
10499 return StmtError();
10500
10501 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10502
10503 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10505 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10506 // define the nested loops number.
10507 unsigned NestedLoopCount =
10508 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10509 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10510 VarsWithImplicitDSA, B);
10511 if (NestedLoopCount == 0)
10512 return StmtError();
10513
10514 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10515 return StmtError();
10516
10518 return StmtError();
10519
10520 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10521 NestedLoopCount, Clauses, AStmt, B);
10522}
10523
10525 Stmt *AStmt, DSAStackTy *Stack) {
10526 if (!AStmt)
10527 return true;
10528
10529 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10530 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10531 auto BaseStmt = AStmt;
10532 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10533 BaseStmt = CS->getCapturedStmt();
10534 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10535 auto S = C->children();
10536 if (S.begin() == S.end())
10537 return true;
10538 // All associated statements must be '#pragma omp section' except for
10539 // the first one.
10540 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10541 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10542 if (SectionStmt)
10543 SemaRef.Diag(SectionStmt->getBeginLoc(),
10544 diag::err_omp_sections_substmt_not_section)
10545 << getOpenMPDirectiveName(DKind, OMPVersion);
10546 return true;
10547 }
10548 cast<OMPSectionDirective>(SectionStmt)
10549 ->setHasCancel(Stack->isCancelRegion());
10550 }
10551 } else {
10552 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10553 << getOpenMPDirectiveName(DKind, OMPVersion);
10554 return true;
10555 }
10556 return false;
10557}
10558
10561 Stmt *AStmt, SourceLocation StartLoc,
10562 SourceLocation EndLoc) {
10563 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10564 return StmtError();
10565
10567
10569 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10570 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10571}
10572
10574 SourceLocation StartLoc,
10575 SourceLocation EndLoc) {
10576 if (!AStmt)
10577 return StmtError();
10578
10580 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10581
10582 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10583 DSAStack->isCancelRegion());
10584}
10585
10588 if (auto *CE = dyn_cast<CallExpr>(E))
10589 if (CE->getDirectCallee())
10590 return E;
10591 return nullptr;
10592}
10593
10596 Stmt *AStmt, SourceLocation StartLoc,
10597 SourceLocation EndLoc) {
10598 if (!AStmt)
10599 return StmtError();
10600
10601 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10602
10603 // 5.1 OpenMP
10604 // expression-stmt : an expression statement with one of the following forms:
10605 // expression = target-call ( [expression-list] );
10606 // target-call ( [expression-list] );
10607
10608 SourceLocation TargetCallLoc;
10609
10611 Expr *TargetCall = nullptr;
10612
10613 auto *E = dyn_cast<Expr>(S);
10614 if (!E) {
10615 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10616 return StmtError();
10617 }
10618
10620
10621 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10622 if (BO->getOpcode() == BO_Assign)
10623 TargetCall = getDirectCallExpr(BO->getRHS());
10624 } else {
10625 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10626 if (COCE->getOperator() == OO_Equal)
10627 TargetCall = getDirectCallExpr(COCE->getArg(1));
10628 if (!TargetCall)
10629 TargetCall = getDirectCallExpr(E);
10630 }
10631 if (!TargetCall) {
10632 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10633 return StmtError();
10634 }
10635 TargetCallLoc = TargetCall->getExprLoc();
10636 }
10637
10639
10640 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10641 Clauses, AStmt, TargetCallLoc);
10642}
10643
10646 DSAStackTy *Stack) {
10647 bool ErrorFound = false;
10648 for (OMPClause *C : Clauses) {
10649 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10650 for (Expr *RefExpr : LPC->varlist()) {
10651 SourceLocation ELoc;
10652 SourceRange ERange;
10653 Expr *SimpleRefExpr = RefExpr;
10654 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10655 if (ValueDecl *D = Res.first) {
10656 auto &&Info = Stack->isLoopControlVariable(D);
10657 if (!Info.first) {
10658 unsigned OMPVersion = S.getLangOpts().OpenMP;
10659 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10660 << getOpenMPDirectiveName(K, OMPVersion);
10661 ErrorFound = true;
10662 }
10663 }
10664 }
10665 }
10666 }
10667 return ErrorFound;
10668}
10669
10671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10673 if (!AStmt)
10674 return StmtError();
10675
10676 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10677 // A list item may not appear in a lastprivate clause unless it is the
10678 // loop iteration variable of a loop that is associated with the construct.
10679 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10680 return StmtError();
10681
10682 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10683
10685 // In presence of clause 'collapse', it will define the nested loops number.
10686 unsigned NestedLoopCount = checkOpenMPLoop(
10687 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10688 AStmt, SemaRef, *DSAStack, 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
10695 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10696 NestedLoopCount, Clauses, AStmt, B);
10697}
10698
10700 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10701 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10702 if (!AStmt)
10703 return StmtError();
10704
10705 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10706 // A list item may not appear in a lastprivate clause unless it is the
10707 // loop iteration variable of a loop that is associated with the construct.
10708 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10709 return StmtError();
10710
10711 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10712
10714 // In presence of clause 'collapse', it will define the nested loops number.
10715 unsigned NestedLoopCount =
10716 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10717 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10718 VarsWithImplicitDSA, B);
10719 if (NestedLoopCount == 0)
10720 return StmtError();
10721
10722 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10723 "omp loop exprs were not built");
10724
10725 DSAStack->setParentTeamsRegionLoc(StartLoc);
10726
10728 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10729}
10730
10732 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10733 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10734 if (!AStmt)
10735 return StmtError();
10736
10737 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10738 // A list item may not appear in a lastprivate clause unless it is the
10739 // loop iteration variable of a loop that is associated with the construct.
10740 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10741 DSAStack))
10742 return StmtError();
10743
10744 CapturedStmt *CS =
10745 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10746
10748 // In presence of clause 'collapse', it will define the nested loops number.
10749 unsigned NestedLoopCount =
10750 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10751 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10752 VarsWithImplicitDSA, B);
10753 if (NestedLoopCount == 0)
10754 return StmtError();
10755
10756 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10757 "omp loop exprs were not built");
10758
10760 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10762}
10763
10765 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10766 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10767 if (!AStmt)
10768 return StmtError();
10769
10770 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10771 // A list item may not appear in a lastprivate clause unless it is the
10772 // loop iteration variable of a loop that is associated with the construct.
10773 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10774 DSAStack))
10775 return StmtError();
10776
10777 CapturedStmt *CS =
10778 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10779
10781 // In presence of clause 'collapse', it will define the nested loops number.
10782 unsigned NestedLoopCount =
10783 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10784 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10785 VarsWithImplicitDSA, B);
10786 if (NestedLoopCount == 0)
10787 return StmtError();
10788
10789 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10790 "omp loop exprs were not built");
10791
10793 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10794}
10795
10797 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10798 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10799 if (!AStmt)
10800 return StmtError();
10801
10802 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10803 // A list item may not appear in a lastprivate clause unless it is the
10804 // loop iteration variable of a loop that is associated with the construct.
10805 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10806 DSAStack))
10807 return StmtError();
10808
10809 CapturedStmt *CS =
10810 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
10811
10813 // In presence of clause 'collapse', it will define the nested loops number.
10814 unsigned NestedLoopCount =
10815 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10816 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10817 VarsWithImplicitDSA, B);
10818 if (NestedLoopCount == 0)
10819 return StmtError();
10820
10821 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10822 "omp loop exprs were not built");
10823
10825 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10826}
10827
10829 Stmt *AStmt,
10830 SourceLocation StartLoc,
10831 SourceLocation EndLoc) {
10832 if (!AStmt)
10833 return StmtError();
10834
10835 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10836
10838
10839 // OpenMP [2.7.3, single Construct, Restrictions]
10840 // The copyprivate clause must not be used with the nowait clause.
10841 const OMPClause *Nowait = nullptr;
10842 const OMPClause *Copyprivate = nullptr;
10843 for (const OMPClause *Clause : Clauses) {
10844 if (Clause->getClauseKind() == OMPC_nowait)
10845 Nowait = Clause;
10846 else if (Clause->getClauseKind() == OMPC_copyprivate)
10847 Copyprivate = Clause;
10848 if (Copyprivate && Nowait) {
10849 Diag(Copyprivate->getBeginLoc(),
10850 diag::err_omp_single_copyprivate_with_nowait);
10851 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10852 return StmtError();
10853 }
10854 }
10855
10856 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10857 AStmt);
10858}
10859
10861 SourceLocation StartLoc,
10862 SourceLocation EndLoc) {
10863 if (!AStmt)
10864 return StmtError();
10865
10867
10868 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
10869}
10870
10872 Stmt *AStmt,
10873 SourceLocation StartLoc,
10874 SourceLocation EndLoc) {
10875 if (!AStmt)
10876 return StmtError();
10877
10879
10880 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10881 AStmt);
10882}
10883
10885 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10886 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10887 if (!AStmt)
10888 return StmtError();
10889
10890 bool ErrorFound = false;
10891 llvm::APSInt Hint;
10892 SourceLocation HintLoc;
10893 bool DependentHint = false;
10894 for (const OMPClause *C : Clauses) {
10895 if (C->getClauseKind() == OMPC_hint) {
10896 if (!DirName.getName()) {
10897 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10898 ErrorFound = true;
10899 }
10900 Expr *E = cast<OMPHintClause>(C)->getHint();
10901 if (E->isTypeDependent() || E->isValueDependent() ||
10903 DependentHint = true;
10904 } else {
10906 HintLoc = C->getBeginLoc();
10907 }
10908 }
10909 }
10910 if (ErrorFound)
10911 return StmtError();
10912 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10913 if (Pair.first && DirName.getName() && !DependentHint) {
10914 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10915 Diag(StartLoc, diag::err_omp_critical_with_hint);
10916 if (HintLoc.isValid())
10917 Diag(HintLoc, diag::note_omp_critical_hint_here)
10918 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10919 else
10920 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10921 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10922 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10923 << 1
10924 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10925 /*Radix=*/10, /*Signed=*/false);
10926 } else {
10927 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10928 }
10929 }
10930 }
10931
10933
10934 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
10935 EndLoc, Clauses, AStmt);
10936 if (!Pair.first && DirName.getName() && !DependentHint)
10937 DSAStack->addCriticalWithHint(Dir, Hint);
10938 return Dir;
10939}
10940
10942 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10943 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10944 if (!AStmt)
10945 return StmtError();
10946
10947 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10948
10950 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10951 // define the nested loops number.
10952 unsigned NestedLoopCount =
10953 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10954 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10955 VarsWithImplicitDSA, B);
10956 if (NestedLoopCount == 0)
10957 return StmtError();
10958
10959 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10960 return StmtError();
10961
10963 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10964 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10965}
10966
10968 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10969 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10970 if (!AStmt)
10971 return StmtError();
10972
10973 CapturedStmt *CS =
10974 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10975
10977 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10978 // define the nested loops number.
10979 unsigned NestedLoopCount =
10980 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10981 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10982 VarsWithImplicitDSA, B);
10983 if (NestedLoopCount == 0)
10984 return StmtError();
10985
10986 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10987 return StmtError();
10988
10990 return StmtError();
10991
10993 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10994}
10995
10997 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10998 SourceLocation EndLoc) {
10999 if (!AStmt)
11000 return StmtError();
11001
11002 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11003
11005 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11006 DSAStack->getTaskgroupReductionRef());
11007}
11008
11010 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11011 SourceLocation EndLoc) {
11012 if (!AStmt)
11013 return StmtError();
11014
11015 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11016
11018 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11019 DSAStack->getTaskgroupReductionRef());
11020}
11021
11023 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11024 SourceLocation EndLoc) {
11025 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11026 return StmtError();
11027
11029
11031 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11032 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11033}
11034
11035/// Find and diagnose mutually exclusive clause kinds.
11037 Sema &S, ArrayRef<OMPClause *> Clauses,
11038 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11039 const OMPClause *PrevClause = nullptr;
11040 bool ErrorFound = false;
11041 for (const OMPClause *C : Clauses) {
11042 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11043 if (!PrevClause) {
11044 PrevClause = C;
11045 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11046 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11047 << getOpenMPClauseNameForDiag(C->getClauseKind())
11048 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11049 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11050 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11051 ErrorFound = true;
11052 }
11053 }
11054 }
11055 return ErrorFound;
11056}
11057
11059 Stmt *AStmt,
11060 SourceLocation StartLoc,
11061 SourceLocation EndLoc) {
11062 if (!AStmt)
11063 return StmtError();
11064
11065 // OpenMP 5.0, 2.10.1 task Construct
11066 // If a detach clause appears on the directive, then a mergeable clause cannot
11067 // appear on the same directive.
11069 {OMPC_detach, OMPC_mergeable}))
11070 return StmtError();
11071
11072 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11073
11074 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11075 AStmt, DSAStack->isCancelRegion());
11076}
11077
11079 SourceLocation EndLoc) {
11080 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11081}
11082
11084 SourceLocation EndLoc) {
11085 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11086}
11087
11089 SourceLocation StartLoc,
11090 SourceLocation EndLoc,
11091 bool InExContext) {
11092 const OMPAtClause *AtC =
11093 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11094
11095 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11096 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11097 return StmtError();
11098 }
11099
11100 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11101 const OMPSeverityClause *SeverityC =
11102 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11103 const OMPMessageClause *MessageC =
11104 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11105 std::optional<std::string> SL =
11106 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11107
11108 if (MessageC && !SL)
11109 Diag(MessageC->getMessageString()->getBeginLoc(),
11110 diag::warn_clause_expected_string)
11111 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11112 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11113 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11114 << SL.value_or("WARNING");
11115 else
11116 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11117 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11118 return StmtError();
11119 }
11120
11121 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11122}
11123
11126 SourceLocation StartLoc,
11127 SourceLocation EndLoc) {
11128 const OMPNowaitClause *NowaitC =
11129 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11130 bool HasDependC =
11131 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11132 .empty();
11133 if (NowaitC && !HasDependC) {
11134 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11135 return StmtError();
11136 }
11137
11138 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11139 Clauses);
11140}
11141
11144 Stmt *AStmt, SourceLocation StartLoc,
11145 SourceLocation EndLoc) {
11146 if (!AStmt)
11147 return StmtError();
11148
11149 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11150
11152
11153 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11154 Clauses, AStmt,
11155 DSAStack->getTaskgroupReductionRef());
11156}
11157
11159 SourceLocation StartLoc,
11160 SourceLocation EndLoc) {
11161 OMPFlushClause *FC = nullptr;
11162 OMPClause *OrderClause = nullptr;
11163 for (OMPClause *C : Clauses) {
11164 if (C->getClauseKind() == OMPC_flush)
11165 FC = cast<OMPFlushClause>(C);
11166 else
11167 OrderClause = C;
11168 }
11169 unsigned OMPVersion = getLangOpts().OpenMP;
11170 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11171 SourceLocation MemOrderLoc;
11172 for (const OMPClause *C : Clauses) {
11173 if (C->getClauseKind() == OMPC_acq_rel ||
11174 C->getClauseKind() == OMPC_acquire ||
11175 C->getClauseKind() == OMPC_release ||
11176 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11177 if (MemOrderKind != OMPC_unknown) {
11178 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11179 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11180 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11181 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11182 << getOpenMPClauseNameForDiag(MemOrderKind);
11183 } else {
11184 MemOrderKind = C->getClauseKind();
11185 MemOrderLoc = C->getBeginLoc();
11186 }
11187 }
11188 }
11189 if (FC && OrderClause) {
11190 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11191 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11192 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11193 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11194 return StmtError();
11195 }
11196 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11197}
11198
11200 SourceLocation StartLoc,
11201 SourceLocation EndLoc) {
11202 if (Clauses.empty()) {
11203 Diag(StartLoc, diag::err_omp_depobj_expected);
11204 return StmtError();
11205 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11206 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11207 return StmtError();
11208 }
11209 // Only depobj expression and another single clause is allowed.
11210 if (Clauses.size() > 2) {
11211 Diag(Clauses[2]->getBeginLoc(),
11212 diag::err_omp_depobj_single_clause_expected);
11213 return StmtError();
11214 } else if (Clauses.size() < 1) {
11215 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11216 return StmtError();
11217 }
11218 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11219}
11220
11222 SourceLocation StartLoc,
11223 SourceLocation EndLoc) {
11224 // Check that exactly one clause is specified.
11225 if (Clauses.size() != 1) {
11226 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11227 diag::err_omp_scan_single_clause_expected);
11228 return StmtError();
11229 }
11230 // Check that scan directive is used in the scope of the OpenMP loop body.
11231 if (Scope *S = DSAStack->getCurScope()) {
11232 Scope *ParentS = S->getParent();
11233 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11234 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11235 unsigned OMPVersion = getLangOpts().OpenMP;
11236 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11237 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11238 }
11239 }
11240 // Check that only one instance of scan directives is used in the same outer
11241 // region.
11242 if (DSAStack->doesParentHasScanDirective()) {
11243 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11244 Diag(DSAStack->getParentScanDirectiveLoc(),
11245 diag::note_omp_previous_directive)
11246 << "scan";
11247 return StmtError();
11248 }
11249 DSAStack->setParentHasScanDirective(StartLoc);
11250 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11251}
11252
11255 Stmt *AStmt, SourceLocation StartLoc,
11256 SourceLocation EndLoc) {
11257 const OMPClause *DependFound = nullptr;
11258 const OMPClause *DependSourceClause = nullptr;
11259 const OMPClause *DependSinkClause = nullptr;
11260 const OMPClause *DoacrossFound = nullptr;
11261 const OMPClause *DoacrossSourceClause = nullptr;
11262 const OMPClause *DoacrossSinkClause = nullptr;
11263 bool ErrorFound = false;
11264 const OMPThreadsClause *TC = nullptr;
11265 const OMPSIMDClause *SC = nullptr;
11266 for (const OMPClause *C : Clauses) {
11267 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11268 auto DC = dyn_cast<OMPDependClause>(C);
11269 if (DC || DOC) {
11270 DependFound = DC ? C : nullptr;
11271 DoacrossFound = DOC ? C : nullptr;
11272 OMPDoacrossKind ODK;
11273 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11274 (DOC && (ODK.isSource(DOC)))) {
11275 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11276 unsigned OMPVersion = getLangOpts().OpenMP;
11277 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11278 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11279 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11280 << 2;
11281 ErrorFound = true;
11282 } else {
11283 if (DC)
11284 DependSourceClause = C;
11285 else
11286 DoacrossSourceClause = C;
11287 }
11288 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11289 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11290 << (DC ? "depend" : "doacross") << 0;
11291 ErrorFound = true;
11292 }
11293 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11294 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11295 if (DependSourceClause || DoacrossSourceClause) {
11296 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11297 << (DC ? "depend" : "doacross") << 1;
11298 ErrorFound = true;
11299 }
11300 if (DC)
11301 DependSinkClause = C;
11302 else
11303 DoacrossSinkClause = C;
11304 }
11305 } else if (C->getClauseKind() == OMPC_threads) {
11306 TC = cast<OMPThreadsClause>(C);
11307 } else if (C->getClauseKind() == OMPC_simd) {
11308 SC = cast<OMPSIMDClause>(C);
11309 }
11310 }
11311 if (!ErrorFound && !SC &&
11312 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11313 // OpenMP [2.8.1,simd Construct, Restrictions]
11314 // An ordered construct with the simd clause is the only OpenMP construct
11315 // that can appear in the simd region.
11316 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11317 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11318 ErrorFound = true;
11319 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11321 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11322 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11323 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11325 : SC->getClauseKind());
11326 ErrorFound = true;
11327 } else if ((DependFound || DoacrossFound) &&
11328 !DSAStack->getParentOrderedRegionParam().first) {
11330 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11331 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11332 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11333 : OMPC_doacross);
11334 ErrorFound = true;
11335 } else if (TC || Clauses.empty()) {
11336 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11337 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11338 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11339 << (TC != nullptr);
11340 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11341 ErrorFound = true;
11342 }
11343 }
11344 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11345 return StmtError();
11346
11347 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11348 // During execution of an iteration of a worksharing-loop or a loop nest
11349 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11350 // must not execute more than one ordered region corresponding to an ordered
11351 // construct without a depend clause.
11352 if (!DependFound && !DoacrossFound) {
11353 if (DSAStack->doesParentHasOrderedDirective()) {
11354 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11355 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11356 diag::note_omp_previous_directive)
11357 << "ordered";
11358 return StmtError();
11359 }
11360 DSAStack->setParentHasOrderedDirective(StartLoc);
11361 }
11362
11363 if (AStmt) {
11364 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11365
11367 }
11368
11369 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11370 AStmt);
11371}
11372
11373namespace {
11374/// Helper class for checking expression in 'omp atomic [update]'
11375/// construct.
11376class OpenMPAtomicUpdateChecker {
11377 /// Error results for atomic update expressions.
11378 enum ExprAnalysisErrorCode {
11379 /// A statement is not an expression statement.
11380 NotAnExpression,
11381 /// Expression is not builtin binary or unary operation.
11382 NotABinaryOrUnaryExpression,
11383 /// Unary operation is not post-/pre- increment/decrement operation.
11384 NotAnUnaryIncDecExpression,
11385 /// An expression is not of scalar type.
11386 NotAScalarType,
11387 /// A binary operation is not an assignment operation.
11388 NotAnAssignmentOp,
11389 /// RHS part of the binary operation is not a binary expression.
11390 NotABinaryExpression,
11391 /// RHS part is not additive/multiplicative/shift/bitwise binary
11392 /// expression.
11393 NotABinaryOperator,
11394 /// RHS binary operation does not have reference to the updated LHS
11395 /// part.
11396 NotAnUpdateExpression,
11397 /// An expression contains semantical error not related to
11398 /// 'omp atomic [update]'
11399 NotAValidExpression,
11400 /// No errors is found.
11401 NoError
11402 };
11403 /// Reference to Sema.
11404 Sema &SemaRef;
11405 /// A location for note diagnostics (when error is found).
11406 SourceLocation NoteLoc;
11407 /// 'x' lvalue part of the source atomic expression.
11408 Expr *X;
11409 /// 'expr' rvalue part of the source atomic expression.
11410 Expr *E;
11411 /// Helper expression of the form
11412 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11413 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11414 Expr *UpdateExpr;
11415 /// Is 'x' a LHS in a RHS part of full update expression. It is
11416 /// important for non-associative operations.
11417 bool IsXLHSInRHSPart;
11419 SourceLocation OpLoc;
11420 /// true if the source expression is a postfix unary operation, false
11421 /// if it is a prefix unary operation.
11422 bool IsPostfixUpdate;
11423
11424public:
11425 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11426 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11427 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11428 /// Check specified statement that it is suitable for 'atomic update'
11429 /// constructs and extract 'x', 'expr' and Operation from the original
11430 /// expression. If DiagId and NoteId == 0, then only check is performed
11431 /// without error notification.
11432 /// \param DiagId Diagnostic which should be emitted if error is found.
11433 /// \param NoteId Diagnostic note for the main error message.
11434 /// \return true if statement is not an update expression, false otherwise.
11435 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11436 /// Return the 'x' lvalue part of the source atomic expression.
11437 Expr *getX() const { return X; }
11438 /// Return the 'expr' rvalue part of the source atomic expression.
11439 Expr *getExpr() const { return E; }
11440 /// Return the update expression used in calculation of the updated
11441 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11442 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11443 Expr *getUpdateExpr() const { return UpdateExpr; }
11444 /// Return true if 'x' is LHS in RHS part of full update expression,
11445 /// false otherwise.
11446 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11447
11448 /// true if the source expression is a postfix unary operation, false
11449 /// if it is a prefix unary operation.
11450 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11451
11452private:
11453 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11454 unsigned NoteId = 0);
11455};
11456
11457bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11458 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11459 ExprAnalysisErrorCode ErrorFound = NoError;
11460 SourceLocation ErrorLoc, NoteLoc;
11461 SourceRange ErrorRange, NoteRange;
11462 // Allowed constructs are:
11463 // x = x binop expr;
11464 // x = expr binop x;
11465 if (AtomicBinOp->getOpcode() == BO_Assign) {
11466 X = AtomicBinOp->getLHS();
11467 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11468 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11469 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11470 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11471 AtomicInnerBinOp->isBitwiseOp()) {
11472 Op = AtomicInnerBinOp->getOpcode();
11473 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11474 Expr *LHS = AtomicInnerBinOp->getLHS();
11475 Expr *RHS = AtomicInnerBinOp->getRHS();
11476 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11477 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11478 /*Canonical=*/true);
11479 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11480 /*Canonical=*/true);
11481 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11482 /*Canonical=*/true);
11483 if (XId == LHSId) {
11484 E = RHS;
11485 IsXLHSInRHSPart = true;
11486 } else if (XId == RHSId) {
11487 E = LHS;
11488 IsXLHSInRHSPart = false;
11489 } else {
11490 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11491 ErrorRange = AtomicInnerBinOp->getSourceRange();
11492 NoteLoc = X->getExprLoc();
11493 NoteRange = X->getSourceRange();
11494 ErrorFound = NotAnUpdateExpression;
11495 }
11496 } else {
11497 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11498 ErrorRange = AtomicInnerBinOp->getSourceRange();
11499 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11500 NoteRange = SourceRange(NoteLoc, NoteLoc);
11501 ErrorFound = NotABinaryOperator;
11502 }
11503 } else {
11504 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11505 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11506 ErrorFound = NotABinaryExpression;
11507 }
11508 } else {
11509 ErrorLoc = AtomicBinOp->getExprLoc();
11510 ErrorRange = AtomicBinOp->getSourceRange();
11511 NoteLoc = AtomicBinOp->getOperatorLoc();
11512 NoteRange = SourceRange(NoteLoc, NoteLoc);
11513 ErrorFound = NotAnAssignmentOp;
11514 }
11515 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11516 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11517 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11518 return true;
11519 }
11520 if (SemaRef.CurContext->isDependentContext())
11521 E = X = UpdateExpr = nullptr;
11522 return ErrorFound != NoError;
11523}
11524
11525bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11526 unsigned NoteId) {
11527 ExprAnalysisErrorCode ErrorFound = NoError;
11528 SourceLocation ErrorLoc, NoteLoc;
11529 SourceRange ErrorRange, NoteRange;
11530 // Allowed constructs are:
11531 // x++;
11532 // x--;
11533 // ++x;
11534 // --x;
11535 // x binop= expr;
11536 // x = x binop expr;
11537 // x = expr binop x;
11538 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11539 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11540 if (AtomicBody->getType()->isScalarType() ||
11541 AtomicBody->isInstantiationDependent()) {
11542 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11543 AtomicBody->IgnoreParenImpCasts())) {
11544 // Check for Compound Assignment Operation
11546 AtomicCompAssignOp->getOpcode());
11547 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11548 E = AtomicCompAssignOp->getRHS();
11549 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11550 IsXLHSInRHSPart = true;
11551 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11552 AtomicBody->IgnoreParenImpCasts())) {
11553 // Check for Binary Operation
11554 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11555 return true;
11556 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11557 AtomicBody->IgnoreParenImpCasts())) {
11558 // Check for Unary Operation
11559 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11560 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11561 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11562 OpLoc = AtomicUnaryOp->getOperatorLoc();
11563 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11564 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11565 IsXLHSInRHSPart = true;
11566 } else {
11567 ErrorFound = NotAnUnaryIncDecExpression;
11568 ErrorLoc = AtomicUnaryOp->getExprLoc();
11569 ErrorRange = AtomicUnaryOp->getSourceRange();
11570 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11571 NoteRange = SourceRange(NoteLoc, NoteLoc);
11572 }
11573 } else if (!AtomicBody->isInstantiationDependent()) {
11574 ErrorFound = NotABinaryOrUnaryExpression;
11575 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11576 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11577 } else if (AtomicBody->containsErrors()) {
11578 ErrorFound = NotAValidExpression;
11579 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11580 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11581 }
11582 } else {
11583 ErrorFound = NotAScalarType;
11584 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11585 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11586 }
11587 } else {
11588 ErrorFound = NotAnExpression;
11589 NoteLoc = ErrorLoc = S->getBeginLoc();
11590 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11591 }
11592 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11593 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11594 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11595 return true;
11596 }
11597 if (SemaRef.CurContext->isDependentContext())
11598 E = X = UpdateExpr = nullptr;
11599 if (ErrorFound == NoError && E && X) {
11600 // Build an update expression of form 'OpaqueValueExpr(x) binop
11601 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11602 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11603 auto *OVEX = new (SemaRef.getASTContext())
11604 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11605 auto *OVEExpr = new (SemaRef.getASTContext())
11608 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11609 IsXLHSInRHSPart ? OVEExpr : OVEX);
11610 if (Update.isInvalid())
11611 return true;
11612 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11614 if (Update.isInvalid())
11615 return true;
11616 UpdateExpr = Update.get();
11617 }
11618 return ErrorFound != NoError;
11619}
11620
11621/// Get the node id of the fixed point of an expression \a S.
11622llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11623 llvm::FoldingSetNodeID Id;
11624 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11625 return Id;
11626}
11627
11628/// Check if two expressions are same.
11629bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11630 const Expr *RHS) {
11631 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11632}
11633
11634class OpenMPAtomicCompareChecker {
11635public:
11636 /// All kinds of errors that can occur in `atomic compare`
11637 enum ErrorTy {
11638 /// Empty compound statement.
11639 NoStmt = 0,
11640 /// More than one statement in a compound statement.
11641 MoreThanOneStmt,
11642 /// Not an assignment binary operator.
11643 NotAnAssignment,
11644 /// Not a conditional operator.
11645 NotCondOp,
11646 /// Wrong false expr. According to the spec, 'x' should be at the false
11647 /// expression of a conditional expression.
11648 WrongFalseExpr,
11649 /// The condition of a conditional expression is not a binary operator.
11650 NotABinaryOp,
11651 /// Invalid binary operator (not <, >, or ==).
11652 InvalidBinaryOp,
11653 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11654 InvalidComparison,
11655 /// X is not a lvalue.
11656 XNotLValue,
11657 /// Not a scalar.
11658 NotScalar,
11659 /// Not an integer.
11660 NotInteger,
11661 /// 'else' statement is not expected.
11662 UnexpectedElse,
11663 /// Not an equality operator.
11664 NotEQ,
11665 /// Invalid assignment (not v == x).
11666 InvalidAssignment,
11667 /// Not if statement
11668 NotIfStmt,
11669 /// More than two statements in a compound statement.
11670 MoreThanTwoStmts,
11671 /// Not a compound statement.
11672 NotCompoundStmt,
11673 /// No else statement.
11674 NoElse,
11675 /// Not 'if (r)'.
11676 InvalidCondition,
11677 /// No error.
11678 NoError,
11679 };
11680
11681 struct ErrorInfoTy {
11682 ErrorTy Error;
11683 SourceLocation ErrorLoc;
11684 SourceRange ErrorRange;
11685 SourceLocation NoteLoc;
11686 SourceRange NoteRange;
11687 };
11688
11689 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11690
11691 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11692 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11693
11694 Expr *getX() const { return X; }
11695 Expr *getE() const { return E; }
11696 Expr *getD() const { return D; }
11697 Expr *getCond() const { return C; }
11698 bool isXBinopExpr() const { return IsXBinopExpr; }
11699
11700protected:
11701 /// Reference to ASTContext
11702 ASTContext &ContextRef;
11703 /// 'x' lvalue part of the source atomic expression.
11704 Expr *X = nullptr;
11705 /// 'expr' or 'e' rvalue part of the source atomic expression.
11706 Expr *E = nullptr;
11707 /// 'd' rvalue part of the source atomic expression.
11708 Expr *D = nullptr;
11709 /// 'cond' part of the source atomic expression. It is in one of the following
11710 /// forms:
11711 /// expr ordop x
11712 /// x ordop expr
11713 /// x == e
11714 /// e == x
11715 Expr *C = nullptr;
11716 /// True if the cond expr is in the form of 'x ordop expr'.
11717 bool IsXBinopExpr = true;
11718
11719 /// Check if it is a valid conditional update statement (cond-update-stmt).
11720 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11721
11722 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11723 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11724
11725 /// Check if all captured values have right type.
11726 bool checkType(ErrorInfoTy &ErrorInfo) const;
11727
11728 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11729 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11731 return true;
11732
11733 if (ShouldBeLValue && !E->isLValue()) {
11734 ErrorInfo.Error = ErrorTy::XNotLValue;
11735 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11736 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11737 return false;
11738 }
11739
11740 QualType QTy = E->getType();
11741 if (!QTy->isScalarType()) {
11742 ErrorInfo.Error = ErrorTy::NotScalar;
11743 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11744 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11745 return false;
11746 }
11747 if (ShouldBeInteger && !QTy->isIntegerType()) {
11748 ErrorInfo.Error = ErrorTy::NotInteger;
11749 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11750 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11751 return false;
11752 }
11753
11754 return true;
11755 }
11756};
11757
11758bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11759 ErrorInfoTy &ErrorInfo) {
11760 auto *Then = S->getThen();
11761 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11762 if (CS->body_empty()) {
11763 ErrorInfo.Error = ErrorTy::NoStmt;
11764 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11765 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11766 return false;
11767 }
11768 if (CS->size() > 1) {
11769 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11770 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11771 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11772 return false;
11773 }
11774 Then = CS->body_front();
11775 }
11776
11777 auto *BO = dyn_cast<BinaryOperator>(Then);
11778 if (!BO) {
11779 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11780 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11781 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11782 return false;
11783 }
11784 if (BO->getOpcode() != BO_Assign) {
11785 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11786 ErrorInfo.ErrorLoc = BO->getExprLoc();
11787 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11788 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11789 return false;
11790 }
11791
11792 X = BO->getLHS();
11793
11794 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11795 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
11796 Expr *LHS = nullptr;
11797 Expr *RHS = nullptr;
11798 if (Cond) {
11799 LHS = Cond->getLHS();
11800 RHS = Cond->getRHS();
11801 } else if (Call) {
11802 LHS = Call->getArg(0);
11803 RHS = Call->getArg(1);
11804 } else {
11805 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11806 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11807 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11808 return false;
11809 }
11810
11811 if ((Cond && Cond->getOpcode() == BO_EQ) ||
11812 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11813 C = S->getCond();
11814 D = BO->getRHS();
11815 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
11816 E = RHS;
11817 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
11818 E = LHS;
11819 } else {
11820 ErrorInfo.Error = ErrorTy::InvalidComparison;
11821 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11822 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11823 S->getCond()->getSourceRange();
11824 return false;
11825 }
11826 } else if ((Cond &&
11827 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11828 (Call &&
11829 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11830 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11831 E = BO->getRHS();
11832 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
11833 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
11834 C = S->getCond();
11835 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
11836 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
11837 C = S->getCond();
11838 IsXBinopExpr = false;
11839 } else {
11840 ErrorInfo.Error = ErrorTy::InvalidComparison;
11841 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11842 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11843 S->getCond()->getSourceRange();
11844 return false;
11845 }
11846 } else {
11847 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11848 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11849 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11850 return false;
11851 }
11852
11853 if (S->getElse()) {
11854 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11855 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11856 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11857 return false;
11858 }
11859
11860 return true;
11861}
11862
11863bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11864 ErrorInfoTy &ErrorInfo) {
11865 auto *BO = dyn_cast<BinaryOperator>(S);
11866 if (!BO) {
11867 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11868 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11869 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11870 return false;
11871 }
11872 if (BO->getOpcode() != BO_Assign) {
11873 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11874 ErrorInfo.ErrorLoc = BO->getExprLoc();
11875 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11876 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11877 return false;
11878 }
11879
11880 X = BO->getLHS();
11881
11882 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11883 if (!CO) {
11884 ErrorInfo.Error = ErrorTy::NotCondOp;
11885 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11886 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11887 return false;
11888 }
11889
11890 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11891 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11892 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11893 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11894 CO->getFalseExpr()->getSourceRange();
11895 return false;
11896 }
11897
11898 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11899 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
11900 Expr *LHS = nullptr;
11901 Expr *RHS = nullptr;
11902 if (Cond) {
11903 LHS = Cond->getLHS();
11904 RHS = Cond->getRHS();
11905 } else if (Call) {
11906 LHS = Call->getArg(0);
11907 RHS = Call->getArg(1);
11908 } else {
11909 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11910 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11911 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11912 CO->getCond()->getSourceRange();
11913 return false;
11914 }
11915
11916 if ((Cond && Cond->getOpcode() == BO_EQ) ||
11917 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
11918 C = CO->getCond();
11919 D = CO->getTrueExpr();
11920 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
11921 E = RHS;
11922 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
11923 E = LHS;
11924 } else {
11925 ErrorInfo.Error = ErrorTy::InvalidComparison;
11926 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11927 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11928 CO->getCond()->getSourceRange();
11929 return false;
11930 }
11931 } else if ((Cond &&
11932 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
11933 (Call &&
11934 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
11935 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
11936
11937 E = CO->getTrueExpr();
11938 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
11939 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
11940 C = CO->getCond();
11941 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
11942 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
11943 C = CO->getCond();
11944 IsXBinopExpr = false;
11945 } else {
11946 ErrorInfo.Error = ErrorTy::InvalidComparison;
11947 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11948 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11949 CO->getCond()->getSourceRange();
11950 return false;
11951 }
11952 } else {
11953 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11954 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11955 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11956 CO->getCond()->getSourceRange();
11957 return false;
11958 }
11959
11960 return true;
11961}
11962
11963bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11964 // 'x' and 'e' cannot be nullptr
11965 assert(X && E && "X and E cannot be nullptr");
11966
11967 if (!CheckValue(X, ErrorInfo, true))
11968 return false;
11969
11970 if (!CheckValue(E, ErrorInfo, false))
11971 return false;
11972
11973 if (D && !CheckValue(D, ErrorInfo, false))
11974 return false;
11975
11976 return true;
11977}
11978
11979bool OpenMPAtomicCompareChecker::checkStmt(
11980 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11981 auto *CS = dyn_cast<CompoundStmt>(S);
11982 if (CS) {
11983 if (CS->body_empty()) {
11984 ErrorInfo.Error = ErrorTy::NoStmt;
11985 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11986 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11987 return false;
11988 }
11989
11990 if (CS->size() != 1) {
11991 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11992 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11993 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11994 return false;
11995 }
11996 S = CS->body_front();
11997 }
11998
11999 auto Res = false;
12000
12001 if (auto *IS = dyn_cast<IfStmt>(S)) {
12002 // Check if the statement is in one of the following forms
12003 // (cond-update-stmt):
12004 // if (expr ordop x) { x = expr; }
12005 // if (x ordop expr) { x = expr; }
12006 // if (x == e) { x = d; }
12007 Res = checkCondUpdateStmt(IS, ErrorInfo);
12008 } else {
12009 // Check if the statement is in one of the following forms (cond-expr-stmt):
12010 // x = expr ordop x ? expr : x;
12011 // x = x ordop expr ? expr : x;
12012 // x = x == e ? d : x;
12013 Res = checkCondExprStmt(S, ErrorInfo);
12014 }
12015
12016 if (!Res)
12017 return false;
12018
12019 return checkType(ErrorInfo);
12020}
12021
12022class OpenMPAtomicCompareCaptureChecker final
12023 : public OpenMPAtomicCompareChecker {
12024public:
12025 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12026
12027 Expr *getV() const { return V; }
12028 Expr *getR() const { return R; }
12029 bool isFailOnly() const { return IsFailOnly; }
12030 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12031
12032 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12033 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12034
12035private:
12036 bool checkType(ErrorInfoTy &ErrorInfo);
12037
12038 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12039 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12040 // spec p.p. 82:
12041 // (1) { v = x; cond-update-stmt }
12042 // (2) { cond-update-stmt v = x; }
12043 // (3) if(x == e) { x = d; } else { v = x; }
12044 // (4) { r = x == e; if(r) { x = d; } }
12045 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12046
12047 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12048 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12049
12050 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12051 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12052 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12053
12054 /// 'v' lvalue part of the source atomic expression.
12055 Expr *V = nullptr;
12056 /// 'r' lvalue part of the source atomic expression.
12057 Expr *R = nullptr;
12058 /// If 'v' is only updated when the comparison fails.
12059 bool IsFailOnly = false;
12060 /// If original value of 'x' must be stored in 'v', not an updated one.
12061 bool IsPostfixUpdate = false;
12062};
12063
12064bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12065 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12066 return false;
12067
12068 if (V && !CheckValue(V, ErrorInfo, true))
12069 return false;
12070
12071 if (R && !CheckValue(R, ErrorInfo, true, true))
12072 return false;
12073
12074 return true;
12075}
12076
12077bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12078 ErrorInfoTy &ErrorInfo) {
12079 IsFailOnly = true;
12080
12081 auto *Then = S->getThen();
12082 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12083 if (CS->body_empty()) {
12084 ErrorInfo.Error = ErrorTy::NoStmt;
12085 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12086 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12087 return false;
12088 }
12089 if (CS->size() > 1) {
12090 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12091 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12092 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12093 return false;
12094 }
12095 Then = CS->body_front();
12096 }
12097
12098 auto *BO = dyn_cast<BinaryOperator>(Then);
12099 if (!BO) {
12100 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12101 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12102 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12103 return false;
12104 }
12105 if (BO->getOpcode() != BO_Assign) {
12106 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12107 ErrorInfo.ErrorLoc = BO->getExprLoc();
12108 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12109 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12110 return false;
12111 }
12112
12113 X = BO->getLHS();
12114 D = BO->getRHS();
12115
12116 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12117 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12118 Expr *LHS = nullptr;
12119 Expr *RHS = nullptr;
12120 if (Cond) {
12121 LHS = Cond->getLHS();
12122 RHS = Cond->getRHS();
12123 } else if (Call) {
12124 LHS = Call->getArg(0);
12125 RHS = Call->getArg(1);
12126 } else {
12127 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12128 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12129 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12130 return false;
12131 }
12132 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12133 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12134 ErrorInfo.Error = ErrorTy::NotEQ;
12135 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12136 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12137 return false;
12138 }
12139
12140 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12141 E = RHS;
12142 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12143 E = LHS;
12144 } else {
12145 ErrorInfo.Error = ErrorTy::InvalidComparison;
12146 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12147 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12148 return false;
12149 }
12150
12151 C = S->getCond();
12152
12153 if (!S->getElse()) {
12154 ErrorInfo.Error = ErrorTy::NoElse;
12155 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12156 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12157 return false;
12158 }
12159
12160 auto *Else = S->getElse();
12161 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12162 if (CS->body_empty()) {
12163 ErrorInfo.Error = ErrorTy::NoStmt;
12164 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12165 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12166 return false;
12167 }
12168 if (CS->size() > 1) {
12169 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12170 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12171 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12172 return false;
12173 }
12174 Else = CS->body_front();
12175 }
12176
12177 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12178 if (!ElseBO) {
12179 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12180 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12181 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12182 return false;
12183 }
12184 if (ElseBO->getOpcode() != BO_Assign) {
12185 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12186 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12187 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12188 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12189 return false;
12190 }
12191
12192 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12193 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12194 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12195 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12196 ElseBO->getRHS()->getSourceRange();
12197 return false;
12198 }
12199
12200 V = ElseBO->getLHS();
12201
12202 return checkType(ErrorInfo);
12203}
12204
12205bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12206 ErrorInfoTy &ErrorInfo) {
12207 // We don't check here as they should be already done before call this
12208 // function.
12209 auto *CS = cast<CompoundStmt>(S);
12210 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12211 auto *S1 = cast<BinaryOperator>(CS->body_front());
12212 auto *S2 = cast<IfStmt>(CS->body_back());
12213 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12214
12215 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12216 ErrorInfo.Error = ErrorTy::InvalidCondition;
12217 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12218 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12219 return false;
12220 }
12221
12222 R = S1->getLHS();
12223
12224 auto *Then = S2->getThen();
12225 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12226 if (ThenCS->body_empty()) {
12227 ErrorInfo.Error = ErrorTy::NoStmt;
12228 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12229 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12230 return false;
12231 }
12232 if (ThenCS->size() > 1) {
12233 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12234 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12235 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12236 return false;
12237 }
12238 Then = ThenCS->body_front();
12239 }
12240
12241 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12242 if (!ThenBO) {
12243 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12244 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12245 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12246 return false;
12247 }
12248 if (ThenBO->getOpcode() != BO_Assign) {
12249 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12250 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12251 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12252 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12253 return false;
12254 }
12255
12256 X = ThenBO->getLHS();
12257 D = ThenBO->getRHS();
12258
12259 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12260 if (BO->getOpcode() != BO_EQ) {
12261 ErrorInfo.Error = ErrorTy::NotEQ;
12262 ErrorInfo.ErrorLoc = BO->getExprLoc();
12263 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12264 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12265 return false;
12266 }
12267
12268 C = BO;
12269
12270 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12271 E = BO->getRHS();
12272 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12273 E = BO->getLHS();
12274 } else {
12275 ErrorInfo.Error = ErrorTy::InvalidComparison;
12276 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12277 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12278 return false;
12279 }
12280
12281 if (S2->getElse()) {
12282 IsFailOnly = true;
12283
12284 auto *Else = S2->getElse();
12285 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12286 if (ElseCS->body_empty()) {
12287 ErrorInfo.Error = ErrorTy::NoStmt;
12288 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12289 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12290 return false;
12291 }
12292 if (ElseCS->size() > 1) {
12293 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12294 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12295 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12296 return false;
12297 }
12298 Else = ElseCS->body_front();
12299 }
12300
12301 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12302 if (!ElseBO) {
12303 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12304 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12305 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12306 return false;
12307 }
12308 if (ElseBO->getOpcode() != BO_Assign) {
12309 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12310 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12311 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12312 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12313 return false;
12314 }
12315 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12316 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12317 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12318 ErrorInfo.NoteLoc = X->getExprLoc();
12319 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12320 ErrorInfo.NoteRange = X->getSourceRange();
12321 return false;
12322 }
12323
12324 V = ElseBO->getLHS();
12325 }
12326
12327 return checkType(ErrorInfo);
12328}
12329
12330bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12331 ErrorInfoTy &ErrorInfo) {
12332 // if(x == e) { x = d; } else { v = x; }
12333 if (auto *IS = dyn_cast<IfStmt>(S))
12334 return checkForm3(IS, ErrorInfo);
12335
12336 auto *CS = dyn_cast<CompoundStmt>(S);
12337 if (!CS) {
12338 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12339 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12340 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12341 return false;
12342 }
12343 if (CS->body_empty()) {
12344 ErrorInfo.Error = ErrorTy::NoStmt;
12345 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12346 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12347 return false;
12348 }
12349
12350 // { if(x == e) { x = d; } else { v = x; } }
12351 if (CS->size() == 1) {
12352 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12353 if (!IS) {
12354 ErrorInfo.Error = ErrorTy::NotIfStmt;
12355 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12356 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12357 CS->body_front()->getSourceRange();
12358 return false;
12359 }
12360
12361 return checkForm3(IS, ErrorInfo);
12362 } else if (CS->size() == 2) {
12363 auto *S1 = CS->body_front();
12364 auto *S2 = CS->body_back();
12365
12366 Stmt *UpdateStmt = nullptr;
12367 Stmt *CondUpdateStmt = nullptr;
12368 Stmt *CondExprStmt = nullptr;
12369
12370 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12371 // It could be one of the following cases:
12372 // { v = x; cond-update-stmt }
12373 // { v = x; cond-expr-stmt }
12374 // { cond-expr-stmt; v = x; }
12375 // form 45
12376 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12377 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12378 // check if form 45
12379 if (isa<IfStmt>(S2))
12380 return checkForm45(CS, ErrorInfo);
12381 // { cond-expr-stmt; v = x; }
12382 CondExprStmt = S1;
12383 UpdateStmt = S2;
12384 } else {
12385 IsPostfixUpdate = true;
12386 UpdateStmt = S1;
12387 if (isa<IfStmt>(S2)) {
12388 // { v = x; cond-update-stmt }
12389 CondUpdateStmt = S2;
12390 } else {
12391 // { v = x; cond-expr-stmt }
12392 CondExprStmt = S2;
12393 }
12394 }
12395 } else {
12396 // { cond-update-stmt v = x; }
12397 UpdateStmt = S2;
12398 CondUpdateStmt = S1;
12399 }
12400
12401 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12402 auto *IS = dyn_cast<IfStmt>(CUS);
12403 if (!IS) {
12404 ErrorInfo.Error = ErrorTy::NotIfStmt;
12405 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12406 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12407 return false;
12408 }
12409
12410 return checkCondUpdateStmt(IS, ErrorInfo);
12411 };
12412
12413 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12414 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12415 auto *BO = dyn_cast<BinaryOperator>(US);
12416 if (!BO) {
12417 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12418 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12419 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12420 return false;
12421 }
12422 if (BO->getOpcode() != BO_Assign) {
12423 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12424 ErrorInfo.ErrorLoc = BO->getExprLoc();
12425 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12426 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12427 return false;
12428 }
12429 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12430 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12431 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12432 ErrorInfo.NoteLoc = this->X->getExprLoc();
12433 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12434 ErrorInfo.NoteRange = this->X->getSourceRange();
12435 return false;
12436 }
12437
12438 this->V = BO->getLHS();
12439
12440 return true;
12441 };
12442
12443 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12444 return false;
12445 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12446 return false;
12447 if (!CheckUpdateStmt(UpdateStmt))
12448 return false;
12449 } else {
12450 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12451 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12452 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12453 return false;
12454 }
12455
12456 return checkType(ErrorInfo);
12457}
12458} // namespace
12459
12461 Stmt *AStmt,
12462 SourceLocation StartLoc,
12463 SourceLocation EndLoc) {
12464 ASTContext &Context = getASTContext();
12465 unsigned OMPVersion = getLangOpts().OpenMP;
12466 // Register location of the first atomic directive.
12467 DSAStack->addAtomicDirectiveLoc(StartLoc);
12468 if (!AStmt)
12469 return StmtError();
12470
12471 // 1.2.2 OpenMP Language Terminology
12472 // Structured block - An executable statement with a single entry at the
12473 // top and a single exit at the bottom.
12474 // The point of exit cannot be a branch out of the structured block.
12475 // longjmp() and throw() must not violate the entry/exit criteria.
12476 OpenMPClauseKind AtomicKind = OMPC_unknown;
12477 SourceLocation AtomicKindLoc;
12478 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12479 SourceLocation MemOrderLoc;
12480 bool MutexClauseEncountered = false;
12481 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12482 for (const OMPClause *C : Clauses) {
12483 switch (C->getClauseKind()) {
12484 case OMPC_read:
12485 case OMPC_write:
12486 case OMPC_update:
12487 MutexClauseEncountered = true;
12488 [[fallthrough]];
12489 case OMPC_capture:
12490 case OMPC_compare: {
12491 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12492 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12493 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12494 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12495 << getOpenMPClauseNameForDiag(AtomicKind);
12496 } else {
12497 AtomicKind = C->getClauseKind();
12498 AtomicKindLoc = C->getBeginLoc();
12499 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12500 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12501 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12502 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12503 << getOpenMPClauseNameForDiag(AtomicKind);
12504 }
12505 }
12506 break;
12507 }
12508 case OMPC_weak:
12509 case OMPC_fail: {
12510 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12511 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12512 << getOpenMPClauseNameForDiag(C->getClauseKind())
12513 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12514 return StmtError();
12515 }
12516 break;
12517 }
12518 case OMPC_seq_cst:
12519 case OMPC_acq_rel:
12520 case OMPC_acquire:
12521 case OMPC_release:
12522 case OMPC_relaxed: {
12523 if (MemOrderKind != OMPC_unknown) {
12524 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12525 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12526 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12527 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12528 << getOpenMPClauseNameForDiag(MemOrderKind);
12529 } else {
12530 MemOrderKind = C->getClauseKind();
12531 MemOrderLoc = C->getBeginLoc();
12532 }
12533 break;
12534 }
12535 // The following clauses are allowed, but we don't need to do anything here.
12536 case OMPC_hint:
12537 break;
12538 default:
12539 llvm_unreachable("unknown clause is encountered");
12540 }
12541 }
12542 bool IsCompareCapture = false;
12543 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12544 EncounteredAtomicKinds.contains(OMPC_capture)) {
12545 IsCompareCapture = true;
12546 AtomicKind = OMPC_compare;
12547 }
12548 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12549 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12550 // release.
12551 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12552 // acquire.
12553 // If atomic-clause is update or not present then memory-order-clause must not
12554 // be acq_rel or acquire.
12555 if ((AtomicKind == OMPC_read &&
12556 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12557 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12558 AtomicKind == OMPC_unknown) &&
12559 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12560 SourceLocation Loc = AtomicKindLoc;
12561 if (AtomicKind == OMPC_unknown)
12562 Loc = StartLoc;
12563 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12564 << getOpenMPClauseNameForDiag(AtomicKind)
12565 << (AtomicKind == OMPC_unknown ? 1 : 0)
12566 << getOpenMPClauseNameForDiag(MemOrderKind);
12567 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12568 << getOpenMPClauseNameForDiag(MemOrderKind);
12569 }
12570
12571 Stmt *Body = AStmt;
12572 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12573 Body = EWC->getSubExpr();
12574
12575 Expr *X = nullptr;
12576 Expr *V = nullptr;
12577 Expr *E = nullptr;
12578 Expr *UE = nullptr;
12579 Expr *D = nullptr;
12580 Expr *CE = nullptr;
12581 Expr *R = nullptr;
12582 bool IsXLHSInRHSPart = false;
12583 bool IsPostfixUpdate = false;
12584 bool IsFailOnly = false;
12585 // OpenMP [2.12.6, atomic Construct]
12586 // In the next expressions:
12587 // * x and v (as applicable) are both l-value expressions with scalar type.
12588 // * During the execution of an atomic region, multiple syntactic
12589 // occurrences of x must designate the same storage location.
12590 // * Neither of v and expr (as applicable) may access the storage location
12591 // designated by x.
12592 // * Neither of x and expr (as applicable) may access the storage location
12593 // designated by v.
12594 // * expr is an expression with scalar type.
12595 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12596 // * binop, binop=, ++, and -- are not overloaded operators.
12597 // * The expression x binop expr must be numerically equivalent to x binop
12598 // (expr). This requirement is satisfied if the operators in expr have
12599 // precedence greater than binop, or by using parentheses around expr or
12600 // subexpressions of expr.
12601 // * The expression expr binop x must be numerically equivalent to (expr)
12602 // binop x. This requirement is satisfied if the operators in expr have
12603 // precedence equal to or greater than binop, or by using parentheses around
12604 // expr or subexpressions of expr.
12605 // * For forms that allow multiple occurrences of x, the number of times
12606 // that x is evaluated is unspecified.
12607 if (AtomicKind == OMPC_read) {
12608 enum {
12609 NotAnExpression,
12610 NotAnAssignmentOp,
12611 NotAScalarType,
12612 NotAnLValue,
12613 NoError
12614 } ErrorFound = NoError;
12615 SourceLocation ErrorLoc, NoteLoc;
12616 SourceRange ErrorRange, NoteRange;
12617 // If clause is read:
12618 // v = x;
12619 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12620 const auto *AtomicBinOp =
12621 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12622 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12623 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12624 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12625 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12626 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12627 if (!X->isLValue() || !V->isLValue()) {
12628 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12629 ErrorFound = NotAnLValue;
12630 ErrorLoc = AtomicBinOp->getExprLoc();
12631 ErrorRange = AtomicBinOp->getSourceRange();
12632 NoteLoc = NotLValueExpr->getExprLoc();
12633 NoteRange = NotLValueExpr->getSourceRange();
12634 }
12635 } else if (!X->isInstantiationDependent() ||
12636 !V->isInstantiationDependent()) {
12637 const Expr *NotScalarExpr =
12638 (X->isInstantiationDependent() || X->getType()->isScalarType())
12639 ? V
12640 : X;
12641 ErrorFound = NotAScalarType;
12642 ErrorLoc = AtomicBinOp->getExprLoc();
12643 ErrorRange = AtomicBinOp->getSourceRange();
12644 NoteLoc = NotScalarExpr->getExprLoc();
12645 NoteRange = NotScalarExpr->getSourceRange();
12646 }
12647 } else if (!AtomicBody->isInstantiationDependent()) {
12648 ErrorFound = NotAnAssignmentOp;
12649 ErrorLoc = AtomicBody->getExprLoc();
12650 ErrorRange = AtomicBody->getSourceRange();
12651 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12652 : AtomicBody->getExprLoc();
12653 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12654 : AtomicBody->getSourceRange();
12655 }
12656 } else {
12657 ErrorFound = NotAnExpression;
12658 NoteLoc = ErrorLoc = Body->getBeginLoc();
12659 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12660 }
12661 if (ErrorFound != NoError) {
12662 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12663 << ErrorRange;
12664 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12665 << ErrorFound << NoteRange;
12666 return StmtError();
12667 }
12669 V = X = nullptr;
12670 } else if (AtomicKind == OMPC_write) {
12671 enum {
12672 NotAnExpression,
12673 NotAnAssignmentOp,
12674 NotAScalarType,
12675 NotAnLValue,
12676 NoError
12677 } ErrorFound = NoError;
12678 SourceLocation ErrorLoc, NoteLoc;
12679 SourceRange ErrorRange, NoteRange;
12680 // If clause is write:
12681 // x = expr;
12682 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12683 const auto *AtomicBinOp =
12684 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12685 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12686 X = AtomicBinOp->getLHS();
12687 E = AtomicBinOp->getRHS();
12688 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12690 if (!X->isLValue()) {
12691 ErrorFound = NotAnLValue;
12692 ErrorLoc = AtomicBinOp->getExprLoc();
12693 ErrorRange = AtomicBinOp->getSourceRange();
12694 NoteLoc = X->getExprLoc();
12695 NoteRange = X->getSourceRange();
12696 }
12697 } else if (!X->isInstantiationDependent() ||
12699 const Expr *NotScalarExpr =
12700 (X->isInstantiationDependent() || X->getType()->isScalarType())
12701 ? E
12702 : X;
12703 ErrorFound = NotAScalarType;
12704 ErrorLoc = AtomicBinOp->getExprLoc();
12705 ErrorRange = AtomicBinOp->getSourceRange();
12706 NoteLoc = NotScalarExpr->getExprLoc();
12707 NoteRange = NotScalarExpr->getSourceRange();
12708 }
12709 } else if (!AtomicBody->isInstantiationDependent()) {
12710 ErrorFound = NotAnAssignmentOp;
12711 ErrorLoc = AtomicBody->getExprLoc();
12712 ErrorRange = AtomicBody->getSourceRange();
12713 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12714 : AtomicBody->getExprLoc();
12715 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12716 : AtomicBody->getSourceRange();
12717 }
12718 } else {
12719 ErrorFound = NotAnExpression;
12720 NoteLoc = ErrorLoc = Body->getBeginLoc();
12721 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12722 }
12723 if (ErrorFound != NoError) {
12724 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12725 << ErrorRange;
12726 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12727 << ErrorFound << NoteRange;
12728 return StmtError();
12729 }
12731 E = X = nullptr;
12732 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12733 // If clause is update:
12734 // x++;
12735 // x--;
12736 // ++x;
12737 // --x;
12738 // x binop= expr;
12739 // x = x binop expr;
12740 // x = expr binop x;
12741 OpenMPAtomicUpdateChecker Checker(SemaRef);
12742 if (Checker.checkStatement(
12743 Body,
12744 (AtomicKind == OMPC_update)
12745 ? diag::err_omp_atomic_update_not_expression_statement
12746 : diag::err_omp_atomic_not_expression_statement,
12747 diag::note_omp_atomic_update))
12748 return StmtError();
12750 E = Checker.getExpr();
12751 X = Checker.getX();
12752 UE = Checker.getUpdateExpr();
12753 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12754 }
12755 } else if (AtomicKind == OMPC_capture) {
12756 enum {
12757 NotAnAssignmentOp,
12758 NotACompoundStatement,
12759 NotTwoSubstatements,
12760 NotASpecificExpression,
12761 NoError
12762 } ErrorFound = NoError;
12763 SourceLocation ErrorLoc, NoteLoc;
12764 SourceRange ErrorRange, NoteRange;
12765 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12766 // If clause is a capture:
12767 // v = x++;
12768 // v = x--;
12769 // v = ++x;
12770 // v = --x;
12771 // v = x binop= expr;
12772 // v = x = x binop expr;
12773 // v = x = expr binop x;
12774 const auto *AtomicBinOp =
12775 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12776 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12777 V = AtomicBinOp->getLHS();
12778 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12779 OpenMPAtomicUpdateChecker Checker(SemaRef);
12780 if (Checker.checkStatement(
12781 Body, diag::err_omp_atomic_capture_not_expression_statement,
12782 diag::note_omp_atomic_update))
12783 return StmtError();
12784 E = Checker.getExpr();
12785 X = Checker.getX();
12786 UE = Checker.getUpdateExpr();
12787 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12788 IsPostfixUpdate = Checker.isPostfixUpdate();
12789 } else if (!AtomicBody->isInstantiationDependent()) {
12790 ErrorLoc = AtomicBody->getExprLoc();
12791 ErrorRange = AtomicBody->getSourceRange();
12792 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12793 : AtomicBody->getExprLoc();
12794 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12795 : AtomicBody->getSourceRange();
12796 ErrorFound = NotAnAssignmentOp;
12797 }
12798 if (ErrorFound != NoError) {
12799 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12800 << ErrorRange;
12801 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12802 return StmtError();
12803 }
12805 UE = V = E = X = nullptr;
12806 } else {
12807 // If clause is a capture:
12808 // { v = x; x = expr; }
12809 // { v = x; x++; }
12810 // { v = x; x--; }
12811 // { v = x; ++x; }
12812 // { v = x; --x; }
12813 // { v = x; x binop= expr; }
12814 // { v = x; x = x binop expr; }
12815 // { v = x; x = expr binop x; }
12816 // { x++; v = x; }
12817 // { x--; v = x; }
12818 // { ++x; v = x; }
12819 // { --x; v = x; }
12820 // { x binop= expr; v = x; }
12821 // { x = x binop expr; v = x; }
12822 // { x = expr binop x; v = x; }
12823 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12824 // Check that this is { expr1; expr2; }
12825 if (CS->size() == 2) {
12826 Stmt *First = CS->body_front();
12827 Stmt *Second = CS->body_back();
12828 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12829 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12830 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12831 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12832 // Need to find what subexpression is 'v' and what is 'x'.
12833 OpenMPAtomicUpdateChecker Checker(SemaRef);
12834 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12835 BinaryOperator *BinOp = nullptr;
12836 if (IsUpdateExprFound) {
12837 BinOp = dyn_cast<BinaryOperator>(First);
12838 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12839 }
12840 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12841 // { v = x; x++; }
12842 // { v = x; x--; }
12843 // { v = x; ++x; }
12844 // { v = x; --x; }
12845 // { v = x; x binop= expr; }
12846 // { v = x; x = x binop expr; }
12847 // { v = x; x = expr binop x; }
12848 // Check that the first expression has form v = x.
12849 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12850 llvm::FoldingSetNodeID XId, PossibleXId;
12851 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12852 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12853 IsUpdateExprFound = XId == PossibleXId;
12854 if (IsUpdateExprFound) {
12855 V = BinOp->getLHS();
12856 X = Checker.getX();
12857 E = Checker.getExpr();
12858 UE = Checker.getUpdateExpr();
12859 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12860 IsPostfixUpdate = true;
12861 }
12862 }
12863 if (!IsUpdateExprFound) {
12864 IsUpdateExprFound = !Checker.checkStatement(First);
12865 BinOp = nullptr;
12866 if (IsUpdateExprFound) {
12867 BinOp = dyn_cast<BinaryOperator>(Second);
12868 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12869 }
12870 if (IsUpdateExprFound &&
12872 // { x++; v = x; }
12873 // { x--; v = x; }
12874 // { ++x; v = x; }
12875 // { --x; v = x; }
12876 // { x binop= expr; v = x; }
12877 // { x = x binop expr; v = x; }
12878 // { x = expr binop x; v = x; }
12879 // Check that the second expression has form v = x.
12880 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12881 llvm::FoldingSetNodeID XId, PossibleXId;
12882 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12883 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12884 IsUpdateExprFound = XId == PossibleXId;
12885 if (IsUpdateExprFound) {
12886 V = BinOp->getLHS();
12887 X = Checker.getX();
12888 E = Checker.getExpr();
12889 UE = Checker.getUpdateExpr();
12890 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12891 IsPostfixUpdate = false;
12892 }
12893 }
12894 }
12895 if (!IsUpdateExprFound) {
12896 // { v = x; x = expr; }
12897 auto *FirstExpr = dyn_cast<Expr>(First);
12898 auto *SecondExpr = dyn_cast<Expr>(Second);
12899 if (!FirstExpr || !SecondExpr ||
12900 !(FirstExpr->isInstantiationDependent() ||
12901 SecondExpr->isInstantiationDependent())) {
12902 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12903 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12904 ErrorFound = NotAnAssignmentOp;
12905 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12906 : First->getBeginLoc();
12907 NoteRange = ErrorRange = FirstBinOp
12908 ? FirstBinOp->getSourceRange()
12909 : SourceRange(ErrorLoc, ErrorLoc);
12910 } else {
12911 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12912 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12913 ErrorFound = NotAnAssignmentOp;
12914 NoteLoc = ErrorLoc = SecondBinOp
12915 ? SecondBinOp->getOperatorLoc()
12916 : Second->getBeginLoc();
12917 NoteRange = ErrorRange =
12918 SecondBinOp ? SecondBinOp->getSourceRange()
12919 : SourceRange(ErrorLoc, ErrorLoc);
12920 } else {
12921 Expr *PossibleXRHSInFirst =
12922 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12923 Expr *PossibleXLHSInSecond =
12924 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12925 llvm::FoldingSetNodeID X1Id, X2Id;
12926 PossibleXRHSInFirst->Profile(X1Id, Context,
12927 /*Canonical=*/true);
12928 PossibleXLHSInSecond->Profile(X2Id, Context,
12929 /*Canonical=*/true);
12930 IsUpdateExprFound = X1Id == X2Id;
12931 if (IsUpdateExprFound) {
12932 V = FirstBinOp->getLHS();
12933 X = SecondBinOp->getLHS();
12934 E = SecondBinOp->getRHS();
12935 UE = nullptr;
12936 IsXLHSInRHSPart = false;
12937 IsPostfixUpdate = true;
12938 } else {
12939 ErrorFound = NotASpecificExpression;
12940 ErrorLoc = FirstBinOp->getExprLoc();
12941 ErrorRange = FirstBinOp->getSourceRange();
12942 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12943 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12944 }
12945 }
12946 }
12947 }
12948 }
12949 } else {
12950 NoteLoc = ErrorLoc = Body->getBeginLoc();
12951 NoteRange = ErrorRange =
12952 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12953 ErrorFound = NotTwoSubstatements;
12954 }
12955 } else {
12956 NoteLoc = ErrorLoc = Body->getBeginLoc();
12957 NoteRange = ErrorRange =
12958 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12959 ErrorFound = NotACompoundStatement;
12960 }
12961 }
12962 if (ErrorFound != NoError) {
12963 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12964 << ErrorRange;
12965 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12966 return StmtError();
12967 }
12969 UE = V = E = X = nullptr;
12970 } else if (AtomicKind == OMPC_compare) {
12971 if (IsCompareCapture) {
12972 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12973 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12974 if (!Checker.checkStmt(Body, ErrorInfo)) {
12975 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12976 << ErrorInfo.ErrorRange;
12977 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12978 << ErrorInfo.Error << ErrorInfo.NoteRange;
12979 return StmtError();
12980 }
12981 X = Checker.getX();
12982 E = Checker.getE();
12983 D = Checker.getD();
12984 CE = Checker.getCond();
12985 V = Checker.getV();
12986 R = Checker.getR();
12987 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12988 IsXLHSInRHSPart = Checker.isXBinopExpr();
12989 IsFailOnly = Checker.isFailOnly();
12990 IsPostfixUpdate = Checker.isPostfixUpdate();
12991 } else {
12992 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12993 OpenMPAtomicCompareChecker Checker(SemaRef);
12994 if (!Checker.checkStmt(Body, ErrorInfo)) {
12995 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12996 << ErrorInfo.ErrorRange;
12997 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12998 << ErrorInfo.Error << ErrorInfo.NoteRange;
12999 return StmtError();
13000 }
13001 X = Checker.getX();
13002 E = Checker.getE();
13003 D = Checker.getD();
13004 CE = Checker.getCond();
13005 // The weak clause may only appear if the resulting atomic operation is
13006 // an atomic conditional update for which the comparison tests for
13007 // equality. It was not possible to do this check in
13008 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13009 // could not be performed (Clauses are not available).
13010 auto *It = find_if(Clauses, [](OMPClause *C) {
13011 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13012 });
13013 if (It != Clauses.end()) {
13014 auto *Cond = dyn_cast<BinaryOperator>(CE);
13015 if (Cond->getOpcode() != BO_EQ) {
13016 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13017 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13018 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13019 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13020
13021 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13022 << ErrorInfo.ErrorRange;
13023 return StmtError();
13024 }
13025 }
13026 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13027 IsXLHSInRHSPart = Checker.isXBinopExpr();
13028 }
13029 }
13030
13032
13034 Context, StartLoc, EndLoc, Clauses, AStmt,
13035 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13036}
13037
13039 Stmt *AStmt,
13040 SourceLocation StartLoc,
13041 SourceLocation EndLoc) {
13042 if (!AStmt)
13043 return StmtError();
13044
13045 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13046
13047 // OpenMP [2.16, Nesting of Regions]
13048 // If specified, a teams construct must be contained within a target
13049 // construct. That target construct must contain no statements or directives
13050 // outside of the teams construct.
13051 if (DSAStack->hasInnerTeamsRegion()) {
13052 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13053 bool OMPTeamsFound = true;
13054 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13055 auto I = CS->body_begin();
13056 while (I != CS->body_end()) {
13057 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13058 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13059 if (!IsTeams || I != CS->body_begin()) {
13060 OMPTeamsFound = false;
13061 if (IsTeams && I != CS->body_begin()) {
13062 // This is the two teams case. Since the InnerTeamsRegionLoc will
13063 // point to this second one reset the iterator to the other teams.
13064 --I;
13065 }
13066 break;
13067 }
13068 ++I;
13069 }
13070 assert(I != CS->body_end() && "Not found statement");
13071 S = *I;
13072 } else {
13073 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13074 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13075 }
13076 if (!OMPTeamsFound) {
13077 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13078 Diag(DSAStack->getInnerTeamsRegionLoc(),
13079 diag::note_omp_nested_teams_construct_here);
13080 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13081 << isa<OMPExecutableDirective>(S);
13082 return StmtError();
13083 }
13084 }
13085
13086 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13087 AStmt);
13088}
13089
13091 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13092 SourceLocation EndLoc) {
13093 if (!AStmt)
13094 return StmtError();
13095
13096 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13097
13099 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13100 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13101}
13102
13104 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13105 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13106 if (!AStmt)
13107 return StmtError();
13108
13109 CapturedStmt *CS =
13110 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13111
13113 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13114 // define the nested loops number.
13115 unsigned NestedLoopCount =
13116 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13117 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13118 VarsWithImplicitDSA, B);
13119 if (NestedLoopCount == 0)
13120 return StmtError();
13121
13122 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13123 return StmtError();
13124
13126 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13127 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13128}
13129
13130/// Check for existence of a map clause in the list of clauses.
13132 const OpenMPClauseKind K) {
13133 return llvm::any_of(
13134 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13135}
13136
13137template <typename... Params>
13139 const Params... ClauseTypes) {
13140 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13141}
13142
13143/// Check if the variables in the mapping clause are externally visible.
13145 for (const OMPClause *C : Clauses) {
13146 if (auto *TC = dyn_cast<OMPToClause>(C))
13147 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13148 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13149 (VD->isExternallyVisible() &&
13150 VD->getVisibility() != HiddenVisibility);
13151 });
13152 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13153 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13154 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13155 (VD->isExternallyVisible() &&
13156 VD->getVisibility() != HiddenVisibility);
13157 });
13158 }
13159
13160 return true;
13161}
13162
13165 Stmt *AStmt, SourceLocation StartLoc,
13166 SourceLocation EndLoc) {
13167 if (!AStmt)
13168 return StmtError();
13169
13170 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13171
13172 // OpenMP [2.12.2, target data Construct, Restrictions]
13173 // At least one map, use_device_addr or use_device_ptr clause must appear on
13174 // the directive.
13175 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13176 (getLangOpts().OpenMP < 50 ||
13177 !hasClauses(Clauses, OMPC_use_device_addr))) {
13178 StringRef Expected;
13179 if (getLangOpts().OpenMP < 50)
13180 Expected = "'map' or 'use_device_ptr'";
13181 else
13182 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13183 unsigned OMPVersion = getLangOpts().OpenMP;
13184 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13185 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13186 return StmtError();
13187 }
13188
13190
13191 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13192 Clauses, AStmt);
13193}
13194
13196 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13197 SourceLocation EndLoc, Stmt *AStmt) {
13198 if (!AStmt)
13199 return StmtError();
13200
13201 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13202
13203 // OpenMP [2.10.2, Restrictions, p. 99]
13204 // At least one map clause must appear on the directive.
13205 if (!hasClauses(Clauses, OMPC_map)) {
13206 unsigned OMPVersion = getLangOpts().OpenMP;
13207 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13208 << "'map'"
13209 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13210 return StmtError();
13211 }
13212
13213 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13214 Clauses, AStmt);
13215}
13216
13218 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13219 SourceLocation EndLoc, Stmt *AStmt) {
13220 if (!AStmt)
13221 return StmtError();
13222
13223 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13224
13225 // OpenMP [2.10.3, Restrictions, p. 102]
13226 // At least one map clause must appear on the directive.
13227 if (!hasClauses(Clauses, OMPC_map)) {
13228 unsigned OMPVersion = getLangOpts().OpenMP;
13229 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13230 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13231 return StmtError();
13232 }
13233
13234 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13235 Clauses, AStmt);
13236}
13237
13239 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13240 SourceLocation EndLoc, Stmt *AStmt) {
13241 if (!AStmt)
13242 return StmtError();
13243
13244 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13245
13246 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13247 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13248 return StmtError();
13249 }
13250
13251 if (!isClauseMappable(Clauses)) {
13252 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13253 return StmtError();
13254 }
13255
13256 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13257 Clauses, AStmt);
13258}
13259
13260/// This checks whether a \p ClauseType clause \p C has at most \p Max
13261/// expression. If not, a diag of number \p Diag will be emitted.
13262template <typename ClauseType>
13263static bool checkNumExprsInClause(SemaBase &SemaRef,
13264 ArrayRef<OMPClause *> Clauses,
13265 unsigned MaxNum, unsigned Diag) {
13266 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13267 if (ClauseItr == Clauses.end())
13268 return true;
13269 const auto *C = cast<ClauseType>(*ClauseItr);
13270 auto VarList = C->getVarRefs();
13271 if (VarList.size() > MaxNum) {
13272 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13273 << getOpenMPClauseNameForDiag(C->getClauseKind());
13274 return false;
13275 }
13276 return true;
13277}
13278
13280 Stmt *AStmt,
13281 SourceLocation StartLoc,
13282 SourceLocation EndLoc) {
13283 if (!AStmt)
13284 return StmtError();
13285
13286 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13287 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13288 !checkNumExprsInClause<OMPThreadLimitClause>(
13289 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13290 return StmtError();
13291
13292 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13293 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13294 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13295
13296 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13297
13298 DSAStack->setParentTeamsRegionLoc(StartLoc);
13299
13300 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13301 AStmt);
13302}
13303
13305 SourceLocation StartLoc, SourceLocation EndLoc,
13306 OpenMPDirectiveKind CancelRegion) {
13307 if (DSAStack->isParentNowaitRegion()) {
13308 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13309 return StmtError();
13310 }
13311 if (DSAStack->isParentOrderedRegion()) {
13312 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13313 return StmtError();
13314 }
13316 EndLoc, CancelRegion);
13317}
13318
13320 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13321 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13322 if (DSAStack->isParentNowaitRegion()) {
13323 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13324 return StmtError();
13325 }
13326 if (DSAStack->isParentOrderedRegion()) {
13327 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13328 return StmtError();
13329 }
13330 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13331 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13332 CancelRegion);
13333}
13334
13336 ArrayRef<OMPClause *> Clauses) {
13337 const OMPClause *ReductionClause = nullptr;
13338 const OMPClause *NogroupClause = nullptr;
13339 for (const OMPClause *C : Clauses) {
13340 if (C->getClauseKind() == OMPC_reduction) {
13341 ReductionClause = C;
13342 if (NogroupClause)
13343 break;
13344 continue;
13345 }
13346 if (C->getClauseKind() == OMPC_nogroup) {
13347 NogroupClause = C;
13348 if (ReductionClause)
13349 break;
13350 continue;
13351 }
13352 }
13353 if (ReductionClause && NogroupClause) {
13354 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13355 << SourceRange(NogroupClause->getBeginLoc(),
13356 NogroupClause->getEndLoc());
13357 return true;
13358 }
13359 return false;
13360}
13361
13363 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13364 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13365 if (!AStmt)
13366 return StmtError();
13367
13368 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13370 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13371 // define the nested loops number.
13372 unsigned NestedLoopCount =
13373 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13374 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13375 *DSAStack, VarsWithImplicitDSA, B);
13376 if (NestedLoopCount == 0)
13377 return StmtError();
13378
13379 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13380 "omp for loop exprs were not built");
13381
13382 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13383 // The grainsize clause and num_tasks clause are mutually exclusive and may
13384 // not appear on the same taskloop directive.
13386 {OMPC_grainsize, OMPC_num_tasks}))
13387 return StmtError();
13388 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13389 // If a reduction clause is present on the taskloop directive, the nogroup
13390 // clause must not be specified.
13392 return StmtError();
13393
13395 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13396 NestedLoopCount, Clauses, AStmt, B,
13397 DSAStack->isCancelRegion());
13398}
13399
13401 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13402 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13403 if (!AStmt)
13404 return StmtError();
13405
13406 CapturedStmt *CS =
13407 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13408
13409 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13411 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13412 // define the nested loops number.
13413 unsigned NestedLoopCount =
13414 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13415 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13416 VarsWithImplicitDSA, B);
13417 if (NestedLoopCount == 0)
13418 return StmtError();
13419
13420 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13421 return StmtError();
13422
13423 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13424 // The grainsize clause and num_tasks clause are mutually exclusive and may
13425 // not appear on the same taskloop directive.
13427 {OMPC_grainsize, OMPC_num_tasks}))
13428 return StmtError();
13429 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13430 // If a reduction clause is present on the taskloop directive, the nogroup
13431 // clause must not be specified.
13433 return StmtError();
13435 return StmtError();
13436
13437 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13438 NestedLoopCount, Clauses, AStmt, B);
13439}
13440
13442 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13443 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13444 if (!AStmt)
13445 return StmtError();
13446
13447 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13449 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13450 // define the nested loops number.
13451 unsigned NestedLoopCount =
13452 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13453 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13454 *DSAStack, VarsWithImplicitDSA, B);
13455 if (NestedLoopCount == 0)
13456 return StmtError();
13457
13458 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13459 "omp for loop exprs were not built");
13460
13461 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13462 // The grainsize clause and num_tasks clause are mutually exclusive and may
13463 // not appear on the same taskloop directive.
13465 {OMPC_grainsize, OMPC_num_tasks}))
13466 return StmtError();
13467 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13468 // If a reduction clause is present on the taskloop directive, the nogroup
13469 // clause must not be specified.
13471 return StmtError();
13472
13474 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13475 NestedLoopCount, Clauses, AStmt, B,
13476 DSAStack->isCancelRegion());
13477}
13478
13480 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13481 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13482 if (!AStmt)
13483 return StmtError();
13484
13485 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13487 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13488 // define the nested loops number.
13489 unsigned NestedLoopCount =
13490 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13491 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13492 *DSAStack, VarsWithImplicitDSA, B);
13493 if (NestedLoopCount == 0)
13494 return StmtError();
13495
13496 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13497 "omp for loop exprs were not built");
13498
13499 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13500 // The grainsize clause and num_tasks clause are mutually exclusive and may
13501 // not appear on the same taskloop directive.
13503 {OMPC_grainsize, OMPC_num_tasks}))
13504 return StmtError();
13505 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13506 // If a reduction clause is present on the taskloop directive, the nogroup
13507 // clause must not be specified.
13509 return StmtError();
13510
13512 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13513 NestedLoopCount, Clauses, AStmt, B,
13514 DSAStack->isCancelRegion());
13515}
13516
13518 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13519 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13520 if (!AStmt)
13521 return StmtError();
13522
13523 CapturedStmt *CS =
13524 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13525
13526 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13528 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13529 // define the nested loops number.
13530 unsigned NestedLoopCount =
13531 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13532 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13533 VarsWithImplicitDSA, B);
13534 if (NestedLoopCount == 0)
13535 return StmtError();
13536
13537 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13538 return StmtError();
13539
13540 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13541 // The grainsize clause and num_tasks clause are mutually exclusive and may
13542 // not appear on the same taskloop directive.
13544 {OMPC_grainsize, OMPC_num_tasks}))
13545 return StmtError();
13546 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13547 // If a reduction clause is present on the taskloop directive, the nogroup
13548 // clause must not be specified.
13550 return StmtError();
13552 return StmtError();
13553
13555 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13556}
13557
13559 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13560 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13561 if (!AStmt)
13562 return StmtError();
13563
13564 CapturedStmt *CS =
13565 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13566
13567 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13569 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13570 // define the nested loops number.
13571 unsigned NestedLoopCount =
13572 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13573 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13574 VarsWithImplicitDSA, B);
13575 if (NestedLoopCount == 0)
13576 return StmtError();
13577
13578 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13579 return StmtError();
13580
13581 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13582 // The grainsize clause and num_tasks clause are mutually exclusive and may
13583 // not appear on the same taskloop directive.
13585 {OMPC_grainsize, OMPC_num_tasks}))
13586 return StmtError();
13587 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13588 // If a reduction clause is present on the taskloop directive, the nogroup
13589 // clause must not be specified.
13591 return StmtError();
13593 return StmtError();
13594
13596 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13597}
13598
13600 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13601 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13602 if (!AStmt)
13603 return StmtError();
13604
13605 CapturedStmt *CS =
13606 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13607
13609 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13610 // define the nested loops number.
13611 unsigned NestedLoopCount = checkOpenMPLoop(
13612 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13613 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13614 VarsWithImplicitDSA, B);
13615 if (NestedLoopCount == 0)
13616 return StmtError();
13617
13618 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13619 "omp for loop exprs were not built");
13620
13621 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13622 // The grainsize clause and num_tasks clause are mutually exclusive and may
13623 // not appear on the same taskloop directive.
13625 {OMPC_grainsize, OMPC_num_tasks}))
13626 return StmtError();
13627 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13628 // If a reduction clause is present on the taskloop directive, the nogroup
13629 // clause must not be specified.
13631 return StmtError();
13632
13634 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13635 DSAStack->isCancelRegion());
13636}
13637
13639 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13640 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13641 if (!AStmt)
13642 return StmtError();
13643
13644 CapturedStmt *CS =
13645 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13646
13648 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13649 // define the nested loops number.
13650 unsigned NestedLoopCount = checkOpenMPLoop(
13651 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13652 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13653 VarsWithImplicitDSA, B);
13654 if (NestedLoopCount == 0)
13655 return StmtError();
13656
13657 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13658 "omp for loop exprs were not built");
13659
13660 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13661 // The grainsize clause and num_tasks clause are mutually exclusive and may
13662 // not appear on the same taskloop directive.
13664 {OMPC_grainsize, OMPC_num_tasks}))
13665 return StmtError();
13666 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13667 // If a reduction clause is present on the taskloop directive, the nogroup
13668 // clause must not be specified.
13670 return StmtError();
13671
13673 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13674 DSAStack->isCancelRegion());
13675}
13676
13678 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13679 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13680 if (!AStmt)
13681 return StmtError();
13682
13684 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13685
13687 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13688 // define the nested loops number.
13689 unsigned NestedLoopCount = checkOpenMPLoop(
13690 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13691 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13692 VarsWithImplicitDSA, B);
13693 if (NestedLoopCount == 0)
13694 return StmtError();
13695
13696 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13697 return StmtError();
13698
13699 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13700 // The grainsize clause and num_tasks clause are mutually exclusive and may
13701 // not appear on the same taskloop directive.
13703 {OMPC_grainsize, OMPC_num_tasks}))
13704 return StmtError();
13705 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13706 // If a reduction clause is present on the taskloop directive, the nogroup
13707 // clause must not be specified.
13709 return StmtError();
13711 return StmtError();
13712
13714 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13715}
13716
13718 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13719 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13720 if (!AStmt)
13721 return StmtError();
13722
13724 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13725
13727 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13728 // define the nested loops number.
13729 unsigned NestedLoopCount = checkOpenMPLoop(
13730 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13731 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13732 VarsWithImplicitDSA, B);
13733 if (NestedLoopCount == 0)
13734 return StmtError();
13735
13736 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13737 return StmtError();
13738
13739 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13740 // The grainsize clause and num_tasks clause are mutually exclusive and may
13741 // not appear on the same taskloop directive.
13743 {OMPC_grainsize, OMPC_num_tasks}))
13744 return StmtError();
13745 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13746 // If a reduction clause is present on the taskloop directive, the nogroup
13747 // clause must not be specified.
13749 return StmtError();
13751 return StmtError();
13752
13754 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13755}
13756
13758 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13759 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13760 if (!AStmt)
13761 return StmtError();
13762
13763 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13765 // In presence of clause 'collapse' with number of loops, it will
13766 // define the nested loops number.
13767 unsigned NestedLoopCount =
13768 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13769 nullptr /*ordered not a clause on distribute*/, AStmt,
13770 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13771 if (NestedLoopCount == 0)
13772 return StmtError();
13773
13774 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13775 "omp for loop exprs were not built");
13776
13778 auto *DistributeDirective = OMPDistributeDirective::Create(
13779 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13780 return DistributeDirective;
13781}
13782
13784 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13785 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13786 if (!AStmt)
13787 return StmtError();
13788
13789 CapturedStmt *CS =
13790 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13791
13793 // In presence of clause 'collapse' with number of loops, it will
13794 // define the nested loops number.
13795 unsigned NestedLoopCount = checkOpenMPLoop(
13796 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13797 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13798 VarsWithImplicitDSA, B);
13799 if (NestedLoopCount == 0)
13800 return StmtError();
13801
13802 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13803 "omp for loop exprs were not built");
13804
13806 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13807 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13808}
13809
13811 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13812 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13813 if (!AStmt)
13814 return StmtError();
13815
13817 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13818
13820 // In presence of clause 'collapse' with number of loops, it will
13821 // define the nested loops number.
13822 unsigned NestedLoopCount = checkOpenMPLoop(
13823 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13824 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13825 VarsWithImplicitDSA, B);
13826 if (NestedLoopCount == 0)
13827 return StmtError();
13828
13829 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13830 return StmtError();
13831
13833 return StmtError();
13834
13836 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13837}
13838
13840 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13841 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13842 if (!AStmt)
13843 return StmtError();
13844
13845 CapturedStmt *CS =
13846 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
13847
13849 // In presence of clause 'collapse' with number of loops, it will
13850 // define the nested loops number.
13851 unsigned NestedLoopCount =
13852 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13853 nullptr /*ordered not a clause on distribute*/, CS,
13854 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13855 if (NestedLoopCount == 0)
13856 return StmtError();
13857
13858 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13859 return StmtError();
13860
13862 return StmtError();
13863
13864 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13865 NestedLoopCount, Clauses, AStmt, B);
13866}
13867
13869 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13870 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13871 if (!AStmt)
13872 return StmtError();
13873
13874 CapturedStmt *CS =
13875 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13876
13878 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13879 // define the nested loops number.
13880 unsigned NestedLoopCount = checkOpenMPLoop(
13881 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13882 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13883 VarsWithImplicitDSA, B);
13884 if (NestedLoopCount == 0)
13885 return StmtError();
13886
13887 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13888 return StmtError();
13889
13891 return StmtError();
13892
13894 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13895}
13896
13898 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13899 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13900 if (!AStmt)
13901 return StmtError();
13902
13903 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13904
13906 // In presence of clause 'collapse' with number of loops, it will define the
13907 // nested loops number.
13908 unsigned NestedLoopCount =
13909 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13910 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13911 VarsWithImplicitDSA, B);
13912 if (NestedLoopCount == 0)
13913 return StmtError();
13914
13915 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13916 return StmtError();
13917
13919 return StmtError();
13920
13921 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13922 NestedLoopCount, Clauses, AStmt, B);
13923}
13924
13926 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13927 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13928 if (!AStmt)
13929 return StmtError();
13930
13931 CapturedStmt *CS =
13932 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13933
13935 // In presence of clause 'collapse' with number of loops, it will
13936 // define the nested loops number.
13937 unsigned NestedLoopCount =
13938 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13939 nullptr /*ordered not a clause on distribute*/, CS,
13940 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13941 if (NestedLoopCount == 0)
13942 return StmtError();
13943
13944 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13945 "omp teams distribute loop exprs were not built");
13946
13947 DSAStack->setParentTeamsRegionLoc(StartLoc);
13948
13950 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13951}
13952
13954 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13955 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13956 if (!AStmt)
13957 return StmtError();
13958
13959 CapturedStmt *CS =
13960 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13961
13963 // In presence of clause 'collapse' with number of loops, it will
13964 // define the nested loops number.
13965 unsigned NestedLoopCount = checkOpenMPLoop(
13966 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13967 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13968 VarsWithImplicitDSA, B);
13969 if (NestedLoopCount == 0)
13970 return StmtError();
13971
13972 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13973 return StmtError();
13974
13976 return StmtError();
13977
13978 DSAStack->setParentTeamsRegionLoc(StartLoc);
13979
13981 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13982}
13983
13985 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13986 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13987 if (!AStmt)
13988 return StmtError();
13989
13991 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13992
13994 // In presence of clause 'collapse' with number of loops, it will
13995 // define the nested loops number.
13996 unsigned NestedLoopCount = checkOpenMPLoop(
13997 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13998 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13999 VarsWithImplicitDSA, B);
14000 if (NestedLoopCount == 0)
14001 return StmtError();
14002
14003 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14004 return StmtError();
14005
14007 return StmtError();
14008
14009 DSAStack->setParentTeamsRegionLoc(StartLoc);
14010
14012 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14013}
14014
14016 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14017 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14018 if (!AStmt)
14019 return StmtError();
14020
14022 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14023
14025 // In presence of clause 'collapse' with number of loops, it will
14026 // define the nested loops number.
14027 unsigned NestedLoopCount = checkOpenMPLoop(
14028 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14029 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14030 VarsWithImplicitDSA, B);
14031
14032 if (NestedLoopCount == 0)
14033 return StmtError();
14034
14035 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14036 "omp for loop exprs were not built");
14037
14038 DSAStack->setParentTeamsRegionLoc(StartLoc);
14039
14041 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14042 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14043}
14044
14046 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14047 SourceLocation EndLoc) {
14048 if (!AStmt)
14049 return StmtError();
14050
14051 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14052
14053 const OMPClause *BareClause = nullptr;
14054 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14055 hasClauses(Clauses, OMPC_thread_limit);
14056 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14057 BareClause = C;
14058 return C->getClauseKind() == OMPC_ompx_bare;
14059 });
14060
14061 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14062 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14063 return StmtError();
14064 }
14065
14066 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
14067 unsigned DiagNo = HasBareClause
14068 ? diag::err_ompx_more_than_three_expr_not_allowed
14069 : diag::err_omp_multi_expr_not_allowed;
14070 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
14071 ClauseMaxNumExprs, DiagNo) ||
14072 !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses,
14073 ClauseMaxNumExprs, DiagNo))
14074 return StmtError();
14075
14076 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14077 Clauses, AStmt);
14078}
14079
14081 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14082 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14083 if (!AStmt)
14084 return StmtError();
14085
14086 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14087 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14088 !checkNumExprsInClause<OMPThreadLimitClause>(
14089 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14090 return StmtError();
14091
14092 CapturedStmt *CS =
14093 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14094
14096 // In presence of clause 'collapse' with number of loops, it will
14097 // define the nested loops number.
14098 unsigned NestedLoopCount = checkOpenMPLoop(
14099 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14100 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14101 VarsWithImplicitDSA, B);
14102 if (NestedLoopCount == 0)
14103 return StmtError();
14104
14105 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14106 "omp target teams distribute loop exprs were not built");
14107
14109 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14110}
14111
14113 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14114 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14115 if (!AStmt)
14116 return StmtError();
14117
14118 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14119 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14120 !checkNumExprsInClause<OMPThreadLimitClause>(
14121 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14122 return StmtError();
14123
14125 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14126
14128 // In presence of clause 'collapse' with number of loops, it will
14129 // define the nested loops number.
14130 unsigned NestedLoopCount = checkOpenMPLoop(
14131 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14132 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14133 VarsWithImplicitDSA, B);
14134 if (NestedLoopCount == 0)
14135 return StmtError();
14136
14137 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14138 return StmtError();
14139
14141 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14142 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14143}
14144
14146 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14147 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14148 if (!AStmt)
14149 return StmtError();
14150
14151 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14152 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14153 !checkNumExprsInClause<OMPThreadLimitClause>(
14154 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14155 return StmtError();
14156
14158 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14159
14161 // In presence of clause 'collapse' with number of loops, it will
14162 // define the nested loops number.
14163 unsigned NestedLoopCount =
14164 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14165 getCollapseNumberExpr(Clauses),
14166 nullptr /*ordered not a clause on distribute*/, CS,
14167 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14168 if (NestedLoopCount == 0)
14169 return StmtError();
14170
14171 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14172 return StmtError();
14173
14175 return StmtError();
14176
14178 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14179}
14180
14182 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14183 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14184 if (!AStmt)
14185 return StmtError();
14186
14187 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14188 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14189 !checkNumExprsInClause<OMPThreadLimitClause>(
14190 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14191 return StmtError();
14192
14194 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14195
14197 // In presence of clause 'collapse' with number of loops, it will
14198 // define the nested loops number.
14199 unsigned NestedLoopCount = checkOpenMPLoop(
14200 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14201 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14202 VarsWithImplicitDSA, B);
14203 if (NestedLoopCount == 0)
14204 return StmtError();
14205
14206 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14207 return StmtError();
14208
14210 return StmtError();
14211
14213 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14214}
14215
14216bool SemaOpenMP::checkTransformableLoopNest(
14217 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14219 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14220 OriginalInits.emplace_back();
14222 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14223 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14224 Stmt *CurStmt) {
14225 VarsWithInheritedDSAType TmpDSA;
14226 unsigned SingleNumLoops =
14227 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14228 TmpDSA, LoopHelpers[Cnt]);
14229 if (SingleNumLoops == 0)
14230 return true;
14231 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14232 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14233 OriginalInits.back().push_back(For->getInit());
14234 Body = For->getBody();
14235 } else {
14236 assert(isa<CXXForRangeStmt>(CurStmt) &&
14237 "Expected canonical for or range-based for loops.");
14238 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14239 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14240 Body = CXXFor->getBody();
14241 }
14242 OriginalInits.emplace_back();
14243 return false;
14244 },
14245 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14246 Stmt *DependentPreInits;
14247 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14248 DependentPreInits = Dir->getPreInits();
14249 else if (auto *Dir = dyn_cast<OMPStripeDirective>(Transform))
14250 DependentPreInits = Dir->getPreInits();
14251 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14252 DependentPreInits = Dir->getPreInits();
14253 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14254 DependentPreInits = Dir->getPreInits();
14255 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14256 DependentPreInits = Dir->getPreInits();
14257 else
14258 llvm_unreachable("Unhandled loop transformation");
14259
14260 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
14261 });
14262 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14263 OriginalInits.pop_back();
14264 return Result;
14265}
14266
14267/// Add preinit statements that need to be propageted from the selected loop.
14268static void addLoopPreInits(ASTContext &Context,
14270 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14271 SmallVectorImpl<Stmt *> &PreInits) {
14272
14273 // For range-based for-statements, ensure that their syntactic sugar is
14274 // executed by adding them as pre-init statements.
14275 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14276 Stmt *RangeInit = CXXRangeFor->getInit();
14277 if (RangeInit)
14278 PreInits.push_back(RangeInit);
14279
14280 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14281 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14282 RangeStmt->getBeginLoc(),
14283 RangeStmt->getEndLoc()));
14284
14285 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14286 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14287 RangeEnd->getBeginLoc(),
14288 RangeEnd->getEndLoc()));
14289 }
14290
14291 llvm::append_range(PreInits, OriginalInit);
14292
14293 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14294 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14295 PreInits.push_back(new (Context) DeclStmt(
14296 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14297 }
14298
14299 // Gather declarations for the data members used as counters.
14300 for (Expr *CounterRef : LoopHelper.Counters) {
14301 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14302 if (isa<OMPCapturedExprDecl>(CounterDecl))
14303 PreInits.push_back(new (Context) DeclStmt(
14304 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14305 }
14306}
14307
14308/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14309/// loop of a construct.
14310static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14311 size_t NumLoops = LoopStmts.size();
14313 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14314 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14315 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14316 LoopStmts[Cnt] = CurStmt;
14317 return false;
14318 });
14319 assert(!is_contained(LoopStmts, nullptr) &&
14320 "Expecting a loop statement for each affected loop");
14321}
14322
14323/// Build and return a DeclRefExpr for the floor induction variable using the
14324/// SemaRef and the provided parameters.
14325static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14326 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14327 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14328 OrigCntVar->getExprLoc());
14329}
14330
14332 Stmt *AStmt,
14333 SourceLocation StartLoc,
14334 SourceLocation EndLoc) {
14335 ASTContext &Context = getASTContext();
14336 Scope *CurScope = SemaRef.getCurScope();
14337
14338 const auto *SizesClause =
14339 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14340 if (!SizesClause ||
14341 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14342 return StmtError();
14343 unsigned NumLoops = SizesClause->getNumSizes();
14344
14345 // Empty statement should only be possible if there already was an error.
14346 if (!AStmt)
14347 return StmtError();
14348
14349 // Verify and diagnose loop nest.
14351 Stmt *Body = nullptr;
14352 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14353 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14354 OriginalInits))
14355 return StmtError();
14356
14357 // Delay tiling to when template is completely instantiated.
14359 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14360 NumLoops, AStmt, nullptr, nullptr);
14361
14362 assert(LoopHelpers.size() == NumLoops &&
14363 "Expecting loop iteration space dimensionality to match number of "
14364 "affected loops");
14365 assert(OriginalInits.size() == NumLoops &&
14366 "Expecting loop iteration space dimensionality to match number of "
14367 "affected loops");
14368
14369 // Collect all affected loop statements.
14370 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14371 collectLoopStmts(AStmt, LoopStmts);
14372
14373 SmallVector<Stmt *, 4> PreInits;
14374 CaptureVars CopyTransformer(SemaRef);
14375
14376 // Create iteration variables for the generated loops.
14377 SmallVector<VarDecl *, 4> FloorIndVars;
14378 SmallVector<VarDecl *, 4> TileIndVars;
14379 FloorIndVars.resize(NumLoops);
14380 TileIndVars.resize(NumLoops);
14381 for (unsigned I = 0; I < NumLoops; ++I) {
14382 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14383
14384 assert(LoopHelper.Counters.size() == 1 &&
14385 "Expect single-dimensional loop iteration space");
14386 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14387 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14388 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14389 QualType CntTy = IterVarRef->getType();
14390
14391 // Iteration variable for the floor (i.e. outer) loop.
14392 {
14393 std::string FloorCntName =
14394 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14395 VarDecl *FloorCntDecl =
14396 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14397 FloorIndVars[I] = FloorCntDecl;
14398 }
14399
14400 // Iteration variable for the tile (i.e. inner) loop.
14401 {
14402 std::string TileCntName =
14403 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14404
14405 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14406 // used by the expressions to derive the original iteration variable's
14407 // value from the logical iteration number.
14408 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14409 TileCntDecl->setDeclName(
14410 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14411 TileIndVars[I] = TileCntDecl;
14412 }
14413
14414 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14415 PreInits);
14416 }
14417
14418 // Once the original iteration values are set, append the innermost body.
14419 Stmt *Inner = Body;
14420
14421 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14422 SizesClause, CurScope](int I) -> Expr * {
14423 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14424
14425 if (DimTileSizeExpr->containsErrors())
14426 return nullptr;
14427
14428 if (isa<ConstantExpr>(DimTileSizeExpr))
14429 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14430
14431 // When the tile size is not a constant but a variable, it is possible to
14432 // pass non-positive numbers. For instance:
14433 // \code{c}
14434 // int a = 0;
14435 // #pragma omp tile sizes(a)
14436 // for (int i = 0; i < 42; ++i)
14437 // body(i);
14438 // \endcode
14439 // Although there is no meaningful interpretation of the tile size, the body
14440 // should still be executed 42 times to avoid surprises. To preserve the
14441 // invariant that every loop iteration is executed exactly once and not
14442 // cause an infinite loop, apply a minimum tile size of one.
14443 // Build expr:
14444 // \code{c}
14445 // (TS <= 0) ? 1 : TS
14446 // \endcode
14447 QualType DimTy = DimTileSizeExpr->getType();
14448 uint64_t DimWidth = Context.getTypeSize(DimTy);
14450 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14451 IntegerLiteral *One =
14452 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14454 CurScope, {}, BO_LE,
14455 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14456 Expr *MinOne = new (Context) ConditionalOperator(
14457 Cond, {}, One, {},
14458 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14460 return MinOne;
14461 };
14462
14463 // Create tile loops from the inside to the outside.
14464 for (int I = NumLoops - 1; I >= 0; --I) {
14465 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14466 Expr *NumIterations = LoopHelper.NumIterations;
14467 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14468 QualType IVTy = NumIterations->getType();
14469 Stmt *LoopStmt = LoopStmts[I];
14470
14471 // Commonly used variables. One of the constraints of an AST is that every
14472 // node object must appear at most once, hence we define a lambda that
14473 // creates a new AST node at every use.
14474 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14475 OrigCntVar]() {
14476 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14477 OrigCntVar->getExprLoc());
14478 };
14479
14480 // For init-statement: auto .tile.iv = .floor.iv
14482 TileIndVars[I],
14483 SemaRef
14484 .DefaultLvalueConversion(
14485 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14486 .get(),
14487 /*DirectInit=*/false);
14488 Decl *CounterDecl = TileIndVars[I];
14489 StmtResult InitStmt = new (Context)
14490 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14491 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14492 if (!InitStmt.isUsable())
14493 return StmtError();
14494
14495 // For cond-expression:
14496 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14497 Expr *DimTileSize = MakeDimTileSize(I);
14498 if (!DimTileSize)
14499 return StmtError();
14500 ExprResult EndOfTile = SemaRef.BuildBinOp(
14501 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14502 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14503 DimTileSize);
14504 if (!EndOfTile.isUsable())
14505 return StmtError();
14506 ExprResult IsPartialTile =
14507 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14508 NumIterations, EndOfTile.get());
14509 if (!IsPartialTile.isUsable())
14510 return StmtError();
14511 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14512 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14513 IsPartialTile.get(), NumIterations, EndOfTile.get());
14514 if (!MinTileAndIterSpace.isUsable())
14515 return StmtError();
14516 ExprResult CondExpr =
14517 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14518 MakeTileIVRef(), MinTileAndIterSpace.get());
14519 if (!CondExpr.isUsable())
14520 return StmtError();
14521
14522 // For incr-statement: ++.tile.iv
14523 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14524 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14525 if (!IncrStmt.isUsable())
14526 return StmtError();
14527
14528 // Statements to set the original iteration variable's value from the
14529 // logical iteration number.
14530 // Generated for loop is:
14531 // \code
14532 // Original_for_init;
14533 // for (auto .tile.iv = .floor.iv;
14534 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14535 // ++.tile.iv) {
14536 // Original_Body;
14537 // Original_counter_update;
14538 // }
14539 // \endcode
14540 // FIXME: If the innermost body is an loop itself, inserting these
14541 // statements stops it being recognized as a perfectly nested loop (e.g.
14542 // for applying tiling again). If this is the case, sink the expressions
14543 // further into the inner loop.
14544 SmallVector<Stmt *, 4> BodyParts;
14545 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14546 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14547 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14548 BodyParts.push_back(Inner);
14549 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14550 Inner->getBeginLoc(), Inner->getEndLoc());
14551 Inner = new (Context)
14552 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14553 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14554 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14555 }
14556
14557 // Create floor loops from the inside to the outside.
14558 for (int I = NumLoops - 1; I >= 0; --I) {
14559 auto &LoopHelper = LoopHelpers[I];
14560 Expr *NumIterations = LoopHelper.NumIterations;
14561 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14562 QualType IVTy = NumIterations->getType();
14563
14564 // For init-statement: auto .floor.iv = 0
14566 FloorIndVars[I],
14567 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14568 /*DirectInit=*/false);
14569 Decl *CounterDecl = FloorIndVars[I];
14570 StmtResult InitStmt = new (Context)
14571 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14572 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14573 if (!InitStmt.isUsable())
14574 return StmtError();
14575
14576 // For cond-expression: .floor.iv < NumIterations
14577 ExprResult CondExpr = SemaRef.BuildBinOp(
14578 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14579 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14580 NumIterations);
14581 if (!CondExpr.isUsable())
14582 return StmtError();
14583
14584 // For incr-statement: .floor.iv += DimTileSize
14585 Expr *DimTileSize = MakeDimTileSize(I);
14586 if (!DimTileSize)
14587 return StmtError();
14588 ExprResult IncrStmt = SemaRef.BuildBinOp(
14589 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14590 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14591 DimTileSize);
14592 if (!IncrStmt.isUsable())
14593 return StmtError();
14594
14595 Inner = new (Context)
14596 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14597 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14598 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14599 }
14600
14601 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14602 AStmt, Inner,
14603 buildPreInits(Context, PreInits));
14604}
14605
14607 Stmt *AStmt,
14608 SourceLocation StartLoc,
14609 SourceLocation EndLoc) {
14610 ASTContext &Context = getASTContext();
14611 Scope *CurScope = SemaRef.getCurScope();
14612
14613 const auto *SizesClause =
14614 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14615 if (!SizesClause ||
14616 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
14617 return !SizeExpr || SizeExpr->containsErrors();
14618 }))
14619 return StmtError();
14620 unsigned NumLoops = SizesClause->getNumSizes();
14621
14622 // Empty statement should only be possible if there already was an error.
14623 if (!AStmt)
14624 return StmtError();
14625
14626 // Verify and diagnose loop nest.
14628 Stmt *Body = nullptr;
14629 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14630 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
14631 Body, OriginalInits))
14632 return StmtError();
14633
14634 // Delay striping to when template is completely instantiated.
14636 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14637 NumLoops, AStmt, nullptr, nullptr);
14638
14639 assert(LoopHelpers.size() == NumLoops &&
14640 "Expecting loop iteration space dimensionality to match number of "
14641 "affected loops");
14642 assert(OriginalInits.size() == NumLoops &&
14643 "Expecting loop iteration space dimensionality to match number of "
14644 "affected loops");
14645
14646 // Collect all affected loop statements.
14647 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14648 collectLoopStmts(AStmt, LoopStmts);
14649
14650 SmallVector<Stmt *, 4> PreInits;
14651 CaptureVars CopyTransformer(SemaRef);
14652
14653 // Create iteration variables for the generated loops.
14654 SmallVector<VarDecl *, 4> FloorIndVars;
14655 SmallVector<VarDecl *, 4> StripeIndVars;
14656 FloorIndVars.resize(NumLoops);
14657 StripeIndVars.resize(NumLoops);
14658 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
14659 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14660
14661 assert(LoopHelper.Counters.size() == 1 &&
14662 "Expect single-dimensional loop iteration space");
14663 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14664 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14665 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14666 QualType CntTy = IterVarRef->getType();
14667
14668 // Iteration variable for the stripe (i.e. outer) loop.
14669 {
14670 std::string FloorCntName =
14671 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14672 VarDecl *FloorCntDecl =
14673 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14674 FloorIndVars[I] = FloorCntDecl;
14675 }
14676
14677 // Iteration variable for the stripe (i.e. inner) loop.
14678 {
14679 std::string StripeCntName =
14680 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14681
14682 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14683 // used by the expressions to derive the original iteration variable's
14684 // value from the logical iteration number.
14685 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14686 StripeCntDecl->setDeclName(
14687 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
14688 StripeIndVars[I] = StripeCntDecl;
14689 }
14690
14691 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14692 PreInits);
14693 }
14694
14695 // Once the original iteration values are set, append the innermost body.
14696 Stmt *Inner = Body;
14697
14698 auto MakeDimStripeSize = [&](int I) -> Expr * {
14699 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
14700 if (isa<ConstantExpr>(DimStripeSizeExpr))
14701 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
14702
14703 // When the stripe size is not a constant but a variable, it is possible to
14704 // pass non-positive numbers. For instance:
14705 // \code{c}
14706 // int a = 0;
14707 // #pragma omp stripe sizes(a)
14708 // for (int i = 0; i < 42; ++i)
14709 // body(i);
14710 // \endcode
14711 // Although there is no meaningful interpretation of the stripe size, the
14712 // body should still be executed 42 times to avoid surprises. To preserve
14713 // the invariant that every loop iteration is executed exactly once and not
14714 // cause an infinite loop, apply a minimum stripe size of one.
14715 // Build expr:
14716 // \code{c}
14717 // (TS <= 0) ? 1 : TS
14718 // \endcode
14719 QualType DimTy = DimStripeSizeExpr->getType();
14720 uint64_t DimWidth = Context.getTypeSize(DimTy);
14722 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14723 IntegerLiteral *One =
14724 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14726 CurScope, {}, BO_LE,
14727 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
14728 Expr *MinOne = new (Context) ConditionalOperator(
14729 Cond, {}, One, {},
14730 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
14732 return MinOne;
14733 };
14734
14735 // Create stripe loops from the inside to the outside.
14736 for (int I = NumLoops - 1; I >= 0; --I) {
14737 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14738 Expr *NumIterations = LoopHelper.NumIterations;
14739 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14740 QualType IVTy = NumIterations->getType();
14741 Stmt *LoopStmt = LoopStmts[I];
14742
14743 // For init-statement: auto .stripe.iv = .floor.iv
14745 StripeIndVars[I],
14746 SemaRef
14747 .DefaultLvalueConversion(
14748 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
14749 .get(),
14750 /*DirectInit=*/false);
14751 Decl *CounterDecl = StripeIndVars[I];
14752 StmtResult InitStmt = new (Context)
14753 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14754 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14755 if (!InitStmt.isUsable())
14756 return StmtError();
14757
14758 // For cond-expression:
14759 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
14760 ExprResult EndOfStripe = SemaRef.BuildBinOp(
14761 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14762 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14763 MakeDimStripeSize(I));
14764 if (!EndOfStripe.isUsable())
14765 return StmtError();
14766 ExprResult IsPartialStripe =
14767 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14768 NumIterations, EndOfStripe.get());
14769 if (!IsPartialStripe.isUsable())
14770 return StmtError();
14771 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
14772 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14773 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
14774 if (!MinStripeAndIterSpace.isUsable())
14775 return StmtError();
14776 ExprResult CondExpr = SemaRef.BuildBinOp(
14777 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14778 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
14779 MinStripeAndIterSpace.get());
14780 if (!CondExpr.isUsable())
14781 return StmtError();
14782
14783 // For incr-statement: ++.stripe.iv
14784 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14785 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
14786 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
14787 if (!IncrStmt.isUsable())
14788 return StmtError();
14789
14790 // Statements to set the original iteration variable's value from the
14791 // logical iteration number.
14792 // Generated for loop is:
14793 // \code
14794 // Original_for_init;
14795 // for (auto .stripe.iv = .floor.iv;
14796 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
14797 // ++.stripe.iv) {
14798 // Original_Body;
14799 // Original_counter_update;
14800 // }
14801 // \endcode
14802 // FIXME: If the innermost body is a loop itself, inserting these
14803 // statements stops it being recognized as a perfectly nested loop (e.g.
14804 // for applying another loop transformation). If this is the case, sink the
14805 // expressions further into the inner loop.
14806 SmallVector<Stmt *, 4> BodyParts;
14807 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14808 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14809 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14810 BodyParts.push_back(Inner);
14811 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14812 Inner->getBeginLoc(), Inner->getEndLoc());
14813 Inner = new (Context)
14814 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14815 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14816 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14817 }
14818
14819 // Create grid loops from the inside to the outside.
14820 for (int I = NumLoops - 1; I >= 0; --I) {
14821 auto &LoopHelper = LoopHelpers[I];
14822 Expr *NumIterations = LoopHelper.NumIterations;
14823 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14824 QualType IVTy = NumIterations->getType();
14825
14826 // For init-statement: auto .grid.iv = 0
14828 FloorIndVars[I],
14829 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14830 /*DirectInit=*/false);
14831 Decl *CounterDecl = FloorIndVars[I];
14832 StmtResult InitStmt = new (Context)
14833 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14834 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14835 if (!InitStmt.isUsable())
14836 return StmtError();
14837
14838 // For cond-expression: .floor.iv < NumIterations
14839 ExprResult CondExpr = SemaRef.BuildBinOp(
14840 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14841 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14842 NumIterations);
14843 if (!CondExpr.isUsable())
14844 return StmtError();
14845
14846 // For incr-statement: .floor.iv += DimStripeSize
14847 ExprResult IncrStmt = SemaRef.BuildBinOp(
14848 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14849 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
14850 MakeDimStripeSize(I));
14851 if (!IncrStmt.isUsable())
14852 return StmtError();
14853
14854 Inner = new (Context)
14855 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14856 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14857 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14858 }
14859
14860 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14861 NumLoops, AStmt, Inner,
14862 buildPreInits(Context, PreInits));
14863}
14864
14866 Stmt *AStmt,
14867 SourceLocation StartLoc,
14868 SourceLocation EndLoc) {
14869 ASTContext &Context = getASTContext();
14870 Scope *CurScope = SemaRef.getCurScope();
14871 // Empty statement should only be possible if there already was an error.
14872 if (!AStmt)
14873 return StmtError();
14874
14876 {OMPC_partial, OMPC_full}))
14877 return StmtError();
14878
14879 const OMPFullClause *FullClause =
14880 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14881 const OMPPartialClause *PartialClause =
14882 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14883 assert(!(FullClause && PartialClause) &&
14884 "mutual exclusivity must have been checked before");
14885
14886 constexpr unsigned NumLoops = 1;
14887 Stmt *Body = nullptr;
14889 NumLoops);
14890 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14891 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14892 Body, OriginalInits))
14893 return StmtError();
14894
14895 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14896
14897 // Delay unrolling to when template is completely instantiated.
14899 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14900 NumGeneratedLoops, nullptr, nullptr);
14901
14902 assert(LoopHelpers.size() == NumLoops &&
14903 "Expecting a single-dimensional loop iteration space");
14904 assert(OriginalInits.size() == NumLoops &&
14905 "Expecting a single-dimensional loop iteration space");
14906 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14907
14908 if (FullClause) {
14910 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14911 /*SuppressExprDiags=*/true)
14912 .isUsable()) {
14913 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14914 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14915 << "#pragma omp unroll full";
14916 return StmtError();
14917 }
14918 }
14919
14920 // The generated loop may only be passed to other loop-associated directive
14921 // when a partial clause is specified. Without the requirement it is
14922 // sufficient to generate loop unroll metadata at code-generation.
14923 if (NumGeneratedLoops == 0)
14924 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14925 NumGeneratedLoops, nullptr, nullptr);
14926
14927 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14928 // associated with another loop directive.
14929 //
14930 // The canonical loop analysis return by checkTransformableLoopNest assumes
14931 // the following structure to be the same loop without transformations or
14932 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14933 // LoopHelper.Counters;
14934 // for (; IV < LoopHelper.NumIterations; ++IV) {
14935 // LoopHelper.Updates;
14936 // Body;
14937 // }
14938 // \endcode
14939 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14940 // and referenced by LoopHelper.IterationVarRef.
14941 //
14942 // The unrolling directive transforms this into the following loop:
14943 // \code
14944 // OriginalInits; \
14945 // LoopHelper.PreInits; > NewPreInits
14946 // LoopHelper.Counters; /
14947 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14948 // #pragma clang loop unroll_count(Factor)
14949 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14950 // {
14951 // LoopHelper.Updates;
14952 // Body;
14953 // }
14954 // }
14955 // \endcode
14956 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14957 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14958 // references it. If the partially unrolled loop is associated with another
14959 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14960 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14961 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14962 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14963 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14964 // property of the OMPLoopBasedDirective instead of statements in
14965 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14966 // of a canonical loop nest where these PreInits are emitted before the
14967 // outermost directive.
14968
14969 // Find the loop statement.
14970 Stmt *LoopStmt = nullptr;
14971 collectLoopStmts(AStmt, {LoopStmt});
14972
14973 // Determine the PreInit declarations.
14974 SmallVector<Stmt *, 4> PreInits;
14975 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14976
14977 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14978 QualType IVTy = IterationVarRef->getType();
14979 assert(LoopHelper.Counters.size() == 1 &&
14980 "Expecting a single-dimensional loop iteration space");
14981 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14982
14983 // Determine the unroll factor.
14984 uint64_t Factor;
14985 SourceLocation FactorLoc;
14986 if (Expr *FactorVal = PartialClause->getFactor();
14987 FactorVal && !FactorVal->containsErrors()) {
14988 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14989 FactorLoc = FactorVal->getExprLoc();
14990 } else {
14991 // TODO: Use a better profitability model.
14992 Factor = 2;
14993 }
14994 assert(Factor > 0 && "Expected positive unroll factor");
14995 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14997 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14998 IVTy, FactorLoc);
14999 };
15000
15001 // Iteration variable SourceLocations.
15002 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15003 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15004 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15005
15006 // Internal variable names.
15007 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15008 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15009 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15010
15011 // Create the iteration variable for the unrolled loop.
15012 VarDecl *OuterIVDecl =
15013 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15014 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15015 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15016 };
15017
15018 // Iteration variable for the inner loop: Reuse the iteration variable created
15019 // by checkOpenMPLoop.
15020 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15021 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15022 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15023 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15024 };
15025
15026 // Make a copy of the NumIterations expression for each use: By the AST
15027 // constraints, every expression object in a DeclContext must be unique.
15028 CaptureVars CopyTransformer(SemaRef);
15029 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15030 return AssertSuccess(
15031 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15032 };
15033
15034 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15035 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15036 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15037 /*DirectInit=*/false);
15038 StmtResult InnerInit = new (Context)
15039 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15040 if (!InnerInit.isUsable())
15041 return StmtError();
15042
15043 // Inner For cond-expression:
15044 // \code
15045 // .unroll_inner.iv < .unrolled.iv + Factor &&
15046 // .unroll_inner.iv < NumIterations
15047 // \endcode
15048 // This conjunction of two conditions allows ScalarEvolution to derive the
15049 // maximum trip count of the inner loop.
15050 ExprResult EndOfTile =
15051 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15052 MakeOuterRef(), MakeFactorExpr());
15053 if (!EndOfTile.isUsable())
15054 return StmtError();
15055 ExprResult InnerCond1 =
15056 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15057 MakeInnerRef(), EndOfTile.get());
15058 if (!InnerCond1.isUsable())
15059 return StmtError();
15060 ExprResult InnerCond2 =
15061 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15062 MakeInnerRef(), MakeNumIterations());
15063 if (!InnerCond2.isUsable())
15064 return StmtError();
15065 ExprResult InnerCond =
15066 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15067 InnerCond1.get(), InnerCond2.get());
15068 if (!InnerCond.isUsable())
15069 return StmtError();
15070
15071 // Inner For incr-statement: ++.unroll_inner.iv
15072 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15073 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15074 if (!InnerIncr.isUsable())
15075 return StmtError();
15076
15077 // Inner For statement.
15078 SmallVector<Stmt *> InnerBodyStmts;
15079 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15080 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15081 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15082 InnerBodyStmts.push_back(Body);
15083 CompoundStmt *InnerBody =
15085 Body->getBeginLoc(), Body->getEndLoc());
15086 ForStmt *InnerFor = new (Context)
15087 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15088 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15089 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15090
15091 // Unroll metadata for the inner loop.
15092 // This needs to take into account the remainder portion of the unrolled loop,
15093 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15094 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15095 // the maximum trip count, which will also generate a remainder loop. Just
15096 // `unroll(enable)` (which could have been useful if the user has not
15097 // specified a concrete factor; even though the outer loop cannot be
15098 // influenced anymore, would avoid more code bloat than necessary) will refuse
15099 // the loop because "Won't unroll; remainder loop could not be generated when
15100 // assuming runtime trip count". Even if it did work, it must not choose a
15101 // larger unroll factor than the maximum loop length, or it would always just
15102 // execute the remainder loop.
15103 LoopHintAttr *UnrollHintAttr =
15104 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15105 LoopHintAttr::Numeric, MakeFactorExpr());
15106 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15107 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15108
15109 // Outer For init-statement: auto .unrolled.iv = 0
15111 OuterIVDecl,
15112 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15113 /*DirectInit=*/false);
15114 StmtResult OuterInit = new (Context)
15115 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15116 if (!OuterInit.isUsable())
15117 return StmtError();
15118
15119 // Outer For cond-expression: .unrolled.iv < NumIterations
15120 ExprResult OuterConde =
15121 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15122 MakeOuterRef(), MakeNumIterations());
15123 if (!OuterConde.isUsable())
15124 return StmtError();
15125
15126 // Outer For incr-statement: .unrolled.iv += Factor
15127 ExprResult OuterIncr =
15128 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15129 MakeOuterRef(), MakeFactorExpr());
15130 if (!OuterIncr.isUsable())
15131 return StmtError();
15132
15133 // Outer For statement.
15134 ForStmt *OuterFor = new (Context)
15135 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15136 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15137 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15138
15139 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15140 NumGeneratedLoops, OuterFor,
15141 buildPreInits(Context, PreInits));
15142}
15143
15145 SourceLocation StartLoc,
15146 SourceLocation EndLoc) {
15147 ASTContext &Context = getASTContext();
15148 Scope *CurScope = SemaRef.getCurScope();
15149
15150 // Empty statement should only be possible if there already was an error.
15151 if (!AStmt)
15152 return StmtError();
15153
15154 constexpr unsigned NumLoops = 1;
15155 Stmt *Body = nullptr;
15157 NumLoops);
15158 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
15159 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15160 Body, OriginalInits))
15161 return StmtError();
15162
15163 // Delay applying the transformation to when template is completely
15164 // instantiated.
15166 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15167 NumLoops, nullptr, nullptr);
15168
15169 assert(LoopHelpers.size() == NumLoops &&
15170 "Expecting a single-dimensional loop iteration space");
15171 assert(OriginalInits.size() == NumLoops &&
15172 "Expecting a single-dimensional loop iteration space");
15173 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15174
15175 // Find the loop statement.
15176 Stmt *LoopStmt = nullptr;
15177 collectLoopStmts(AStmt, {LoopStmt});
15178
15179 // Determine the PreInit declarations.
15180 SmallVector<Stmt *> PreInits;
15181 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15182
15183 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15184 QualType IVTy = IterationVarRef->getType();
15185 uint64_t IVWidth = Context.getTypeSize(IVTy);
15186 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15187
15188 // Iteration variable SourceLocations.
15189 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15190 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15191 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15192
15193 // Locations pointing to the transformation.
15194 SourceLocation TransformLoc = StartLoc;
15195 SourceLocation TransformLocBegin = StartLoc;
15196 SourceLocation TransformLocEnd = EndLoc;
15197
15198 // Internal variable names.
15199 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15200 SmallString<64> ForwardIVName(".forward.iv.");
15201 ForwardIVName += OrigVarName;
15202 SmallString<64> ReversedIVName(".reversed.iv.");
15203 ReversedIVName += OrigVarName;
15204
15205 // LoopHelper.Updates will read the logical iteration number from
15206 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15207 // that logical iteration from it, then assign it to the user loop counter
15208 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15209 // induction variable of the generated loop because it may cause an underflow:
15210 // \code{.c}
15211 // for (unsigned i = 0; i < n; ++i)
15212 // body(i);
15213 // \endcode
15214 //
15215 // Naive reversal:
15216 // \code{.c}
15217 // for (unsigned i = n-1; i >= 0; --i)
15218 // body(i);
15219 // \endcode
15220 //
15221 // Instead, we introduce a new iteration variable representing the logical
15222 // iteration counter of the original loop, convert it to the logical iteration
15223 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15224 // loop iteration variable from it.
15225 // \code{.cpp}
15226 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15227 // auto .reversed.iv = n - .forward.iv - 1;
15228 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15229 // body(i); // Body
15230 // }
15231 // \endcode
15232
15233 // Subexpressions with more than one use. One of the constraints of an AST is
15234 // that every node object must appear at most once, hence we define a lambda
15235 // that creates a new AST node at every use.
15236 CaptureVars CopyTransformer(SemaRef);
15237 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15238 return AssertSuccess(
15239 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15240 };
15241
15242 // Create the iteration variable for the forward loop (from 0 to n-1).
15243 VarDecl *ForwardIVDecl =
15244 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15245 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15246 OrigVarLoc]() {
15247 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15248 };
15249
15250 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15251 // Reuse the iteration variable created by checkOpenMPLoop.
15252 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15253 ReversedIVDecl->setDeclName(
15254 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15255
15256 // For init-statement:
15257 // \code{.cpp}
15258 // auto .forward.iv = 0;
15259 // \endcode
15260 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15261 ForwardIVDecl->getType(), OrigVarLoc);
15262 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15263 StmtResult Init = new (Context)
15264 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15265 if (!Init.isUsable())
15266 return StmtError();
15267
15268 // Forward iv cond-expression:
15269 // \code{.cpp}
15270 // .forward.iv < MakeNumIterations()
15271 // \endcode
15272 ExprResult Cond =
15273 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15274 MakeForwardRef(), MakeNumIterations());
15275 if (!Cond.isUsable())
15276 return StmtError();
15277
15278 // Forward incr-statement:
15279 // \code{.c}
15280 // ++.forward.iv
15281 // \endcode
15282 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15283 UO_PreInc, MakeForwardRef());
15284 if (!Incr.isUsable())
15285 return StmtError();
15286
15287 // Reverse the forward-iv:
15288 // \code{.cpp}
15289 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15290 // \endcode
15291 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15292 TransformLoc);
15293 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15294 MakeNumIterations(), One);
15295 if (!Minus.isUsable())
15296 return StmtError();
15297 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15298 MakeForwardRef());
15299 if (!Minus.isUsable())
15300 return StmtError();
15301 StmtResult InitReversed = new (Context) DeclStmt(
15302 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15303 if (!InitReversed.isUsable())
15304 return StmtError();
15305 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15306 /*DirectInit=*/false);
15307
15308 // The new loop body.
15309 SmallVector<Stmt *, 4> BodyStmts;
15310 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15311 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15312 BodyStmts.push_back(InitReversed.get());
15313 llvm::append_range(BodyStmts, LoopHelper.Updates);
15314 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15315 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15316 BodyStmts.push_back(Body);
15317 auto *ReversedBody =
15318 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15319 Body->getBeginLoc(), Body->getEndLoc());
15320
15321 // Finally create the reversed For-statement.
15322 auto *ReversedFor = new (Context)
15323 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15324 ReversedBody, LoopHelper.Init->getBeginLoc(),
15325 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15326 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15327 ReversedFor,
15328 buildPreInits(Context, PreInits));
15329}
15330
15332 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15333 SourceLocation EndLoc) {
15334 ASTContext &Context = getASTContext();
15335 DeclContext *CurContext = SemaRef.CurContext;
15336 Scope *CurScope = SemaRef.getCurScope();
15337
15338 // Empty statement should only be possible if there already was an error.
15339 if (!AStmt)
15340 return StmtError();
15341
15342 // interchange without permutation clause swaps two loops.
15343 const OMPPermutationClause *PermutationClause =
15344 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15345 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15346
15347 // Verify and diagnose loop nest.
15349 Stmt *Body = nullptr;
15350 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
15351 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15352 LoopHelpers, Body, OriginalInits))
15353 return StmtError();
15354
15355 // Delay interchange to when template is completely instantiated.
15356 if (CurContext->isDependentContext())
15357 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15358 NumLoops, AStmt, nullptr, nullptr);
15359
15360 // An invalid expression in the permutation clause is set to nullptr in
15361 // ActOnOpenMPPermutationClause.
15362 if (PermutationClause &&
15363 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15364 return StmtError();
15365
15366 assert(LoopHelpers.size() == NumLoops &&
15367 "Expecting loop iteration space dimensionaly to match number of "
15368 "affected loops");
15369 assert(OriginalInits.size() == NumLoops &&
15370 "Expecting loop iteration space dimensionaly to match number of "
15371 "affected loops");
15372
15373 // Decode the permutation clause.
15374 SmallVector<uint64_t, 2> Permutation;
15375 if (!PermutationClause) {
15376 Permutation = {1, 0};
15377 } else {
15378 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15379 llvm::BitVector Flags(PermArgs.size());
15380 for (Expr *PermArg : PermArgs) {
15381 std::optional<llvm::APSInt> PermCstExpr =
15382 PermArg->getIntegerConstantExpr(Context);
15383 if (!PermCstExpr)
15384 continue;
15385 uint64_t PermInt = PermCstExpr->getZExtValue();
15386 assert(1 <= PermInt && PermInt <= NumLoops &&
15387 "Must be a permutation; diagnostic emitted in "
15388 "ActOnOpenMPPermutationClause");
15389 if (Flags[PermInt - 1]) {
15390 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15391 Diag(PermArg->getExprLoc(),
15392 diag::err_omp_interchange_permutation_value_repeated)
15393 << PermInt << ExprRange;
15394 continue;
15395 }
15396 Flags[PermInt - 1] = true;
15397
15398 Permutation.push_back(PermInt - 1);
15399 }
15400
15401 if (Permutation.size() != NumLoops)
15402 return StmtError();
15403 }
15404
15405 // Nothing to transform with trivial permutation.
15406 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15407 auto [Idx, Arg] = P;
15408 return Idx == Arg;
15409 }))
15410 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15411 NumLoops, AStmt, AStmt, nullptr);
15412
15413 // Find the affected loops.
15414 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15415 collectLoopStmts(AStmt, LoopStmts);
15416
15417 // Collect pre-init statements on the order before the permuation.
15418 SmallVector<Stmt *> PreInits;
15419 for (auto I : llvm::seq<int>(NumLoops)) {
15420 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15421
15422 assert(LoopHelper.Counters.size() == 1 &&
15423 "Single-dimensional loop iteration space expected");
15424
15425 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15426 PreInits);
15427 }
15428
15429 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15430 CaptureVars CopyTransformer(SemaRef);
15431
15432 // Create the permuted loops from the inside to the outside of the
15433 // interchanged loop nest. Body of the innermost new loop is the original
15434 // innermost body.
15435 Stmt *Inner = Body;
15436 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15437 // Get the original loop that belongs to this new position.
15438 uint64_t SourceIdx = Permutation[TargetIdx];
15439 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15440 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15441 assert(SourceHelper.Counters.size() == 1 &&
15442 "Single-dimensional loop iteration space expected");
15443 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15444
15445 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15446 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15447 QualType IVTy = IterVarRef->getType();
15448 assert(IVTy->isIntegerType() &&
15449 "Expected the logical iteration counter to be an integer");
15450
15451 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15452 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15453
15454 // Make a copy of the NumIterations expression for each use: By the AST
15455 // constraints, every expression object in a DeclContext must be unique.
15456 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15457 return AssertSuccess(
15458 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15459 };
15460
15461 // Iteration variable for the permuted loop. Reuse the one from
15462 // checkOpenMPLoop which will also be used to update the original loop
15463 // variable.
15464 SmallString<64> PermutedCntName(".permuted_");
15465 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15466 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15467 PermutedCntDecl->setDeclName(
15468 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15469 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15470 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15471 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15472 };
15473
15474 // For init-statement:
15475 // \code
15476 // auto .permuted_{target}.iv = 0
15477 // \endcode
15479 if (!Zero.isUsable())
15480 return StmtError();
15481 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15482 /*DirectInit=*/false);
15483 StmtResult InitStmt = new (Context)
15484 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15485 OrigCntVar->getEndLoc());
15486 if (!InitStmt.isUsable())
15487 return StmtError();
15488
15489 // For cond-expression:
15490 // \code
15491 // .permuted_{target}.iv < MakeNumIterations()
15492 // \endcode
15493 ExprResult CondExpr =
15494 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15495 MakePermutedRef(), MakeNumIterations());
15496 if (!CondExpr.isUsable())
15497 return StmtError();
15498
15499 // For incr-statement:
15500 // \code
15501 // ++.tile.iv
15502 // \endcode
15503 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15504 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15505 if (!IncrStmt.isUsable())
15506 return StmtError();
15507
15508 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15509 SourceHelper.Updates.end());
15510 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15511 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15512 BodyParts.push_back(Inner);
15513 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15514 Inner->getBeginLoc(), Inner->getEndLoc());
15515 Inner = new (Context) ForStmt(
15516 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15517 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15518 SourceHelper.Inc->getEndLoc());
15519 }
15520
15521 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15522 NumLoops, AStmt, Inner,
15523 buildPreInits(Context, PreInits));
15524}
15525
15527 Expr *Expr,
15528 SourceLocation StartLoc,
15529 SourceLocation LParenLoc,
15530 SourceLocation EndLoc) {
15531 OMPClause *Res = nullptr;
15532 switch (Kind) {
15533 case OMPC_final:
15534 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15535 break;
15536 case OMPC_safelen:
15537 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15538 break;
15539 case OMPC_simdlen:
15540 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15541 break;
15542 case OMPC_allocator:
15543 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15544 break;
15545 case OMPC_collapse:
15546 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15547 break;
15548 case OMPC_ordered:
15549 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15550 break;
15551 case OMPC_priority:
15552 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15553 break;
15554 case OMPC_hint:
15555 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15556 break;
15557 case OMPC_depobj:
15558 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15559 break;
15560 case OMPC_detach:
15561 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15562 break;
15563 case OMPC_novariants:
15564 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15565 break;
15566 case OMPC_nocontext:
15567 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15568 break;
15569 case OMPC_filter:
15570 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15571 break;
15572 case OMPC_partial:
15573 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15574 break;
15575 case OMPC_message:
15576 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15577 break;
15578 case OMPC_align:
15579 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15580 break;
15581 case OMPC_ompx_dyn_cgroup_mem:
15582 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15583 break;
15584 case OMPC_holds:
15585 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
15586 break;
15587 case OMPC_grainsize:
15588 case OMPC_num_tasks:
15589 case OMPC_num_threads:
15590 case OMPC_device:
15591 case OMPC_if:
15592 case OMPC_default:
15593 case OMPC_proc_bind:
15594 case OMPC_schedule:
15595 case OMPC_private:
15596 case OMPC_firstprivate:
15597 case OMPC_lastprivate:
15598 case OMPC_shared:
15599 case OMPC_reduction:
15600 case OMPC_task_reduction:
15601 case OMPC_in_reduction:
15602 case OMPC_linear:
15603 case OMPC_aligned:
15604 case OMPC_copyin:
15605 case OMPC_copyprivate:
15606 case OMPC_nowait:
15607 case OMPC_untied:
15608 case OMPC_mergeable:
15609 case OMPC_threadprivate:
15610 case OMPC_sizes:
15611 case OMPC_allocate:
15612 case OMPC_flush:
15613 case OMPC_read:
15614 case OMPC_write:
15615 case OMPC_update:
15616 case OMPC_capture:
15617 case OMPC_compare:
15618 case OMPC_seq_cst:
15619 case OMPC_acq_rel:
15620 case OMPC_acquire:
15621 case OMPC_release:
15622 case OMPC_relaxed:
15623 case OMPC_depend:
15624 case OMPC_threads:
15625 case OMPC_simd:
15626 case OMPC_map:
15627 case OMPC_nogroup:
15628 case OMPC_dist_schedule:
15629 case OMPC_defaultmap:
15630 case OMPC_unknown:
15631 case OMPC_uniform:
15632 case OMPC_to:
15633 case OMPC_from:
15634 case OMPC_use_device_ptr:
15635 case OMPC_use_device_addr:
15636 case OMPC_is_device_ptr:
15637 case OMPC_unified_address:
15638 case OMPC_unified_shared_memory:
15639 case OMPC_reverse_offload:
15640 case OMPC_dynamic_allocators:
15641 case OMPC_atomic_default_mem_order:
15642 case OMPC_self_maps:
15643 case OMPC_device_type:
15644 case OMPC_match:
15645 case OMPC_nontemporal:
15646 case OMPC_order:
15647 case OMPC_at:
15648 case OMPC_severity:
15649 case OMPC_destroy:
15650 case OMPC_inclusive:
15651 case OMPC_exclusive:
15652 case OMPC_uses_allocators:
15653 case OMPC_affinity:
15654 case OMPC_when:
15655 case OMPC_bind:
15656 case OMPC_num_teams:
15657 case OMPC_thread_limit:
15658 default:
15659 llvm_unreachable("Clause is not allowed.");
15660 }
15661 return Res;
15662}
15663
15664// An OpenMP directive such as 'target parallel' has two captured regions:
15665// for the 'target' and 'parallel' respectively. This function returns
15666// the region in which to capture expressions associated with a clause.
15667// A return value of OMPD_unknown signifies that the expression should not
15668// be captured.
15670 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15671 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15672 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15673 "Invalid directive with CKind-clause");
15674
15675 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15676 if (NameModifier != OMPD_unknown &&
15677 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15678 return OMPD_unknown;
15679
15680 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15681
15682 // [5.2:341:24-30]
15683 // If the clauses have expressions on them, such as for various clauses where
15684 // the argument of the clause is an expression, or lower-bound, length, or
15685 // stride expressions inside array sections (or subscript and stride
15686 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15687 // expressions, the expressions are evaluated immediately before the construct
15688 // to which the clause has been split or duplicated per the above rules
15689 // (therefore inside of the outer leaf constructs). However, the expressions
15690 // inside the num_teams and thread_limit clauses are always evaluated before
15691 // the outermost leaf construct.
15692
15693 // Process special cases first.
15694 switch (CKind) {
15695 case OMPC_if:
15696 switch (DKind) {
15697 case OMPD_teams_loop:
15698 case OMPD_target_teams_loop:
15699 // For [target] teams loop, assume capture region is 'teams' so it's
15700 // available for codegen later to use if/when necessary.
15701 return OMPD_teams;
15702 case OMPD_target_update:
15703 case OMPD_target_enter_data:
15704 case OMPD_target_exit_data:
15705 return OMPD_task;
15706 default:
15707 break;
15708 }
15709 break;
15710 case OMPC_num_teams:
15711 case OMPC_thread_limit:
15712 case OMPC_ompx_dyn_cgroup_mem:
15713 if (Leafs[0] == OMPD_target)
15714 return OMPD_target;
15715 break;
15716 case OMPC_device:
15717 if (Leafs[0] == OMPD_target ||
15718 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15719 OMPD_target_enter_data, OMPD_target_exit_data},
15720 DKind))
15721 return OMPD_task;
15722 break;
15723 case OMPC_novariants:
15724 case OMPC_nocontext:
15725 if (DKind == OMPD_dispatch)
15726 return OMPD_task;
15727 break;
15728 case OMPC_when:
15729 if (DKind == OMPD_metadirective)
15730 return OMPD_metadirective;
15731 break;
15732 case OMPC_filter:
15733 return OMPD_unknown;
15734 default:
15735 break;
15736 }
15737
15738 // If none of the special cases above applied, and DKind is a capturing
15739 // directive, find the innermost enclosing leaf construct that allows the
15740 // clause, and returns the corresponding capture region.
15741
15742 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15743 // Find the index in "Leafs" of the last leaf that allows the given
15744 // clause. The search will only include indexes [0, EndIdx).
15745 // EndIdx may be set to the index of the NameModifier, if present.
15746 int InnermostIdx = [&]() {
15747 for (int I = EndIdx - 1; I >= 0; --I) {
15748 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15749 return I;
15750 }
15751 return -1;
15752 }();
15753
15754 // Find the nearest enclosing capture region.
15756 for (int I = InnermostIdx - 1; I >= 0; --I) {
15757 if (!isOpenMPCapturingDirective(Leafs[I]))
15758 continue;
15759 Regions.clear();
15760 getOpenMPCaptureRegions(Regions, Leafs[I]);
15761 if (Regions[0] != OMPD_unknown)
15762 return Regions.back();
15763 }
15764 return OMPD_unknown;
15765 };
15766
15767 if (isOpenMPCapturingDirective(DKind)) {
15768 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15769 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15770 if (Leafs[I] == Dir)
15771 return I + 1;
15772 }
15773 return 0;
15774 };
15775
15776 int End = NameModifier == OMPD_unknown ? Leafs.size()
15777 : GetLeafIndex(NameModifier);
15778 return GetEnclosingRegion(End, CKind);
15779 }
15780
15781 return OMPD_unknown;
15782}
15783
15785 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15786 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15787 SourceLocation ColonLoc, SourceLocation EndLoc) {
15788 Expr *ValExpr = Condition;
15789 Stmt *HelperValStmt = nullptr;
15790 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15791 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15792 !Condition->isInstantiationDependent() &&
15793 !Condition->containsUnexpandedParameterPack()) {
15795 if (Val.isInvalid())
15796 return nullptr;
15797
15798 ValExpr = Val.get();
15799
15800 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15801 CaptureRegion = getOpenMPCaptureRegionForClause(
15802 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15803 if (CaptureRegion != OMPD_unknown &&
15805 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15806 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15807 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15808 HelperValStmt = buildPreInits(getASTContext(), Captures);
15809 }
15810 }
15811
15812 return new (getASTContext())
15813 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15814 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15815}
15816
15818 SourceLocation StartLoc,
15819 SourceLocation LParenLoc,
15820 SourceLocation EndLoc) {
15821 Expr *ValExpr = Condition;
15822 Stmt *HelperValStmt = nullptr;
15823 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15824 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15825 !Condition->isInstantiationDependent() &&
15826 !Condition->containsUnexpandedParameterPack()) {
15828 if (Val.isInvalid())
15829 return nullptr;
15830
15831 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
15832
15833 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15834 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15835 getLangOpts().OpenMP);
15836 if (CaptureRegion != OMPD_unknown &&
15838 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15839 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15840 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15841 HelperValStmt = buildPreInits(getASTContext(), Captures);
15842 }
15843 }
15844
15845 return new (getASTContext()) OMPFinalClause(
15846 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15847}
15848
15851 Expr *Op) {
15852 if (!Op)
15853 return ExprError();
15854
15855 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15856 public:
15857 IntConvertDiagnoser()
15858 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
15859 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15860 QualType T) override {
15861 return S.Diag(Loc, diag::err_omp_not_integral) << T;
15862 }
15863 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15864 QualType T) override {
15865 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15866 }
15867 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15868 QualType T,
15869 QualType ConvTy) override {
15870 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15871 }
15872 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15873 QualType ConvTy) override {
15874 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15875 << ConvTy->isEnumeralType() << ConvTy;
15876 }
15877 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15878 QualType T) override {
15879 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15880 }
15881 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15882 QualType ConvTy) override {
15883 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15884 << ConvTy->isEnumeralType() << ConvTy;
15885 }
15886 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15887 QualType) override {
15888 llvm_unreachable("conversion functions are permitted");
15889 }
15890 } ConvertDiagnoser;
15891 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
15892}
15893
15894static bool
15896 bool StrictlyPositive, bool BuildCapture = false,
15897 OpenMPDirectiveKind DKind = OMPD_unknown,
15898 OpenMPDirectiveKind *CaptureRegion = nullptr,
15899 Stmt **HelperValStmt = nullptr) {
15900 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15901 !ValExpr->isInstantiationDependent()) {
15902 SourceLocation Loc = ValExpr->getExprLoc();
15905 if (Value.isInvalid())
15906 return false;
15907
15908 ValExpr = Value.get();
15909 // The expression must evaluate to a non-negative integer value.
15910 if (std::optional<llvm::APSInt> Result =
15911 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
15912 if (Result->isSigned() &&
15913 !((!StrictlyPositive && Result->isNonNegative()) ||
15914 (StrictlyPositive && Result->isStrictlyPositive()))) {
15915 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15916 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
15917 << ValExpr->getSourceRange();
15918 return false;
15919 }
15920 }
15921 if (!BuildCapture)
15922 return true;
15923 *CaptureRegion =
15924 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15925 if (*CaptureRegion != OMPD_unknown &&
15926 !SemaRef.CurContext->isDependentContext()) {
15927 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15928 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15929 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15930 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
15931 }
15932 }
15933 return true;
15934}
15935
15936static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
15937 unsigned Last,
15938 ArrayRef<unsigned> Exclude = {}) {
15939 SmallString<256> Buffer;
15940 llvm::raw_svector_ostream Out(Buffer);
15941 unsigned Skipped = Exclude.size();
15942 for (unsigned I = First; I < Last; ++I) {
15943 if (llvm::is_contained(Exclude, I)) {
15944 --Skipped;
15945 continue;
15946 }
15947 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15948 if (I + Skipped + 2 == Last)
15949 Out << " or ";
15950 else if (I + Skipped + 1 != Last)
15951 Out << ", ";
15952 }
15953 return std::string(Out.str());
15954}
15955
15957 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
15958 SourceLocation StartLoc, SourceLocation LParenLoc,
15959 SourceLocation ModifierLoc, SourceLocation EndLoc) {
15960 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
15961 "Unexpected num_threads modifier in OpenMP < 60.");
15962
15963 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
15964 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
15966 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
15967 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
15968 return nullptr;
15969 }
15970
15971 Expr *ValExpr = NumThreads;
15972 Stmt *HelperValStmt = nullptr;
15973
15974 // OpenMP [2.5, Restrictions]
15975 // The num_threads expression must evaluate to a positive integer value.
15976 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15977 /*StrictlyPositive=*/true))
15978 return nullptr;
15979
15980 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15982 DKind, OMPC_num_threads, getLangOpts().OpenMP);
15983 if (CaptureRegion != OMPD_unknown &&
15985 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15986 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15987 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15988 HelperValStmt = buildPreInits(getASTContext(), Captures);
15989 }
15990
15991 return new (getASTContext())
15992 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
15993 StartLoc, LParenLoc, ModifierLoc, EndLoc);
15994}
15995
15997 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15998 bool SuppressExprDiags) {
15999 if (!E)
16000 return ExprError();
16001 if (E->isValueDependent() || E->isTypeDependent() ||
16003 return E;
16004
16005 llvm::APSInt Result;
16006 ExprResult ICE;
16007 if (SuppressExprDiags) {
16008 // Use a custom diagnoser that suppresses 'note' diagnostics about the
16009 // expression.
16010 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
16011 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
16013 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
16014 llvm_unreachable("Diagnostic suppressed");
16015 }
16016 } Diagnoser;
16019 } else {
16020 ICE =
16022 /*FIXME*/ AllowFoldKind::Allow);
16023 }
16024 if (ICE.isInvalid())
16025 return ExprError();
16026
16027 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
16028 (!StrictlyPositive && !Result.isNonNegative())) {
16029 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
16030 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16031 << E->getSourceRange();
16032 return ExprError();
16033 }
16034 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
16035 CKind == OMPC_allocate) &&
16036 !Result.isPowerOf2()) {
16037 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
16038 << E->getSourceRange();
16039 return ExprError();
16040 }
16041
16042 if (!Result.isRepresentableByInt64()) {
16043 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
16045 return ExprError();
16046 }
16047
16048 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
16049 DSAStack->setAssociatedLoops(Result.getExtValue());
16050 else if (CKind == OMPC_ordered)
16051 DSAStack->setAssociatedLoops(Result.getExtValue());
16052 return ICE;
16053}
16054
16055void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
16056
16057void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
16058
16059int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
16060
16062 llvm::APSInt Result;
16063 Expr::EvalResult EvalResult;
16064 // Evaluate the expression to an integer value
16065 if (!DeviceNumExpr->isValueDependent() &&
16066 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
16067 // The device expression must evaluate to a non-negative integer value.
16068 Result = EvalResult.Val.getInt();
16069 if (Result.isNonNegative()) {
16070 setOpenMPDeviceNum(Result.getZExtValue());
16071 } else {
16072 Diag(DeviceNumExpr->getExprLoc(),
16073 diag::err_omp_negative_expression_in_clause)
16074 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
16075 }
16076 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
16077 // Check if the expression is an identifier
16078 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
16079 if (IdInfo) {
16080 setOpenMPDeviceNumID(IdInfo->getName());
16081 }
16082 } else {
16083 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
16084 }
16085}
16086
16088 SourceLocation StartLoc,
16089 SourceLocation LParenLoc,
16090 SourceLocation EndLoc) {
16091 // OpenMP [2.8.1, simd construct, Description]
16092 // The parameter of the safelen clause must be a constant
16093 // positive integer expression.
16094 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
16095 if (Safelen.isInvalid())
16096 return nullptr;
16097 return new (getASTContext())
16098 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
16099}
16100
16102 SourceLocation StartLoc,
16103 SourceLocation LParenLoc,
16104 SourceLocation EndLoc) {
16105 // OpenMP [2.8.1, simd construct, Description]
16106 // The parameter of the simdlen clause must be a constant
16107 // positive integer expression.
16108 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
16109 if (Simdlen.isInvalid())
16110 return nullptr;
16111 return new (getASTContext())
16112 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
16113}
16114
16115/// Tries to find omp_allocator_handle_t type.
16117 DSAStackTy *Stack) {
16118 if (!Stack->getOMPAllocatorHandleT().isNull())
16119 return true;
16120
16121 // Set the allocator handle type.
16122 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
16123 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
16124 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
16125 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16126 << "omp_allocator_handle_t";
16127 return false;
16128 }
16129 QualType AllocatorHandleEnumTy = PT.get();
16130 AllocatorHandleEnumTy.addConst();
16131 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
16132
16133 // Fill the predefined allocator map.
16134 bool ErrorFound = false;
16135 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
16136 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
16137 StringRef Allocator =
16138 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
16139 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
16140 auto *VD = dyn_cast_or_null<ValueDecl>(
16141 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
16142 if (!VD) {
16143 ErrorFound = true;
16144 break;
16145 }
16146 QualType AllocatorType =
16148 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
16149 if (!Res.isUsable()) {
16150 ErrorFound = true;
16151 break;
16152 }
16153 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
16155 /*AllowExplicit=*/true);
16156 if (!Res.isUsable()) {
16157 ErrorFound = true;
16158 break;
16159 }
16160 Stack->setAllocator(AllocatorKind, Res.get());
16161 }
16162 if (ErrorFound) {
16163 S.Diag(Loc, diag::err_omp_implied_type_not_found)
16164 << "omp_allocator_handle_t";
16165 return false;
16166 }
16167
16168 return true;
16169}
16170
16172 SourceLocation StartLoc,
16173 SourceLocation LParenLoc,
16174 SourceLocation EndLoc) {
16175 // OpenMP [2.11.3, allocate Directive, Description]
16176 // allocator is an expression of omp_allocator_handle_t type.
16178 return nullptr;
16179
16181 if (Allocator.isInvalid())
16182 return nullptr;
16184 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
16186 /*AllowExplicit=*/true);
16187 if (Allocator.isInvalid())
16188 return nullptr;
16189 return new (getASTContext())
16190 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
16191}
16192
16194 SourceLocation StartLoc,
16195 SourceLocation LParenLoc,
16196 SourceLocation EndLoc) {
16197 // OpenMP [2.7.1, loop construct, Description]
16198 // OpenMP [2.8.1, simd construct, Description]
16199 // OpenMP [2.9.6, distribute construct, Description]
16200 // The parameter of the collapse clause must be a constant
16201 // positive integer expression.
16202 ExprResult NumForLoopsResult =
16203 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
16204 if (NumForLoopsResult.isInvalid())
16205 return nullptr;
16206 return new (getASTContext())
16207 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
16208}
16209
16211 SourceLocation EndLoc,
16212 SourceLocation LParenLoc,
16213 Expr *NumForLoops) {
16214 // OpenMP [2.7.1, loop construct, Description]
16215 // OpenMP [2.8.1, simd construct, Description]
16216 // OpenMP [2.9.6, distribute construct, Description]
16217 // The parameter of the ordered clause must be a constant
16218 // positive integer expression if any.
16219 if (NumForLoops && LParenLoc.isValid()) {
16220 ExprResult NumForLoopsResult =
16221 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
16222 if (NumForLoopsResult.isInvalid())
16223 return nullptr;
16224 NumForLoops = NumForLoopsResult.get();
16225 } else {
16226 NumForLoops = nullptr;
16227 }
16228 auto *Clause =
16230 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
16231 StartLoc, LParenLoc, EndLoc);
16232 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
16233 return Clause;
16234}
16235
16237 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
16238 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16239 OMPClause *Res = nullptr;
16240 switch (Kind) {
16241 case OMPC_default:
16242 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
16243 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16244 break;
16245 case OMPC_proc_bind:
16246 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
16247 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16248 break;
16249 case OMPC_atomic_default_mem_order:
16251 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
16252 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16253 break;
16254 case OMPC_fail:
16255 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
16256 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16257 break;
16258 case OMPC_update:
16259 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
16260 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16261 break;
16262 case OMPC_bind:
16263 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
16264 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16265 break;
16266 case OMPC_at:
16267 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
16268 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
16269 break;
16270 case OMPC_severity:
16272 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
16273 LParenLoc, EndLoc);
16274 break;
16275 case OMPC_if:
16276 case OMPC_final:
16277 case OMPC_num_threads:
16278 case OMPC_safelen:
16279 case OMPC_simdlen:
16280 case OMPC_sizes:
16281 case OMPC_allocator:
16282 case OMPC_collapse:
16283 case OMPC_schedule:
16284 case OMPC_private:
16285 case OMPC_firstprivate:
16286 case OMPC_lastprivate:
16287 case OMPC_shared:
16288 case OMPC_reduction:
16289 case OMPC_task_reduction:
16290 case OMPC_in_reduction:
16291 case OMPC_linear:
16292 case OMPC_aligned:
16293 case OMPC_copyin:
16294 case OMPC_copyprivate:
16295 case OMPC_ordered:
16296 case OMPC_nowait:
16297 case OMPC_untied:
16298 case OMPC_mergeable:
16299 case OMPC_threadprivate:
16300 case OMPC_allocate:
16301 case OMPC_flush:
16302 case OMPC_depobj:
16303 case OMPC_read:
16304 case OMPC_write:
16305 case OMPC_capture:
16306 case OMPC_compare:
16307 case OMPC_seq_cst:
16308 case OMPC_acq_rel:
16309 case OMPC_acquire:
16310 case OMPC_release:
16311 case OMPC_relaxed:
16312 case OMPC_depend:
16313 case OMPC_device:
16314 case OMPC_threads:
16315 case OMPC_simd:
16316 case OMPC_map:
16317 case OMPC_num_teams:
16318 case OMPC_thread_limit:
16319 case OMPC_priority:
16320 case OMPC_grainsize:
16321 case OMPC_nogroup:
16322 case OMPC_num_tasks:
16323 case OMPC_hint:
16324 case OMPC_dist_schedule:
16325 case OMPC_defaultmap:
16326 case OMPC_unknown:
16327 case OMPC_uniform:
16328 case OMPC_to:
16329 case OMPC_from:
16330 case OMPC_use_device_ptr:
16331 case OMPC_use_device_addr:
16332 case OMPC_is_device_ptr:
16333 case OMPC_has_device_addr:
16334 case OMPC_unified_address:
16335 case OMPC_unified_shared_memory:
16336 case OMPC_reverse_offload:
16337 case OMPC_dynamic_allocators:
16338 case OMPC_self_maps:
16339 case OMPC_device_type:
16340 case OMPC_match:
16341 case OMPC_nontemporal:
16342 case OMPC_destroy:
16343 case OMPC_novariants:
16344 case OMPC_nocontext:
16345 case OMPC_detach:
16346 case OMPC_inclusive:
16347 case OMPC_exclusive:
16348 case OMPC_uses_allocators:
16349 case OMPC_affinity:
16350 case OMPC_when:
16351 case OMPC_message:
16352 default:
16353 llvm_unreachable("Clause is not allowed.");
16354 }
16355 return Res;
16356}
16357
16359 SourceLocation KindKwLoc,
16360 SourceLocation StartLoc,
16361 SourceLocation LParenLoc,
16362 SourceLocation EndLoc) {
16363 if (Kind == OMP_DEFAULT_unknown) {
16364 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16365 << getListOfPossibleValues(OMPC_default, /*First=*/0,
16366 /*Last=*/unsigned(OMP_DEFAULT_unknown))
16367 << getOpenMPClauseNameForDiag(OMPC_default);
16368 return nullptr;
16369 }
16370
16371 switch (Kind) {
16372 case OMP_DEFAULT_none:
16373 DSAStack->setDefaultDSANone(KindKwLoc);
16374 break;
16375 case OMP_DEFAULT_shared:
16376 DSAStack->setDefaultDSAShared(KindKwLoc);
16377 break;
16378 case OMP_DEFAULT_firstprivate:
16379 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
16380 break;
16381 case OMP_DEFAULT_private:
16382 DSAStack->setDefaultDSAPrivate(KindKwLoc);
16383 break;
16384 default:
16385 llvm_unreachable("DSA unexpected in OpenMP default clause");
16386 }
16387
16388 return new (getASTContext())
16389 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16390}
16391
16393 SourceLocation KindKwLoc,
16394 SourceLocation StartLoc,
16395 SourceLocation LParenLoc,
16396 SourceLocation EndLoc) {
16397 if (Kind == OMP_PROC_BIND_unknown) {
16398 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16399 << getListOfPossibleValues(OMPC_proc_bind,
16400 /*First=*/unsigned(OMP_PROC_BIND_master),
16401 /*Last=*/
16402 unsigned(getLangOpts().OpenMP > 50
16403 ? OMP_PROC_BIND_primary
16404 : OMP_PROC_BIND_spread) +
16405 1)
16406 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
16407 return nullptr;
16408 }
16409 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
16410 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16411 << getListOfPossibleValues(OMPC_proc_bind,
16412 /*First=*/unsigned(OMP_PROC_BIND_master),
16413 /*Last=*/
16414 unsigned(OMP_PROC_BIND_spread) + 1)
16415 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
16416 return new (getASTContext())
16417 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16418}
16419
16422 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
16424 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16426 OMPC_atomic_default_mem_order, /*First=*/0,
16428 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
16429 return nullptr;
16430 }
16432 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16433}
16434
16436 SourceLocation KindKwLoc,
16437 SourceLocation StartLoc,
16438 SourceLocation LParenLoc,
16439 SourceLocation EndLoc) {
16440 if (Kind == OMPC_AT_unknown) {
16441 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16442 << getListOfPossibleValues(OMPC_at, /*First=*/0,
16443 /*Last=*/OMPC_AT_unknown)
16444 << getOpenMPClauseNameForDiag(OMPC_at);
16445 return nullptr;
16446 }
16447 return new (getASTContext())
16448 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16449}
16450
16452 SourceLocation KindKwLoc,
16453 SourceLocation StartLoc,
16454 SourceLocation LParenLoc,
16455 SourceLocation EndLoc) {
16456 if (Kind == OMPC_SEVERITY_unknown) {
16457 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16458 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
16459 /*Last=*/OMPC_SEVERITY_unknown)
16460 << getOpenMPClauseNameForDiag(OMPC_severity);
16461 return nullptr;
16462 }
16463 return new (getASTContext())
16464 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
16465}
16466
16468 SourceLocation StartLoc,
16469 SourceLocation LParenLoc,
16470 SourceLocation EndLoc) {
16471 assert(ME && "NULL expr in Message clause");
16472 QualType Type = ME->getType();
16473 if ((!Type->isPointerType() && !Type->isArrayType()) ||
16475 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
16476 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
16477 return nullptr;
16478 }
16479
16480 Stmt *HelperValStmt = nullptr;
16481
16482 // Depending on whether this clause appears in an executable context or not,
16483 // we may or may not build a capture.
16484 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16485 OpenMPDirectiveKind CaptureRegion =
16486 DKind == OMPD_unknown ? OMPD_unknown
16488 DKind, OMPC_message, getLangOpts().OpenMP);
16489 if (CaptureRegion != OMPD_unknown &&
16491 ME = SemaRef.MakeFullExpr(ME).get();
16492 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16493 ME = tryBuildCapture(SemaRef, ME, Captures).get();
16494 HelperValStmt = buildPreInits(getASTContext(), Captures);
16495 }
16496
16497 // Convert array type to pointer type if needed.
16499
16500 return new (getASTContext()) OMPMessageClause(
16501 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16502}
16503
16506 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16507 SourceLocation KindLoc, SourceLocation EndLoc) {
16508 if (Kind != OMPC_ORDER_concurrent ||
16509 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16510 // Kind should be concurrent,
16511 // Modifiers introduced in OpenMP 5.1
16512 static_assert(OMPC_ORDER_unknown > 0,
16513 "OMPC_ORDER_unknown not greater than 0");
16514
16515 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16516 << getListOfPossibleValues(OMPC_order,
16517 /*First=*/0,
16518 /*Last=*/OMPC_ORDER_unknown)
16519 << getOpenMPClauseNameForDiag(OMPC_order);
16520 return nullptr;
16521 }
16522 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
16523 MLoc.isValid()) {
16524 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16525 << getListOfPossibleValues(OMPC_order,
16526 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16527 /*Last=*/OMPC_ORDER_MODIFIER_last)
16528 << getOpenMPClauseNameForDiag(OMPC_order);
16529 } else if (getLangOpts().OpenMP >= 50) {
16530 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16531 if (DSAStack->getCurScope()) {
16532 // mark the current scope with 'order' flag
16533 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16534 DSAStack->getCurScope()->setFlags(existingFlags |
16536 }
16537 }
16538 return new (getASTContext()) OMPOrderClause(
16539 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16540}
16541
16543 SourceLocation KindKwLoc,
16544 SourceLocation StartLoc,
16545 SourceLocation LParenLoc,
16546 SourceLocation EndLoc) {
16547 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16548 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16549 SmallVector<unsigned> Except = {
16550 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16551 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16552 if (getLangOpts().OpenMP < 51)
16553 Except.push_back(OMPC_DEPEND_inoutset);
16554 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16555 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16556 /*Last=*/OMPC_DEPEND_unknown, Except)
16557 << getOpenMPClauseNameForDiag(OMPC_update);
16558 return nullptr;
16559 }
16560 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
16561 KindKwLoc, Kind, EndLoc);
16562}
16563
16565 SourceLocation StartLoc,
16566 SourceLocation LParenLoc,
16567 SourceLocation EndLoc) {
16568 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16569
16570 for (Expr *&SizeExpr : SanitizedSizeExprs) {
16571 // Skip if already sanitized, e.g. during a partial template instantiation.
16572 if (!SizeExpr)
16573 continue;
16574
16575 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
16576 /*StrictlyPositive=*/true);
16577
16578 // isNonNegativeIntegerValue returns true for non-integral types (but still
16579 // emits error diagnostic), so check for the expected type explicitly.
16580 QualType SizeTy = SizeExpr->getType();
16581 if (!SizeTy->isIntegerType())
16582 IsValid = false;
16583
16584 // Handling in templates is tricky. There are four possibilities to
16585 // consider:
16586 //
16587 // 1a. The expression is valid and we are in a instantiated template or not
16588 // in a template:
16589 // Pass valid expression to be further analysed later in Sema.
16590 // 1b. The expression is valid and we are in a template (including partial
16591 // instantiation):
16592 // isNonNegativeIntegerValue skipped any checks so there is no
16593 // guarantee it will be correct after instantiation.
16594 // ActOnOpenMPSizesClause will be called again at instantiation when
16595 // it is not in a dependent context anymore. This may cause warnings
16596 // to be emitted multiple times.
16597 // 2a. The expression is invalid and we are in an instantiated template or
16598 // not in a template:
16599 // Invalidate the expression with a clearly wrong value (nullptr) so
16600 // later in Sema we do not have to do the same validity analysis again
16601 // or crash from unexpected data. Error diagnostics have already been
16602 // emitted.
16603 // 2b. The expression is invalid and we are in a template (including partial
16604 // instantiation):
16605 // Pass the invalid expression as-is, template instantiation may
16606 // replace unexpected types/values with valid ones. The directives
16607 // with this clause must not try to use these expressions in dependent
16608 // contexts, but delay analysis until full instantiation.
16609 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16610 SizeExpr = nullptr;
16611 }
16612
16613 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16614 SanitizedSizeExprs);
16615}
16616
16618 SourceLocation StartLoc,
16619 SourceLocation LParenLoc,
16620 SourceLocation EndLoc) {
16621 size_t NumLoops = PermExprs.size();
16622 SmallVector<Expr *> SanitizedPermExprs;
16623 llvm::append_range(SanitizedPermExprs, PermExprs);
16624
16625 for (Expr *&PermExpr : SanitizedPermExprs) {
16626 // Skip if template-dependent or already sanitized, e.g. during a partial
16627 // template instantiation.
16628 if (!PermExpr || PermExpr->isInstantiationDependent())
16629 continue;
16630
16631 llvm::APSInt PermVal;
16633 PermExpr, &PermVal, AllowFoldKind::Allow);
16634 bool IsValid = PermEvalExpr.isUsable();
16635 if (IsValid)
16636 PermExpr = PermEvalExpr.get();
16637
16638 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
16639 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
16640 PermEvalExpr.get()->getEndLoc());
16641 Diag(PermEvalExpr.get()->getExprLoc(),
16642 diag::err_omp_interchange_permutation_value_range)
16643 << NumLoops << ExprRange;
16644 IsValid = false;
16645 }
16646
16647 if (!PermExpr->isInstantiationDependent() && !IsValid)
16648 PermExpr = nullptr;
16649 }
16650
16651 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
16652 EndLoc, SanitizedPermExprs);
16653}
16654
16656 SourceLocation EndLoc) {
16657 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16658}
16659
16661 SourceLocation StartLoc,
16662 SourceLocation LParenLoc,
16663 SourceLocation EndLoc) {
16664 if (FactorExpr) {
16665 // If an argument is specified, it must be a constant (or an unevaluated
16666 // template expression).
16668 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16669 if (FactorResult.isInvalid())
16670 return nullptr;
16671 FactorExpr = FactorResult.get();
16672 }
16673
16674 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16675 FactorExpr);
16676}
16677
16679 SourceLocation LParenLoc,
16680 SourceLocation EndLoc) {
16681 ExprResult AlignVal;
16682 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16683 if (AlignVal.isInvalid())
16684 return nullptr;
16685 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16686 LParenLoc, EndLoc);
16687}
16688
16691 SourceLocation StartLoc, SourceLocation LParenLoc,
16692 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16693 SourceLocation EndLoc) {
16694 OMPClause *Res = nullptr;
16695 switch (Kind) {
16696 case OMPC_schedule:
16697 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16698 assert(Argument.size() == NumberOfElements &&
16699 ArgumentLoc.size() == NumberOfElements);
16701 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16702 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16703 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16704 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16705 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16706 break;
16707 case OMPC_if:
16708 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16709 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16710 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16711 DelimLoc, EndLoc);
16712 break;
16713 case OMPC_dist_schedule:
16715 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16716 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16717 break;
16718 case OMPC_defaultmap:
16719 enum { Modifier, DefaultmapKind };
16721 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16722 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16723 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16724 EndLoc);
16725 break;
16726 case OMPC_order:
16727 enum { OrderModifier, OrderKind };
16729 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16730 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16731 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16732 break;
16733 case OMPC_device:
16734 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16736 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16737 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16738 break;
16739 case OMPC_grainsize:
16740 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16741 "Modifier for grainsize clause and its location are expected.");
16743 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16744 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16745 break;
16746 case OMPC_num_tasks:
16747 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16748 "Modifier for num_tasks clause and its location are expected.");
16750 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16751 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16752 break;
16753 case OMPC_num_threads:
16754 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16755 "Modifier for num_threads clause and its location are expected.");
16757 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
16758 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16759 break;
16760 case OMPC_final:
16761 case OMPC_safelen:
16762 case OMPC_simdlen:
16763 case OMPC_sizes:
16764 case OMPC_allocator:
16765 case OMPC_collapse:
16766 case OMPC_default:
16767 case OMPC_proc_bind:
16768 case OMPC_private:
16769 case OMPC_firstprivate:
16770 case OMPC_lastprivate:
16771 case OMPC_shared:
16772 case OMPC_reduction:
16773 case OMPC_task_reduction:
16774 case OMPC_in_reduction:
16775 case OMPC_linear:
16776 case OMPC_aligned:
16777 case OMPC_copyin:
16778 case OMPC_copyprivate:
16779 case OMPC_ordered:
16780 case OMPC_nowait:
16781 case OMPC_untied:
16782 case OMPC_mergeable:
16783 case OMPC_threadprivate:
16784 case OMPC_allocate:
16785 case OMPC_flush:
16786 case OMPC_depobj:
16787 case OMPC_read:
16788 case OMPC_write:
16789 case OMPC_update:
16790 case OMPC_capture:
16791 case OMPC_compare:
16792 case OMPC_seq_cst:
16793 case OMPC_acq_rel:
16794 case OMPC_acquire:
16795 case OMPC_release:
16796 case OMPC_relaxed:
16797 case OMPC_depend:
16798 case OMPC_threads:
16799 case OMPC_simd:
16800 case OMPC_map:
16801 case OMPC_num_teams:
16802 case OMPC_thread_limit:
16803 case OMPC_priority:
16804 case OMPC_nogroup:
16805 case OMPC_hint:
16806 case OMPC_unknown:
16807 case OMPC_uniform:
16808 case OMPC_to:
16809 case OMPC_from:
16810 case OMPC_use_device_ptr:
16811 case OMPC_use_device_addr:
16812 case OMPC_is_device_ptr:
16813 case OMPC_has_device_addr:
16814 case OMPC_unified_address:
16815 case OMPC_unified_shared_memory:
16816 case OMPC_reverse_offload:
16817 case OMPC_dynamic_allocators:
16818 case OMPC_atomic_default_mem_order:
16819 case OMPC_self_maps:
16820 case OMPC_device_type:
16821 case OMPC_match:
16822 case OMPC_nontemporal:
16823 case OMPC_at:
16824 case OMPC_severity:
16825 case OMPC_message:
16826 case OMPC_destroy:
16827 case OMPC_novariants:
16828 case OMPC_nocontext:
16829 case OMPC_detach:
16830 case OMPC_inclusive:
16831 case OMPC_exclusive:
16832 case OMPC_uses_allocators:
16833 case OMPC_affinity:
16834 case OMPC_when:
16835 case OMPC_bind:
16836 default:
16837 llvm_unreachable("Clause is not allowed.");
16838 }
16839 return Res;
16840}
16841
16844 SourceLocation M1Loc, SourceLocation M2Loc) {
16845 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16846 SmallVector<unsigned, 2> Excluded;
16848 Excluded.push_back(M2);
16849 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16850 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16851 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16852 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16853 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16854 << getListOfPossibleValues(OMPC_schedule,
16855 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16857 Excluded)
16858 << getOpenMPClauseNameForDiag(OMPC_schedule);
16859 return true;
16860 }
16861 return false;
16862}
16863
16866 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16867 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16868 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16869 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16870 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16871 return nullptr;
16872 // OpenMP, 2.7.1, Loop Construct, Restrictions
16873 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16874 // but not both.
16875 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16876 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16877 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16878 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16879 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16880 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16881 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16882 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16883 return nullptr;
16884 }
16885 if (Kind == OMPC_SCHEDULE_unknown) {
16886 std::string Values;
16887 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16888 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16889 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16891 Exclude);
16892 } else {
16893 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16894 /*Last=*/OMPC_SCHEDULE_unknown);
16895 }
16896 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16897 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
16898 return nullptr;
16899 }
16900 // OpenMP, 2.7.1, Loop Construct, Restrictions
16901 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16902 // schedule(guided).
16903 // OpenMP 5.0 does not have this restriction.
16904 if (getLangOpts().OpenMP < 50 &&
16905 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16906 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16907 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16908 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16909 diag::err_omp_schedule_nonmonotonic_static);
16910 return nullptr;
16911 }
16912 Expr *ValExpr = ChunkSize;
16913 Stmt *HelperValStmt = nullptr;
16914 if (ChunkSize) {
16915 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16916 !ChunkSize->isInstantiationDependent() &&
16917 !ChunkSize->containsUnexpandedParameterPack()) {
16918 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16919 ExprResult Val =
16920 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16921 if (Val.isInvalid())
16922 return nullptr;
16923
16924 ValExpr = Val.get();
16925
16926 // OpenMP [2.7.1, Restrictions]
16927 // chunk_size must be a loop invariant integer expression with a positive
16928 // value.
16929 if (std::optional<llvm::APSInt> Result =
16931 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16932 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16933 << "schedule" << 1 << ChunkSize->getSourceRange();
16934 return nullptr;
16935 }
16937 DSAStack->getCurrentDirective(), OMPC_schedule,
16938 getLangOpts().OpenMP) != OMPD_unknown &&
16940 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16941 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16942 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16943 HelperValStmt = buildPreInits(getASTContext(), Captures);
16944 }
16945 }
16946 }
16947
16948 return new (getASTContext())
16949 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16950 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16951}
16952
16954 SourceLocation StartLoc,
16955 SourceLocation EndLoc) {
16956 OMPClause *Res = nullptr;
16957 switch (Kind) {
16958 case OMPC_ordered:
16959 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16960 break;
16961 case OMPC_nowait:
16962 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16963 break;
16964 case OMPC_untied:
16965 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16966 break;
16967 case OMPC_mergeable:
16968 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16969 break;
16970 case OMPC_read:
16971 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16972 break;
16973 case OMPC_write:
16974 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16975 break;
16976 case OMPC_update:
16977 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16978 break;
16979 case OMPC_capture:
16980 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16981 break;
16982 case OMPC_compare:
16983 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16984 break;
16985 case OMPC_fail:
16986 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16987 break;
16988 case OMPC_seq_cst:
16989 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16990 break;
16991 case OMPC_acq_rel:
16992 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16993 break;
16994 case OMPC_acquire:
16995 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16996 break;
16997 case OMPC_release:
16998 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16999 break;
17000 case OMPC_relaxed:
17001 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
17002 break;
17003 case OMPC_weak:
17004 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
17005 break;
17006 case OMPC_threads:
17007 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
17008 break;
17009 case OMPC_simd:
17010 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
17011 break;
17012 case OMPC_nogroup:
17013 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
17014 break;
17015 case OMPC_unified_address:
17016 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
17017 break;
17018 case OMPC_unified_shared_memory:
17019 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17020 break;
17021 case OMPC_reverse_offload:
17022 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
17023 break;
17024 case OMPC_dynamic_allocators:
17025 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
17026 break;
17027 case OMPC_self_maps:
17028 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
17029 break;
17030 case OMPC_destroy:
17031 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
17032 /*LParenLoc=*/SourceLocation(),
17033 /*VarLoc=*/SourceLocation(), EndLoc);
17034 break;
17035 case OMPC_full:
17036 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
17037 break;
17038 case OMPC_partial:
17039 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
17040 break;
17041 case OMPC_ompx_bare:
17042 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
17043 break;
17044 case OMPC_if:
17045 case OMPC_final:
17046 case OMPC_num_threads:
17047 case OMPC_safelen:
17048 case OMPC_simdlen:
17049 case OMPC_sizes:
17050 case OMPC_allocator:
17051 case OMPC_collapse:
17052 case OMPC_schedule:
17053 case OMPC_private:
17054 case OMPC_firstprivate:
17055 case OMPC_lastprivate:
17056 case OMPC_shared:
17057 case OMPC_reduction:
17058 case OMPC_task_reduction:
17059 case OMPC_in_reduction:
17060 case OMPC_linear:
17061 case OMPC_aligned:
17062 case OMPC_copyin:
17063 case OMPC_copyprivate:
17064 case OMPC_default:
17065 case OMPC_proc_bind:
17066 case OMPC_threadprivate:
17067 case OMPC_allocate:
17068 case OMPC_flush:
17069 case OMPC_depobj:
17070 case OMPC_depend:
17071 case OMPC_device:
17072 case OMPC_map:
17073 case OMPC_num_teams:
17074 case OMPC_thread_limit:
17075 case OMPC_priority:
17076 case OMPC_grainsize:
17077 case OMPC_num_tasks:
17078 case OMPC_hint:
17079 case OMPC_dist_schedule:
17080 case OMPC_defaultmap:
17081 case OMPC_unknown:
17082 case OMPC_uniform:
17083 case OMPC_to:
17084 case OMPC_from:
17085 case OMPC_use_device_ptr:
17086 case OMPC_use_device_addr:
17087 case OMPC_is_device_ptr:
17088 case OMPC_has_device_addr:
17089 case OMPC_atomic_default_mem_order:
17090 case OMPC_device_type:
17091 case OMPC_match:
17092 case OMPC_nontemporal:
17093 case OMPC_order:
17094 case OMPC_at:
17095 case OMPC_severity:
17096 case OMPC_message:
17097 case OMPC_novariants:
17098 case OMPC_nocontext:
17099 case OMPC_detach:
17100 case OMPC_inclusive:
17101 case OMPC_exclusive:
17102 case OMPC_uses_allocators:
17103 case OMPC_affinity:
17104 case OMPC_when:
17105 case OMPC_ompx_dyn_cgroup_mem:
17106 default:
17107 llvm_unreachable("Clause is not allowed.");
17108 }
17109 return Res;
17110}
17111
17113 SourceLocation EndLoc) {
17114 DSAStack->setNowaitRegion();
17115 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
17116}
17117
17119 SourceLocation EndLoc) {
17120 DSAStack->setUntiedRegion();
17121 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
17122}
17123
17125 SourceLocation EndLoc) {
17126 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
17127}
17128
17130 SourceLocation EndLoc) {
17131 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
17132}
17133
17135 SourceLocation EndLoc) {
17136 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
17137}
17138
17140 SourceLocation EndLoc) {
17141 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
17142}
17143
17145 SourceLocation EndLoc) {
17146 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
17147}
17148
17150 SourceLocation EndLoc) {
17151 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
17152}
17153
17155 SourceLocation EndLoc) {
17156 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
17157}
17158
17160 SourceLocation KindLoc,
17161 SourceLocation StartLoc,
17162 SourceLocation LParenLoc,
17163 SourceLocation EndLoc) {
17164
17166 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
17167 return nullptr;
17168 }
17169 return new (getASTContext())
17170 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
17171}
17172
17174 SourceLocation EndLoc) {
17175 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
17176}
17177
17179 SourceLocation EndLoc) {
17180 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
17181}
17182
17184 SourceLocation EndLoc) {
17185 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
17186}
17187
17189 SourceLocation EndLoc) {
17190 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
17191}
17192
17194 SourceLocation EndLoc) {
17195 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
17196}
17197
17199 SourceLocation EndLoc) {
17200 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
17201}
17202
17204 SourceLocation EndLoc) {
17205 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
17206}
17207
17209 SourceLocation EndLoc) {
17210 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
17211}
17212
17214 SourceLocation EndLoc) {
17215 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
17216}
17217
17219 SourceLocation EndLoc) {
17220 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
17221}
17222
17223OMPClause *
17225 SourceLocation EndLoc) {
17226 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
17227}
17228
17230 SourceLocation EndLoc) {
17231 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
17232}
17233
17234OMPClause *
17236 SourceLocation EndLoc) {
17237 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
17238}
17239
17241 SourceLocation EndLoc) {
17242 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
17243}
17244
17247 SourceLocation StartLoc,
17248 SourceLocation EndLoc) {
17249
17250 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17251 // At least one action-clause must appear on a directive.
17252 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
17253 unsigned OMPVersion = getLangOpts().OpenMP;
17254 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
17255 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
17256 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
17257 return StmtError();
17258 }
17259
17260 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17261 // A depend clause can only appear on the directive if a targetsync
17262 // interop-type is present or the interop-var was initialized with
17263 // the targetsync interop-type.
17264
17265 // If there is any 'init' clause diagnose if there is no 'init' clause with
17266 // interop-type of 'targetsync'. Cases involving other directives cannot be
17267 // diagnosed.
17268 const OMPDependClause *DependClause = nullptr;
17269 bool HasInitClause = false;
17270 bool IsTargetSync = false;
17271 for (const OMPClause *C : Clauses) {
17272 if (IsTargetSync)
17273 break;
17274 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
17275 HasInitClause = true;
17276 if (InitClause->getIsTargetSync())
17277 IsTargetSync = true;
17278 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
17279 DependClause = DC;
17280 }
17281 }
17282 if (DependClause && HasInitClause && !IsTargetSync) {
17283 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
17284 return StmtError();
17285 }
17286
17287 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17288 // Each interop-var may be specified for at most one action-clause of each
17289 // interop construct.
17291 for (OMPClause *C : Clauses) {
17292 OpenMPClauseKind ClauseKind = C->getClauseKind();
17293 std::pair<ValueDecl *, bool> DeclResult;
17294 SourceLocation ELoc;
17295 SourceRange ERange;
17296
17297 if (ClauseKind == OMPC_init) {
17298 auto *E = cast<OMPInitClause>(C)->getInteropVar();
17299 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17300 } else if (ClauseKind == OMPC_use) {
17301 auto *E = cast<OMPUseClause>(C)->getInteropVar();
17302 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17303 } else if (ClauseKind == OMPC_destroy) {
17304 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
17305 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
17306 }
17307
17308 if (DeclResult.first) {
17309 if (!InteropVars.insert(DeclResult.first).second) {
17310 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
17311 << DeclResult.first;
17312 return StmtError();
17313 }
17314 }
17315 }
17316
17317 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
17318 Clauses);
17319}
17320
17321static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
17322 SourceLocation VarLoc,
17323 OpenMPClauseKind Kind) {
17324 SourceLocation ELoc;
17325 SourceRange ERange;
17326 Expr *RefExpr = InteropVarExpr;
17327 auto Res =
17328 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
17329 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
17330
17331 if (Res.second) {
17332 // It will be analyzed later.
17333 return true;
17334 }
17335
17336 if (!Res.first)
17337 return false;
17338
17339 // Interop variable should be of type omp_interop_t.
17340 bool HasError = false;
17341 QualType InteropType;
17342 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
17343 VarLoc, Sema::LookupOrdinaryName);
17344 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
17345 NamedDecl *ND = Result.getFoundDecl();
17346 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
17347 InteropType = QualType(TD->getTypeForDecl(), 0);
17348 } else {
17349 HasError = true;
17350 }
17351 } else {
17352 HasError = true;
17353 }
17354
17355 if (HasError) {
17356 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
17357 << "omp_interop_t";
17358 return false;
17359 }
17360
17361 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
17362 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
17363 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
17364 return false;
17365 }
17366
17367 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
17368 // The interop-var passed to init or destroy must be non-const.
17369 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
17370 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
17371 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
17372 << /*non-const*/ 1;
17373 return false;
17374 }
17375 return true;
17376}
17377
17379 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
17380 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
17381
17382 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
17383 return nullptr;
17384
17385 // Check prefer_type values. These foreign-runtime-id values are either
17386 // string literals or constant integral expressions.
17387 for (const Expr *E : InteropInfo.PreferTypes) {
17388 if (E->isValueDependent() || E->isTypeDependent() ||
17390 continue;
17392 continue;
17393 if (isa<StringLiteral>(E))
17394 continue;
17395 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
17396 return nullptr;
17397 }
17398
17399 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
17400 StartLoc, LParenLoc, VarLoc, EndLoc);
17401}
17402
17404 SourceLocation StartLoc,
17405 SourceLocation LParenLoc,
17406 SourceLocation VarLoc,
17407 SourceLocation EndLoc) {
17408
17409 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
17410 return nullptr;
17411
17412 return new (getASTContext())
17413 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17414}
17415
17417 SourceLocation StartLoc,
17418 SourceLocation LParenLoc,
17419 SourceLocation VarLoc,
17420 SourceLocation EndLoc) {
17421 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
17422 DSAStack->getCurrentDirective() == OMPD_depobj) {
17423 unsigned OMPVersion = getLangOpts().OpenMP;
17424 Diag(StartLoc, diag::err_omp_expected_clause_argument)
17425 << getOpenMPClauseNameForDiag(OMPC_destroy)
17426 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
17427 return nullptr;
17428 }
17429 if (InteropVar &&
17430 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
17431 return nullptr;
17432
17433 return new (getASTContext())
17434 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
17435}
17436
17438 SourceLocation StartLoc,
17439 SourceLocation LParenLoc,
17440 SourceLocation EndLoc) {
17441 Expr *ValExpr = Condition;
17442 Stmt *HelperValStmt = nullptr;
17443 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17444 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17445 !Condition->isInstantiationDependent() &&
17446 !Condition->containsUnexpandedParameterPack()) {
17448 if (Val.isInvalid())
17449 return nullptr;
17450
17451 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17452
17453 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17454 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
17455 getLangOpts().OpenMP);
17456 if (CaptureRegion != OMPD_unknown &&
17458 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17459 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17460 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17461 HelperValStmt = buildPreInits(getASTContext(), Captures);
17462 }
17463 }
17464
17465 return new (getASTContext()) OMPNovariantsClause(
17466 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17467}
17468
17470 SourceLocation StartLoc,
17471 SourceLocation LParenLoc,
17472 SourceLocation EndLoc) {
17473 Expr *ValExpr = Condition;
17474 Stmt *HelperValStmt = nullptr;
17475 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
17476 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
17477 !Condition->isInstantiationDependent() &&
17478 !Condition->containsUnexpandedParameterPack()) {
17480 if (Val.isInvalid())
17481 return nullptr;
17482
17483 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
17484
17485 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17486 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
17487 getLangOpts().OpenMP);
17488 if (CaptureRegion != OMPD_unknown &&
17490 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17491 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17492 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17493 HelperValStmt = buildPreInits(getASTContext(), Captures);
17494 }
17495 }
17496
17497 return new (getASTContext()) OMPNocontextClause(
17498 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17499}
17500
17502 SourceLocation StartLoc,
17503 SourceLocation LParenLoc,
17504 SourceLocation EndLoc) {
17505 Expr *ValExpr = ThreadID;
17506 Stmt *HelperValStmt = nullptr;
17507
17508 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17509 OpenMPDirectiveKind CaptureRegion =
17510 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
17511 if (CaptureRegion != OMPD_unknown &&
17513 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17514 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17515 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17516 HelperValStmt = buildPreInits(getASTContext(), Captures);
17517 }
17518
17519 return new (getASTContext()) OMPFilterClause(
17520 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17521}
17522
17524 ArrayRef<Expr *> VarList,
17525 const OMPVarListLocTy &Locs,
17527 SourceLocation StartLoc = Locs.StartLoc;
17528 SourceLocation LParenLoc = Locs.LParenLoc;
17529 SourceLocation EndLoc = Locs.EndLoc;
17530 OMPClause *Res = nullptr;
17531 int ExtraModifier = Data.ExtraModifier;
17532 int OriginalSharingModifier = Data.OriginalSharingModifier;
17533 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
17534 SourceLocation ColonLoc = Data.ColonLoc;
17535 switch (Kind) {
17536 case OMPC_private:
17537 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17538 break;
17539 case OMPC_firstprivate:
17540 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17541 break;
17542 case OMPC_lastprivate:
17543 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
17544 "Unexpected lastprivate modifier.");
17546 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
17547 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
17548 break;
17549 case OMPC_shared:
17550 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
17551 break;
17552 case OMPC_reduction:
17553 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
17554 "Unexpected lastprivate modifier.");
17556 VarList,
17558 ExtraModifier, OriginalSharingModifier),
17559 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17560 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17561 break;
17562 case OMPC_task_reduction:
17564 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17565 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17566 break;
17567 case OMPC_in_reduction:
17569 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17570 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17571 break;
17572 case OMPC_linear:
17573 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17574 "Unexpected linear modifier.");
17576 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17577 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17578 ColonLoc, Data.StepModifierLoc, EndLoc);
17579 break;
17580 case OMPC_aligned:
17581 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17582 LParenLoc, ColonLoc, EndLoc);
17583 break;
17584 case OMPC_copyin:
17585 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17586 break;
17587 case OMPC_copyprivate:
17588 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17589 break;
17590 case OMPC_flush:
17591 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17592 break;
17593 case OMPC_depend:
17594 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17595 "Unexpected depend modifier.");
17597 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17598 ColonLoc, Data.OmpAllMemoryLoc},
17599 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17600 break;
17601 case OMPC_map:
17602 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17603 "Unexpected map modifier.");
17605 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17606 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17607 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17608 ExtraModifierLoc, ColonLoc, VarList, Locs);
17609 break;
17610 case OMPC_to:
17611 Res =
17612 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17613 Data.ReductionOrMapperIdScopeSpec,
17614 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17615 break;
17616 case OMPC_from:
17617 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17618 Data.ReductionOrMapperIdScopeSpec,
17619 Data.ReductionOrMapperId, ColonLoc, VarList,
17620 Locs);
17621 break;
17622 case OMPC_use_device_ptr:
17623 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17624 break;
17625 case OMPC_use_device_addr:
17626 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17627 break;
17628 case OMPC_is_device_ptr:
17629 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17630 break;
17631 case OMPC_has_device_addr:
17632 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17633 break;
17634 case OMPC_allocate: {
17637 SourceLocation Modifier1Loc, Modifier2Loc;
17638 if (!Data.AllocClauseModifiers.empty()) {
17639 assert(Data.AllocClauseModifiers.size() <= 2 &&
17640 "More allocate modifiers than expected");
17641 Modifier1 = Data.AllocClauseModifiers[0];
17642 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
17643 if (Data.AllocClauseModifiers.size() == 2) {
17644 Modifier2 = Data.AllocClauseModifiers[1];
17645 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
17646 }
17647 }
17649 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
17650 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
17651 EndLoc);
17652 break;
17653 }
17654 case OMPC_nontemporal:
17655 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17656 break;
17657 case OMPC_inclusive:
17658 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17659 break;
17660 case OMPC_exclusive:
17661 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17662 break;
17663 case OMPC_affinity:
17664 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17665 Data.DepModOrTailExpr, VarList);
17666 break;
17667 case OMPC_doacross:
17669 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17670 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17671 break;
17672 case OMPC_num_teams:
17673 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17674 break;
17675 case OMPC_thread_limit:
17676 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17677 break;
17678 case OMPC_if:
17679 case OMPC_depobj:
17680 case OMPC_final:
17681 case OMPC_num_threads:
17682 case OMPC_safelen:
17683 case OMPC_simdlen:
17684 case OMPC_sizes:
17685 case OMPC_allocator:
17686 case OMPC_collapse:
17687 case OMPC_default:
17688 case OMPC_proc_bind:
17689 case OMPC_schedule:
17690 case OMPC_ordered:
17691 case OMPC_nowait:
17692 case OMPC_untied:
17693 case OMPC_mergeable:
17694 case OMPC_threadprivate:
17695 case OMPC_read:
17696 case OMPC_write:
17697 case OMPC_update:
17698 case OMPC_capture:
17699 case OMPC_compare:
17700 case OMPC_seq_cst:
17701 case OMPC_acq_rel:
17702 case OMPC_acquire:
17703 case OMPC_release:
17704 case OMPC_relaxed:
17705 case OMPC_device:
17706 case OMPC_threads:
17707 case OMPC_simd:
17708 case OMPC_priority:
17709 case OMPC_grainsize:
17710 case OMPC_nogroup:
17711 case OMPC_num_tasks:
17712 case OMPC_hint:
17713 case OMPC_dist_schedule:
17714 case OMPC_defaultmap:
17715 case OMPC_unknown:
17716 case OMPC_uniform:
17717 case OMPC_unified_address:
17718 case OMPC_unified_shared_memory:
17719 case OMPC_reverse_offload:
17720 case OMPC_dynamic_allocators:
17721 case OMPC_atomic_default_mem_order:
17722 case OMPC_self_maps:
17723 case OMPC_device_type:
17724 case OMPC_match:
17725 case OMPC_order:
17726 case OMPC_at:
17727 case OMPC_severity:
17728 case OMPC_message:
17729 case OMPC_destroy:
17730 case OMPC_novariants:
17731 case OMPC_nocontext:
17732 case OMPC_detach:
17733 case OMPC_uses_allocators:
17734 case OMPC_when:
17735 case OMPC_bind:
17736 default:
17737 llvm_unreachable("Clause is not allowed.");
17738 }
17739 return Res;
17740}
17741
17743 ExprObjectKind OK,
17746 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17747 if (!Res.isUsable())
17748 return ExprError();
17749 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17750 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17751 if (!Res.isUsable())
17752 return ExprError();
17753 }
17754 if (VK != VK_LValue && Res.get()->isGLValue()) {
17755 Res = SemaRef.DefaultLvalueConversion(Res.get());
17756 if (!Res.isUsable())
17757 return ExprError();
17758 }
17759 return Res;
17760}
17761
17763 SourceLocation StartLoc,
17764 SourceLocation LParenLoc,
17765 SourceLocation EndLoc) {
17767 SmallVector<Expr *, 8> PrivateCopies;
17768 unsigned OMPVersion = getLangOpts().OpenMP;
17769 bool IsImplicitClause =
17770 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17771 for (Expr *RefExpr : VarList) {
17772 assert(RefExpr && "NULL expr in OpenMP private clause.");
17773 SourceLocation ELoc;
17774 SourceRange ERange;
17775 Expr *SimpleRefExpr = RefExpr;
17776 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17777 if (Res.second) {
17778 // It will be analyzed later.
17779 Vars.push_back(RefExpr);
17780 PrivateCopies.push_back(nullptr);
17781 }
17782 ValueDecl *D = Res.first;
17783 if (!D)
17784 continue;
17785
17786 QualType Type = D->getType();
17787 auto *VD = dyn_cast<VarDecl>(D);
17788
17789 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17790 // A variable that appears in a private clause must not have an incomplete
17791 // type or a reference type.
17793 diag::err_omp_private_incomplete_type))
17794 continue;
17795 Type = Type.getNonReferenceType();
17796
17797 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17798 // A variable that is privatized must not have a const-qualified type
17799 // unless it is of class type with a mutable member. This restriction does
17800 // not apply to the firstprivate clause.
17801 //
17802 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17803 // A variable that appears in a private clause must not have a
17804 // const-qualified type unless it is of class type with a mutable member.
17805 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17806 continue;
17807
17808 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17809 // in a Construct]
17810 // Variables with the predetermined data-sharing attributes may not be
17811 // listed in data-sharing attributes clauses, except for the cases
17812 // listed below. For these exceptions only, listing a predetermined
17813 // variable in a data-sharing attribute clause is allowed and overrides
17814 // the variable's predetermined data-sharing attributes.
17815 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17816 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17817 Diag(ELoc, diag::err_omp_wrong_dsa)
17818 << getOpenMPClauseNameForDiag(DVar.CKind)
17819 << getOpenMPClauseNameForDiag(OMPC_private);
17821 continue;
17822 }
17823
17824 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17825 // Variably modified types are not supported for tasks.
17827 isOpenMPTaskingDirective(CurrDir)) {
17828 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17829 << getOpenMPClauseNameForDiag(OMPC_private) << Type
17830 << getOpenMPDirectiveName(CurrDir, OMPVersion);
17831 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17833 Diag(D->getLocation(),
17834 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17835 << D;
17836 continue;
17837 }
17838
17839 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17840 // A list item cannot appear in both a map clause and a data-sharing
17841 // attribute clause on the same construct
17842 //
17843 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17844 // A list item cannot appear in both a map clause and a data-sharing
17845 // attribute clause on the same construct unless the construct is a
17846 // combined construct.
17847 if ((getLangOpts().OpenMP <= 45 &&
17849 CurrDir == OMPD_target) {
17850 OpenMPClauseKind ConflictKind;
17851 if (DSAStack->checkMappableExprComponentListsForDecl(
17852 VD, /*CurrentRegionOnly=*/true,
17854 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17855 ConflictKind = WhereFoundClauseKind;
17856 return true;
17857 })) {
17858 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17859 << getOpenMPClauseNameForDiag(OMPC_private)
17860 << getOpenMPClauseNameForDiag(ConflictKind)
17861 << getOpenMPDirectiveName(CurrDir, OMPVersion);
17863 continue;
17864 }
17865 }
17866
17867 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17868 // A variable of class type (or array thereof) that appears in a private
17869 // clause requires an accessible, unambiguous default constructor for the
17870 // class type.
17871 // Generate helper private variable and initialize it with the default
17872 // value. The address of the original variable is replaced by the address of
17873 // the new private variable in CodeGen. This new variable is not added to
17874 // IdResolver, so the code in the OpenMP region uses original variable for
17875 // proper diagnostics.
17876 Type = Type.getUnqualifiedType();
17877 VarDecl *VDPrivate =
17878 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17879 D->hasAttrs() ? &D->getAttrs() : nullptr,
17880 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17882 if (VDPrivate->isInvalidDecl())
17883 continue;
17884 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17885 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17886
17887 DeclRefExpr *Ref = nullptr;
17888 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17889 auto *FD = dyn_cast<FieldDecl>(D);
17890 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17891 if (VD)
17893 RefExpr->getExprLoc());
17894 else
17895 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17896 }
17897 if (!IsImplicitClause)
17898 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17899 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17900 ? RefExpr->IgnoreParens()
17901 : Ref);
17902 PrivateCopies.push_back(VDPrivateRefExpr);
17903 }
17904
17905 if (Vars.empty())
17906 return nullptr;
17907
17908 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17909 Vars, PrivateCopies);
17910}
17911
17913 SourceLocation StartLoc,
17914 SourceLocation LParenLoc,
17915 SourceLocation EndLoc) {
17917 SmallVector<Expr *, 8> PrivateCopies;
17919 SmallVector<Decl *, 4> ExprCaptures;
17920 bool IsImplicitClause =
17921 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17922 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17923 unsigned OMPVersion = getLangOpts().OpenMP;
17924
17925 for (Expr *RefExpr : VarList) {
17926 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17927 SourceLocation ELoc;
17928 SourceRange ERange;
17929 Expr *SimpleRefExpr = RefExpr;
17930 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17931 if (Res.second) {
17932 // It will be analyzed later.
17933 Vars.push_back(RefExpr);
17934 PrivateCopies.push_back(nullptr);
17935 Inits.push_back(nullptr);
17936 }
17937 ValueDecl *D = Res.first;
17938 if (!D)
17939 continue;
17940
17941 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17942 QualType Type = D->getType();
17943 auto *VD = dyn_cast<VarDecl>(D);
17944
17945 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17946 // A variable that appears in a private clause must not have an incomplete
17947 // type or a reference type.
17949 diag::err_omp_firstprivate_incomplete_type))
17950 continue;
17951 Type = Type.getNonReferenceType();
17952
17953 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17954 // A variable of class type (or array thereof) that appears in a private
17955 // clause requires an accessible, unambiguous copy constructor for the
17956 // class type.
17957 QualType ElemType =
17959
17960 // If an implicit firstprivate variable found it was checked already.
17961 DSAStackTy::DSAVarData TopDVar;
17962 if (!IsImplicitClause) {
17963 DSAStackTy::DSAVarData DVar =
17964 DSAStack->getTopDSA(D, /*FromParent=*/false);
17965 TopDVar = DVar;
17966 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17967 bool IsConstant = ElemType.isConstant(getASTContext());
17968 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17969 // A list item that specifies a given variable may not appear in more
17970 // than one clause on the same directive, except that a variable may be
17971 // specified in both firstprivate and lastprivate clauses.
17972 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17973 // A list item may appear in a firstprivate or lastprivate clause but not
17974 // both.
17975 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17976 (isOpenMPDistributeDirective(CurrDir) ||
17977 DVar.CKind != OMPC_lastprivate) &&
17978 DVar.RefExpr) {
17979 Diag(ELoc, diag::err_omp_wrong_dsa)
17980 << getOpenMPClauseNameForDiag(DVar.CKind)
17981 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
17983 continue;
17984 }
17985
17986 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17987 // in a Construct]
17988 // Variables with the predetermined data-sharing attributes may not be
17989 // listed in data-sharing attributes clauses, except for the cases
17990 // listed below. For these exceptions only, listing a predetermined
17991 // variable in a data-sharing attribute clause is allowed and overrides
17992 // the variable's predetermined data-sharing attributes.
17993 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17994 // in a Construct, C/C++, p.2]
17995 // Variables with const-qualified type having no mutable member may be
17996 // listed in a firstprivate clause, even if they are static data members.
17997 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17998 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17999 Diag(ELoc, diag::err_omp_wrong_dsa)
18000 << getOpenMPClauseNameForDiag(DVar.CKind)
18001 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
18003 continue;
18004 }
18005
18006 // OpenMP [2.9.3.4, Restrictions, p.2]
18007 // A list item that is private within a parallel region must not appear
18008 // in a firstprivate clause on a worksharing construct if any of the
18009 // worksharing regions arising from the worksharing construct ever bind
18010 // to any of the parallel regions arising from the parallel construct.
18011 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18012 // A list item that is private within a teams region must not appear in a
18013 // firstprivate clause on a distribute construct if any of the distribute
18014 // regions arising from the distribute construct ever bind to any of the
18015 // teams regions arising from the teams construct.
18016 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
18017 // A list item that appears in a reduction clause of a teams construct
18018 // must not appear in a firstprivate clause on a distribute construct if
18019 // any of the distribute regions arising from the distribute construct
18020 // ever bind to any of the teams regions arising from the teams construct.
18021 if ((isOpenMPWorksharingDirective(CurrDir) ||
18022 isOpenMPDistributeDirective(CurrDir)) &&
18023 !isOpenMPParallelDirective(CurrDir) &&
18024 !isOpenMPTeamsDirective(CurrDir)) {
18025 DVar = DSAStack->getImplicitDSA(D, true);
18026 if (DVar.CKind != OMPC_shared &&
18027 (isOpenMPParallelDirective(DVar.DKind) ||
18028 isOpenMPTeamsDirective(DVar.DKind) ||
18029 DVar.DKind == OMPD_unknown)) {
18030 Diag(ELoc, diag::err_omp_required_access)
18031 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
18032 << getOpenMPClauseNameForDiag(OMPC_shared);
18034 continue;
18035 }
18036 }
18037 // OpenMP [2.9.3.4, Restrictions, p.3]
18038 // A list item that appears in a reduction clause of a parallel construct
18039 // must not appear in a firstprivate clause on a worksharing or task
18040 // construct if any of the worksharing or task regions arising from the
18041 // worksharing or task construct ever bind to any of the parallel regions
18042 // arising from the parallel construct.
18043 // OpenMP [2.9.3.4, Restrictions, p.4]
18044 // A list item that appears in a reduction clause in worksharing
18045 // construct must not appear in a firstprivate clause in a task construct
18046 // encountered during execution of any of the worksharing regions arising
18047 // from the worksharing construct.
18048 if (isOpenMPTaskingDirective(CurrDir)) {
18049 DVar = DSAStack->hasInnermostDSA(
18050 D,
18051 [](OpenMPClauseKind C, bool AppliedToPointee) {
18052 return C == OMPC_reduction && !AppliedToPointee;
18053 },
18054 [](OpenMPDirectiveKind K) {
18055 return isOpenMPParallelDirective(K) ||
18058 },
18059 /*FromParent=*/true);
18060 if (DVar.CKind == OMPC_reduction &&
18061 (isOpenMPParallelDirective(DVar.DKind) ||
18062 isOpenMPWorksharingDirective(DVar.DKind) ||
18063 isOpenMPTeamsDirective(DVar.DKind))) {
18064 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
18065 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
18067 continue;
18068 }
18069 }
18070
18071 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
18072 // A list item cannot appear in both a map clause and a data-sharing
18073 // attribute clause on the same construct
18074 //
18075 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
18076 // A list item cannot appear in both a map clause and a data-sharing
18077 // attribute clause on the same construct unless the construct is a
18078 // combined construct.
18079 if ((getLangOpts().OpenMP <= 45 &&
18081 CurrDir == OMPD_target) {
18082 OpenMPClauseKind ConflictKind;
18083 if (DSAStack->checkMappableExprComponentListsForDecl(
18084 VD, /*CurrentRegionOnly=*/true,
18085 [&ConflictKind](
18087 OpenMPClauseKind WhereFoundClauseKind) {
18088 ConflictKind = WhereFoundClauseKind;
18089 return true;
18090 })) {
18091 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
18092 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
18093 << getOpenMPClauseNameForDiag(ConflictKind)
18094 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18095 OMPVersion);
18097 continue;
18098 }
18099 }
18100 }
18101
18102 // Variably modified types are not supported for tasks.
18104 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
18105 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
18106 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
18107 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
18108 OMPVersion);
18109 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18111 Diag(D->getLocation(),
18112 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18113 << D;
18114 continue;
18115 }
18116
18117 Type = Type.getUnqualifiedType();
18118 VarDecl *VDPrivate =
18119 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
18120 D->hasAttrs() ? &D->getAttrs() : nullptr,
18121 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18122 // Generate helper private variable and initialize it with the value of the
18123 // original variable. The address of the original variable is replaced by
18124 // the address of the new private variable in the CodeGen. This new variable
18125 // is not added to IdResolver, so the code in the OpenMP region uses
18126 // original variable for proper diagnostics and variable capturing.
18127 Expr *VDInitRefExpr = nullptr;
18128 // For arrays generate initializer for single element and replace it by the
18129 // original array element in CodeGen.
18130 if (Type->isArrayType()) {
18131 VarDecl *VDInit =
18132 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
18133 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
18134 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
18135 ElemType = ElemType.getUnqualifiedType();
18136 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
18137 ElemType, ".firstprivate.temp");
18138 InitializedEntity Entity =
18141
18142 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
18143 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
18144 if (Result.isInvalid())
18145 VDPrivate->setInvalidDecl();
18146 else
18147 VDPrivate->setInit(Result.getAs<Expr>());
18148 // Remove temp variable declaration.
18149 getASTContext().Deallocate(VDInitTemp);
18150 } else {
18151 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
18152 ".firstprivate.temp");
18153 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
18154 RefExpr->getExprLoc());
18156 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
18157 /*DirectInit=*/false);
18158 }
18159 if (VDPrivate->isInvalidDecl()) {
18160 if (IsImplicitClause) {
18161 Diag(RefExpr->getExprLoc(),
18162 diag::note_omp_task_predetermined_firstprivate_here);
18163 }
18164 continue;
18165 }
18166 SemaRef.CurContext->addDecl(VDPrivate);
18167 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
18168 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
18169 RefExpr->getExprLoc());
18170 DeclRefExpr *Ref = nullptr;
18171 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18172 if (TopDVar.CKind == OMPC_lastprivate) {
18173 Ref = TopDVar.PrivateCopy;
18174 } else {
18175 auto *FD = dyn_cast<FieldDecl>(D);
18176 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
18177 if (VD)
18178 Ref =
18180 RefExpr->getExprLoc());
18181 else
18182 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
18183 if (VD || !isOpenMPCapturedDecl(D))
18184 ExprCaptures.push_back(Ref->getDecl());
18185 }
18186 }
18187 if (!IsImplicitClause)
18188 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
18189 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18190 ? RefExpr->IgnoreParens()
18191 : Ref);
18192 PrivateCopies.push_back(VDPrivateRefExpr);
18193 Inits.push_back(VDInitRefExpr);
18194 }
18195
18196 if (Vars.empty())
18197 return nullptr;
18198
18200 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
18201 buildPreInits(getASTContext(), ExprCaptures));
18202}
18203
18206 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
18207 SourceLocation LParenLoc, SourceLocation EndLoc) {
18208 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
18209 assert(ColonLoc.isValid() && "Colon location must be valid.");
18210 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
18211 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
18212 /*Last=*/OMPC_LASTPRIVATE_unknown)
18213 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
18214 return nullptr;
18215 }
18216
18218 SmallVector<Expr *, 8> SrcExprs;
18219 SmallVector<Expr *, 8> DstExprs;
18220 SmallVector<Expr *, 8> AssignmentOps;
18221 SmallVector<Decl *, 4> ExprCaptures;
18222 SmallVector<Expr *, 4> ExprPostUpdates;
18223 for (Expr *RefExpr : VarList) {
18224 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
18225 SourceLocation ELoc;
18226 SourceRange ERange;
18227 Expr *SimpleRefExpr = RefExpr;
18228 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18229 if (Res.second) {
18230 // It will be analyzed later.
18231 Vars.push_back(RefExpr);
18232 SrcExprs.push_back(nullptr);
18233 DstExprs.push_back(nullptr);
18234 AssignmentOps.push_back(nullptr);
18235 }
18236 ValueDecl *D = Res.first;
18237 if (!D)
18238 continue;
18239
18240 QualType Type = D->getType();
18241 auto *VD = dyn_cast<VarDecl>(D);
18242
18243 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
18244 // A variable that appears in a lastprivate clause must not have an
18245 // incomplete type or a reference type.
18247 diag::err_omp_lastprivate_incomplete_type))
18248 continue;
18249 Type = Type.getNonReferenceType();
18250
18251 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18252 // A variable that is privatized must not have a const-qualified type
18253 // unless it is of class type with a mutable member. This restriction does
18254 // not apply to the firstprivate clause.
18255 //
18256 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
18257 // A variable that appears in a lastprivate clause must not have a
18258 // const-qualified type unless it is of class type with a mutable member.
18259 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
18260 continue;
18261
18262 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
18263 // A list item that appears in a lastprivate clause with the conditional
18264 // modifier must be a scalar variable.
18265 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
18266 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
18267 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18269 Diag(D->getLocation(),
18270 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18271 << D;
18272 continue;
18273 }
18274
18275 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
18276 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18277 // in a Construct]
18278 // Variables with the predetermined data-sharing attributes may not be
18279 // listed in data-sharing attributes clauses, except for the cases
18280 // listed below.
18281 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
18282 // A list item may appear in a firstprivate or lastprivate clause but not
18283 // both.
18284 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18285 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
18286 (isOpenMPDistributeDirective(CurrDir) ||
18287 DVar.CKind != OMPC_firstprivate) &&
18288 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
18289 Diag(ELoc, diag::err_omp_wrong_dsa)
18290 << getOpenMPClauseNameForDiag(DVar.CKind)
18291 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
18293 continue;
18294 }
18295
18296 // OpenMP [2.14.3.5, Restrictions, p.2]
18297 // A list item that is private within a parallel region, or that appears in
18298 // the reduction clause of a parallel construct, must not appear in a
18299 // lastprivate clause on a worksharing construct if any of the corresponding
18300 // worksharing regions ever binds to any of the corresponding parallel
18301 // regions.
18302 DSAStackTy::DSAVarData TopDVar = DVar;
18303 if (isOpenMPWorksharingDirective(CurrDir) &&
18304 !isOpenMPParallelDirective(CurrDir) &&
18305 !isOpenMPTeamsDirective(CurrDir)) {
18306 DVar = DSAStack->getImplicitDSA(D, true);
18307 if (DVar.CKind != OMPC_shared) {
18308 Diag(ELoc, diag::err_omp_required_access)
18309 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
18310 << getOpenMPClauseNameForDiag(OMPC_shared);
18312 continue;
18313 }
18314 }
18315
18316 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
18317 // A variable of class type (or array thereof) that appears in a
18318 // lastprivate clause requires an accessible, unambiguous default
18319 // constructor for the class type, unless the list item is also specified
18320 // in a firstprivate clause.
18321 // A variable of class type (or array thereof) that appears in a
18322 // lastprivate clause requires an accessible, unambiguous copy assignment
18323 // operator for the class type.
18325 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
18326 Type.getUnqualifiedType(), ".lastprivate.src",
18327 D->hasAttrs() ? &D->getAttrs() : nullptr);
18328 DeclRefExpr *PseudoSrcExpr =
18329 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
18330 VarDecl *DstVD =
18331 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
18332 D->hasAttrs() ? &D->getAttrs() : nullptr);
18333 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
18334 // For arrays generate assignment operation for single element and replace
18335 // it by the original array element in CodeGen.
18336 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
18337 PseudoDstExpr, PseudoSrcExpr);
18338 if (AssignmentOp.isInvalid())
18339 continue;
18340 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
18341 /*DiscardedValue=*/false);
18342 if (AssignmentOp.isInvalid())
18343 continue;
18344
18345 DeclRefExpr *Ref = nullptr;
18346 if (!VD && !SemaRef.CurContext->isDependentContext()) {
18347 if (TopDVar.CKind == OMPC_firstprivate) {
18348 Ref = TopDVar.PrivateCopy;
18349 } else {
18350 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
18351 if (!isOpenMPCapturedDecl(D))
18352 ExprCaptures.push_back(Ref->getDecl());
18353 }
18354 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
18356 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
18358 if (!RefRes.isUsable())
18359 continue;
18360 ExprResult PostUpdateRes =
18361 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
18362 SimpleRefExpr, RefRes.get());
18363 if (!PostUpdateRes.isUsable())
18364 continue;
18365 ExprPostUpdates.push_back(
18366 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
18367 }
18368 }
18369 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
18370 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
18371 ? RefExpr->IgnoreParens()
18372 : Ref);
18373 SrcExprs.push_back(PseudoSrcExpr);
18374 DstExprs.push_back(PseudoDstExpr);
18375 AssignmentOps.push_back(AssignmentOp.get());
18376 }
18377
18378 if (Vars.empty())
18379 return nullptr;
18380
18382 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
18383 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
18384 buildPreInits(getASTContext(), ExprCaptures),
18385 buildPostUpdate(SemaRef, ExprPostUpdates));
18386}
18387
18389 SourceLocation StartLoc,
18390 SourceLocation LParenLoc,
18391 SourceLocation EndLoc) {
18393 for (Expr *RefExpr : VarList) {
18394 assert(RefExpr && "NULL expr in OpenMP shared clause.");
18395 SourceLocation ELoc;
18396 SourceRange ERange;
18397 Expr *SimpleRefExpr = RefExpr;
18398 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18399 if (Res.second) {
18400 // It will be analyzed later.
18401 Vars.push_back(RefExpr);
18402 }
18403 ValueDecl *D = Res.first;
18404 if (!D)
18405 continue;
18406
18407 auto *VD = dyn_cast<VarDecl>(D);
18408 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
18409 // in a Construct]
18410 // Variables with the predetermined data-sharing attributes may not be
18411 // listed in data-sharing attributes clauses, except for the cases
18412 // listed below. For these exceptions only, listing a predetermined
18413 // variable in a data-sharing attribute clause is allowed and overrides
18414 // the variable's predetermined data-sharing attributes.
18415 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
18416 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
18417 DVar.RefExpr) {
18418 Diag(ELoc, diag::err_omp_wrong_dsa)
18419 << getOpenMPClauseNameForDiag(DVar.CKind)
18420 << getOpenMPClauseNameForDiag(OMPC_shared);
18422 continue;
18423 }
18424
18425 DeclRefExpr *Ref = nullptr;
18426 if (!VD && isOpenMPCapturedDecl(D) &&
18428 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
18429 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
18430 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
18431 ? RefExpr->IgnoreParens()
18432 : Ref);
18433 }
18434
18435 if (Vars.empty())
18436 return nullptr;
18437
18438 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
18439 Vars);
18440}
18441
18442namespace {
18443class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
18444 DSAStackTy *Stack;
18445
18446public:
18447 bool VisitDeclRefExpr(DeclRefExpr *E) {
18448 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
18449 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
18450 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
18451 return false;
18452 if (DVar.CKind != OMPC_unknown)
18453 return true;
18454 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
18455 VD,
18456 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
18457 return isOpenMPPrivate(C) && !AppliedToPointee;
18458 },
18459 [](OpenMPDirectiveKind) { return true; },
18460 /*FromParent=*/true);
18461 return DVarPrivate.CKind != OMPC_unknown;
18462 }
18463 return false;
18464 }
18465 bool VisitStmt(Stmt *S) {
18466 for (Stmt *Child : S->children()) {
18467 if (Child && Visit(Child))
18468 return true;
18469 }
18470 return false;
18471 }
18472 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
18473};
18474} // namespace
18475
18476namespace {
18477// Transform MemberExpression for specified FieldDecl of current class to
18478// DeclRefExpr to specified OMPCapturedExprDecl.
18479class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
18480 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
18481 ValueDecl *Field = nullptr;
18482 DeclRefExpr *CapturedExpr = nullptr;
18483
18484public:
18485 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
18486 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
18487
18488 ExprResult TransformMemberExpr(MemberExpr *E) {
18489 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
18490 E->getMemberDecl() == Field) {
18491 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
18492 return CapturedExpr;
18493 }
18494 return BaseTransform::TransformMemberExpr(E);
18495 }
18496 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
18497};
18498} // namespace
18499
18500template <typename T, typename U>
18502 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
18503 for (U &Set : Lookups) {
18504 for (auto *D : Set) {
18505 if (T Res = Gen(cast<ValueDecl>(D)))
18506 return Res;
18507 }
18508 }
18509 return T();
18510}
18511
18513 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
18514
18515 for (auto *RD : D->redecls()) {
18516 // Don't bother with extra checks if we already know this one isn't visible.
18517 if (RD == D)
18518 continue;
18519
18520 auto ND = cast<NamedDecl>(RD);
18521 if (LookupResult::isVisible(SemaRef, ND))
18522 return ND;
18523 }
18524
18525 return nullptr;
18526}
18527
18528static void
18532 // Find all of the associated namespaces and classes based on the
18533 // arguments we have.
18534 Sema::AssociatedNamespaceSet AssociatedNamespaces;
18535 Sema::AssociatedClassSet AssociatedClasses;
18536 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
18537 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
18538 AssociatedClasses);
18539
18540 // C++ [basic.lookup.argdep]p3:
18541 // Let X be the lookup set produced by unqualified lookup (3.4.1)
18542 // and let Y be the lookup set produced by argument dependent
18543 // lookup (defined as follows). If X contains [...] then Y is
18544 // empty. Otherwise Y is the set of declarations found in the
18545 // namespaces associated with the argument types as described
18546 // below. The set of declarations found by the lookup of the name
18547 // is the union of X and Y.
18548 //
18549 // Here, we compute Y and add its members to the overloaded
18550 // candidate set.
18551 for (auto *NS : AssociatedNamespaces) {
18552 // When considering an associated namespace, the lookup is the
18553 // same as the lookup performed when the associated namespace is
18554 // used as a qualifier (3.4.3.2) except that:
18555 //
18556 // -- Any using-directives in the associated namespace are
18557 // ignored.
18558 //
18559 // -- Any namespace-scope friend functions declared in
18560 // associated classes are visible within their respective
18561 // namespaces even if they are not visible during an ordinary
18562 // lookup (11.4).
18563 DeclContext::lookup_result R = NS->lookup(Id.getName());
18564 for (auto *D : R) {
18565 auto *Underlying = D;
18566 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18567 Underlying = USD->getTargetDecl();
18568
18569 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
18570 !isa<OMPDeclareMapperDecl>(Underlying))
18571 continue;
18572
18573 if (!SemaRef.isVisible(D)) {
18574 D = findAcceptableDecl(SemaRef, D);
18575 if (!D)
18576 continue;
18577 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
18578 Underlying = USD->getTargetDecl();
18579 }
18580 Lookups.emplace_back();
18581 Lookups.back().addDecl(Underlying);
18582 }
18583 }
18584}
18585
18586static ExprResult
18588 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18589 const DeclarationNameInfo &ReductionId, QualType Ty,
18590 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18591 if (ReductionIdScopeSpec.isInvalid())
18592 return ExprError();
18593 SmallVector<UnresolvedSet<8>, 4> Lookups;
18594 if (S) {
18595 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18596 Lookup.suppressDiagnostics();
18597 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
18598 /*ObjectType=*/QualType())) {
18599 NamedDecl *D = Lookup.getRepresentativeDecl();
18600 do {
18601 S = S->getParent();
18602 } while (S && !S->isDeclScope(D));
18603 if (S)
18604 S = S->getParent();
18605 Lookups.emplace_back();
18606 Lookups.back().append(Lookup.begin(), Lookup.end());
18607 Lookup.clear();
18608 }
18609 } else if (auto *ULE =
18610 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18611 Lookups.push_back(UnresolvedSet<8>());
18612 Decl *PrevD = nullptr;
18613 for (NamedDecl *D : ULE->decls()) {
18614 if (D == PrevD)
18615 Lookups.push_back(UnresolvedSet<8>());
18616 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18617 Lookups.back().addDecl(DRD);
18618 PrevD = D;
18619 }
18620 }
18621 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18624 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18625 return !D->isInvalidDecl() &&
18626 (D->getType()->isDependentType() ||
18627 D->getType()->isInstantiationDependentType() ||
18628 D->getType()->containsUnexpandedParameterPack());
18629 })) {
18630 UnresolvedSet<8> ResSet;
18631 for (const UnresolvedSet<8> &Set : Lookups) {
18632 if (Set.empty())
18633 continue;
18634 ResSet.append(Set.begin(), Set.end());
18635 // The last item marks the end of all declarations at the specified scope.
18636 ResSet.addDecl(Set[Set.size() - 1]);
18637 }
18639 SemaRef.Context, /*NamingClass=*/nullptr,
18640 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18641 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
18642 /*KnownInstantiationDependent=*/false);
18643 }
18644 // Lookup inside the classes.
18645 // C++ [over.match.oper]p3:
18646 // For a unary operator @ with an operand of a type whose
18647 // cv-unqualified version is T1, and for a binary operator @ with
18648 // a left operand of a type whose cv-unqualified version is T1 and
18649 // a right operand of a type whose cv-unqualified version is T2,
18650 // three sets of candidate functions, designated member
18651 // candidates, non-member candidates and built-in candidates, are
18652 // constructed as follows:
18653 // -- If T1 is a complete class type or a class currently being
18654 // defined, the set of member candidates is the result of the
18655 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18656 // the set of member candidates is empty.
18657 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18658 Lookup.suppressDiagnostics();
18659 if (Ty->isRecordType()) {
18660 // Complete the type if it can be completed.
18661 // If the type is neither complete nor being defined, bail out now.
18662 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
18663 auto *RD = Ty->castAsRecordDecl();
18664 if (IsComplete || RD->isBeingDefined()) {
18665 Lookup.clear();
18666 SemaRef.LookupQualifiedName(Lookup, RD);
18667 if (Lookup.empty()) {
18668 Lookups.emplace_back();
18669 Lookups.back().append(Lookup.begin(), Lookup.end());
18670 }
18671 }
18672 }
18673 // Perform ADL.
18674 if (SemaRef.getLangOpts().CPlusPlus)
18675 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18676 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18677 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18678 if (!D->isInvalidDecl() &&
18679 SemaRef.Context.hasSameType(D->getType(), Ty))
18680 return D;
18681 return nullptr;
18682 }))
18683 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18684 VK_LValue, Loc);
18685 if (SemaRef.getLangOpts().CPlusPlus) {
18686 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18687 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18688 if (!D->isInvalidDecl() &&
18689 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18690 !Ty.isMoreQualifiedThan(D->getType(),
18691 SemaRef.getASTContext()))
18692 return D;
18693 return nullptr;
18694 })) {
18695 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18696 /*DetectVirtual=*/false);
18697 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18698 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18699 VD->getType().getUnqualifiedType()))) {
18700 if (SemaRef.CheckBaseClassAccess(
18701 Loc, VD->getType(), Ty, Paths.front(),
18702 /*DiagID=*/0) != Sema::AR_inaccessible) {
18703 SemaRef.BuildBasePathArray(Paths, BasePath);
18704 return SemaRef.BuildDeclRefExpr(
18706 }
18707 }
18708 }
18709 }
18710 }
18711 if (ReductionIdScopeSpec.isSet()) {
18712 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18713 << Ty << Range;
18714 return ExprError();
18715 }
18716 return ExprEmpty();
18717}
18718
18719namespace {
18720/// Data for the reduction-based clauses.
18721struct ReductionData {
18722 /// List of original reduction items.
18724 /// List of private copies of the reduction items.
18725 SmallVector<Expr *, 8> Privates;
18726 /// LHS expressions for the reduction_op expressions.
18728 /// RHS expressions for the reduction_op expressions.
18730 /// Reduction operation expression.
18731 SmallVector<Expr *, 8> ReductionOps;
18732 /// inscan copy operation expressions.
18733 SmallVector<Expr *, 8> InscanCopyOps;
18734 /// inscan copy temp array expressions for prefix sums.
18735 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18736 /// inscan copy temp array element expressions for prefix sums.
18737 SmallVector<Expr *, 8> InscanCopyArrayElems;
18738 /// Taskgroup descriptors for the corresponding reduction items in
18739 /// in_reduction clauses.
18740 SmallVector<Expr *, 8> TaskgroupDescriptors;
18741 /// List of captures for clause.
18742 SmallVector<Decl *, 4> ExprCaptures;
18743 /// List of postupdate expressions.
18744 SmallVector<Expr *, 4> ExprPostUpdates;
18745 /// Reduction modifier.
18746 unsigned RedModifier = 0;
18747 /// Original modifier.
18748 unsigned OrigSharingModifier = 0;
18749 /// Private Variable Reduction
18750 SmallVector<bool, 8> IsPrivateVarReduction;
18751 ReductionData() = delete;
18752 /// Reserves required memory for the reduction data.
18753 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
18754 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
18755 Vars.reserve(Size);
18756 Privates.reserve(Size);
18757 LHSs.reserve(Size);
18758 RHSs.reserve(Size);
18759 ReductionOps.reserve(Size);
18760 IsPrivateVarReduction.reserve(Size);
18761 if (RedModifier == OMPC_REDUCTION_inscan) {
18762 InscanCopyOps.reserve(Size);
18763 InscanCopyArrayTemps.reserve(Size);
18764 InscanCopyArrayElems.reserve(Size);
18765 }
18766 TaskgroupDescriptors.reserve(Size);
18767 ExprCaptures.reserve(Size);
18768 ExprPostUpdates.reserve(Size);
18769 }
18770 /// Stores reduction item and reduction operation only (required for dependent
18771 /// reduction item).
18772 void push(Expr *Item, Expr *ReductionOp) {
18773 Vars.emplace_back(Item);
18774 Privates.emplace_back(nullptr);
18775 LHSs.emplace_back(nullptr);
18776 RHSs.emplace_back(nullptr);
18777 ReductionOps.emplace_back(ReductionOp);
18778 IsPrivateVarReduction.emplace_back(false);
18779 TaskgroupDescriptors.emplace_back(nullptr);
18780 if (RedModifier == OMPC_REDUCTION_inscan) {
18781 InscanCopyOps.push_back(nullptr);
18782 InscanCopyArrayTemps.push_back(nullptr);
18783 InscanCopyArrayElems.push_back(nullptr);
18784 }
18785 }
18786 /// Stores reduction data.
18787 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18788 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18789 Expr *CopyArrayElem, bool IsPrivate) {
18790 Vars.emplace_back(Item);
18791 Privates.emplace_back(Private);
18792 LHSs.emplace_back(LHS);
18793 RHSs.emplace_back(RHS);
18794 ReductionOps.emplace_back(ReductionOp);
18795 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18796 if (RedModifier == OMPC_REDUCTION_inscan) {
18797 InscanCopyOps.push_back(CopyOp);
18798 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18799 InscanCopyArrayElems.push_back(CopyArrayElem);
18800 } else {
18801 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18802 CopyArrayElem == nullptr &&
18803 "Copy operation must be used for inscan reductions only.");
18804 }
18805 IsPrivateVarReduction.emplace_back(IsPrivate);
18806 }
18807};
18808} // namespace
18809
18811 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18812 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18813 const Expr *Length = OASE->getLength();
18814 if (Length == nullptr) {
18815 // For array sections of the form [1:] or [:], we would need to analyze
18816 // the lower bound...
18817 if (OASE->getColonLocFirst().isValid())
18818 return false;
18819
18820 // This is an array subscript which has implicit length 1!
18821 SingleElement = true;
18822 ArraySizes.push_back(llvm::APSInt::get(1));
18823 } else {
18825 if (!Length->EvaluateAsInt(Result, Context))
18826 return false;
18827
18828 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18829 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18830 ArraySizes.push_back(ConstantLengthValue);
18831 }
18832
18833 // Get the base of this array section and walk up from there.
18834 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18835
18836 // We require length = 1 for all array sections except the right-most to
18837 // guarantee that the memory region is contiguous and has no holes in it.
18838 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18839 Length = TempOASE->getLength();
18840 if (Length == nullptr) {
18841 // For array sections of the form [1:] or [:], we would need to analyze
18842 // the lower bound...
18843 if (OASE->getColonLocFirst().isValid())
18844 return false;
18845
18846 // This is an array subscript which has implicit length 1!
18847 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18848 ArraySizes.push_back(ConstantOne);
18849 } else {
18851 if (!Length->EvaluateAsInt(Result, Context))
18852 return false;
18853
18854 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18855 if (ConstantLengthValue.getSExtValue() != 1)
18856 return false;
18857
18858 ArraySizes.push_back(ConstantLengthValue);
18859 }
18860 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18861 }
18862
18863 // If we have a single element, we don't need to add the implicit lengths.
18864 if (!SingleElement) {
18865 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18866 // Has implicit length 1!
18867 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
18868 ArraySizes.push_back(ConstantOne);
18869 Base = TempASE->getBase()->IgnoreParenImpCasts();
18870 }
18871 }
18872
18873 // This array section can be privatized as a single value or as a constant
18874 // sized array.
18875 return true;
18876}
18877
18878static BinaryOperatorKind
18880 if (BOK == BO_Add)
18881 return BO_AddAssign;
18882 if (BOK == BO_Mul)
18883 return BO_MulAssign;
18884 if (BOK == BO_And)
18885 return BO_AndAssign;
18886 if (BOK == BO_Or)
18887 return BO_OrAssign;
18888 if (BOK == BO_Xor)
18889 return BO_XorAssign;
18890 return BOK;
18891}
18892
18894 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18895 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18896 SourceLocation ColonLoc, SourceLocation EndLoc,
18897 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18898 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18899 DeclarationName DN = ReductionId.getName();
18901 BinaryOperatorKind BOK = BO_Comma;
18902
18903 ASTContext &Context = S.Context;
18904 // OpenMP [2.14.3.6, reduction clause]
18905 // C
18906 // reduction-identifier is either an identifier or one of the following
18907 // operators: +, -, *, &, |, ^, && and ||
18908 // C++
18909 // reduction-identifier is either an id-expression or one of the following
18910 // operators: +, -, *, &, |, ^, && and ||
18911 switch (OOK) {
18912 case OO_Plus:
18913 BOK = BO_Add;
18914 break;
18915 case OO_Minus:
18916 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18917 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18918 // reduction identifier.
18919 if (S.LangOpts.OpenMP > 52)
18920 BOK = BO_Comma;
18921 else
18922 BOK = BO_Add;
18923 break;
18924 case OO_Star:
18925 BOK = BO_Mul;
18926 break;
18927 case OO_Amp:
18928 BOK = BO_And;
18929 break;
18930 case OO_Pipe:
18931 BOK = BO_Or;
18932 break;
18933 case OO_Caret:
18934 BOK = BO_Xor;
18935 break;
18936 case OO_AmpAmp:
18937 BOK = BO_LAnd;
18938 break;
18939 case OO_PipePipe:
18940 BOK = BO_LOr;
18941 break;
18942 case OO_New:
18943 case OO_Delete:
18944 case OO_Array_New:
18945 case OO_Array_Delete:
18946 case OO_Slash:
18947 case OO_Percent:
18948 case OO_Tilde:
18949 case OO_Exclaim:
18950 case OO_Equal:
18951 case OO_Less:
18952 case OO_Greater:
18953 case OO_LessEqual:
18954 case OO_GreaterEqual:
18955 case OO_PlusEqual:
18956 case OO_MinusEqual:
18957 case OO_StarEqual:
18958 case OO_SlashEqual:
18959 case OO_PercentEqual:
18960 case OO_CaretEqual:
18961 case OO_AmpEqual:
18962 case OO_PipeEqual:
18963 case OO_LessLess:
18964 case OO_GreaterGreater:
18965 case OO_LessLessEqual:
18966 case OO_GreaterGreaterEqual:
18967 case OO_EqualEqual:
18968 case OO_ExclaimEqual:
18969 case OO_Spaceship:
18970 case OO_PlusPlus:
18971 case OO_MinusMinus:
18972 case OO_Comma:
18973 case OO_ArrowStar:
18974 case OO_Arrow:
18975 case OO_Call:
18976 case OO_Subscript:
18977 case OO_Conditional:
18978 case OO_Coawait:
18980 llvm_unreachable("Unexpected reduction identifier");
18981 case OO_None:
18982 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18983 if (II->isStr("max"))
18984 BOK = BO_GT;
18985 else if (II->isStr("min"))
18986 BOK = BO_LT;
18987 }
18988 break;
18989 }
18990
18991 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18992 // A reduction clause with the minus (-) operator was deprecated
18993 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18994 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18995
18996 SourceRange ReductionIdRange;
18997 if (ReductionIdScopeSpec.isValid())
18998 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18999 else
19000 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
19001 ReductionIdRange.setEnd(ReductionId.getEndLoc());
19002
19003 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
19004 bool FirstIter = true;
19005 for (Expr *RefExpr : VarList) {
19006 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
19007 // OpenMP [2.1, C/C++]
19008 // A list item is a variable or array section, subject to the restrictions
19009 // specified in Section 2.4 on page 42 and in each of the sections
19010 // describing clauses and directives for which a list appears.
19011 // OpenMP [2.14.3.3, Restrictions, p.1]
19012 // A variable that is part of another variable (as an array or
19013 // structure element) cannot appear in a private clause.
19014 if (!FirstIter && IR != ER)
19015 ++IR;
19016 FirstIter = false;
19017 SourceLocation ELoc;
19018 SourceRange ERange;
19019 bool IsPrivate = false;
19020 Expr *SimpleRefExpr = RefExpr;
19021 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
19022 /*AllowArraySection=*/true);
19023 if (Res.second) {
19024 // Try to find 'declare reduction' corresponding construct before using
19025 // builtin/overloaded operators.
19026 QualType Type = Context.DependentTy;
19027 CXXCastPath BasePath;
19028 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19029 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19030 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19031 Expr *ReductionOp = nullptr;
19032 if (S.CurContext->isDependentContext() &&
19033 (DeclareReductionRef.isUnset() ||
19034 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
19035 ReductionOp = DeclareReductionRef.get();
19036 // It will be analyzed later.
19037 RD.push(RefExpr, ReductionOp);
19038 }
19039 ValueDecl *D = Res.first;
19040 if (!D)
19041 continue;
19042
19043 Expr *TaskgroupDescriptor = nullptr;
19044 QualType Type;
19045 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
19046 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
19047 if (ASE) {
19048 Type = ASE->getType().getNonReferenceType();
19049 } else if (OASE) {
19050 QualType BaseType =
19052 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19053 Type = ATy->getElementType();
19054 else
19055 Type = BaseType->getPointeeType();
19056 Type = Type.getNonReferenceType();
19057 } else {
19058 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
19059 }
19060 auto *VD = dyn_cast<VarDecl>(D);
19061
19062 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19063 // A variable that appears in a private clause must not have an incomplete
19064 // type or a reference type.
19065 if (S.RequireCompleteType(ELoc, D->getType(),
19066 diag::err_omp_reduction_incomplete_type))
19067 continue;
19068 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19069 // A list item that appears in a reduction clause must not be
19070 // const-qualified.
19071 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
19072 /*AcceptIfMutable=*/false, ASE || OASE))
19073 continue;
19074
19075 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
19076 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
19077 // If a list-item is a reference type then it must bind to the same object
19078 // for all threads of the team.
19079 if (!ASE && !OASE) {
19080 if (VD) {
19081 VarDecl *VDDef = VD->getDefinition();
19082 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
19083 DSARefChecker Check(Stack);
19084 if (Check.Visit(VDDef->getInit())) {
19085 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
19086 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
19087 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
19088 continue;
19089 }
19090 }
19091 }
19092
19093 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19094 // in a Construct]
19095 // Variables with the predetermined data-sharing attributes may not be
19096 // listed in data-sharing attributes clauses, except for the cases
19097 // listed below. For these exceptions only, listing a predetermined
19098 // variable in a data-sharing attribute clause is allowed and overrides
19099 // the variable's predetermined data-sharing attributes.
19100 // OpenMP [2.14.3.6, Restrictions, p.3]
19101 // Any number of reduction clauses can be specified on the directive,
19102 // but a list item can appear only once in the reduction clauses for that
19103 // directive.
19104 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19105 if (DVar.CKind == OMPC_reduction) {
19106 S.Diag(ELoc, diag::err_omp_once_referenced)
19107 << getOpenMPClauseNameForDiag(ClauseKind);
19108 if (DVar.RefExpr)
19109 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
19110 continue;
19111 }
19112 if (DVar.CKind != OMPC_unknown) {
19113 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19114 << getOpenMPClauseNameForDiag(DVar.CKind)
19115 << getOpenMPClauseNameForDiag(OMPC_reduction);
19116 reportOriginalDsa(S, Stack, D, DVar);
19117 continue;
19118 }
19119
19120 // OpenMP [2.14.3.6, Restrictions, p.1]
19121 // A list item that appears in a reduction clause of a worksharing
19122 // construct must be shared in the parallel regions to which any of the
19123 // worksharing regions arising from the worksharing construct bind.
19124
19125 if (S.getLangOpts().OpenMP <= 52 &&
19127 !isOpenMPParallelDirective(CurrDir) &&
19128 !isOpenMPTeamsDirective(CurrDir)) {
19129 DVar = Stack->getImplicitDSA(D, true);
19130 if (DVar.CKind != OMPC_shared) {
19131 S.Diag(ELoc, diag::err_omp_required_access)
19132 << getOpenMPClauseNameForDiag(OMPC_reduction)
19133 << getOpenMPClauseNameForDiag(OMPC_shared);
19134 reportOriginalDsa(S, Stack, D, DVar);
19135 continue;
19136 }
19137 } else if (isOpenMPWorksharingDirective(CurrDir) &&
19138 !isOpenMPParallelDirective(CurrDir) &&
19139 !isOpenMPTeamsDirective(CurrDir)) {
19140 // OpenMP 6.0 [ 7.6.10 ]
19141 // Support Reduction over private variables with reduction clause.
19142 // A list item in a reduction clause can now be private in the enclosing
19143 // context. For orphaned constructs it is assumed to be shared unless
19144 // the original(private) modifier appears in the clause.
19145 DVar = Stack->getImplicitDSA(D, true);
19146 // Determine if the variable should be considered private
19147 IsPrivate = DVar.CKind != OMPC_shared;
19148 bool IsOrphaned = false;
19149 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
19150 IsOrphaned = ParentDir == OMPD_unknown;
19151 if ((IsOrphaned &&
19152 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
19153 IsPrivate = true;
19154 }
19155 } else {
19156 // Threadprivates cannot be shared between threads, so dignose if the base
19157 // is a threadprivate variable.
19158 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
19159 if (DVar.CKind == OMPC_threadprivate) {
19160 S.Diag(ELoc, diag::err_omp_wrong_dsa)
19161 << getOpenMPClauseNameForDiag(DVar.CKind)
19162 << getOpenMPClauseNameForDiag(OMPC_reduction);
19163 reportOriginalDsa(S, Stack, D, DVar);
19164 continue;
19165 }
19166 }
19167
19168 // Try to find 'declare reduction' corresponding construct before using
19169 // builtin/overloaded operators.
19170 CXXCastPath BasePath;
19171 ExprResult DeclareReductionRef = buildDeclareReductionRef(
19172 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
19173 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
19174 if (DeclareReductionRef.isInvalid())
19175 continue;
19176 if (S.CurContext->isDependentContext() &&
19177 (DeclareReductionRef.isUnset() ||
19178 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
19179 RD.push(RefExpr, DeclareReductionRef.get());
19180 continue;
19181 }
19182 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
19183 // Not allowed reduction identifier is found.
19184 if (S.LangOpts.OpenMP > 52)
19185 S.Diag(ReductionId.getBeginLoc(),
19186 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
19187 << Type << ReductionIdRange;
19188 else
19189 S.Diag(ReductionId.getBeginLoc(),
19190 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
19191 << Type << ReductionIdRange;
19192 continue;
19193 }
19194
19195 // OpenMP [2.14.3.6, reduction clause, Restrictions]
19196 // The type of a list item that appears in a reduction clause must be valid
19197 // for the reduction-identifier. For a max or min reduction in C, the type
19198 // of the list item must be an allowed arithmetic data type: char, int,
19199 // float, double, or _Bool, possibly modified with long, short, signed, or
19200 // unsigned. For a max or min reduction in C++, the type of the list item
19201 // must be an allowed arithmetic data type: char, wchar_t, int, float,
19202 // double, or bool, possibly modified with long, short, signed, or unsigned.
19203 if (DeclareReductionRef.isUnset()) {
19204 if ((BOK == BO_GT || BOK == BO_LT) &&
19205 !(Type->isScalarType() ||
19206 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
19207 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
19208 << getOpenMPClauseNameForDiag(ClauseKind)
19209 << S.getLangOpts().CPlusPlus;
19210 if (!ASE && !OASE) {
19211 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19213 S.Diag(D->getLocation(),
19214 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19215 << D;
19216 }
19217 continue;
19218 }
19219 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
19220 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
19221 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
19222 << getOpenMPClauseNameForDiag(ClauseKind);
19223 if (!ASE && !OASE) {
19224 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19226 S.Diag(D->getLocation(),
19227 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19228 << D;
19229 }
19230 continue;
19231 }
19232 }
19233
19234 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
19235 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
19236 D->hasAttrs() ? &D->getAttrs() : nullptr);
19237 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
19238 D->hasAttrs() ? &D->getAttrs() : nullptr);
19239 QualType PrivateTy = Type;
19240
19241 // Try if we can determine constant lengths for all array sections and avoid
19242 // the VLA.
19243 bool ConstantLengthOASE = false;
19244 if (OASE) {
19245 bool SingleElement;
19247 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
19248 Context, OASE, SingleElement, ArraySizes);
19249
19250 // If we don't have a single element, we must emit a constant array type.
19251 if (ConstantLengthOASE && !SingleElement) {
19252 for (llvm::APSInt &Size : ArraySizes)
19253 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
19255 /*IndexTypeQuals=*/0);
19256 }
19257 }
19258
19259 if ((OASE && !ConstantLengthOASE) ||
19260 (!OASE && !ASE &&
19261 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
19262 if (!Context.getTargetInfo().isVLASupported()) {
19263 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
19264 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19265 S.Diag(ELoc, diag::note_vla_unsupported);
19266 continue;
19267 } else {
19268 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
19269 S.targetDiag(ELoc, diag::note_vla_unsupported);
19270 }
19271 }
19272 // For arrays/array sections only:
19273 // Create pseudo array type for private copy. The size for this array will
19274 // be generated during codegen.
19275 // For array subscripts or single variables Private Ty is the same as Type
19276 // (type of the variable or single array element).
19277 PrivateTy = Context.getVariableArrayType(
19278 Type,
19279 new (Context)
19280 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
19281 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
19282 } else if (!ASE && !OASE &&
19283 Context.getAsArrayType(D->getType().getNonReferenceType())) {
19284 PrivateTy = D->getType().getNonReferenceType();
19285 }
19286 // Private copy.
19287 VarDecl *PrivateVD =
19288 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19289 D->hasAttrs() ? &D->getAttrs() : nullptr,
19290 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19291 // Add initializer for private variable.
19292 Expr *Init = nullptr;
19293 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
19294 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
19295 if (DeclareReductionRef.isUsable()) {
19296 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
19297 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
19298 if (DRD->getInitializer()) {
19299 Init = DRDRef;
19300 RHSVD->setInit(DRDRef);
19302 }
19303 } else {
19304 switch (BOK) {
19305 case BO_Add:
19306 case BO_Xor:
19307 case BO_Or:
19308 case BO_LOr:
19309 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
19311 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
19312 break;
19313 case BO_Mul:
19314 case BO_LAnd:
19315 if (Type->isScalarType() || Type->isAnyComplexType()) {
19316 // '*' and '&&' reduction ops - initializer is '1'.
19317 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
19318 }
19319 break;
19320 case BO_And: {
19321 // '&' reduction op - initializer is '~0'.
19322 QualType OrigType = Type;
19323 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
19324 Type = ComplexTy->getElementType();
19325 if (Type->isRealFloatingType()) {
19326 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
19327 Context.getFloatTypeSemantics(Type));
19328 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19329 Type, ELoc);
19330 } else if (Type->isScalarType()) {
19331 uint64_t Size = Context.getTypeSize(Type);
19332 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
19333 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
19334 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19335 }
19336 if (Init && OrigType->isAnyComplexType()) {
19337 // Init = 0xFFFF + 0xFFFFi;
19338 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
19339 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
19340 }
19341 Type = OrigType;
19342 break;
19343 }
19344 case BO_LT:
19345 case BO_GT: {
19346 // 'min' reduction op - initializer is 'Largest representable number in
19347 // the reduction list item type'.
19348 // 'max' reduction op - initializer is 'Least representable number in
19349 // the reduction list item type'.
19350 if (Type->isIntegerType() || Type->isPointerType()) {
19351 bool IsSigned = Type->hasSignedIntegerRepresentation();
19352 uint64_t Size = Context.getTypeSize(Type);
19353 QualType IntTy =
19354 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
19355 llvm::APInt InitValue =
19356 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
19357 : llvm::APInt::getMinValue(Size)
19358 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
19359 : llvm::APInt::getMaxValue(Size);
19360 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
19361 if (Type->isPointerType()) {
19362 // Cast to pointer type.
19364 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
19365 if (CastExpr.isInvalid())
19366 continue;
19367 Init = CastExpr.get();
19368 }
19369 } else if (Type->isRealFloatingType()) {
19370 llvm::APFloat InitValue = llvm::APFloat::getLargest(
19371 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
19372 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
19373 Type, ELoc);
19374 }
19375 break;
19376 }
19377 case BO_PtrMemD:
19378 case BO_PtrMemI:
19379 case BO_MulAssign:
19380 case BO_Div:
19381 case BO_Rem:
19382 case BO_Sub:
19383 case BO_Shl:
19384 case BO_Shr:
19385 case BO_LE:
19386 case BO_GE:
19387 case BO_EQ:
19388 case BO_NE:
19389 case BO_Cmp:
19390 case BO_AndAssign:
19391 case BO_XorAssign:
19392 case BO_OrAssign:
19393 case BO_Assign:
19394 case BO_AddAssign:
19395 case BO_SubAssign:
19396 case BO_DivAssign:
19397 case BO_RemAssign:
19398 case BO_ShlAssign:
19399 case BO_ShrAssign:
19400 case BO_Comma:
19401 llvm_unreachable("Unexpected reduction operation");
19402 }
19403 }
19404 if (Init && DeclareReductionRef.isUnset()) {
19405 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
19406 // Store initializer for single element in private copy. Will be used
19407 // during codegen.
19408 PrivateVD->setInit(RHSVD->getInit());
19409 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19410 } else if (!Init) {
19411 S.ActOnUninitializedDecl(RHSVD);
19412 // Store initializer for single element in private copy. Will be used
19413 // during codegen.
19414 PrivateVD->setInit(RHSVD->getInit());
19415 PrivateVD->setInitStyle(RHSVD->getInitStyle());
19416 }
19417 if (RHSVD->isInvalidDecl())
19418 continue;
19419 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
19420 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
19421 << Type << ReductionIdRange;
19422 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
19424 S.Diag(D->getLocation(),
19425 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19426 << D;
19427 continue;
19428 }
19429 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
19430 ExprResult ReductionOp;
19431 if (DeclareReductionRef.isUsable()) {
19432 QualType RedTy = DeclareReductionRef.get()->getType();
19433 QualType PtrRedTy = Context.getPointerType(RedTy);
19434 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
19435 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
19436 if (!BasePath.empty()) {
19437 LHS = S.DefaultLvalueConversion(LHS.get());
19438 RHS = S.DefaultLvalueConversion(RHS.get());
19440 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
19441 LHS.get()->getValueKind(), FPOptionsOverride());
19443 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
19444 RHS.get()->getValueKind(), FPOptionsOverride());
19445 }
19447 QualType Params[] = {PtrRedTy, PtrRedTy};
19448 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
19449 auto *OVE = new (Context) OpaqueValueExpr(
19450 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
19451 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
19452 Expr *Args[] = {LHS.get(), RHS.get()};
19453 ReductionOp =
19454 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
19456 } else {
19458 if (Type->isRecordType() && CombBOK != BOK) {
19460 ReductionOp =
19461 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19462 CombBOK, LHSDRE, RHSDRE);
19463 }
19464 if (!ReductionOp.isUsable()) {
19465 ReductionOp =
19466 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
19467 LHSDRE, RHSDRE);
19468 if (ReductionOp.isUsable()) {
19469 if (BOK != BO_LT && BOK != BO_GT) {
19470 ReductionOp =
19471 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19472 BO_Assign, LHSDRE, ReductionOp.get());
19473 } else {
19474 auto *ConditionalOp = new (Context)
19475 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
19476 RHSDRE, Type, VK_LValue, OK_Ordinary);
19477 ReductionOp =
19478 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
19479 BO_Assign, LHSDRE, ConditionalOp);
19480 }
19481 }
19482 }
19483 if (ReductionOp.isUsable())
19484 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
19485 /*DiscardedValue=*/false);
19486 if (!ReductionOp.isUsable())
19487 continue;
19488 }
19489
19490 // Add copy operations for inscan reductions.
19491 // LHS = RHS;
19492 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
19493 if (ClauseKind == OMPC_reduction &&
19494 RD.RedModifier == OMPC_REDUCTION_inscan) {
19495 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
19496 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
19497 RHS.get());
19498 if (!CopyOpRes.isUsable())
19499 continue;
19500 CopyOpRes =
19501 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
19502 if (!CopyOpRes.isUsable())
19503 continue;
19504 // For simd directive and simd-based directives in simd mode no need to
19505 // construct temp array, need just a single temp element.
19506 if (Stack->getCurrentDirective() == OMPD_simd ||
19507 (S.getLangOpts().OpenMPSimd &&
19508 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
19509 VarDecl *TempArrayVD =
19510 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
19511 D->hasAttrs() ? &D->getAttrs() : nullptr);
19512 // Add a constructor to the temp decl.
19513 S.ActOnUninitializedDecl(TempArrayVD);
19514 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
19515 } else {
19516 // Build temp array for prefix sum.
19517 auto *Dim = new (S.Context)
19520 PrivateTy, Dim, ArraySizeModifier::Normal,
19521 /*IndexTypeQuals=*/0);
19522 VarDecl *TempArrayVD =
19523 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
19524 D->hasAttrs() ? &D->getAttrs() : nullptr);
19525 // Add a constructor to the temp decl.
19526 S.ActOnUninitializedDecl(TempArrayVD);
19527 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
19528 TempArrayElem =
19529 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
19530 auto *Idx = new (S.Context)
19532 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
19533 ELoc, Idx, ELoc);
19534 }
19535 }
19536
19537 // OpenMP [2.15.4.6, Restrictions, p.2]
19538 // A list item that appears in an in_reduction clause of a task construct
19539 // must appear in a task_reduction clause of a construct associated with a
19540 // taskgroup region that includes the participating task in its taskgroup
19541 // set. The construct associated with the innermost region that meets this
19542 // condition must specify the same reduction-identifier as the in_reduction
19543 // clause.
19544 if (ClauseKind == OMPC_in_reduction) {
19545 SourceRange ParentSR;
19546 BinaryOperatorKind ParentBOK;
19547 const Expr *ParentReductionOp = nullptr;
19548 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
19549 DSAStackTy::DSAVarData ParentBOKDSA =
19550 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
19551 ParentBOKTD);
19552 DSAStackTy::DSAVarData ParentReductionOpDSA =
19553 Stack->getTopMostTaskgroupReductionData(
19554 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
19555 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
19556 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
19557 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
19558 (DeclareReductionRef.isUsable() && IsParentBOK) ||
19559 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
19560 bool EmitError = true;
19561 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
19562 llvm::FoldingSetNodeID RedId, ParentRedId;
19563 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
19564 DeclareReductionRef.get()->Profile(RedId, Context,
19565 /*Canonical=*/true);
19566 EmitError = RedId != ParentRedId;
19567 }
19568 if (EmitError) {
19569 S.Diag(ReductionId.getBeginLoc(),
19570 diag::err_omp_reduction_identifier_mismatch)
19571 << ReductionIdRange << RefExpr->getSourceRange();
19572 S.Diag(ParentSR.getBegin(),
19573 diag::note_omp_previous_reduction_identifier)
19574 << ParentSR
19575 << (IsParentBOK ? ParentBOKDSA.RefExpr
19576 : ParentReductionOpDSA.RefExpr)
19577 ->getSourceRange();
19578 continue;
19579 }
19580 }
19581 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
19582 }
19583
19584 DeclRefExpr *Ref = nullptr;
19585 Expr *VarsExpr = RefExpr->IgnoreParens();
19586 if (!VD && !S.CurContext->isDependentContext()) {
19587 if (ASE || OASE) {
19588 TransformExprToCaptures RebuildToCapture(S, D);
19589 VarsExpr =
19590 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
19591 Ref = RebuildToCapture.getCapturedExpr();
19592 } else {
19593 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
19594 }
19595 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
19596 RD.ExprCaptures.emplace_back(Ref->getDecl());
19597 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19598 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
19599 if (!RefRes.isUsable())
19600 continue;
19601 ExprResult PostUpdateRes =
19602 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
19603 RefRes.get());
19604 if (!PostUpdateRes.isUsable())
19605 continue;
19606 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
19607 Stack->getCurrentDirective() == OMPD_taskgroup) {
19608 S.Diag(RefExpr->getExprLoc(),
19609 diag::err_omp_reduction_non_addressable_expression)
19610 << RefExpr->getSourceRange();
19611 continue;
19612 }
19613 RD.ExprPostUpdates.emplace_back(
19614 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19615 }
19616 }
19617 }
19618 // All reduction items are still marked as reduction (to do not increase
19619 // code base size).
19620 unsigned Modifier = RD.RedModifier;
19621 // Consider task_reductions as reductions with task modifier. Required for
19622 // correct analysis of in_reduction clauses.
19623 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19624 Modifier = OMPC_REDUCTION_task;
19625 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19626 ASE || OASE);
19627 if (Modifier == OMPC_REDUCTION_task &&
19628 (CurrDir == OMPD_taskgroup ||
19629 ((isOpenMPParallelDirective(CurrDir) ||
19630 isOpenMPWorksharingDirective(CurrDir)) &&
19631 !isOpenMPSimdDirective(CurrDir)))) {
19632 if (DeclareReductionRef.isUsable())
19633 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19634 DeclareReductionRef.get());
19635 else
19636 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19637 }
19638 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19639 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19640 TempArrayElem.get(), IsPrivate);
19641 }
19642 return RD.Vars.empty();
19643}
19644
19646 ArrayRef<Expr *> VarList,
19648 SourceLocation StartLoc, SourceLocation LParenLoc,
19649 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19650 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19651 ArrayRef<Expr *> UnresolvedReductions) {
19653 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
19654 OpenMPOriginalSharingModifier OriginalSharingModifier =
19655 static_cast<OpenMPOriginalSharingModifier>(
19656 Modifiers.OriginalSharingModifier);
19657 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19658 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19659 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19660 /*Last=*/OMPC_REDUCTION_unknown)
19661 << getOpenMPClauseNameForDiag(OMPC_reduction);
19662 return nullptr;
19663 }
19664 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19665 // A reduction clause with the inscan reduction-modifier may only appear on a
19666 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19667 // construct, a parallel worksharing-loop construct or a parallel
19668 // worksharing-loop SIMD construct.
19669 if (Modifier == OMPC_REDUCTION_inscan &&
19670 (DSAStack->getCurrentDirective() != OMPD_for &&
19671 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19672 DSAStack->getCurrentDirective() != OMPD_simd &&
19673 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19674 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19675 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19676 return nullptr;
19677 }
19678 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
19679 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
19680 StartLoc, LParenLoc, ColonLoc, EndLoc,
19681 ReductionIdScopeSpec, ReductionId,
19682 UnresolvedReductions, RD))
19683 return nullptr;
19684
19686 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19687 Modifier, RD.Vars,
19688 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19689 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19690 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19691 buildPreInits(getASTContext(), RD.ExprCaptures),
19692 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
19693 OriginalSharingModifier);
19694}
19695
19697 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19698 SourceLocation ColonLoc, SourceLocation EndLoc,
19699 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19700 ArrayRef<Expr *> UnresolvedReductions) {
19701 ReductionData RD(VarList.size());
19702 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
19703 VarList, StartLoc, LParenLoc, ColonLoc,
19704 EndLoc, ReductionIdScopeSpec, ReductionId,
19705 UnresolvedReductions, RD))
19706 return nullptr;
19707
19709 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19710 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19711 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19712 buildPreInits(getASTContext(), RD.ExprCaptures),
19713 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19714}
19715
19717 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19718 SourceLocation ColonLoc, SourceLocation EndLoc,
19719 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19720 ArrayRef<Expr *> UnresolvedReductions) {
19721 ReductionData RD(VarList.size());
19722 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19723 StartLoc, LParenLoc, ColonLoc, EndLoc,
19724 ReductionIdScopeSpec, ReductionId,
19725 UnresolvedReductions, RD))
19726 return nullptr;
19727
19729 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19730 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19731 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19732 buildPreInits(getASTContext(), RD.ExprCaptures),
19733 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19734}
19735
19737 SourceLocation LinLoc) {
19738 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19739 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19740 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19741 << getLangOpts().CPlusPlus;
19742 return true;
19743 }
19744 return false;
19745}
19746
19748 OpenMPLinearClauseKind LinKind,
19749 QualType Type, bool IsDeclareSimd) {
19750 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19751 // A variable must not have an incomplete type or a reference type.
19753 diag::err_omp_linear_incomplete_type))
19754 return true;
19755 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19756 !Type->isReferenceType()) {
19757 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19758 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19759 return true;
19760 }
19761 Type = Type.getNonReferenceType();
19762
19763 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19764 // A variable that is privatized must not have a const-qualified type
19765 // unless it is of class type with a mutable member. This restriction does
19766 // not apply to the firstprivate clause, nor to the linear clause on
19767 // declarative directives (like declare simd).
19768 if (!IsDeclareSimd &&
19769 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19770 return true;
19771
19772 // A list item must be of integral or pointer type.
19773 Type = Type.getUnqualifiedType().getCanonicalType();
19774 const auto *Ty = Type.getTypePtrOrNull();
19775 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19776 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
19777 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19778 if (D) {
19779 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19781 Diag(D->getLocation(),
19782 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19783 << D;
19784 }
19785 return true;
19786 }
19787 return false;
19788}
19789
19791 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19792 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19793 SourceLocation LinLoc, SourceLocation ColonLoc,
19794 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19796 SmallVector<Expr *, 8> Privates;
19798 SmallVector<Decl *, 4> ExprCaptures;
19799 SmallVector<Expr *, 4> ExprPostUpdates;
19800 // OpenMP 5.2 [Section 5.4.6, linear clause]
19801 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19802 // 'ref'
19803 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19804 getLangOpts().OpenMP >= 52)
19805 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19806 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19807 LinKind = OMPC_LINEAR_val;
19808 for (Expr *RefExpr : VarList) {
19809 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19810 SourceLocation ELoc;
19811 SourceRange ERange;
19812 Expr *SimpleRefExpr = RefExpr;
19813 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19814 if (Res.second) {
19815 // It will be analyzed later.
19816 Vars.push_back(RefExpr);
19817 Privates.push_back(nullptr);
19818 Inits.push_back(nullptr);
19819 }
19820 ValueDecl *D = Res.first;
19821 if (!D)
19822 continue;
19823
19824 QualType Type = D->getType();
19825 auto *VD = dyn_cast<VarDecl>(D);
19826
19827 // OpenMP [2.14.3.7, linear clause]
19828 // A list-item cannot appear in more than one linear clause.
19829 // A list-item that appears in a linear clause cannot appear in any
19830 // other data-sharing attribute clause.
19831 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19832 if (DVar.RefExpr) {
19833 Diag(ELoc, diag::err_omp_wrong_dsa)
19834 << getOpenMPClauseNameForDiag(DVar.CKind)
19835 << getOpenMPClauseNameForDiag(OMPC_linear);
19837 continue;
19838 }
19839
19840 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19841 continue;
19842 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19843
19844 // Build private copy of original var.
19845 VarDecl *Private =
19846 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19847 D->hasAttrs() ? &D->getAttrs() : nullptr,
19848 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19849 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19850 // Build var to save initial value.
19851 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19852 Expr *InitExpr;
19853 DeclRefExpr *Ref = nullptr;
19854 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19855 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19856 if (!isOpenMPCapturedDecl(D)) {
19857 ExprCaptures.push_back(Ref->getDecl());
19858 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19860 if (!RefRes.isUsable())
19861 continue;
19862 ExprResult PostUpdateRes =
19863 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19864 SimpleRefExpr, RefRes.get());
19865 if (!PostUpdateRes.isUsable())
19866 continue;
19867 ExprPostUpdates.push_back(
19868 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19869 }
19870 }
19871 }
19872 if (LinKind == OMPC_LINEAR_uval)
19873 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19874 else
19875 InitExpr = VD ? SimpleRefExpr : Ref;
19878 /*DirectInit=*/false);
19879 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19880
19881 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19882 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19883 ? RefExpr->IgnoreParens()
19884 : Ref);
19885 Privates.push_back(PrivateRef);
19886 Inits.push_back(InitRef);
19887 }
19888
19889 if (Vars.empty())
19890 return nullptr;
19891
19892 Expr *StepExpr = Step;
19893 Expr *CalcStepExpr = nullptr;
19894 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19895 !Step->isInstantiationDependent() &&
19897 SourceLocation StepLoc = Step->getBeginLoc();
19899 if (Val.isInvalid())
19900 return nullptr;
19901 StepExpr = Val.get();
19902
19903 // Build var to save the step value.
19904 VarDecl *SaveVar =
19905 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19906 ExprResult SaveRef =
19907 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19908 ExprResult CalcStep = SemaRef.BuildBinOp(
19909 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19910 CalcStep =
19911 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
19912
19913 // Warn about zero linear step (it would be probably better specified as
19914 // making corresponding variables 'const').
19915 if (std::optional<llvm::APSInt> Result =
19917 if (!Result->isNegative() && !Result->isStrictlyPositive())
19918 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19919 << Vars[0] << (Vars.size() > 1);
19920 } else if (CalcStep.isUsable()) {
19921 // Calculate the step beforehand instead of doing this on each iteration.
19922 // (This is not used if the number of iterations may be kfold-ed).
19923 CalcStepExpr = CalcStep.get();
19924 }
19925 }
19926
19927 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19928 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19929 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19930 buildPreInits(getASTContext(), ExprCaptures),
19931 buildPostUpdate(SemaRef, ExprPostUpdates));
19932}
19933
19935 Expr *NumIterations, Sema &SemaRef,
19936 Scope *S, DSAStackTy *Stack) {
19937 // Walk the vars and build update/final expressions for the CodeGen.
19938 SmallVector<Expr *, 8> Updates;
19940 SmallVector<Expr *, 8> UsedExprs;
19941 Expr *Step = Clause.getStep();
19942 Expr *CalcStep = Clause.getCalcStep();
19943 // OpenMP [2.14.3.7, linear clause]
19944 // If linear-step is not specified it is assumed to be 1.
19945 if (!Step)
19946 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19947 else if (CalcStep)
19948 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19949 bool HasErrors = false;
19950 auto CurInit = Clause.inits().begin();
19951 auto CurPrivate = Clause.privates().begin();
19952 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19953 for (Expr *RefExpr : Clause.varlist()) {
19954 SourceLocation ELoc;
19955 SourceRange ERange;
19956 Expr *SimpleRefExpr = RefExpr;
19957 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19958 ValueDecl *D = Res.first;
19959 if (Res.second || !D) {
19960 Updates.push_back(nullptr);
19961 Finals.push_back(nullptr);
19962 HasErrors = true;
19963 continue;
19964 }
19965 auto &&Info = Stack->isLoopControlVariable(D);
19966 // OpenMP [2.15.11, distribute simd Construct]
19967 // A list item may not appear in a linear clause, unless it is the loop
19968 // iteration variable.
19969 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19970 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19971 SemaRef.Diag(ELoc,
19972 diag::err_omp_linear_distribute_var_non_loop_iteration);
19973 Updates.push_back(nullptr);
19974 Finals.push_back(nullptr);
19975 HasErrors = true;
19976 continue;
19977 }
19978 Expr *InitExpr = *CurInit;
19979
19980 // Build privatized reference to the current linear var.
19981 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19982 Expr *CapturedRef;
19983 if (LinKind == OMPC_LINEAR_uval)
19984 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19985 else
19986 CapturedRef =
19987 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19988 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19989 /*RefersToCapture=*/true);
19990
19991 // Build update: Var = InitExpr + IV * Step
19993 if (!Info.first)
19995 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19996 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19997 else
19998 Update = *CurPrivate;
19999 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
20000 /*DiscardedValue=*/false);
20001
20002 // Build final: Var = PrivCopy;
20003 ExprResult Final;
20004 if (!Info.first)
20005 Final = SemaRef.BuildBinOp(
20006 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
20007 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
20008 else
20009 Final = *CurPrivate;
20010 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
20011 /*DiscardedValue=*/false);
20012
20013 if (!Update.isUsable() || !Final.isUsable()) {
20014 Updates.push_back(nullptr);
20015 Finals.push_back(nullptr);
20016 UsedExprs.push_back(nullptr);
20017 HasErrors = true;
20018 } else {
20019 Updates.push_back(Update.get());
20020 Finals.push_back(Final.get());
20021 if (!Info.first)
20022 UsedExprs.push_back(SimpleRefExpr);
20023 }
20024 ++CurInit;
20025 ++CurPrivate;
20026 }
20027 if (Expr *S = Clause.getStep())
20028 UsedExprs.push_back(S);
20029 // Fill the remaining part with the nullptr.
20030 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
20031 Clause.setUpdates(Updates);
20032 Clause.setFinals(Finals);
20033 Clause.setUsedExprs(UsedExprs);
20034 return HasErrors;
20035}
20036
20038 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
20039 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
20041 for (Expr *RefExpr : VarList) {
20042 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
20043 SourceLocation ELoc;
20044 SourceRange ERange;
20045 Expr *SimpleRefExpr = RefExpr;
20046 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20047 if (Res.second) {
20048 // It will be analyzed later.
20049 Vars.push_back(RefExpr);
20050 }
20051 ValueDecl *D = Res.first;
20052 if (!D)
20053 continue;
20054
20055 QualType QType = D->getType();
20056 auto *VD = dyn_cast<VarDecl>(D);
20057
20058 // OpenMP [2.8.1, simd construct, Restrictions]
20059 // The type of list items appearing in the aligned clause must be
20060 // array, pointer, reference to array, or reference to pointer.
20062 const Type *Ty = QType.getTypePtrOrNull();
20063 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
20064 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
20065 << QType << getLangOpts().CPlusPlus << ERange;
20066 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20068 Diag(D->getLocation(),
20069 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20070 << D;
20071 continue;
20072 }
20073
20074 // OpenMP [2.8.1, simd construct, Restrictions]
20075 // A list-item cannot appear in more than one aligned clause.
20076 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
20077 Diag(ELoc, diag::err_omp_used_in_clause_twice)
20078 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
20079 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
20080 << getOpenMPClauseNameForDiag(OMPC_aligned);
20081 continue;
20082 }
20083
20084 DeclRefExpr *Ref = nullptr;
20085 if (!VD && isOpenMPCapturedDecl(D))
20086 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
20087 Vars.push_back(SemaRef
20088 .DefaultFunctionArrayConversion(
20089 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
20090 .get());
20091 }
20092
20093 // OpenMP [2.8.1, simd construct, Description]
20094 // The parameter of the aligned clause, alignment, must be a constant
20095 // positive integer expression.
20096 // If no optional parameter is specified, implementation-defined default
20097 // alignments for SIMD instructions on the target platforms are assumed.
20098 if (Alignment != nullptr) {
20099 ExprResult AlignResult =
20100 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
20101 if (AlignResult.isInvalid())
20102 return nullptr;
20103 Alignment = AlignResult.get();
20104 }
20105 if (Vars.empty())
20106 return nullptr;
20107
20108 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
20109 ColonLoc, EndLoc, Vars, Alignment);
20110}
20111
20113 SourceLocation StartLoc,
20114 SourceLocation LParenLoc,
20115 SourceLocation EndLoc) {
20117 SmallVector<Expr *, 8> SrcExprs;
20118 SmallVector<Expr *, 8> DstExprs;
20119 SmallVector<Expr *, 8> AssignmentOps;
20120 for (Expr *RefExpr : VarList) {
20121 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
20122 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20123 // It will be analyzed later.
20124 Vars.push_back(RefExpr);
20125 SrcExprs.push_back(nullptr);
20126 DstExprs.push_back(nullptr);
20127 AssignmentOps.push_back(nullptr);
20128 continue;
20129 }
20130
20131 SourceLocation ELoc = RefExpr->getExprLoc();
20132 // OpenMP [2.1, C/C++]
20133 // A list item is a variable name.
20134 // OpenMP [2.14.4.1, Restrictions, p.1]
20135 // A list item that appears in a copyin clause must be threadprivate.
20136 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
20137 if (!DE || !isa<VarDecl>(DE->getDecl())) {
20138 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
20139 << 0 << RefExpr->getSourceRange();
20140 continue;
20141 }
20142
20143 Decl *D = DE->getDecl();
20144 auto *VD = cast<VarDecl>(D);
20145
20146 QualType Type = VD->getType();
20148 // It will be analyzed later.
20149 Vars.push_back(DE);
20150 SrcExprs.push_back(nullptr);
20151 DstExprs.push_back(nullptr);
20152 AssignmentOps.push_back(nullptr);
20153 continue;
20154 }
20155
20156 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
20157 // A list item that appears in a copyin clause must be threadprivate.
20158 if (!DSAStack->isThreadPrivate(VD)) {
20159 unsigned OMPVersion = getLangOpts().OpenMP;
20160 Diag(ELoc, diag::err_omp_required_access)
20161 << getOpenMPClauseNameForDiag(OMPC_copyin)
20162 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
20163 continue;
20164 }
20165
20166 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20167 // A variable of class type (or array thereof) that appears in a
20168 // copyin clause requires an accessible, unambiguous copy assignment
20169 // operator for the class type.
20170 QualType ElemType =
20172 VarDecl *SrcVD =
20173 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
20174 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20175 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
20176 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
20177 VarDecl *DstVD =
20178 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
20179 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
20180 DeclRefExpr *PseudoDstExpr =
20181 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
20182 // For arrays generate assignment operation for single element and replace
20183 // it by the original array element in CodeGen.
20184 ExprResult AssignmentOp =
20185 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
20186 PseudoDstExpr, PseudoSrcExpr);
20187 if (AssignmentOp.isInvalid())
20188 continue;
20189 AssignmentOp =
20190 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
20191 /*DiscardedValue=*/false);
20192 if (AssignmentOp.isInvalid())
20193 continue;
20194
20195 DSAStack->addDSA(VD, DE, OMPC_copyin);
20196 Vars.push_back(DE);
20197 SrcExprs.push_back(PseudoSrcExpr);
20198 DstExprs.push_back(PseudoDstExpr);
20199 AssignmentOps.push_back(AssignmentOp.get());
20200 }
20201
20202 if (Vars.empty())
20203 return nullptr;
20204
20205 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20206 Vars, SrcExprs, DstExprs, AssignmentOps);
20207}
20208
20210 SourceLocation StartLoc,
20211 SourceLocation LParenLoc,
20212 SourceLocation EndLoc) {
20214 SmallVector<Expr *, 8> SrcExprs;
20215 SmallVector<Expr *, 8> DstExprs;
20216 SmallVector<Expr *, 8> AssignmentOps;
20217 for (Expr *RefExpr : VarList) {
20218 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
20219 SourceLocation ELoc;
20220 SourceRange ERange;
20221 Expr *SimpleRefExpr = RefExpr;
20222 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
20223 if (Res.second) {
20224 // It will be analyzed later.
20225 Vars.push_back(RefExpr);
20226 SrcExprs.push_back(nullptr);
20227 DstExprs.push_back(nullptr);
20228 AssignmentOps.push_back(nullptr);
20229 }
20230 ValueDecl *D = Res.first;
20231 if (!D)
20232 continue;
20233
20234 QualType Type = D->getType();
20235 auto *VD = dyn_cast<VarDecl>(D);
20236
20237 // OpenMP [2.14.4.2, Restrictions, p.2]
20238 // A list item that appears in a copyprivate clause may not appear in a
20239 // private or firstprivate clause on the single construct.
20240 if (!VD || !DSAStack->isThreadPrivate(VD)) {
20241 DSAStackTy::DSAVarData DVar =
20242 DSAStack->getTopDSA(D, /*FromParent=*/false);
20243 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
20244 DVar.RefExpr) {
20245 Diag(ELoc, diag::err_omp_wrong_dsa)
20246 << getOpenMPClauseNameForDiag(DVar.CKind)
20247 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
20249 continue;
20250 }
20251
20252 // OpenMP [2.11.4.2, Restrictions, p.1]
20253 // All list items that appear in a copyprivate clause must be either
20254 // threadprivate or private in the enclosing context.
20255 if (DVar.CKind == OMPC_unknown) {
20256 DVar = DSAStack->getImplicitDSA(D, false);
20257 if (DVar.CKind == OMPC_shared) {
20258 Diag(ELoc, diag::err_omp_required_access)
20259 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
20260 << "threadprivate or private in the enclosing context";
20262 continue;
20263 }
20264 }
20265 }
20266
20267 // Variably modified types are not supported.
20269 unsigned OMPVersion = getLangOpts().OpenMP;
20270 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
20271 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
20272 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
20273 OMPVersion);
20274 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
20276 Diag(D->getLocation(),
20277 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20278 << D;
20279 continue;
20280 }
20281
20282 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
20283 // A variable of class type (or array thereof) that appears in a
20284 // copyin clause requires an accessible, unambiguous copy assignment
20285 // operator for the class type.
20287 .getBaseElementType(Type.getNonReferenceType())
20289 VarDecl *SrcVD =
20290 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
20291 D->hasAttrs() ? &D->getAttrs() : nullptr);
20292 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
20293 VarDecl *DstVD =
20294 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
20295 D->hasAttrs() ? &D->getAttrs() : nullptr);
20296 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
20297 ExprResult AssignmentOp = SemaRef.BuildBinOp(
20298 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
20299 if (AssignmentOp.isInvalid())
20300 continue;
20301 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
20302 /*DiscardedValue=*/false);
20303 if (AssignmentOp.isInvalid())
20304 continue;
20305
20306 // No need to mark vars as copyprivate, they are already threadprivate or
20307 // implicitly private.
20308 assert(VD || isOpenMPCapturedDecl(D));
20309 Vars.push_back(
20310 VD ? RefExpr->IgnoreParens()
20311 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
20312 SrcExprs.push_back(PseudoSrcExpr);
20313 DstExprs.push_back(PseudoDstExpr);
20314 AssignmentOps.push_back(AssignmentOp.get());
20315 }
20316
20317 if (Vars.empty())
20318 return nullptr;
20319
20320 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
20321 EndLoc, Vars, SrcExprs, DstExprs,
20322 AssignmentOps);
20323}
20324
20326 SourceLocation StartLoc,
20327 SourceLocation LParenLoc,
20328 SourceLocation EndLoc) {
20329 if (VarList.empty())
20330 return nullptr;
20331
20332 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20333 VarList);
20334}
20335
20336/// Tries to find omp_depend_t. type.
20337static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
20338 bool Diagnose = true) {
20339 QualType OMPDependT = Stack->getOMPDependT();
20340 if (!OMPDependT.isNull())
20341 return true;
20342 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
20343 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
20344 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
20345 if (Diagnose)
20346 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
20347 return false;
20348 }
20349 Stack->setOMPDependT(PT.get());
20350 return true;
20351}
20352
20354 SourceLocation StartLoc,
20355 SourceLocation LParenLoc,
20356 SourceLocation EndLoc) {
20357 if (!Depobj)
20358 return nullptr;
20359
20360 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
20361
20362 // OpenMP 5.0, 2.17.10.1 depobj Construct
20363 // depobj is an lvalue expression of type omp_depend_t.
20364 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
20365 !Depobj->isInstantiationDependent() &&
20367 (OMPDependTFound && !getASTContext().typesAreCompatible(
20368 DSAStack->getOMPDependT(), Depobj->getType(),
20369 /*CompareUnqualified=*/true))) {
20370 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20371 << 0 << Depobj->getType() << Depobj->getSourceRange();
20372 }
20373
20374 if (!Depobj->isLValue()) {
20375 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
20376 << 1 << Depobj->getSourceRange();
20377 }
20378
20379 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
20380 Depobj);
20381}
20382
20383namespace {
20384// Utility struct that gathers the related info for doacross clause.
20385struct DoacrossDataInfoTy {
20386 // The list of expressions.
20388 // The OperatorOffset for doacross loop.
20390 // The depended loop count.
20391 llvm::APSInt TotalDepCount;
20392};
20393} // namespace
20394static DoacrossDataInfoTy
20396 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
20397 SourceLocation EndLoc) {
20398
20401 llvm::APSInt DepCounter(/*BitWidth=*/32);
20402 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20403
20404 if (const Expr *OrderedCountExpr =
20405 Stack->getParentOrderedRegionParam().first) {
20406 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
20407 TotalDepCount.setIsUnsigned(/*Val=*/true);
20408 }
20409
20410 for (Expr *RefExpr : VarList) {
20411 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
20412 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20413 // It will be analyzed later.
20414 Vars.push_back(RefExpr);
20415 continue;
20416 }
20417
20418 SourceLocation ELoc = RefExpr->getExprLoc();
20419 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20420 if (!IsSource) {
20421 if (Stack->getParentOrderedRegionParam().first &&
20422 DepCounter >= TotalDepCount) {
20423 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
20424 continue;
20425 }
20426 ++DepCounter;
20427 // OpenMP [2.13.9, Summary]
20428 // depend(dependence-type : vec), where dependence-type is:
20429 // 'sink' and where vec is the iteration vector, which has the form:
20430 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
20431 // where n is the value specified by the ordered clause in the loop
20432 // directive, xi denotes the loop iteration variable of the i-th nested
20433 // loop associated with the loop directive, and di is a constant
20434 // non-negative integer.
20435 if (SemaRef.CurContext->isDependentContext()) {
20436 // It will be analyzed later.
20437 Vars.push_back(RefExpr);
20438 continue;
20439 }
20440 SimpleExpr = SimpleExpr->IgnoreImplicit();
20442 SourceLocation OOLoc;
20443 Expr *LHS = SimpleExpr;
20444 Expr *RHS = nullptr;
20445 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
20446 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
20447 OOLoc = BO->getOperatorLoc();
20448 LHS = BO->getLHS()->IgnoreParenImpCasts();
20449 RHS = BO->getRHS()->IgnoreParenImpCasts();
20450 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
20451 OOK = OCE->getOperator();
20452 OOLoc = OCE->getOperatorLoc();
20453 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20454 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
20455 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
20456 OOK = MCE->getMethodDecl()
20457 ->getNameInfo()
20458 .getName()
20459 .getCXXOverloadedOperator();
20460 OOLoc = MCE->getCallee()->getExprLoc();
20461 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
20462 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
20463 }
20464 SourceLocation ELoc;
20465 SourceRange ERange;
20466 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
20467 if (Res.second) {
20468 // It will be analyzed later.
20469 Vars.push_back(RefExpr);
20470 }
20471 ValueDecl *D = Res.first;
20472 if (!D)
20473 continue;
20474
20475 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
20476 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
20477 continue;
20478 }
20479 if (RHS) {
20480 ExprResult RHSRes =
20482 RHS, OMPC_depend, /*StrictlyPositive=*/false);
20483 if (RHSRes.isInvalid())
20484 continue;
20485 }
20486 if (!SemaRef.CurContext->isDependentContext() &&
20487 Stack->getParentOrderedRegionParam().first &&
20488 DepCounter != Stack->isParentLoopControlVariable(D).first) {
20489 const ValueDecl *VD =
20490 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
20491 if (VD)
20492 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20493 << 1 << VD;
20494 else
20495 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
20496 << 0;
20497 continue;
20498 }
20499 OpsOffs.emplace_back(RHS, OOK);
20500 }
20501 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20502 }
20503 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
20504 TotalDepCount > VarList.size() &&
20505 Stack->getParentOrderedRegionParam().first &&
20506 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
20507 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
20508 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
20509 }
20510 return {Vars, OpsOffs, TotalDepCount};
20511}
20512
20514 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
20515 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20516 SourceLocation EndLoc) {
20517 OpenMPDependClauseKind DepKind = Data.DepKind;
20518 SourceLocation DepLoc = Data.DepLoc;
20519 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
20520 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
20521 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20522 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
20523 return nullptr;
20524 }
20525 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
20526 DepKind == OMPC_DEPEND_mutexinoutset) {
20527 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
20528 return nullptr;
20529 }
20530 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
20531 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20532 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
20533 DepKind == OMPC_DEPEND_sink ||
20534 ((getLangOpts().OpenMP < 50 ||
20535 DSAStack->getCurrentDirective() == OMPD_depobj) &&
20536 DepKind == OMPC_DEPEND_depobj))) {
20537 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
20538 OMPC_DEPEND_outallmemory,
20539 OMPC_DEPEND_inoutallmemory};
20540 if (getLangOpts().OpenMP < 50 ||
20541 DSAStack->getCurrentDirective() == OMPD_depobj)
20542 Except.push_back(OMPC_DEPEND_depobj);
20543 if (getLangOpts().OpenMP < 51)
20544 Except.push_back(OMPC_DEPEND_inoutset);
20545 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
20546 ? "depend modifier(iterator) or "
20547 : "";
20548 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
20549 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
20550 /*Last=*/OMPC_DEPEND_unknown,
20551 Except)
20552 << getOpenMPClauseNameForDiag(OMPC_depend);
20553 return nullptr;
20554 }
20555 if (DepModifier &&
20556 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
20557 Diag(DepModifier->getExprLoc(),
20558 diag::err_omp_depend_sink_source_with_modifier);
20559 return nullptr;
20560 }
20561 if (DepModifier &&
20562 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
20563 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
20564
20567 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
20568
20569 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
20570 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
20571 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
20572 Vars = VarOffset.Vars;
20573 OpsOffs = VarOffset.OpsOffs;
20574 TotalDepCount = VarOffset.TotalDepCount;
20575 } else {
20576 for (Expr *RefExpr : VarList) {
20577 assert(RefExpr && "NULL expr in OpenMP depend clause.");
20578 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
20579 // It will be analyzed later.
20580 Vars.push_back(RefExpr);
20581 continue;
20582 }
20583
20584 SourceLocation ELoc = RefExpr->getExprLoc();
20585 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
20586 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
20587 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
20588 if (OMPDependTFound)
20589 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
20590 DepKind == OMPC_DEPEND_depobj);
20591 if (DepKind == OMPC_DEPEND_depobj) {
20592 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20593 // List items used in depend clauses with the depobj dependence type
20594 // must be expressions of the omp_depend_t type.
20595 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20596 !RefExpr->isInstantiationDependent() &&
20597 !RefExpr->containsUnexpandedParameterPack() &&
20598 (OMPDependTFound &&
20599 !getASTContext().hasSameUnqualifiedType(
20600 DSAStack->getOMPDependT(), RefExpr->getType()))) {
20601 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20602 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
20603 continue;
20604 }
20605 if (!RefExpr->isLValue()) {
20606 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
20607 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
20608 continue;
20609 }
20610 } else {
20611 // OpenMP 5.0 [2.17.11, Restrictions]
20612 // List items used in depend clauses cannot be zero-length array
20613 // sections.
20614 QualType ExprTy = RefExpr->getType().getNonReferenceType();
20615 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
20616 if (OASE) {
20617 QualType BaseType =
20619 if (BaseType.isNull())
20620 return nullptr;
20621 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20622 ExprTy = ATy->getElementType();
20623 else
20624 ExprTy = BaseType->getPointeeType();
20625 if (BaseType.isNull() || ExprTy.isNull())
20626 return nullptr;
20627 ExprTy = ExprTy.getNonReferenceType();
20628 const Expr *Length = OASE->getLength();
20630 if (Length && !Length->isValueDependent() &&
20631 Length->EvaluateAsInt(Result, getASTContext()) &&
20632 Result.Val.getInt().isZero()) {
20633 Diag(ELoc,
20634 diag::err_omp_depend_zero_length_array_section_not_allowed)
20635 << SimpleExpr->getSourceRange();
20636 continue;
20637 }
20638 }
20639
20640 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20641 // List items used in depend clauses with the in, out, inout,
20642 // inoutset, or mutexinoutset dependence types cannot be
20643 // expressions of the omp_depend_t type.
20644 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20645 !RefExpr->isInstantiationDependent() &&
20646 !RefExpr->containsUnexpandedParameterPack() &&
20647 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20648 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20649 ExprTy.getTypePtr()))) {
20650 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20651 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20652 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20653 << RefExpr->getSourceRange();
20654 continue;
20655 }
20656
20657 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20658 if (ASE && !ASE->getBase()->isTypeDependent() &&
20659 !ASE->getBase()
20660 ->getType()
20661 .getNonReferenceType()
20662 ->isPointerType() &&
20663 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20664 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20665 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20666 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20667 << RefExpr->getSourceRange();
20668 continue;
20669 }
20670
20671 ExprResult Res;
20672 {
20674 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20675 RefExpr->IgnoreParenImpCasts());
20676 }
20677 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20678 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20679 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20680 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20681 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20682 << RefExpr->getSourceRange();
20683 continue;
20684 }
20685 }
20686 }
20687 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20688 }
20689 }
20690
20691 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20692 DepKind != OMPC_DEPEND_outallmemory &&
20693 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20694 return nullptr;
20695
20696 auto *C = OMPDependClause::Create(
20697 getASTContext(), StartLoc, LParenLoc, EndLoc,
20698 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20699 TotalDepCount.getZExtValue());
20700 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20701 DSAStack->isParentOrderedRegion())
20702 DSAStack->addDoacrossDependClause(C, OpsOffs);
20703 return C;
20704}
20705
20708 SourceLocation LParenLoc, SourceLocation ModifierLoc,
20709 SourceLocation EndLoc) {
20710 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20711 "Unexpected device modifier in OpenMP < 50.");
20712
20713 bool ErrorFound = false;
20714 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20715 std::string Values =
20716 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20717 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20718 << Values << getOpenMPClauseNameForDiag(OMPC_device);
20719 ErrorFound = true;
20720 }
20721
20722 Expr *ValExpr = Device;
20723 Stmt *HelperValStmt = nullptr;
20724
20725 // OpenMP [2.9.1, Restrictions]
20726 // The device expression must evaluate to a non-negative integer value.
20727 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20728 /*StrictlyPositive=*/false) ||
20729 ErrorFound;
20730 if (ErrorFound)
20731 return nullptr;
20732
20733 // OpenMP 5.0 [2.12.5, Restrictions]
20734 // In case of ancestor device-modifier, a requires directive with
20735 // the reverse_offload clause must be specified.
20736 if (Modifier == OMPC_DEVICE_ancestor) {
20737 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20739 StartLoc,
20740 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20741 ErrorFound = true;
20742 }
20743 }
20744
20745 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20746 OpenMPDirectiveKind CaptureRegion =
20747 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20748 if (CaptureRegion != OMPD_unknown &&
20750 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20751 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20752 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20753 HelperValStmt = buildPreInits(getASTContext(), Captures);
20754 }
20755
20756 return new (getASTContext())
20757 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20758 LParenLoc, ModifierLoc, EndLoc);
20759}
20760
20762 DSAStackTy *Stack, QualType QTy,
20763 bool FullCheck = true) {
20764 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20765 return false;
20766 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20767 !QTy.isTriviallyCopyableType(SemaRef.Context))
20768 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20769 return true;
20770}
20771
20772/// Return true if it can be proven that the provided array expression
20773/// (array section or array subscript) does NOT specify the whole size of the
20774/// array whose base type is \a BaseQTy.
20776 const Expr *E,
20777 QualType BaseQTy) {
20778 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20779
20780 // If this is an array subscript, it refers to the whole size if the size of
20781 // the dimension is constant and equals 1. Also, an array section assumes the
20782 // format of an array subscript if no colon is used.
20783 if (isa<ArraySubscriptExpr>(E) ||
20784 (OASE && OASE->getColonLocFirst().isInvalid())) {
20785 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20786 return ATy->getSExtSize() != 1;
20787 // Size can't be evaluated statically.
20788 return false;
20789 }
20790
20791 assert(OASE && "Expecting array section if not an array subscript.");
20792 const Expr *LowerBound = OASE->getLowerBound();
20793 const Expr *Length = OASE->getLength();
20794
20795 // If there is a lower bound that does not evaluates to zero, we are not
20796 // covering the whole dimension.
20797 if (LowerBound) {
20799 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20800 return false; // Can't get the integer value as a constant.
20801
20802 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20803 if (ConstLowerBound.getSExtValue())
20804 return true;
20805 }
20806
20807 // If we don't have a length we covering the whole dimension.
20808 if (!Length)
20809 return false;
20810
20811 // If the base is a pointer, we don't have a way to get the size of the
20812 // pointee.
20813 if (BaseQTy->isPointerType())
20814 return false;
20815
20816 // We can only check if the length is the same as the size of the dimension
20817 // if we have a constant array.
20818 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20819 if (!CATy)
20820 return false;
20821
20823 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20824 return false; // Can't get the integer value as a constant.
20825
20826 llvm::APSInt ConstLength = Result.Val.getInt();
20827 return CATy->getSExtSize() != ConstLength.getSExtValue();
20828}
20829
20830// Return true if it can be proven that the provided array expression (array
20831// section or array subscript) does NOT specify a single element of the array
20832// whose base type is \a BaseQTy.
20834 const Expr *E,
20835 QualType BaseQTy) {
20836 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20837
20838 // An array subscript always refer to a single element. Also, an array section
20839 // assumes the format of an array subscript if no colon is used.
20840 if (isa<ArraySubscriptExpr>(E) ||
20841 (OASE && OASE->getColonLocFirst().isInvalid()))
20842 return false;
20843
20844 assert(OASE && "Expecting array section if not an array subscript.");
20845 const Expr *Length = OASE->getLength();
20846
20847 // If we don't have a length we have to check if the array has unitary size
20848 // for this dimension. Also, we should always expect a length if the base type
20849 // is pointer.
20850 if (!Length) {
20851 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20852 return ATy->getSExtSize() != 1;
20853 // We cannot assume anything.
20854 return false;
20855 }
20856
20857 // Check if the length evaluates to 1.
20859 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20860 return false; // Can't get the integer value as a constant.
20861
20862 llvm::APSInt ConstLength = Result.Val.getInt();
20863 return ConstLength.getSExtValue() != 1;
20864}
20865
20866// The base of elements of list in a map clause have to be either:
20867// - a reference to variable or field.
20868// - a member expression.
20869// - an array expression.
20870//
20871// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20872// reference to 'r'.
20873//
20874// If we have:
20875//
20876// struct SS {
20877// Bla S;
20878// foo() {
20879// #pragma omp target map (S.Arr[:12]);
20880// }
20881// }
20882//
20883// We want to retrieve the member expression 'this->S';
20884
20885// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20886// If a list item is an array section, it must specify contiguous storage.
20887//
20888// For this restriction it is sufficient that we make sure only references
20889// to variables or fields and array expressions, and that no array sections
20890// exist except in the rightmost expression (unless they cover the whole
20891// dimension of the array). E.g. these would be invalid:
20892//
20893// r.ArrS[3:5].Arr[6:7]
20894//
20895// r.ArrS[3:5].x
20896//
20897// but these would be valid:
20898// r.ArrS[3].Arr[6:7]
20899//
20900// r.ArrS[3].x
20901namespace {
20902class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20903 Sema &SemaRef;
20904 OpenMPClauseKind CKind = OMPC_unknown;
20905 OpenMPDirectiveKind DKind = OMPD_unknown;
20907 bool IsNonContiguous = false;
20908 bool NoDiagnose = false;
20909 const Expr *RelevantExpr = nullptr;
20910 bool AllowUnitySizeArraySection = true;
20911 bool AllowWholeSizeArraySection = true;
20912 bool AllowAnotherPtr = true;
20913 SourceLocation ELoc;
20914 SourceRange ERange;
20915
20916 void emitErrorMsg() {
20917 // If nothing else worked, this is not a valid map clause expression.
20918 if (SemaRef.getLangOpts().OpenMP < 50) {
20919 SemaRef.Diag(ELoc,
20920 diag::err_omp_expected_named_var_member_or_array_expression)
20921 << ERange;
20922 } else {
20923 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20924 << getOpenMPClauseNameForDiag(CKind) << ERange;
20925 }
20926 }
20927
20928public:
20929 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20930 if (!isa<VarDecl>(DRE->getDecl())) {
20931 emitErrorMsg();
20932 return false;
20933 }
20934 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20935 RelevantExpr = DRE;
20936 // Record the component.
20937 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20938 return true;
20939 }
20940
20941 bool VisitMemberExpr(MemberExpr *ME) {
20942 Expr *E = ME;
20943 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20944
20945 if (isa<CXXThisExpr>(BaseE)) {
20946 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20947 // We found a base expression: this->Val.
20948 RelevantExpr = ME;
20949 } else {
20950 E = BaseE;
20951 }
20952
20953 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20954 if (!NoDiagnose) {
20955 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20956 << ME->getSourceRange();
20957 return false;
20958 }
20959 if (RelevantExpr)
20960 return false;
20961 return Visit(E);
20962 }
20963
20964 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20965
20966 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20967 // A bit-field cannot appear in a map clause.
20968 //
20969 if (FD->isBitField()) {
20970 if (!NoDiagnose) {
20971 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20972 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
20973 return false;
20974 }
20975 if (RelevantExpr)
20976 return false;
20977 return Visit(E);
20978 }
20979
20980 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20981 // If the type of a list item is a reference to a type T then the type
20982 // will be considered to be T for all purposes of this clause.
20983 QualType CurType = BaseE->getType().getNonReferenceType();
20984
20985 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20986 // A list item cannot be a variable that is a member of a structure with
20987 // a union type.
20988 //
20989 if (CurType->isUnionType()) {
20990 if (!NoDiagnose) {
20991 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20992 << ME->getSourceRange();
20993 return false;
20994 }
20995 return RelevantExpr || Visit(E);
20996 }
20997
20998 // If we got a member expression, we should not expect any array section
20999 // before that:
21000 //
21001 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
21002 // If a list item is an element of a structure, only the rightmost symbol
21003 // of the variable reference can be an array section.
21004 //
21005 AllowUnitySizeArraySection = false;
21006 AllowWholeSizeArraySection = false;
21007
21008 // Record the component.
21009 Components.emplace_back(ME, FD, IsNonContiguous);
21010 return RelevantExpr || Visit(E);
21011 }
21012
21013 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
21014 Expr *E = AE->getBase()->IgnoreParenImpCasts();
21015
21016 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
21017 if (!NoDiagnose) {
21018 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21019 << 0 << AE->getSourceRange();
21020 return false;
21021 }
21022 return RelevantExpr || Visit(E);
21023 }
21024
21025 // If we got an array subscript that express the whole dimension we
21026 // can have any array expressions before. If it only expressing part of
21027 // the dimension, we can only have unitary-size array expressions.
21029 AllowWholeSizeArraySection = false;
21030
21031 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
21032 Expr::EvalResult Result;
21033 if (!AE->getIdx()->isValueDependent() &&
21034 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
21035 !Result.Val.getInt().isZero()) {
21036 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21037 diag::err_omp_invalid_map_this_expr);
21038 SemaRef.Diag(AE->getIdx()->getExprLoc(),
21039 diag::note_omp_invalid_subscript_on_this_ptr_map);
21040 }
21041 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21042 RelevantExpr = TE;
21043 }
21044
21045 // Record the component - we don't have any declaration associated.
21046 Components.emplace_back(AE, nullptr, IsNonContiguous);
21047
21048 return RelevantExpr || Visit(E);
21049 }
21050
21051 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
21052 // After OMP 5.0 Array section in reduction clause will be implicitly
21053 // mapped
21054 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
21055 "Array sections cannot be implicitly mapped.");
21056 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21057 QualType CurType =
21059
21060 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21061 // If the type of a list item is a reference to a type T then the type
21062 // will be considered to be T for all purposes of this clause.
21063 if (CurType->isReferenceType())
21064 CurType = CurType->getPointeeType();
21065
21066 bool IsPointer = CurType->isAnyPointerType();
21067
21068 if (!IsPointer && !CurType->isArrayType()) {
21069 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
21070 << 0 << OASE->getSourceRange();
21071 return false;
21072 }
21073
21074 bool NotWhole =
21075 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
21076 bool NotUnity =
21077 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
21078
21079 if (AllowWholeSizeArraySection) {
21080 // Any array section is currently allowed. Allowing a whole size array
21081 // section implies allowing a unity array section as well.
21082 //
21083 // If this array section refers to the whole dimension we can still
21084 // accept other array sections before this one, except if the base is a
21085 // pointer. Otherwise, only unitary sections are accepted.
21086 if (NotWhole || IsPointer)
21087 AllowWholeSizeArraySection = false;
21088 } else if (DKind == OMPD_target_update &&
21089 SemaRef.getLangOpts().OpenMP >= 50) {
21090 if (IsPointer && !AllowAnotherPtr)
21091 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
21092 << /*array of unknown bound */ 1;
21093 else
21094 IsNonContiguous = true;
21095 } else if (AllowUnitySizeArraySection && NotUnity) {
21096 // A unity or whole array section is not allowed and that is not
21097 // compatible with the properties of the current array section.
21098 if (NoDiagnose)
21099 return false;
21100 SemaRef.Diag(ELoc,
21101 diag::err_array_section_does_not_specify_contiguous_storage)
21102 << OASE->getSourceRange();
21103 return false;
21104 }
21105
21106 if (IsPointer)
21107 AllowAnotherPtr = false;
21108
21109 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
21110 Expr::EvalResult ResultR;
21111 Expr::EvalResult ResultL;
21112 if (!OASE->getLength()->isValueDependent() &&
21113 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
21114 !ResultR.Val.getInt().isOne()) {
21115 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21116 diag::err_omp_invalid_map_this_expr);
21117 SemaRef.Diag(OASE->getLength()->getExprLoc(),
21118 diag::note_omp_invalid_length_on_this_ptr_mapping);
21119 }
21120 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
21121 OASE->getLowerBound()->EvaluateAsInt(ResultL,
21122 SemaRef.getASTContext()) &&
21123 !ResultL.Val.getInt().isZero()) {
21124 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21125 diag::err_omp_invalid_map_this_expr);
21126 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
21127 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
21128 }
21129 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21130 RelevantExpr = TE;
21131 }
21132
21133 // Record the component - we don't have any declaration associated.
21134 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
21135 return RelevantExpr || Visit(E);
21136 }
21137 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
21138 Expr *Base = E->getBase();
21139
21140 // Record the component - we don't have any declaration associated.
21141 Components.emplace_back(E, nullptr, IsNonContiguous);
21142
21143 return Visit(Base->IgnoreParenImpCasts());
21144 }
21145
21146 bool VisitUnaryOperator(UnaryOperator *UO) {
21147 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
21148 UO->getOpcode() != UO_Deref) {
21149 emitErrorMsg();
21150 return false;
21151 }
21152 if (!RelevantExpr) {
21153 // Record the component if haven't found base decl.
21154 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
21155 }
21156 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
21157 }
21158 bool VisitBinaryOperator(BinaryOperator *BO) {
21159 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
21160 emitErrorMsg();
21161 return false;
21162 }
21163
21164 // Pointer arithmetic is the only thing we expect to happen here so after we
21165 // make sure the binary operator is a pointer type, the only thing we need
21166 // to do is to visit the subtree that has the same type as root (so that we
21167 // know the other subtree is just an offset)
21168 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
21169 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
21170 Components.emplace_back(BO, nullptr, false);
21171 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
21172 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
21173 "Either LHS or RHS have base decl inside");
21174 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
21175 return RelevantExpr || Visit(LE);
21176 return RelevantExpr || Visit(RE);
21177 }
21178 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
21179 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21180 RelevantExpr = CTE;
21181 Components.emplace_back(CTE, nullptr, IsNonContiguous);
21182 return true;
21183 }
21184 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
21185 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
21186 Components.emplace_back(COCE, nullptr, IsNonContiguous);
21187 return true;
21188 }
21189 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
21190 Expr *Source = E->getSourceExpr();
21191 if (!Source) {
21192 emitErrorMsg();
21193 return false;
21194 }
21195 return Visit(Source);
21196 }
21197 bool VisitStmt(Stmt *) {
21198 emitErrorMsg();
21199 return false;
21200 }
21201 const Expr *getFoundBase() const { return RelevantExpr; }
21202 explicit MapBaseChecker(
21203 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
21205 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
21206 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
21207 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
21208};
21209} // namespace
21210
21211/// Return the expression of the base of the mappable expression or null if it
21212/// cannot be determined and do all the necessary checks to see if the
21213/// expression is valid as a standalone mappable expression. In the process,
21214/// record all the components of the expression.
21216 Sema &SemaRef, Expr *E,
21218 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
21219 SourceLocation ELoc = E->getExprLoc();
21220 SourceRange ERange = E->getSourceRange();
21221 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
21222 ERange);
21223 if (Checker.Visit(E->IgnoreParens())) {
21224 // Check if the highest dimension array section has length specified
21225 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
21226 (CKind == OMPC_to || CKind == OMPC_from)) {
21227 auto CI = CurComponents.rbegin();
21228 auto CE = CurComponents.rend();
21229 for (; CI != CE; ++CI) {
21230 const auto *OASE =
21231 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
21232 if (!OASE)
21233 continue;
21234 if (OASE && OASE->getLength())
21235 break;
21236 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
21237 << ERange;
21238 }
21239 }
21240 return Checker.getFoundBase();
21241 }
21242 return nullptr;
21243}
21244
21245// Return true if expression E associated with value VD has conflicts with other
21246// map information.
21248 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
21249 bool CurrentRegionOnly,
21251 OpenMPClauseKind CKind) {
21252 assert(VD && E);
21253 SourceLocation ELoc = E->getExprLoc();
21254 SourceRange ERange = E->getSourceRange();
21255
21256 // In order to easily check the conflicts we need to match each component of
21257 // the expression under test with the components of the expressions that are
21258 // already in the stack.
21259
21260 assert(!CurComponents.empty() && "Map clause expression with no components!");
21261 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
21262 "Map clause expression with unexpected base!");
21263
21264 // Variables to help detecting enclosing problems in data environment nests.
21265 bool IsEnclosedByDataEnvironmentExpr = false;
21266 const Expr *EnclosingExpr = nullptr;
21267
21268 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
21269 VD, CurrentRegionOnly,
21270 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
21271 ERange, CKind, &EnclosingExpr,
21273 StackComponents,
21274 OpenMPClauseKind Kind) {
21275 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
21276 return false;
21277 assert(!StackComponents.empty() &&
21278 "Map clause expression with no components!");
21279 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
21280 "Map clause expression with unexpected base!");
21281 (void)VD;
21282
21283 // The whole expression in the stack.
21284 const Expr *RE = StackComponents.front().getAssociatedExpression();
21285
21286 // Expressions must start from the same base. Here we detect at which
21287 // point both expressions diverge from each other and see if we can
21288 // detect if the memory referred to both expressions is contiguous and
21289 // do not overlap.
21290 auto CI = CurComponents.rbegin();
21291 auto CE = CurComponents.rend();
21292 auto SI = StackComponents.rbegin();
21293 auto SE = StackComponents.rend();
21294 for (; CI != CE && SI != SE; ++CI, ++SI) {
21295
21296 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
21297 // At most one list item can be an array item derived from a given
21298 // variable in map clauses of the same construct.
21299 if (CurrentRegionOnly &&
21300 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
21301 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
21302 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
21303 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
21304 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
21305 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
21306 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
21307 diag::err_omp_multiple_array_items_in_map_clause)
21308 << CI->getAssociatedExpression()->getSourceRange();
21309 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
21310 diag::note_used_here)
21311 << SI->getAssociatedExpression()->getSourceRange();
21312 return true;
21313 }
21314
21315 // Do both expressions have the same kind?
21316 if (CI->getAssociatedExpression()->getStmtClass() !=
21317 SI->getAssociatedExpression()->getStmtClass())
21318 break;
21319
21320 // Are we dealing with different variables/fields?
21321 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
21322 break;
21323 }
21324 // Check if the extra components of the expressions in the enclosing
21325 // data environment are redundant for the current base declaration.
21326 // If they are, the maps completely overlap, which is legal.
21327 for (; SI != SE; ++SI) {
21328 QualType Type;
21329 if (const auto *ASE =
21330 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
21331 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
21332 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
21333 SI->getAssociatedExpression())) {
21334 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
21335 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
21336 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
21337 SI->getAssociatedExpression())) {
21338 Type = OASE->getBase()->getType()->getPointeeType();
21339 }
21340 if (Type.isNull() || Type->isAnyPointerType() ||
21342 SemaRef, SI->getAssociatedExpression(), Type))
21343 break;
21344 }
21345
21346 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21347 // List items of map clauses in the same construct must not share
21348 // original storage.
21349 //
21350 // If the expressions are exactly the same or one is a subset of the
21351 // other, it means they are sharing storage.
21352 if (CI == CE && SI == SE) {
21353 if (CurrentRegionOnly) {
21354 if (CKind == OMPC_map) {
21355 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21356 } else {
21357 assert(CKind == OMPC_to || CKind == OMPC_from);
21358 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21359 << ERange;
21360 }
21361 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21362 << RE->getSourceRange();
21363 return true;
21364 }
21365 // If we find the same expression in the enclosing data environment,
21366 // that is legal.
21367 IsEnclosedByDataEnvironmentExpr = true;
21368 return false;
21369 }
21370
21371 QualType DerivedType =
21372 std::prev(CI)->getAssociatedDeclaration()->getType();
21373 SourceLocation DerivedLoc =
21374 std::prev(CI)->getAssociatedExpression()->getExprLoc();
21375
21376 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21377 // If the type of a list item is a reference to a type T then the type
21378 // will be considered to be T for all purposes of this clause.
21379 DerivedType = DerivedType.getNonReferenceType();
21380
21381 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
21382 // A variable for which the type is pointer and an array section
21383 // derived from that variable must not appear as list items of map
21384 // clauses of the same construct.
21385 //
21386 // Also, cover one of the cases in:
21387 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21388 // If any part of the original storage of a list item has corresponding
21389 // storage in the device data environment, all of the original storage
21390 // must have corresponding storage in the device data environment.
21391 //
21392 if (DerivedType->isAnyPointerType()) {
21393 if (CI == CE || SI == SE) {
21394 SemaRef.Diag(
21395 DerivedLoc,
21396 diag::err_omp_pointer_mapped_along_with_derived_section)
21397 << DerivedLoc;
21398 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21399 << RE->getSourceRange();
21400 return true;
21401 }
21402 if (CI->getAssociatedExpression()->getStmtClass() !=
21403 SI->getAssociatedExpression()->getStmtClass() ||
21404 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
21405 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
21406 assert(CI != CE && SI != SE);
21407 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
21408 << DerivedLoc;
21409 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21410 << RE->getSourceRange();
21411 return true;
21412 }
21413 }
21414
21415 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
21416 // List items of map clauses in the same construct must not share
21417 // original storage.
21418 //
21419 // An expression is a subset of the other.
21420 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
21421 if (CKind == OMPC_map) {
21422 if (CI != CE || SI != SE) {
21423 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
21424 // a pointer.
21425 auto Begin =
21426 CI != CE ? CurComponents.begin() : StackComponents.begin();
21427 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
21428 auto It = Begin;
21429 while (It != End && !It->getAssociatedDeclaration())
21430 std::advance(It, 1);
21431 assert(It != End &&
21432 "Expected at least one component with the declaration.");
21433 if (It != Begin && It->getAssociatedDeclaration()
21434 ->getType()
21435 .getCanonicalType()
21436 ->isAnyPointerType()) {
21437 IsEnclosedByDataEnvironmentExpr = false;
21438 EnclosingExpr = nullptr;
21439 return false;
21440 }
21441 }
21442 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
21443 } else {
21444 assert(CKind == OMPC_to || CKind == OMPC_from);
21445 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
21446 << ERange;
21447 }
21448 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
21449 << RE->getSourceRange();
21450 return true;
21451 }
21452
21453 // The current expression uses the same base as other expression in the
21454 // data environment but does not contain it completely.
21455 if (!CurrentRegionOnly && SI != SE)
21456 EnclosingExpr = RE;
21457
21458 // The current expression is a subset of the expression in the data
21459 // environment.
21460 IsEnclosedByDataEnvironmentExpr |=
21461 (!CurrentRegionOnly && CI != CE && SI == SE);
21462
21463 return false;
21464 });
21465
21466 if (CurrentRegionOnly)
21467 return FoundError;
21468
21469 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
21470 // If any part of the original storage of a list item has corresponding
21471 // storage in the device data environment, all of the original storage must
21472 // have corresponding storage in the device data environment.
21473 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
21474 // If a list item is an element of a structure, and a different element of
21475 // the structure has a corresponding list item in the device data environment
21476 // prior to a task encountering the construct associated with the map clause,
21477 // then the list item must also have a corresponding list item in the device
21478 // data environment prior to the task encountering the construct.
21479 //
21480 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
21481 SemaRef.Diag(ELoc,
21482 diag::err_omp_original_storage_is_shared_and_does_not_contain)
21483 << ERange;
21484 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
21485 << EnclosingExpr->getSourceRange();
21486 return true;
21487 }
21488
21489 return FoundError;
21490}
21491
21492// Look up the user-defined mapper given the mapper name and mapped type, and
21493// build a reference to it.
21495 CXXScopeSpec &MapperIdScopeSpec,
21496 const DeclarationNameInfo &MapperId,
21497 QualType Type,
21498 Expr *UnresolvedMapper) {
21499 if (MapperIdScopeSpec.isInvalid())
21500 return ExprError();
21501 // Get the actual type for the array type.
21502 if (Type->isArrayType()) {
21503 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
21505 }
21506 // Find all user-defined mappers with the given MapperId.
21507 SmallVector<UnresolvedSet<8>, 4> Lookups;
21508 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21509 Lookup.suppressDiagnostics();
21510 if (S) {
21511 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21512 /*ObjectType=*/QualType())) {
21513 NamedDecl *D = Lookup.getRepresentativeDecl();
21514 while (S && !S->isDeclScope(D))
21515 S = S->getParent();
21516 if (S)
21517 S = S->getParent();
21518 Lookups.emplace_back();
21519 Lookups.back().append(Lookup.begin(), Lookup.end());
21520 Lookup.clear();
21521 }
21522 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
21523 // Extract the user-defined mappers with the given MapperId.
21524 Lookups.push_back(UnresolvedSet<8>());
21525 for (NamedDecl *D : ULE->decls()) {
21526 auto *DMD = cast<OMPDeclareMapperDecl>(D);
21527 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
21528 Lookups.back().addDecl(DMD);
21529 }
21530 }
21531 // Defer the lookup for dependent types. The results will be passed through
21532 // UnresolvedMapper on instantiation.
21533 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21536 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21537 return !D->isInvalidDecl() &&
21538 (D->getType()->isDependentType() ||
21539 D->getType()->isInstantiationDependentType() ||
21540 D->getType()->containsUnexpandedParameterPack());
21541 })) {
21542 UnresolvedSet<8> URS;
21543 for (const UnresolvedSet<8> &Set : Lookups) {
21544 if (Set.empty())
21545 continue;
21546 URS.append(Set.begin(), Set.end());
21547 }
21549 SemaRef.Context, /*NamingClass=*/nullptr,
21550 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
21551 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
21552 /*KnownInstantiationDependent=*/false);
21553 }
21554 SourceLocation Loc = MapperId.getLoc();
21555 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21556 // The type must be of struct, union or class type in C and C++
21558 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
21559 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
21560 return ExprError();
21561 }
21562 // Perform argument dependent lookup.
21563 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21564 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21565 // Return the first user-defined mapper with the desired type.
21566 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21567 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21568 if (!D->isInvalidDecl() &&
21569 SemaRef.Context.hasSameType(D->getType(), Type))
21570 return D;
21571 return nullptr;
21572 }))
21573 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21574 // Find the first user-defined mapper with a type derived from the desired
21575 // type.
21576 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21577 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21578 if (!D->isInvalidDecl() &&
21579 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21580 !Type.isMoreQualifiedThan(D->getType(),
21581 SemaRef.getASTContext()))
21582 return D;
21583 return nullptr;
21584 })) {
21585 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21586 /*DetectVirtual=*/false);
21587 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21588 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
21589 VD->getType().getUnqualifiedType()))) {
21590 if (SemaRef.CheckBaseClassAccess(
21591 Loc, VD->getType(), Type, Paths.front(),
21592 /*DiagID=*/0) != Sema::AR_inaccessible) {
21593 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
21594 }
21595 }
21596 }
21597 }
21598 // Report error if a mapper is specified, but cannot be found.
21599 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
21600 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
21601 << Type << MapperId.getName();
21602 return ExprError();
21603 }
21604 return ExprEmpty();
21605}
21606
21607namespace {
21608// Utility struct that gathers all the related lists associated with a mappable
21609// expression.
21610struct MappableVarListInfo {
21611 // The list of expressions.
21612 ArrayRef<Expr *> VarList;
21613 // The list of processed expressions.
21614 SmallVector<Expr *, 16> ProcessedVarList;
21615 // The mappble components for each expression.
21617 // The base declaration of the variable.
21618 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
21619 // The reference to the user-defined mapper associated with every expression.
21620 SmallVector<Expr *, 16> UDMapperList;
21621
21622 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
21623 // We have a list of components and base declarations for each entry in the
21624 // variable list.
21625 VarComponents.reserve(VarList.size());
21626 VarBaseDeclarations.reserve(VarList.size());
21627 }
21628};
21629} // namespace
21630
21632 DSAStackTy *Stack,
21634
21635 const RecordDecl *RD = BaseType->getAsRecordDecl();
21637 DeclarationNameInfo ImplicitName;
21638 // Dummy variable _s for Mapper.
21639 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
21640 DeclRefExpr *MapperVarRef =
21641 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
21642
21643 // Create implicit map clause for mapper.
21645 for (auto *FD : RD->fields()) {
21646 Expr *BE = S.BuildMemberExpr(
21647 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
21650 /*HadMultipleCandidates=*/false,
21652 FD->getType(), VK_LValue, OK_Ordinary);
21653 SExprs.push_back(BE);
21654 }
21655 CXXScopeSpec MapperIdScopeSpec;
21656 DeclarationNameInfo MapperId;
21657 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21658
21659 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21660 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
21661 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21662 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
21663 OMPVarListLocTy());
21664 Maps.push_back(MapClause);
21665 return MapperVarRef;
21666}
21667
21669 DSAStackTy *Stack) {
21670
21671 // Build impilicit map for mapper
21673 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21674
21675 const RecordDecl *RD = BaseType->getAsRecordDecl();
21676 // AST context is RD's ParentASTContext().
21677 ASTContext &Ctx = RD->getParentASTContext();
21678 // DeclContext is RD's DeclContext.
21679 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21680
21681 // Create implicit default mapper for "RD".
21682 DeclarationName MapperId;
21683 auto &DeclNames = Ctx.DeclarationNames;
21684 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
21685 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
21686 BaseType, MapperId, Maps, nullptr);
21687 Scope *Scope = S.getScopeForContext(DCT);
21688 if (Scope)
21689 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
21690 DCT->addDecl(DMD);
21691 DMD->setAccess(clang::AS_none);
21692 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21693 VD->setDeclContext(DMD);
21694 VD->setLexicalDeclContext(DMD);
21695 DMD->addDecl(VD);
21696 DMD->setMapperVarRef(MapperVarRef);
21697 FieldDecl *FD = *RD->field_begin();
21698 // create mapper refence.
21700 DMD, false, SourceLocation(), BaseType, VK_LValue);
21701}
21702
21703// Look up the user-defined mapper given the mapper name and mapper type,
21704// return true if found one.
21705static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21706 CXXScopeSpec &MapperIdScopeSpec,
21707 const DeclarationNameInfo &MapperId,
21708 QualType Type) {
21709 // Find all user-defined mappers with the given MapperId.
21710 SmallVector<UnresolvedSet<8>, 4> Lookups;
21711 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21712 Lookup.suppressDiagnostics();
21713 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21714 /*ObjectType=*/QualType())) {
21715 NamedDecl *D = Lookup.getRepresentativeDecl();
21716 while (S && !S->isDeclScope(D))
21717 S = S->getParent();
21718 if (S)
21719 S = S->getParent();
21720 Lookups.emplace_back();
21721 Lookups.back().append(Lookup.begin(), Lookup.end());
21722 Lookup.clear();
21723 }
21724 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21727 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21728 return !D->isInvalidDecl() &&
21729 (D->getType()->isDependentType() ||
21730 D->getType()->isInstantiationDependentType() ||
21731 D->getType()->containsUnexpandedParameterPack());
21732 }))
21733 return false;
21734 // Perform argument dependent lookup.
21735 SourceLocation Loc = MapperId.getLoc();
21736 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21737 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21738 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21739 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21740 if (!D->isInvalidDecl() &&
21741 SemaRef.Context.hasSameType(D->getType(), Type))
21742 return D;
21743 return nullptr;
21744 }))
21745 return true;
21746 // Find the first user-defined mapper with a type derived from the desired
21747 // type.
21748 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21749 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21750 if (!D->isInvalidDecl() &&
21751 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21752 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
21753 return D;
21754 return nullptr;
21755 });
21756 if (!VD)
21757 return false;
21758 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21759 /*DetectVirtual=*/false);
21760 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21761 bool IsAmbiguous = !Paths.isAmbiguous(
21763 if (IsAmbiguous)
21764 return false;
21765 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
21766 /*DiagID=*/0) != Sema::AR_inaccessible)
21767 return true;
21768 }
21769 return false;
21770}
21771
21772static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21773 QualType CanonType, const Expr *E) {
21774
21775 // DFS over data members in structures/classes.
21777 {CanonType, nullptr});
21778 llvm::DenseMap<const Type *, bool> Visited;
21779 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21780 while (!Types.empty()) {
21781 auto [BaseType, CurFD] = Types.pop_back_val();
21782 while (ParentChain.back().second == 0)
21783 ParentChain.pop_back();
21784 --ParentChain.back().second;
21785 if (BaseType.isNull())
21786 continue;
21787 // Only structs/classes are allowed to have mappers.
21788 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21789 if (!RD)
21790 continue;
21791 auto It = Visited.find(BaseType.getTypePtr());
21792 if (It == Visited.end()) {
21793 // Try to find the associated user-defined mapper.
21794 CXXScopeSpec MapperIdScopeSpec;
21795 DeclarationNameInfo DefaultMapperId;
21797 &S.Context.Idents.get("default")));
21798 DefaultMapperId.setLoc(E->getExprLoc());
21799 bool HasUDMapper =
21800 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
21801 DefaultMapperId, BaseType);
21802 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21803 }
21804 // Found default mapper.
21805 if (It->second)
21806 return true;
21807 // Check for the "default" mapper for data members.
21808 bool FirstIter = true;
21809 for (FieldDecl *FD : RD->fields()) {
21810 if (!FD)
21811 continue;
21812 QualType FieldTy = FD->getType();
21813 if (FieldTy.isNull() ||
21814 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21815 continue;
21816 if (FirstIter) {
21817 FirstIter = false;
21818 ParentChain.emplace_back(CurFD, 1);
21819 } else {
21820 ++ParentChain.back().second;
21821 }
21822 Types.emplace_back(FieldTy, FD);
21823 }
21824 }
21825 return false;
21826}
21827
21828// Check the validity of the provided variable list for the provided clause kind
21829// \a CKind. In the check process the valid expressions, mappable expression
21830// components, variables, and user-defined mappers are extracted and used to
21831// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21832// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21833// and \a MapperId are expected to be valid if the clause kind is 'map'.
21835 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21836 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21837 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21838 ArrayRef<Expr *> UnresolvedMappers,
21840 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
21841 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21842 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21843 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21844 "Unexpected clause kind with mappable expressions!");
21845 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
21846
21847 // If the identifier of user-defined mapper is not specified, it is "default".
21848 // We do not change the actual name in this clause to distinguish whether a
21849 // mapper is specified explicitly, i.e., it is not explicitly specified when
21850 // MapperId.getName() is empty.
21851 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21852 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21853 MapperId.setName(DeclNames.getIdentifier(
21854 &SemaRef.getASTContext().Idents.get("default")));
21855 MapperId.setLoc(StartLoc);
21856 }
21857
21858 // Iterators to find the current unresolved mapper expression.
21859 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21860 bool UpdateUMIt = false;
21861 Expr *UnresolvedMapper = nullptr;
21862
21863 bool HasHoldModifier =
21864 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21865
21866 // Keep track of the mappable components and base declarations in this clause.
21867 // Each entry in the list is going to have a list of components associated. We
21868 // record each set of the components so that we can build the clause later on.
21869 // In the end we should have the same amount of declarations and component
21870 // lists.
21871
21872 for (Expr *RE : MVLI.VarList) {
21873 assert(RE && "Null expr in omp to/from/map clause");
21874 SourceLocation ELoc = RE->getExprLoc();
21875
21876 // Find the current unresolved mapper expression.
21877 if (UpdateUMIt && UMIt != UMEnd) {
21878 UMIt++;
21879 assert(
21880 UMIt != UMEnd &&
21881 "Expect the size of UnresolvedMappers to match with that of VarList");
21882 }
21883 UpdateUMIt = true;
21884 if (UMIt != UMEnd)
21885 UnresolvedMapper = *UMIt;
21886
21887 const Expr *VE = RE->IgnoreParenLValueCasts();
21888
21889 if (VE->isValueDependent() || VE->isTypeDependent() ||
21892 // Try to find the associated user-defined mapper.
21894 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21895 VE->getType().getCanonicalType(), UnresolvedMapper);
21896 if (ER.isInvalid())
21897 continue;
21898 MVLI.UDMapperList.push_back(ER.get());
21899 // We can only analyze this information once the missing information is
21900 // resolved.
21901 MVLI.ProcessedVarList.push_back(RE);
21902 continue;
21903 }
21904
21906
21907 if (!RE->isLValue()) {
21908 if (SemaRef.getLangOpts().OpenMP < 50) {
21909 SemaRef.Diag(
21910 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21911 << RE->getSourceRange();
21912 } else {
21913 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21914 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
21915 }
21916 continue;
21917 }
21918
21920 ValueDecl *CurDeclaration = nullptr;
21921
21922 // Obtain the array or member expression bases if required. Also, fill the
21923 // components array with all the components identified in the process.
21924 const Expr *BE =
21925 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21926 DSAS->getCurrentDirective(), NoDiagnose);
21927 if (!BE)
21928 continue;
21929
21930 assert(!CurComponents.empty() &&
21931 "Invalid mappable expression information.");
21932
21933 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21934 // Add store "this" pointer to class in DSAStackTy for future checking
21935 DSAS->addMappedClassesQualTypes(TE->getType());
21936 // Try to find the associated user-defined mapper.
21938 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21939 VE->getType().getCanonicalType(), UnresolvedMapper);
21940 if (ER.isInvalid())
21941 continue;
21942 MVLI.UDMapperList.push_back(ER.get());
21943 // Skip restriction checking for variable or field declarations
21944 MVLI.ProcessedVarList.push_back(RE);
21945 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21946 MVLI.VarComponents.back().append(CurComponents.begin(),
21947 CurComponents.end());
21948 MVLI.VarBaseDeclarations.push_back(nullptr);
21949 continue;
21950 }
21951
21952 // For the following checks, we rely on the base declaration which is
21953 // expected to be associated with the last component. The declaration is
21954 // expected to be a variable or a field (if 'this' is being mapped).
21955 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21956 assert(CurDeclaration && "Null decl on map clause.");
21957 assert(
21958 CurDeclaration->isCanonicalDecl() &&
21959 "Expecting components to have associated only canonical declarations.");
21960
21961 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21962 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21963
21964 assert((VD || FD) && "Only variables or fields are expected here!");
21965 (void)FD;
21966
21967 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21968 // threadprivate variables cannot appear in a map clause.
21969 // OpenMP 4.5 [2.10.5, target update Construct]
21970 // threadprivate variables cannot appear in a from clause.
21971 if (VD && DSAS->isThreadPrivate(VD)) {
21972 if (NoDiagnose)
21973 continue;
21974 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21975 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21977 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21978 continue;
21979 }
21980
21981 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21982 // A list item cannot appear in both a map clause and a data-sharing
21983 // attribute clause on the same construct.
21984
21985 // Check conflicts with other map clause expressions. We check the conflicts
21986 // with the current construct separately from the enclosing data
21987 // environment, because the restrictions are different. We only have to
21988 // check conflicts across regions for the map clauses.
21989 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21990 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21991 break;
21992 if (CKind == OMPC_map &&
21993 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21994 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21995 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21996 break;
21997
21998 // OpenMP 4.5 [2.10.5, target update Construct]
21999 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22000 // If the type of a list item is a reference to a type T then the type will
22001 // be considered to be T for all purposes of this clause.
22002 auto I = llvm::find_if(
22003 CurComponents,
22005 return MC.getAssociatedDeclaration();
22006 });
22007 assert(I != CurComponents.end() && "Null decl on map clause.");
22008 (void)I;
22009 QualType Type;
22010 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
22011 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
22012 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
22013 if (ASE) {
22014 Type = ASE->getType().getNonReferenceType();
22015 } else if (OASE) {
22016 QualType BaseType =
22018 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22019 Type = ATy->getElementType();
22020 else
22021 Type = BaseType->getPointeeType();
22022 Type = Type.getNonReferenceType();
22023 } else if (OAShE) {
22024 Type = OAShE->getBase()->getType()->getPointeeType();
22025 } else {
22026 Type = VE->getType();
22027 }
22028
22029 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
22030 // A list item in a to or from clause must have a mappable type.
22031 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
22032 // A list item must have a mappable type.
22033 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
22034 DSAS, Type, /*FullCheck=*/true))
22035 continue;
22036
22037 if (CKind == OMPC_map) {
22038 // target enter data
22039 // OpenMP [2.10.2, Restrictions, p. 99]
22040 // A map-type must be specified in all map clauses and must be either
22041 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
22042 // no map type is present.
22043 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
22044 if (DKind == OMPD_target_enter_data &&
22045 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
22046 SemaRef.getLangOpts().OpenMP >= 52)) {
22047 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22048 << (IsMapTypeImplicit ? 1 : 0)
22049 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22050 << getOpenMPDirectiveName(DKind, OMPVersion);
22051 continue;
22052 }
22053
22054 // target exit_data
22055 // OpenMP [2.10.3, Restrictions, p. 102]
22056 // A map-type must be specified in all map clauses and must be either
22057 // from, release, or delete. Starting with OpenMP 5.2 the default map
22058 // type is `from` if no map type is present.
22059 if (DKind == OMPD_target_exit_data &&
22060 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
22061 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
22062 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22063 << (IsMapTypeImplicit ? 1 : 0)
22064 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22065 << getOpenMPDirectiveName(DKind, OMPVersion);
22066 continue;
22067 }
22068
22069 // The 'ompx_hold' modifier is specifically intended to be used on a
22070 // 'target' or 'target data' directive to prevent data from being unmapped
22071 // during the associated statement. It is not permitted on a 'target
22072 // enter data' or 'target exit data' directive, which have no associated
22073 // statement.
22074 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
22075 HasHoldModifier) {
22076 SemaRef.Diag(StartLoc,
22077 diag::err_omp_invalid_map_type_modifier_for_directive)
22079 OMPC_MAP_MODIFIER_ompx_hold)
22080 << getOpenMPDirectiveName(DKind, OMPVersion);
22081 continue;
22082 }
22083
22084 // target, target data
22085 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
22086 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
22087 // A map-type in a map clause must be to, from, tofrom or alloc
22088 if ((DKind == OMPD_target_data ||
22090 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
22091 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
22092 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
22093 << (IsMapTypeImplicit ? 1 : 0)
22094 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
22095 << getOpenMPDirectiveName(DKind, OMPVersion);
22096 continue;
22097 }
22098
22099 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
22100 // A list item cannot appear in both a map clause and a data-sharing
22101 // attribute clause on the same construct
22102 //
22103 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
22104 // A list item cannot appear in both a map clause and a data-sharing
22105 // attribute clause on the same construct unless the construct is a
22106 // combined construct.
22107 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
22109 DKind == OMPD_target)) {
22110 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
22111 if (isOpenMPPrivate(DVar.CKind)) {
22112 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22113 << getOpenMPClauseNameForDiag(DVar.CKind)
22114 << getOpenMPClauseNameForDiag(OMPC_map)
22115 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
22116 OMPVersion);
22117 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
22118 continue;
22119 }
22120 }
22121 }
22122
22123 // Try to find the associated user-defined mapper.
22125 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
22126 Type.getCanonicalType(), UnresolvedMapper);
22127 if (ER.isInvalid())
22128 continue;
22129
22130 // If no user-defined mapper is found, we need to create an implicit one for
22131 // arrays/array-sections on structs that have members that have
22132 // user-defined mappers. This is needed to ensure that the mapper for the
22133 // member is invoked when mapping each element of the array/array-section.
22134 if (!ER.get()) {
22135 QualType BaseType;
22136
22137 if (isa<ArraySectionExpr>(VE)) {
22138 BaseType = VE->getType().getCanonicalType();
22139 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
22140 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
22141 QualType BType =
22143 QualType ElemType;
22144 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
22145 ElemType = ATy->getElementType();
22146 else
22147 ElemType = BType->getPointeeType();
22148 BaseType = ElemType.getCanonicalType();
22149 }
22150 } else if (VE->getType()->isArrayType()) {
22151 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
22152 const QualType ElemType = AT->getElementType();
22153 BaseType = ElemType.getCanonicalType();
22154 }
22155
22156 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
22157 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
22158 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
22159 }
22160 }
22161 MVLI.UDMapperList.push_back(ER.get());
22162
22163 // Save the current expression.
22164 MVLI.ProcessedVarList.push_back(RE);
22165
22166 // Store the components in the stack so that they can be used to check
22167 // against other clauses later on.
22168 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
22169 /*WhereFoundClauseKind=*/OMPC_map);
22170
22171 // Save the components and declaration to create the clause. For purposes of
22172 // the clause creation, any component list that has base 'this' uses
22173 // null as base declaration.
22174 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22175 MVLI.VarComponents.back().append(CurComponents.begin(),
22176 CurComponents.end());
22177 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
22178 : CurDeclaration);
22179 }
22180}
22181
22183 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
22184 ArrayRef<SourceLocation> MapTypeModifiersLoc,
22185 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22186 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
22187 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22188 const OMPVarListLocTy &Locs, bool NoDiagnose,
22189 ArrayRef<Expr *> UnresolvedMappers) {
22190 OpenMPMapModifierKind Modifiers[] = {
22196
22197 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
22198 BuiltinType::OMPIterator))
22199 Diag(IteratorModifier->getExprLoc(),
22200 diag::err_omp_map_modifier_not_iterator);
22201
22202 // Process map-type-modifiers, flag errors for duplicate modifiers.
22203 unsigned Count = 0;
22204 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
22205 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
22206 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
22207 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
22208 continue;
22209 }
22210 assert(Count < NumberOfOMPMapClauseModifiers &&
22211 "Modifiers exceed the allowed number of map type modifiers");
22212 Modifiers[Count] = MapTypeModifiers[I];
22213 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
22214 ++Count;
22215 }
22216
22217 MappableVarListInfo MVLI(VarList);
22219 MapperIdScopeSpec, MapperId, UnresolvedMappers,
22220 MapType, Modifiers, IsMapTypeImplicit,
22221 NoDiagnose);
22222
22223 // We need to produce a map clause even if we don't have variables so that
22224 // other diagnostics related with non-existing map clauses are accurate.
22225 return OMPMapClause::Create(
22226 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22227 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
22228 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
22229 MapperId, MapType, IsMapTypeImplicit, MapLoc);
22230}
22231
22234 assert(ParsedType.isUsable());
22235
22236 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
22237 if (ReductionType.isNull())
22238 return QualType();
22239
22240 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
22241 // A type name in a declare reduction directive cannot be a function type, an
22242 // array type, a reference type, or a type qualified with const, volatile or
22243 // restrict.
22244 if (ReductionType.hasQualifiers()) {
22245 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
22246 return QualType();
22247 }
22248
22249 if (ReductionType->isFunctionType()) {
22250 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
22251 return QualType();
22252 }
22253 if (ReductionType->isReferenceType()) {
22254 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
22255 return QualType();
22256 }
22257 if (ReductionType->isArrayType()) {
22258 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
22259 return QualType();
22260 }
22261 return ReductionType;
22262}
22263
22266 Scope *S, DeclContext *DC, DeclarationName Name,
22267 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
22268 AccessSpecifier AS, Decl *PrevDeclInScope) {
22270 Decls.reserve(ReductionTypes.size());
22271
22272 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22275 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
22276 // A reduction-identifier may not be re-declared in the current scope for the
22277 // same type or for a type that is compatible according to the base language
22278 // rules.
22279 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22280 OMPDeclareReductionDecl *PrevDRD = nullptr;
22281 bool InCompoundScope = true;
22282 if (S != nullptr) {
22283 // Find previous declaration with the same name not referenced in other
22284 // declarations.
22286 InCompoundScope =
22287 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22288 SemaRef.LookupName(Lookup, S);
22289 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22290 /*AllowInlineNamespace=*/false);
22291 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
22292 LookupResult::Filter Filter = Lookup.makeFilter();
22293 while (Filter.hasNext()) {
22294 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
22295 if (InCompoundScope) {
22296 UsedAsPrevious.try_emplace(PrevDecl, false);
22297 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
22298 UsedAsPrevious[D] = true;
22299 }
22300 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22301 PrevDecl->getLocation();
22302 }
22303 Filter.done();
22304 if (InCompoundScope) {
22305 for (const auto &PrevData : UsedAsPrevious) {
22306 if (!PrevData.second) {
22307 PrevDRD = PrevData.first;
22308 break;
22309 }
22310 }
22311 }
22312 } else if (PrevDeclInScope != nullptr) {
22313 auto *PrevDRDInScope = PrevDRD =
22314 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
22315 do {
22316 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
22317 PrevDRDInScope->getLocation();
22318 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
22319 } while (PrevDRDInScope != nullptr);
22320 }
22321 for (const auto &TyData : ReductionTypes) {
22322 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
22323 bool Invalid = false;
22324 if (I != PreviousRedeclTypes.end()) {
22325 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
22326 << TyData.first;
22327 Diag(I->second, diag::note_previous_definition);
22328 Invalid = true;
22329 }
22330 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
22332 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
22333 DC->addDecl(DRD);
22334 DRD->setAccess(AS);
22335 Decls.push_back(DRD);
22336 if (Invalid)
22337 DRD->setInvalidDecl();
22338 else
22339 PrevDRD = DRD;
22340 }
22341
22342 return DeclGroupPtrTy::make(
22343 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
22344}
22345
22347 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22348
22349 // Enter new function scope.
22353
22354 if (S != nullptr)
22355 SemaRef.PushDeclContext(S, DRD);
22356 else
22357 SemaRef.CurContext = DRD;
22358
22361
22362 QualType ReductionType = DRD->getType();
22363 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
22364 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
22365 // uses semantics of argument handles by value, but it should be passed by
22366 // reference. C lang does not support references, so pass all parameters as
22367 // pointers.
22368 // Create 'T omp_in;' variable.
22369 VarDecl *OmpInParm =
22370 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
22371 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
22372 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
22373 // uses semantics of argument handles by value, but it should be passed by
22374 // reference. C lang does not support references, so pass all parameters as
22375 // pointers.
22376 // Create 'T omp_out;' variable.
22377 VarDecl *OmpOutParm =
22378 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
22379 if (S != nullptr) {
22380 SemaRef.PushOnScopeChains(OmpInParm, S);
22381 SemaRef.PushOnScopeChains(OmpOutParm, S);
22382 } else {
22383 DRD->addDecl(OmpInParm);
22384 DRD->addDecl(OmpOutParm);
22385 }
22386 Expr *InE =
22387 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
22388 Expr *OutE =
22389 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
22390 DRD->setCombinerData(InE, OutE);
22391}
22392
22394 Expr *Combiner) {
22395 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22398
22401
22402 if (Combiner != nullptr)
22403 DRD->setCombiner(Combiner);
22404 else
22405 DRD->setInvalidDecl();
22406}
22407
22409 Decl *D) {
22410 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22411
22412 // Enter new function scope.
22415
22416 if (S != nullptr)
22417 SemaRef.PushDeclContext(S, DRD);
22418 else
22419 SemaRef.CurContext = DRD;
22420
22423
22424 QualType ReductionType = DRD->getType();
22425 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
22426 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
22427 // uses semantics of argument handles by value, but it should be passed by
22428 // reference. C lang does not support references, so pass all parameters as
22429 // pointers.
22430 // Create 'T omp_priv;' variable.
22431 VarDecl *OmpPrivParm =
22432 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
22433 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
22434 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
22435 // uses semantics of argument handles by value, but it should be passed by
22436 // reference. C lang does not support references, so pass all parameters as
22437 // pointers.
22438 // Create 'T omp_orig;' variable.
22439 VarDecl *OmpOrigParm =
22440 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
22441 if (S != nullptr) {
22442 SemaRef.PushOnScopeChains(OmpPrivParm, S);
22443 SemaRef.PushOnScopeChains(OmpOrigParm, S);
22444 } else {
22445 DRD->addDecl(OmpPrivParm);
22446 DRD->addDecl(OmpOrigParm);
22447 }
22448 Expr *OrigE =
22449 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
22450 Expr *PrivE =
22451 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
22452 DRD->setInitializerData(OrigE, PrivE);
22453 return OmpPrivParm;
22454}
22455
22457 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
22458 auto *DRD = cast<OMPDeclareReductionDecl>(D);
22461
22464
22465 if (Initializer != nullptr) {
22466 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
22467 } else if (OmpPrivParm->hasInit()) {
22468 DRD->setInitializer(OmpPrivParm->getInit(),
22469 OmpPrivParm->isDirectInit()
22472 } else {
22473 DRD->setInvalidDecl();
22474 }
22475}
22476
22478 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
22479 for (Decl *D : DeclReductions.get()) {
22480 if (IsValid) {
22481 if (S)
22482 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
22483 /*AddToContext=*/false);
22484 } else {
22485 D->setInvalidDecl();
22486 }
22487 }
22488 return DeclReductions;
22489}
22490
22492 Declarator &D) {
22494 QualType T = TInfo->getType();
22495 if (D.isInvalidType())
22496 return true;
22497
22498 if (getLangOpts().CPlusPlus) {
22499 // Check that there are no default arguments (C++ only).
22501 }
22502
22503 return SemaRef.CreateParsedType(T, TInfo);
22504}
22505
22508 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
22509
22511 assert(!MapperType.isNull() && "Expect valid mapper type");
22512
22513 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22514 // The type must be of struct, union or class type in C and C++
22515 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
22516 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
22517 return QualType();
22518 }
22519 return MapperType;
22520}
22521
22523 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
22525 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
22526 LookupResult Lookup(SemaRef, Name, SourceLocation(),
22529 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22530 // A mapper-identifier may not be redeclared in the current scope for the
22531 // same type or for a type that is compatible according to the base language
22532 // rules.
22533 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
22534 OMPDeclareMapperDecl *PrevDMD = nullptr;
22535 bool InCompoundScope = true;
22536 if (S != nullptr) {
22537 // Find previous declaration with the same name not referenced in other
22538 // declarations.
22540 InCompoundScope =
22541 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
22542 SemaRef.LookupName(Lookup, S);
22543 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
22544 /*AllowInlineNamespace=*/false);
22545 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
22546 LookupResult::Filter Filter = Lookup.makeFilter();
22547 while (Filter.hasNext()) {
22548 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
22549 if (InCompoundScope) {
22550 UsedAsPrevious.try_emplace(PrevDecl, false);
22551 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
22552 UsedAsPrevious[D] = true;
22553 }
22554 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
22555 PrevDecl->getLocation();
22556 }
22557 Filter.done();
22558 if (InCompoundScope) {
22559 for (const auto &PrevData : UsedAsPrevious) {
22560 if (!PrevData.second) {
22561 PrevDMD = PrevData.first;
22562 break;
22563 }
22564 }
22565 }
22566 } else if (PrevDeclInScope) {
22567 auto *PrevDMDInScope = PrevDMD =
22568 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
22569 do {
22570 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
22571 PrevDMDInScope->getLocation();
22572 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
22573 } while (PrevDMDInScope != nullptr);
22574 }
22575 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
22576 bool Invalid = false;
22577 if (I != PreviousRedeclTypes.end()) {
22578 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
22579 << MapperType << Name;
22580 Diag(I->second, diag::note_previous_definition);
22581 Invalid = true;
22582 }
22583 // Build expressions for implicit maps of data members with 'default'
22584 // mappers.
22585 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
22586 if (getLangOpts().OpenMP >= 50)
22588 ClausesWithImplicit);
22589 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
22590 MapperType, VN, ClausesWithImplicit,
22591 PrevDMD);
22592 if (S)
22593 SemaRef.PushOnScopeChains(DMD, S);
22594 else
22595 DC->addDecl(DMD);
22596 DMD->setAccess(AS);
22597 if (Invalid)
22598 DMD->setInvalidDecl();
22599
22600 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22601 VD->setDeclContext(DMD);
22602 VD->setLexicalDeclContext(DMD);
22603 DMD->addDecl(VD);
22604 DMD->setMapperVarRef(MapperVarRef);
22605
22607}
22608
22610 Scope *S, QualType MapperType, SourceLocation StartLoc,
22611 DeclarationName VN) {
22612 TypeSourceInfo *TInfo =
22613 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
22614 auto *VD = VarDecl::Create(
22615 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
22616 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
22617 if (S)
22618 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
22619 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
22620 DSAStack->addDeclareMapperVarRef(E);
22621 return E;
22622}
22623
22625 if (DSAStack->getDeclareMapperVarRef())
22626 DSAStack->addIteratorVarDecl(VD);
22627}
22628
22630 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22631 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
22632 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
22633 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
22634 return true;
22636 return true;
22637 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22638 return true;
22639 return false;
22640 }
22641 return true;
22642}
22643
22645 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22646 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22647}
22648
22650 SourceLocation StartLoc,
22651 SourceLocation LParenLoc,
22652 SourceLocation EndLoc) {
22653 if (VarList.empty())
22654 return nullptr;
22655
22656 for (Expr *ValExpr : VarList) {
22657 // OpenMP [teams Constrcut, Restrictions]
22658 // The num_teams expression must evaluate to a positive integer value.
22659 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
22660 /*StrictlyPositive=*/true))
22661 return nullptr;
22662 }
22663
22664 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22666 DKind, OMPC_num_teams, getLangOpts().OpenMP);
22667 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22668 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22669 LParenLoc, EndLoc, VarList,
22670 /*PreInit=*/nullptr);
22671
22672 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22674 for (Expr *ValExpr : VarList) {
22675 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22676 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22677 Vars.push_back(ValExpr);
22678 }
22679
22680 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22681 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22682 LParenLoc, EndLoc, Vars, PreInit);
22683}
22684
22686 SourceLocation StartLoc,
22687 SourceLocation LParenLoc,
22688 SourceLocation EndLoc) {
22689 if (VarList.empty())
22690 return nullptr;
22691
22692 for (Expr *ValExpr : VarList) {
22693 // OpenMP [teams Constrcut, Restrictions]
22694 // The thread_limit expression must evaluate to a positive integer value.
22695 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
22696 /*StrictlyPositive=*/true))
22697 return nullptr;
22698 }
22699
22700 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22702 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
22703 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22704 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
22705 StartLoc, LParenLoc, EndLoc, VarList,
22706 /*PreInit=*/nullptr);
22707
22708 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22710 for (Expr *ValExpr : VarList) {
22711 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22712 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22713 Vars.push_back(ValExpr);
22714 }
22715
22716 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22717 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
22718 LParenLoc, EndLoc, Vars, PreInit);
22719}
22720
22722 SourceLocation StartLoc,
22723 SourceLocation LParenLoc,
22724 SourceLocation EndLoc) {
22725 Expr *ValExpr = Priority;
22726 Stmt *HelperValStmt = nullptr;
22727 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22728
22729 // OpenMP [2.9.1, task Constrcut]
22730 // The priority-value is a non-negative numerical scalar expression.
22732 ValExpr, SemaRef, OMPC_priority,
22733 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22734 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22735 return nullptr;
22736
22737 return new (getASTContext()) OMPPriorityClause(
22738 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22739}
22740
22742 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22743 SourceLocation StartLoc, SourceLocation LParenLoc,
22744 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22745 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22746 "Unexpected grainsize modifier in OpenMP < 51.");
22747
22748 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22749 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22751 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22752 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
22753 return nullptr;
22754 }
22755
22756 Expr *ValExpr = Grainsize;
22757 Stmt *HelperValStmt = nullptr;
22758 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22759
22760 // OpenMP [2.9.2, taskloop Constrcut]
22761 // The parameter of the grainsize clause must be a positive integer
22762 // expression.
22763 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22764 /*StrictlyPositive=*/true,
22765 /*BuildCapture=*/true,
22766 DSAStack->getCurrentDirective(),
22767 &CaptureRegion, &HelperValStmt))
22768 return nullptr;
22769
22770 return new (getASTContext())
22771 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22772 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22773}
22774
22776 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22777 SourceLocation StartLoc, SourceLocation LParenLoc,
22778 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22779 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22780 "Unexpected num_tasks modifier in OpenMP < 51.");
22781
22782 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22783 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22785 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22786 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
22787 return nullptr;
22788 }
22789
22790 Expr *ValExpr = NumTasks;
22791 Stmt *HelperValStmt = nullptr;
22792 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22793
22794 // OpenMP [2.9.2, taskloop Constrcut]
22795 // The parameter of the num_tasks clause must be a positive integer
22796 // expression.
22798 ValExpr, SemaRef, OMPC_num_tasks,
22799 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22800 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22801 return nullptr;
22802
22803 return new (getASTContext())
22804 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22805 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22806}
22807
22809 SourceLocation StartLoc,
22810 SourceLocation LParenLoc,
22811 SourceLocation EndLoc) {
22812 // OpenMP [2.13.2, critical construct, Description]
22813 // ... where hint-expression is an integer constant expression that evaluates
22814 // to a valid lock hint.
22815 ExprResult HintExpr =
22816 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22817 if (HintExpr.isInvalid())
22818 return nullptr;
22819 return new (getASTContext())
22820 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22821}
22822
22823/// Tries to find omp_event_handle_t type.
22825 DSAStackTy *Stack) {
22826 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22827 if (!OMPEventHandleT.isNull())
22828 return true;
22829 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22830 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22831 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22832 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22833 return false;
22834 }
22835 Stack->setOMPEventHandleT(PT.get());
22836 return true;
22837}
22838
22840 SourceLocation StartLoc,
22841 SourceLocation LParenLoc,
22842 SourceLocation EndLoc) {
22843 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22844 !Evt->isInstantiationDependent() &&
22847 return nullptr;
22848 // OpenMP 5.0, 2.10.1 task Construct.
22849 // event-handle is a variable of the omp_event_handle_t type.
22850 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22851 if (!Ref) {
22852 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22853 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22854 return nullptr;
22855 }
22856 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22857 if (!VD) {
22858 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22859 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22860 return nullptr;
22861 }
22862 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22863 VD->getType()) ||
22864 VD->getType().isConstant(getASTContext())) {
22865 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22866 << "omp_event_handle_t" << 1 << VD->getType()
22867 << Evt->getSourceRange();
22868 return nullptr;
22869 }
22870 // OpenMP 5.0, 2.10.1 task Construct
22871 // [detach clause]... The event-handle will be considered as if it was
22872 // specified on a firstprivate clause.
22873 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22874 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22875 DVar.RefExpr) {
22876 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22877 << getOpenMPClauseNameForDiag(DVar.CKind)
22878 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
22880 return nullptr;
22881 }
22882 }
22883
22884 return new (getASTContext())
22885 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22886}
22887
22889 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22890 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22891 SourceLocation EndLoc) {
22892 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22893 std::string Values;
22894 Values += "'";
22895 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22896 Values += "'";
22897 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22898 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
22899 return nullptr;
22900 }
22901 Expr *ValExpr = ChunkSize;
22902 Stmt *HelperValStmt = nullptr;
22903 if (ChunkSize) {
22904 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22905 !ChunkSize->isInstantiationDependent() &&
22906 !ChunkSize->containsUnexpandedParameterPack()) {
22907 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22908 ExprResult Val =
22909 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22910 if (Val.isInvalid())
22911 return nullptr;
22912
22913 ValExpr = Val.get();
22914
22915 // OpenMP [2.7.1, Restrictions]
22916 // chunk_size must be a loop invariant integer expression with a positive
22917 // value.
22918 if (std::optional<llvm::APSInt> Result =
22920 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22921 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22922 << "dist_schedule" << /*strictly positive*/ 1
22923 << ChunkSize->getSourceRange();
22924 return nullptr;
22925 }
22927 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22928 getLangOpts().OpenMP) != OMPD_unknown &&
22930 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22931 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22932 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22933 HelperValStmt = buildPreInits(getASTContext(), Captures);
22934 }
22935 }
22936 }
22937
22938 return new (getASTContext())
22939 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22940 Kind, ValExpr, HelperValStmt);
22941}
22942
22945 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22946 SourceLocation KindLoc, SourceLocation EndLoc) {
22947 if (getLangOpts().OpenMP < 50) {
22948 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22949 Kind != OMPC_DEFAULTMAP_scalar) {
22950 std::string Value;
22952 Value += "'";
22953 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22954 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22955 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22956 Loc = MLoc;
22957 } else {
22958 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22959 OMPC_DEFAULTMAP_scalar);
22960 Loc = KindLoc;
22961 }
22962 Value += "'";
22963 Diag(Loc, diag::err_omp_unexpected_clause_value)
22964 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22965 return nullptr;
22966 }
22967 } else {
22968 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22969 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22970 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22971 if (!isDefaultmapKind || !isDefaultmapModifier) {
22972 StringRef KindValue = getLangOpts().OpenMP < 52
22973 ? "'scalar', 'aggregate', 'pointer'"
22974 : "'scalar', 'aggregate', 'pointer', 'all'";
22975 if (getLangOpts().OpenMP == 50) {
22976 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22977 "'firstprivate', 'none', 'default'";
22978 if (!isDefaultmapKind && isDefaultmapModifier) {
22979 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22980 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22981 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22982 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22983 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22984 } else {
22985 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22986 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22987 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22988 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22989 }
22990 } else {
22991 StringRef ModifierValue =
22992 "'alloc', 'from', 'to', 'tofrom', "
22993 "'firstprivate', 'none', 'default', 'present'";
22994 if (!isDefaultmapKind && isDefaultmapModifier) {
22995 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22996 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
22997 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22998 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22999 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23000 } else {
23001 Diag(MLoc, diag::err_omp_unexpected_clause_value)
23002 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23003 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23004 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
23005 }
23006 }
23007 return nullptr;
23008 }
23009
23010 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
23011 // At most one defaultmap clause for each category can appear on the
23012 // directive.
23013 if (DSAStack->checkDefaultmapCategory(Kind)) {
23014 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
23015 return nullptr;
23016 }
23017 }
23018 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
23019 // Variable category is not specified - mark all categories.
23020 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
23021 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
23022 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
23023 } else {
23024 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
23025 }
23026
23027 return new (getASTContext())
23028 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
23029}
23030
23033 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
23034 if (!CurLexicalContext->isFileContext() &&
23035 !CurLexicalContext->isExternCContext() &&
23036 !CurLexicalContext->isExternCXXContext() &&
23037 !isa<CXXRecordDecl>(CurLexicalContext) &&
23038 !isa<ClassTemplateDecl>(CurLexicalContext) &&
23039 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
23040 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
23041 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
23042 return false;
23043 }
23044
23045 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23046 if (getLangOpts().HIP)
23047 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
23048
23049 DeclareTargetNesting.push_back(DTCI);
23050 return true;
23051}
23052
23055 assert(!DeclareTargetNesting.empty() &&
23056 "check isInOpenMPDeclareTargetContext() first!");
23057 return DeclareTargetNesting.pop_back_val();
23058}
23059
23062 for (auto &It : DTCI.ExplicitlyMapped)
23063 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
23064}
23065
23067 if (DeclareTargetNesting.empty())
23068 return;
23069 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23070 unsigned OMPVersion = getLangOpts().OpenMP;
23071 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
23072 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
23073}
23074
23076 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
23078 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
23079 /*ObjectType=*/QualType(),
23080 /*AllowBuiltinCreation=*/true);
23081
23082 if (Lookup.isAmbiguous())
23083 return nullptr;
23084 Lookup.suppressDiagnostics();
23085
23086 if (!Lookup.isSingleResult()) {
23087 VarOrFuncDeclFilterCCC CCC(SemaRef);
23088 if (TypoCorrection Corrected =
23089 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
23091 SemaRef.diagnoseTypo(Corrected,
23092 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
23093 << Id.getName());
23094 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
23095 return nullptr;
23096 }
23097
23098 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
23099 return nullptr;
23100 }
23101
23102 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
23103 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
23104 !isa<FunctionTemplateDecl>(ND)) {
23105 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
23106 return nullptr;
23107 }
23108 return ND;
23109}
23110
23112 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
23114 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
23115 isa<FunctionTemplateDecl>(ND)) &&
23116 "Expected variable, function or function template.");
23117
23118 if (auto *VD = dyn_cast<VarDecl>(ND)) {
23119 // Only global variables can be marked as declare target.
23120 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23121 !VD->isStaticDataMember()) {
23122 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
23123 << VD->getNameAsString();
23124 return;
23125 }
23126 }
23127 // Diagnose marking after use as it may lead to incorrect diagnosis and
23128 // codegen.
23129 if (getLangOpts().OpenMP >= 50 &&
23130 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
23131 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
23132
23133 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
23134 if (getLangOpts().HIP)
23135 Diag(Loc, diag::warn_hip_omp_target_directives);
23136
23137 // Explicit declare target lists have precedence.
23138 const unsigned Level = -1;
23139
23140 auto *VD = cast<ValueDecl>(ND);
23141 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23142 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23143 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
23144 (*ActiveAttr)->getLevel() == Level) {
23145 Diag(Loc, diag::err_omp_device_type_mismatch)
23146 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
23147 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
23148 (*ActiveAttr)->getDevType());
23149 return;
23150 }
23151 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
23152 (*ActiveAttr)->getLevel() == Level) {
23153 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
23154 return;
23155 }
23156
23157 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
23158 return;
23159
23160 Expr *IndirectE = nullptr;
23161 bool IsIndirect = false;
23162 if (DTCI.Indirect) {
23163 IndirectE = *DTCI.Indirect;
23164 if (!IndirectE)
23165 IsIndirect = true;
23166 }
23167 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23168 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
23169 SourceRange(Loc, Loc));
23170 ND->addAttr(A);
23171 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23172 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
23174 if (auto *VD = dyn_cast<VarDecl>(ND);
23175 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
23176 VD->hasGlobalStorage())
23178}
23179
23181 Sema &SemaRef, Decl *D) {
23182 if (!D || !isa<VarDecl>(D))
23183 return;
23184 auto *VD = cast<VarDecl>(D);
23185 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
23186 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
23187 if (SemaRef.LangOpts.OpenMP >= 50 &&
23188 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
23189 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
23190 VD->hasGlobalStorage()) {
23191 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
23192 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
23193 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
23194 // If a lambda declaration and definition appears between a
23195 // declare target directive and the matching end declare target
23196 // directive, all variables that are captured by the lambda
23197 // expression must also appear in a to clause.
23198 SemaRef.Diag(VD->getLocation(),
23199 diag::err_omp_lambda_capture_in_declare_target_not_to);
23200 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
23201 << VD << 0 << SR;
23202 return;
23203 }
23204 }
23205 if (MapTy)
23206 return;
23207 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
23208 SemaRef.Diag(SL, diag::note_used_here) << SR;
23209}
23210
23212 Sema &SemaRef, DSAStackTy *Stack,
23213 ValueDecl *VD) {
23214 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
23215 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
23216 /*FullCheck=*/false);
23217}
23218
23220 SourceLocation IdLoc) {
23221 if (!D || D->isInvalidDecl())
23222 return;
23224 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
23225 if (auto *VD = dyn_cast<VarDecl>(D)) {
23226 // Only global variables can be marked as declare target.
23227 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
23228 !VD->isStaticDataMember())
23229 return;
23230 // 2.10.6: threadprivate variable cannot appear in a declare target
23231 // directive.
23232 if (DSAStack->isThreadPrivate(VD)) {
23233 Diag(SL, diag::err_omp_threadprivate_in_target);
23234 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
23235 return;
23236 }
23237 }
23238 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
23239 D = FTD->getTemplatedDecl();
23240 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
23241 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
23242 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
23243 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
23244 Diag(IdLoc, diag::err_omp_function_in_link_clause);
23245 Diag(FD->getLocation(), diag::note_defined_here) << FD;
23246 return;
23247 }
23248 }
23249 if (auto *VD = dyn_cast<ValueDecl>(D)) {
23250 // Problem if any with var declared with incomplete type will be reported
23251 // as normal, so no need to check it here.
23252 if ((E || !VD->getType()->isIncompleteType()) &&
23254 return;
23256 // Checking declaration inside declare target region.
23257 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
23258 isa<FunctionTemplateDecl>(D)) {
23259 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
23260 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
23261 unsigned Level = DeclareTargetNesting.size();
23262 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
23263 return;
23264 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
23265 Expr *IndirectE = nullptr;
23266 bool IsIndirect = false;
23267 if (DTCI.Indirect) {
23268 IndirectE = *DTCI.Indirect;
23269 if (!IndirectE)
23270 IsIndirect = true;
23271 }
23272 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
23273 getASTContext(),
23274 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
23275 : OMPDeclareTargetDeclAttr::MT_To,
23276 DTCI.DT, IndirectE, IsIndirect, Level,
23277 SourceRange(DTCI.Loc, DTCI.Loc));
23278 D->addAttr(A);
23279 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
23280 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
23281 }
23282 return;
23283 }
23284 }
23285 if (!E)
23286 return;
23288}
23289
23290/// This class visits every VarDecl that the initializer references and adds
23291/// OMPDeclareTargetDeclAttr to each of them.
23292class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
23293 SmallVector<VarDecl *> DeclVector;
23294 Attr *A;
23295
23296public:
23297 /// A StmtVisitor class function that visits all DeclRefExpr and adds
23298 /// OMPDeclareTargetDeclAttr to them.
23300 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
23301 VD->addAttr(A);
23302 DeclVector.push_back(VD);
23303 }
23304 }
23305 /// A function that iterates across each of the Expr's children.
23306 void VisitExpr(Expr *Ex) {
23307 for (auto *Child : Ex->children()) {
23308 Visit(Child);
23309 }
23310 }
23311 /// A function that keeps a record of all the Decls that are variables, has
23312 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
23313 /// each Decl one at a time and use the inherited 'visit' functions to look
23314 /// for DeclRefExpr.
23316 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
23317 DeclVector.push_back(cast<VarDecl>(TD));
23318 llvm::SmallDenseSet<Decl *> Visited;
23319 while (!DeclVector.empty()) {
23320 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
23321 if (!Visited.insert(TargetVarDecl).second)
23322 continue;
23323
23324 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
23325 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
23326 if (Expr *Ex = TargetVarDecl->getInit())
23327 Visit(Ex);
23328 }
23329 }
23330 }
23331};
23332
23333/// Adding OMPDeclareTargetDeclAttr to variables with static storage
23334/// duration that are referenced in the initializer expression list of
23335/// variables with static storage duration in declare target directive.
23337 GlobalDeclRefChecker Checker;
23338 if (isa<VarDecl>(TargetDecl))
23339 Checker.declareTargetInitializer(TargetDecl);
23340}
23341
23343 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23344 ArrayRef<SourceLocation> MotionModifiersLoc,
23345 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23346 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23347 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23351
23352 // Process motion-modifiers, flag errors for duplicate modifiers.
23353 unsigned Count = 0;
23354 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23355 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23356 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23357 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23358 continue;
23359 }
23360 assert(Count < NumberOfOMPMotionModifiers &&
23361 "Modifiers exceed the allowed number of motion modifiers");
23362 Modifiers[Count] = MotionModifiers[I];
23363 ModifiersLoc[Count] = MotionModifiersLoc[I];
23364 ++Count;
23365 }
23366
23367 MappableVarListInfo MVLI(VarList);
23369 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23370 if (MVLI.ProcessedVarList.empty())
23371 return nullptr;
23372
23373 return OMPToClause::Create(
23374 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23375 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23376 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23377}
23378
23380 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
23381 ArrayRef<SourceLocation> MotionModifiersLoc,
23382 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23383 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23384 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
23388
23389 // Process motion-modifiers, flag errors for duplicate modifiers.
23390 unsigned Count = 0;
23391 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
23392 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
23393 llvm::is_contained(Modifiers, MotionModifiers[I])) {
23394 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
23395 continue;
23396 }
23397 assert(Count < NumberOfOMPMotionModifiers &&
23398 "Modifiers exceed the allowed number of motion modifiers");
23399 Modifiers[Count] = MotionModifiers[I];
23400 ModifiersLoc[Count] = MotionModifiersLoc[I];
23401 ++Count;
23402 }
23403
23404 MappableVarListInfo MVLI(VarList);
23405 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
23406 MapperIdScopeSpec, MapperId, UnresolvedMappers);
23407 if (MVLI.ProcessedVarList.empty())
23408 return nullptr;
23409
23410 return OMPFromClause::Create(
23411 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23412 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
23413 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
23414}
23415
23416OMPClause *
23418 const OMPVarListLocTy &Locs) {
23419 MappableVarListInfo MVLI(VarList);
23420 SmallVector<Expr *, 8> PrivateCopies;
23422
23423 for (Expr *RefExpr : VarList) {
23424 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
23425 SourceLocation ELoc;
23426 SourceRange ERange;
23427 Expr *SimpleRefExpr = RefExpr;
23428 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23429 if (Res.second) {
23430 // It will be analyzed later.
23431 MVLI.ProcessedVarList.push_back(RefExpr);
23432 PrivateCopies.push_back(nullptr);
23433 Inits.push_back(nullptr);
23434 }
23435 ValueDecl *D = Res.first;
23436 if (!D)
23437 continue;
23438
23439 QualType Type = D->getType();
23440 Type = Type.getNonReferenceType().getUnqualifiedType();
23441
23442 auto *VD = dyn_cast<VarDecl>(D);
23443
23444 // Item should be a pointer or reference to pointer.
23445 if (!Type->isPointerType()) {
23446 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
23447 << 0 << RefExpr->getSourceRange();
23448 continue;
23449 }
23450
23451 // Build the private variable and the expression that refers to it.
23452 auto VDPrivate =
23453 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
23454 D->hasAttrs() ? &D->getAttrs() : nullptr,
23455 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23456 if (VDPrivate->isInvalidDecl())
23457 continue;
23458
23459 SemaRef.CurContext->addDecl(VDPrivate);
23460 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
23461 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
23462
23463 // Add temporary variable to initialize the private copy of the pointer.
23464 VarDecl *VDInit =
23465 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
23466 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
23467 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
23469 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
23470 /*DirectInit=*/false);
23471
23472 // If required, build a capture to implement the privatization initialized
23473 // with the current list item value.
23474 DeclRefExpr *Ref = nullptr;
23475 if (!VD)
23476 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23477 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23478 PrivateCopies.push_back(VDPrivateRefExpr);
23479 Inits.push_back(VDInitRefExpr);
23480
23481 // We need to add a data sharing attribute for this variable to make sure it
23482 // is correctly captured. A variable that shows up in a use_device_ptr has
23483 // similar properties of a first private variable.
23484 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23485
23486 // Create a mappable component for the list item. List items in this clause
23487 // only need a component.
23488 MVLI.VarBaseDeclarations.push_back(D);
23489 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23490 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
23491 /*IsNonContiguous=*/false);
23492 }
23493
23494 if (MVLI.ProcessedVarList.empty())
23495 return nullptr;
23496
23498 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
23499 MVLI.VarBaseDeclarations, MVLI.VarComponents);
23500}
23501
23502OMPClause *
23504 const OMPVarListLocTy &Locs) {
23505 MappableVarListInfo MVLI(VarList);
23506
23507 for (Expr *RefExpr : VarList) {
23508 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
23509 SourceLocation ELoc;
23510 SourceRange ERange;
23511 Expr *SimpleRefExpr = RefExpr;
23512 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23513 /*AllowArraySection=*/true);
23514 if (Res.second) {
23515 // It will be analyzed later.
23516 MVLI.ProcessedVarList.push_back(RefExpr);
23517 }
23518 ValueDecl *D = Res.first;
23519 if (!D)
23520 continue;
23521 auto *VD = dyn_cast<VarDecl>(D);
23522
23523 // If required, build a capture to implement the privatization initialized
23524 // with the current list item value.
23525 DeclRefExpr *Ref = nullptr;
23526 if (!VD)
23527 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23528 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
23529
23530 // We need to add a data sharing attribute for this variable to make sure it
23531 // is correctly captured. A variable that shows up in a use_device_addr has
23532 // similar properties of a first private variable.
23533 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
23534
23535 // Create a mappable component for the list item. List items in this clause
23536 // only need a component.
23537 MVLI.VarBaseDeclarations.push_back(D);
23538 MVLI.VarComponents.emplace_back();
23539 Expr *Component = SimpleRefExpr;
23540 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23541 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23542 Component =
23544 MVLI.VarComponents.back().emplace_back(Component, D,
23545 /*IsNonContiguous=*/false);
23546 }
23547
23548 if (MVLI.ProcessedVarList.empty())
23549 return nullptr;
23550
23552 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23553 MVLI.VarComponents);
23554}
23555
23556OMPClause *
23558 const OMPVarListLocTy &Locs) {
23559 MappableVarListInfo MVLI(VarList);
23560 for (Expr *RefExpr : VarList) {
23561 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
23562 SourceLocation ELoc;
23563 SourceRange ERange;
23564 Expr *SimpleRefExpr = RefExpr;
23565 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23566 if (Res.second) {
23567 // It will be analyzed later.
23568 MVLI.ProcessedVarList.push_back(RefExpr);
23569 }
23570 ValueDecl *D = Res.first;
23571 if (!D)
23572 continue;
23573
23574 QualType Type = D->getType();
23575 // item should be a pointer or array or reference to pointer or array
23576 if (!Type.getNonReferenceType()->isPointerType() &&
23577 !Type.getNonReferenceType()->isArrayType()) {
23578 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
23579 << 0 << RefExpr->getSourceRange();
23580 continue;
23581 }
23582
23583 // Check if the declaration in the clause does not show up in any data
23584 // sharing attribute.
23585 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23586 if (isOpenMPPrivate(DVar.CKind)) {
23587 unsigned OMPVersion = getLangOpts().OpenMP;
23588 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23589 << getOpenMPClauseNameForDiag(DVar.CKind)
23590 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
23591 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23592 OMPVersion);
23594 continue;
23595 }
23596
23597 const Expr *ConflictExpr;
23598 if (DSAStack->checkMappableExprComponentListsForDecl(
23599 D, /*CurrentRegionOnly=*/true,
23600 [&ConflictExpr](
23602 OpenMPClauseKind) -> bool {
23603 ConflictExpr = R.front().getAssociatedExpression();
23604 return true;
23605 })) {
23606 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23607 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23608 << ConflictExpr->getSourceRange();
23609 continue;
23610 }
23611
23612 // Store the components in the stack so that they can be used to check
23613 // against other clauses later on.
23615 SimpleRefExpr, D, /*IsNonContiguous=*/false);
23616 DSAStack->addMappableExpressionComponents(
23617 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
23618
23619 // Record the expression we've just processed.
23620 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
23621
23622 // Create a mappable component for the list item. List items in this clause
23623 // only need a component. We use a null declaration to signal fields in
23624 // 'this'.
23625 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23626 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23627 "Unexpected device pointer expression!");
23628 MVLI.VarBaseDeclarations.push_back(
23629 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23630 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23631 MVLI.VarComponents.back().push_back(MC);
23632 }
23633
23634 if (MVLI.ProcessedVarList.empty())
23635 return nullptr;
23636
23638 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23639 MVLI.VarComponents);
23640}
23641
23642OMPClause *
23644 const OMPVarListLocTy &Locs) {
23645 MappableVarListInfo MVLI(VarList);
23646 for (Expr *RefExpr : VarList) {
23647 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23648 SourceLocation ELoc;
23649 SourceRange ERange;
23650 Expr *SimpleRefExpr = RefExpr;
23651 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23652 /*AllowArraySection=*/true);
23653 if (Res.second) {
23654 // It will be analyzed later.
23655 MVLI.ProcessedVarList.push_back(RefExpr);
23656 }
23657 ValueDecl *D = Res.first;
23658 if (!D)
23659 continue;
23660
23661 // Check if the declaration in the clause does not show up in any data
23662 // sharing attribute.
23663 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23664 if (isOpenMPPrivate(DVar.CKind)) {
23665 unsigned OMPVersion = getLangOpts().OpenMP;
23666 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23667 << getOpenMPClauseNameForDiag(DVar.CKind)
23668 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
23669 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23670 OMPVersion);
23672 continue;
23673 }
23674
23675 const Expr *ConflictExpr;
23676 if (DSAStack->checkMappableExprComponentListsForDecl(
23677 D, /*CurrentRegionOnly=*/true,
23678 [&ConflictExpr](
23680 OpenMPClauseKind) -> bool {
23681 ConflictExpr = R.front().getAssociatedExpression();
23682 return true;
23683 })) {
23684 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23685 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23686 << ConflictExpr->getSourceRange();
23687 continue;
23688 }
23689
23690 // Store the components in the stack so that they can be used to check
23691 // against other clauses later on.
23692 Expr *Component = SimpleRefExpr;
23693 auto *VD = dyn_cast<VarDecl>(D);
23694 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23695 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23696 Component =
23699 Component, D, /*IsNonContiguous=*/false);
23700 DSAStack->addMappableExpressionComponents(
23701 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23702
23703 // Record the expression we've just processed.
23704 if (!VD && !SemaRef.CurContext->isDependentContext()) {
23705 DeclRefExpr *Ref =
23706 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23707 assert(Ref && "has_device_addr capture failed");
23708 MVLI.ProcessedVarList.push_back(Ref);
23709 } else
23710 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23711
23712 // Create a mappable component for the list item. List items in this clause
23713 // only need a component. We use a null declaration to signal fields in
23714 // 'this'.
23715 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23716 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23717 "Unexpected device pointer expression!");
23718 MVLI.VarBaseDeclarations.push_back(
23719 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23720 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23721 MVLI.VarComponents.back().push_back(MC);
23722 }
23723
23724 if (MVLI.ProcessedVarList.empty())
23725 return nullptr;
23726
23728 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23729 MVLI.VarComponents);
23730}
23731
23733 Expr *Allocator, Expr *Alignment,
23734 OpenMPAllocateClauseModifier FirstAllocateModifier,
23735 SourceLocation FirstAllocateModifierLoc,
23736 OpenMPAllocateClauseModifier SecondAllocateModifier,
23737 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
23738 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23739 SourceLocation EndLoc) {
23740 if (Allocator) {
23741 // Allocator expression is dependent - skip it for now and build the
23742 // allocator when instantiated.
23743 bool AllocDependent =
23744 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
23745 Allocator->isInstantiationDependent() ||
23746 Allocator->containsUnexpandedParameterPack());
23747 if (!AllocDependent) {
23748 // OpenMP [2.11.4 allocate Clause, Description]
23749 // allocator is an expression of omp_allocator_handle_t type.
23750 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
23751 return nullptr;
23752
23753 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
23754 if (AllocatorRes.isInvalid())
23755 return nullptr;
23756 AllocatorRes = SemaRef.PerformImplicitConversion(
23757 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23759 /*AllowExplicit=*/true);
23760 if (AllocatorRes.isInvalid())
23761 return nullptr;
23762 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
23763 }
23764 } else {
23765 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23766 // allocate clauses that appear on a target construct or on constructs in a
23767 // target region must specify an allocator expression unless a requires
23768 // directive with the dynamic_allocators clause is present in the same
23769 // compilation unit.
23770 if (getLangOpts().OpenMPIsTargetDevice &&
23771 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23772 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
23773 }
23774 if (Alignment) {
23775 bool AlignmentDependent = Alignment->isTypeDependent() ||
23776 Alignment->isValueDependent() ||
23777 Alignment->isInstantiationDependent() ||
23779 if (!AlignmentDependent) {
23780 ExprResult AlignResult =
23781 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
23782 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
23783 }
23784 }
23785 // Analyze and build list of variables.
23787 for (Expr *RefExpr : VarList) {
23788 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
23789 SourceLocation ELoc;
23790 SourceRange ERange;
23791 Expr *SimpleRefExpr = RefExpr;
23792 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23793 if (Res.second) {
23794 // It will be analyzed later.
23795 Vars.push_back(RefExpr);
23796 }
23797 ValueDecl *D = Res.first;
23798 if (!D)
23799 continue;
23800
23801 auto *VD = dyn_cast<VarDecl>(D);
23802 DeclRefExpr *Ref = nullptr;
23803 if (!VD && !SemaRef.CurContext->isDependentContext())
23804 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
23805 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
23806 ? RefExpr->IgnoreParens()
23807 : Ref);
23808 }
23809
23810 if (Vars.empty())
23811 return nullptr;
23812
23813 if (Allocator)
23814 DSAStack->addInnerAllocatorExpr(Allocator);
23815
23817 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
23818 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
23819 SecondAllocateModifierLoc, EndLoc, Vars);
23820}
23821
23823 SourceLocation StartLoc,
23824 SourceLocation LParenLoc,
23825 SourceLocation EndLoc) {
23827 for (Expr *RefExpr : VarList) {
23828 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23829 SourceLocation ELoc;
23830 SourceRange ERange;
23831 Expr *SimpleRefExpr = RefExpr;
23832 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23833 if (Res.second)
23834 // It will be analyzed later.
23835 Vars.push_back(RefExpr);
23836 ValueDecl *D = Res.first;
23837 if (!D)
23838 continue;
23839
23840 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23841 // A list-item cannot appear in more than one nontemporal clause.
23842 if (const Expr *PrevRef =
23843 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23844 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23845 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
23846 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23847 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
23848 continue;
23849 }
23850
23851 Vars.push_back(RefExpr);
23852 }
23853
23854 if (Vars.empty())
23855 return nullptr;
23856
23857 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
23858 EndLoc, Vars);
23859}
23860
23862 Stmt *AStmt,
23863 SourceLocation StartLoc,
23864 SourceLocation EndLoc) {
23865 if (!AStmt)
23866 return StmtError();
23867
23869
23870 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
23871 AStmt);
23872}
23873
23875 SourceLocation StartLoc,
23876 SourceLocation LParenLoc,
23877 SourceLocation EndLoc) {
23879 for (Expr *RefExpr : VarList) {
23880 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
23881 SourceLocation ELoc;
23882 SourceRange ERange;
23883 Expr *SimpleRefExpr = RefExpr;
23884 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23885 /*AllowArraySection=*/true);
23886 if (Res.second)
23887 // It will be analyzed later.
23888 Vars.push_back(RefExpr);
23889 ValueDecl *D = Res.first;
23890 if (!D)
23891 continue;
23892
23893 const DSAStackTy::DSAVarData DVar =
23894 DSAStack->getTopDSA(D, /*FromParent=*/true);
23895 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23896 // A list item that appears in the inclusive or exclusive clause must appear
23897 // in a reduction clause with the inscan modifier on the enclosing
23898 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23899 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23900 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23901 << RefExpr->getSourceRange();
23902
23903 if (DSAStack->getParentDirective() != OMPD_unknown)
23904 DSAStack->markDeclAsUsedInScanDirective(D);
23905 Vars.push_back(RefExpr);
23906 }
23907
23908 if (Vars.empty())
23909 return nullptr;
23910
23911 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23912 EndLoc, Vars);
23913}
23914
23916 SourceLocation StartLoc,
23917 SourceLocation LParenLoc,
23918 SourceLocation EndLoc) {
23920 for (Expr *RefExpr : VarList) {
23921 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
23922 SourceLocation ELoc;
23923 SourceRange ERange;
23924 Expr *SimpleRefExpr = RefExpr;
23925 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23926 /*AllowArraySection=*/true);
23927 if (Res.second)
23928 // It will be analyzed later.
23929 Vars.push_back(RefExpr);
23930 ValueDecl *D = Res.first;
23931 if (!D)
23932 continue;
23933
23934 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23935 DSAStackTy::DSAVarData DVar;
23936 if (ParentDirective != OMPD_unknown)
23937 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23938 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23939 // A list item that appears in the inclusive or exclusive clause must appear
23940 // in a reduction clause with the inscan modifier on the enclosing
23941 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23942 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23943 DVar.Modifier != OMPC_REDUCTION_inscan) {
23944 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23945 << RefExpr->getSourceRange();
23946 } else {
23947 DSAStack->markDeclAsUsedInScanDirective(D);
23948 }
23949 Vars.push_back(RefExpr);
23950 }
23951
23952 if (Vars.empty())
23953 return nullptr;
23954
23955 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23956 EndLoc, Vars);
23957}
23958
23959/// Tries to find omp_alloctrait_t type.
23960static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23961 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23962 if (!OMPAlloctraitT.isNull())
23963 return true;
23964 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23965 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23966 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23967 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23968 return false;
23969 }
23970 Stack->setOMPAlloctraitT(PT.get());
23971 return true;
23972}
23973
23975 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23977 ASTContext &Context = getASTContext();
23978 // OpenMP [2.12.5, target Construct]
23979 // allocator is an identifier of omp_allocator_handle_t type.
23980 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
23981 return nullptr;
23982 // OpenMP [2.12.5, target Construct]
23983 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23984 if (llvm::any_of(
23985 Data,
23986 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23987 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
23988 return nullptr;
23989 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23990 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23991 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23992 StringRef Allocator =
23993 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23994 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23995 PredefinedAllocators.insert(SemaRef.LookupSingleName(
23996 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23997 }
23998
24000 for (const UsesAllocatorsData &D : Data) {
24001 Expr *AllocatorExpr = nullptr;
24002 // Check allocator expression.
24003 if (D.Allocator->isTypeDependent()) {
24004 AllocatorExpr = D.Allocator;
24005 } else {
24006 // Traits were specified - need to assign new allocator to the specified
24007 // allocator, so it must be an lvalue.
24008 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
24009 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
24010 bool IsPredefinedAllocator = false;
24011 if (DRE) {
24012 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
24013 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
24014 IsPredefinedAllocator =
24015 AllocatorTy !=
24016 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
24017 }
24018 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
24019 QualType AllocatorExprType = AllocatorExpr->getType();
24020 bool IsTypeCompatible = IsPredefinedAllocator;
24021 IsTypeCompatible = IsTypeCompatible ||
24022 Context.hasSameUnqualifiedType(AllocatorExprType,
24023 OMPAllocatorHandleT);
24024 IsTypeCompatible =
24025 IsTypeCompatible ||
24026 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
24027 bool IsNonConstantLValue =
24028 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
24029 if (!DRE || !IsTypeCompatible ||
24030 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
24031 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
24032 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
24033 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
24034 continue;
24035 }
24036 // OpenMP [2.12.5, target Construct]
24037 // Predefined allocators appearing in a uses_allocators clause cannot have
24038 // traits specified.
24039 if (IsPredefinedAllocator && D.AllocatorTraits) {
24040 Diag(D.AllocatorTraits->getExprLoc(),
24041 diag::err_omp_predefined_allocator_with_traits)
24042 << D.AllocatorTraits->getSourceRange();
24043 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
24044 << cast<NamedDecl>(DRE->getDecl())->getName()
24045 << D.Allocator->getSourceRange();
24046 continue;
24047 }
24048 // OpenMP [2.12.5, target Construct]
24049 // Non-predefined allocators appearing in a uses_allocators clause must
24050 // have traits specified.
24051 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
24052 Diag(D.Allocator->getExprLoc(),
24053 diag::err_omp_nonpredefined_allocator_without_traits);
24054 continue;
24055 }
24056 // No allocator traits - just convert it to rvalue.
24057 if (!D.AllocatorTraits)
24058 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
24059 DSAStack->addUsesAllocatorsDecl(
24060 DRE->getDecl(),
24061 IsPredefinedAllocator
24062 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
24063 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
24064 }
24065 Expr *AllocatorTraitsExpr = nullptr;
24066 if (D.AllocatorTraits) {
24067 if (D.AllocatorTraits->isTypeDependent()) {
24068 AllocatorTraitsExpr = D.AllocatorTraits;
24069 } else {
24070 // OpenMP [2.12.5, target Construct]
24071 // Arrays that contain allocator traits that appear in a uses_allocators
24072 // clause must be constant arrays, have constant values and be defined
24073 // in the same scope as the construct in which the clause appears.
24074 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
24075 // Check that traits expr is a constant array.
24076 QualType TraitTy;
24077 if (const ArrayType *Ty =
24078 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
24079 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
24080 TraitTy = ConstArrayTy->getElementType();
24081 if (TraitTy.isNull() ||
24082 !(Context.hasSameUnqualifiedType(TraitTy,
24083 DSAStack->getOMPAlloctraitT()) ||
24084 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
24085 /*CompareUnqualified=*/true))) {
24086 Diag(D.AllocatorTraits->getExprLoc(),
24087 diag::err_omp_expected_array_alloctraits)
24088 << AllocatorTraitsExpr->getType();
24089 continue;
24090 }
24091 // Do not map by default allocator traits if it is a standalone
24092 // variable.
24093 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
24094 DSAStack->addUsesAllocatorsDecl(
24095 DRE->getDecl(),
24096 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
24097 }
24098 }
24099 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
24100 NewD.Allocator = AllocatorExpr;
24101 NewD.AllocatorTraits = AllocatorTraitsExpr;
24102 NewD.LParenLoc = D.LParenLoc;
24103 NewD.RParenLoc = D.RParenLoc;
24104 }
24105 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
24106 EndLoc, NewData);
24107}
24108
24110 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
24111 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
24113 for (Expr *RefExpr : Locators) {
24114 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
24115 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
24116 // It will be analyzed later.
24117 Vars.push_back(RefExpr);
24118 continue;
24119 }
24120
24121 SourceLocation ELoc = RefExpr->getExprLoc();
24122 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
24123
24124 if (!SimpleExpr->isLValue()) {
24125 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24126 << 1 << 0 << RefExpr->getSourceRange();
24127 continue;
24128 }
24129
24130 ExprResult Res;
24131 {
24133 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
24134 }
24135 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
24136 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
24137 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24138 << 1 << 0 << RefExpr->getSourceRange();
24139 continue;
24140 }
24141 Vars.push_back(SimpleExpr);
24142 }
24143
24144 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
24145 ColonLoc, EndLoc, Modifier, Vars);
24146}
24147
24149 SourceLocation KindLoc,
24150 SourceLocation StartLoc,
24151 SourceLocation LParenLoc,
24152 SourceLocation EndLoc) {
24153 if (Kind == OMPC_BIND_unknown) {
24154 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24155 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
24156 /*Last=*/unsigned(OMPC_BIND_unknown))
24157 << getOpenMPClauseNameForDiag(OMPC_bind);
24158 return nullptr;
24159 }
24160
24161 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
24162 LParenLoc, EndLoc);
24163}
24164
24166 SourceLocation StartLoc,
24167 SourceLocation LParenLoc,
24168 SourceLocation EndLoc) {
24169 Expr *ValExpr = Size;
24170 Stmt *HelperValStmt = nullptr;
24171
24172 // OpenMP [2.5, Restrictions]
24173 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
24174 // value.
24175 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
24176 /*StrictlyPositive=*/false))
24177 return nullptr;
24178
24179 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24181 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
24182 if (CaptureRegion != OMPD_unknown &&
24184 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24185 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24186 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24187 HelperValStmt = buildPreInits(getASTContext(), Captures);
24188 }
24189
24191 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24192}
24193
24196 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
24197 SourceLocation LParenLoc, SourceLocation EndLoc) {
24198
24199 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
24200 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
24201 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
24202 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
24203 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24204 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
24205 return nullptr;
24206 }
24207
24210 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24211 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24212 SemaRef,
24213 DepType == OMPC_DOACROSS_source ||
24214 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
24215 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
24216 VarList, DSAStack, EndLoc);
24217 Vars = VarOffset.Vars;
24218 OpsOffs = VarOffset.OpsOffs;
24219 TotalDepCount = VarOffset.TotalDepCount;
24220 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
24221 EndLoc, DepType, DepLoc, ColonLoc, Vars,
24222 TotalDepCount.getZExtValue());
24223 if (DSAStack->isParentOrderedRegion())
24224 DSAStack->addDoacrossDependClause(C, OpsOffs);
24225 return C;
24226}
24227
24229 SourceLocation StartLoc,
24230 SourceLocation LParenLoc,
24231 SourceLocation EndLoc) {
24232 return new (getASTContext())
24233 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
24234}
24235
24237 SourceLocation EndLoc) {
24238 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
24239}
24240
24242 SourceLocation LParenLoc,
24243 SourceLocation EndLoc) {
24244 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
24245}
24246
24250 switch (CK) {
24251 case OMPC_absent:
24252 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
24253 case OMPC_contains:
24254 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
24255 default:
24256 llvm_unreachable("Unexpected OpenMP clause");
24257 }
24258}
24259
24262 SourceLocation RLoc) {
24263 switch (CK) {
24264 case OMPC_no_openmp:
24265 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
24266 case OMPC_no_openmp_routines:
24267 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
24268 case OMPC_no_parallelism:
24269 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
24270 case OMPC_no_openmp_constructs:
24271 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
24272 default:
24273 llvm_unreachable("Unexpected OpenMP clause");
24274 }
24275}
24276
24278 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
24279 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
24280 Expr *Stride, SourceLocation RBLoc) {
24281 ASTContext &Context = getASTContext();
24282 if (Base->hasPlaceholderType() &&
24283 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24285 if (Result.isInvalid())
24286 return ExprError();
24287 Base = Result.get();
24288 }
24289 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
24291 if (Result.isInvalid())
24292 return ExprError();
24294 if (Result.isInvalid())
24295 return ExprError();
24296 LowerBound = Result.get();
24297 }
24298 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
24300 if (Result.isInvalid())
24301 return ExprError();
24303 if (Result.isInvalid())
24304 return ExprError();
24305 Length = Result.get();
24306 }
24307 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
24309 if (Result.isInvalid())
24310 return ExprError();
24312 if (Result.isInvalid())
24313 return ExprError();
24314 Stride = Result.get();
24315 }
24316
24317 // Build an unanalyzed expression if either operand is type-dependent.
24318 if (Base->isTypeDependent() ||
24319 (LowerBound &&
24320 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
24321 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
24322 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
24323 return new (Context) ArraySectionExpr(
24324 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
24325 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24326 }
24327
24328 // Perform default conversions.
24330 QualType ResultTy;
24331 if (OriginalTy->isAnyPointerType()) {
24332 ResultTy = OriginalTy->getPointeeType();
24333 } else if (OriginalTy->isArrayType()) {
24334 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
24335 } else {
24336 return ExprError(
24337 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
24338 << Base->getSourceRange());
24339 }
24340 // C99 6.5.2.1p1
24341 if (LowerBound) {
24342 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
24343 LowerBound);
24344 if (Res.isInvalid())
24345 return ExprError(Diag(LowerBound->getExprLoc(),
24346 diag::err_omp_typecheck_section_not_integer)
24347 << 0 << LowerBound->getSourceRange());
24348 LowerBound = Res.get();
24349
24350 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24351 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24352 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
24353 << 0 << LowerBound->getSourceRange();
24354 }
24355 if (Length) {
24356 auto Res =
24357 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
24358 if (Res.isInvalid())
24359 return ExprError(Diag(Length->getExprLoc(),
24360 diag::err_omp_typecheck_section_not_integer)
24361 << 1 << Length->getSourceRange());
24362 Length = Res.get();
24363
24364 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24365 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24366 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
24367 << 1 << Length->getSourceRange();
24368 }
24369 if (Stride) {
24370 ExprResult Res =
24372 if (Res.isInvalid())
24373 return ExprError(Diag(Stride->getExprLoc(),
24374 diag::err_omp_typecheck_section_not_integer)
24375 << 1 << Stride->getSourceRange());
24376 Stride = Res.get();
24377
24378 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
24379 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
24380 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
24381 << 1 << Stride->getSourceRange();
24382 }
24383
24384 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
24385 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
24386 // type. Note that functions are not objects, and that (in C99 parlance)
24387 // incomplete types are not object types.
24388 if (ResultTy->isFunctionType()) {
24389 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
24390 << ResultTy << Base->getSourceRange();
24391 return ExprError();
24392 }
24393
24394 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
24395 diag::err_omp_section_incomplete_type, Base))
24396 return ExprError();
24397
24398 if (LowerBound && !OriginalTy->isAnyPointerType()) {
24400 if (LowerBound->EvaluateAsInt(Result, Context)) {
24401 // OpenMP 5.0, [2.1.5 Array Sections]
24402 // The array section must be a subset of the original array.
24403 llvm::APSInt LowerBoundValue = Result.Val.getInt();
24404 if (LowerBoundValue.isNegative()) {
24405 Diag(LowerBound->getExprLoc(),
24406 diag::err_omp_section_not_subset_of_array)
24407 << LowerBound->getSourceRange();
24408 return ExprError();
24409 }
24410 }
24411 }
24412
24413 if (Length) {
24415 if (Length->EvaluateAsInt(Result, Context)) {
24416 // OpenMP 5.0, [2.1.5 Array Sections]
24417 // The length must evaluate to non-negative integers.
24418 llvm::APSInt LengthValue = Result.Val.getInt();
24419 if (LengthValue.isNegative()) {
24420 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
24421 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
24422 << Length->getSourceRange();
24423 return ExprError();
24424 }
24425 }
24426 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
24427 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
24428 !OriginalTy->isVariableArrayType()))) {
24429 // OpenMP 5.0, [2.1.5 Array Sections]
24430 // When the size of the array dimension is not known, the length must be
24431 // specified explicitly.
24432 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
24433 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
24434 return ExprError();
24435 }
24436
24437 if (Stride) {
24439 if (Stride->EvaluateAsInt(Result, Context)) {
24440 // OpenMP 5.0, [2.1.5 Array Sections]
24441 // The stride must evaluate to a positive integer.
24442 llvm::APSInt StrideValue = Result.Val.getInt();
24443 if (!StrideValue.isStrictlyPositive()) {
24444 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
24445 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
24446 << Stride->getSourceRange();
24447 return ExprError();
24448 }
24449 }
24450 }
24451
24452 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
24454 if (Result.isInvalid())
24455 return ExprError();
24456 Base = Result.get();
24457 }
24458 return new (Context) ArraySectionExpr(
24459 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
24460 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
24461}
24462
24464 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
24465 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
24466 ASTContext &Context = getASTContext();
24467 if (Base->hasPlaceholderType()) {
24469 if (Result.isInvalid())
24470 return ExprError();
24472 if (Result.isInvalid())
24473 return ExprError();
24474 Base = Result.get();
24475 }
24476 QualType BaseTy = Base->getType();
24477 // Delay analysis of the types/expressions if instantiation/specialization is
24478 // required.
24479 if (!BaseTy->isPointerType() && Base->isTypeDependent())
24480 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
24481 LParenLoc, RParenLoc, Dims, Brackets);
24482 if (!BaseTy->isPointerType() ||
24483 (!Base->isTypeDependent() &&
24484 BaseTy->getPointeeType()->isIncompleteType()))
24485 return ExprError(Diag(Base->getExprLoc(),
24486 diag::err_omp_non_pointer_type_array_shaping_base)
24487 << Base->getSourceRange());
24488
24489 SmallVector<Expr *, 4> NewDims;
24490 bool ErrorFound = false;
24491 for (Expr *Dim : Dims) {
24492 if (Dim->hasPlaceholderType()) {
24494 if (Result.isInvalid()) {
24495 ErrorFound = true;
24496 continue;
24497 }
24499 if (Result.isInvalid()) {
24500 ErrorFound = true;
24501 continue;
24502 }
24503 Dim = Result.get();
24504 }
24505 if (!Dim->isTypeDependent()) {
24508 if (Result.isInvalid()) {
24509 ErrorFound = true;
24510 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
24511 << Dim->getSourceRange();
24512 continue;
24513 }
24514 Dim = Result.get();
24515 Expr::EvalResult EvResult;
24516 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
24517 // OpenMP 5.0, [2.1.4 Array Shaping]
24518 // Each si is an integral type expression that must evaluate to a
24519 // positive integer.
24520 llvm::APSInt Value = EvResult.Val.getInt();
24521 if (!Value.isStrictlyPositive()) {
24522 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
24523 << toString(Value, /*Radix=*/10, /*Signed=*/true)
24524 << Dim->getSourceRange();
24525 ErrorFound = true;
24526 continue;
24527 }
24528 }
24529 }
24530 NewDims.push_back(Dim);
24531 }
24532 if (ErrorFound)
24533 return ExprError();
24534 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
24535 LParenLoc, RParenLoc, NewDims, Brackets);
24536}
24537
24539 SourceLocation IteratorKwLoc,
24540 SourceLocation LLoc,
24541 SourceLocation RLoc,
24543 ASTContext &Context = getASTContext();
24545 bool IsCorrect = true;
24546 for (const OMPIteratorData &D : Data) {
24547 TypeSourceInfo *TInfo = nullptr;
24548 SourceLocation StartLoc;
24549 QualType DeclTy;
24550 if (!D.Type.getAsOpaquePtr()) {
24551 // OpenMP 5.0, 2.1.6 Iterators
24552 // In an iterator-specifier, if the iterator-type is not specified then
24553 // the type of that iterator is of int type.
24554 DeclTy = Context.IntTy;
24555 StartLoc = D.DeclIdentLoc;
24556 } else {
24557 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
24558 StartLoc = TInfo->getTypeLoc().getBeginLoc();
24559 }
24560
24561 bool IsDeclTyDependent = DeclTy->isDependentType() ||
24562 DeclTy->containsUnexpandedParameterPack() ||
24563 DeclTy->isInstantiationDependentType();
24564 if (!IsDeclTyDependent) {
24565 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
24566 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24567 // The iterator-type must be an integral or pointer type.
24568 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24569 << DeclTy;
24570 IsCorrect = false;
24571 continue;
24572 }
24573 if (DeclTy.isConstant(Context)) {
24574 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
24575 // The iterator-type must not be const qualified.
24576 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
24577 << DeclTy;
24578 IsCorrect = false;
24579 continue;
24580 }
24581 }
24582
24583 // Iterator declaration.
24584 assert(D.DeclIdent && "Identifier expected.");
24585 // Always try to create iterator declarator to avoid extra error messages
24586 // about unknown declarations use.
24587 auto *VD =
24588 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
24589 D.DeclIdent, DeclTy, TInfo, SC_None);
24590 VD->setImplicit();
24591 if (S) {
24592 // Check for conflicting previous declaration.
24593 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
24595 RedeclarationKind::ForVisibleRedeclaration);
24596 Previous.suppressDiagnostics();
24598
24600 /*ConsiderLinkage=*/false,
24601 /*AllowInlineNamespace=*/false);
24602 if (!Previous.empty()) {
24603 NamedDecl *Old = Previous.getRepresentativeDecl();
24604 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
24605 Diag(Old->getLocation(), diag::note_previous_definition);
24606 } else {
24608 }
24609 } else {
24611 }
24612
24613 /// Act on the iterator variable declaration.
24615
24616 Expr *Begin = D.Range.Begin;
24617 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
24620 Begin = BeginRes.get();
24621 }
24622 Expr *End = D.Range.End;
24623 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
24625 End, DeclTy, AssignmentAction::Converting);
24626 End = EndRes.get();
24627 }
24628 Expr *Step = D.Range.Step;
24629 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
24630 if (!Step->getType()->isIntegralType(Context)) {
24631 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
24632 << Step << Step->getSourceRange();
24633 IsCorrect = false;
24634 continue;
24635 }
24636 std::optional<llvm::APSInt> Result =
24637 Step->getIntegerConstantExpr(Context);
24638 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
24639 // If the step expression of a range-specification equals zero, the
24640 // behavior is unspecified.
24641 if (Result && Result->isZero()) {
24642 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
24643 << Step << Step->getSourceRange();
24644 IsCorrect = false;
24645 continue;
24646 }
24647 }
24648 if (!Begin || !End || !IsCorrect) {
24649 IsCorrect = false;
24650 continue;
24651 }
24652 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
24653 IDElem.IteratorDecl = VD;
24654 IDElem.AssignmentLoc = D.AssignLoc;
24655 IDElem.Range.Begin = Begin;
24656 IDElem.Range.End = End;
24657 IDElem.Range.Step = Step;
24658 IDElem.ColonLoc = D.ColonLoc;
24659 IDElem.SecondColonLoc = D.SecColonLoc;
24660 }
24661 if (!IsCorrect) {
24662 // Invalidate all created iterator declarations if error is found.
24663 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24664 if (Decl *ID = D.IteratorDecl)
24665 ID->setInvalidDecl();
24666 }
24667 return ExprError();
24668 }
24671 // Build number of ityeration for each iteration range.
24672 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
24673 // ((Begini-Stepi-1-Endi) / -Stepi);
24675 // (Endi - Begini)
24676 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
24677 D.Range.End, D.Range.Begin);
24678 if (!Res.isUsable()) {
24679 IsCorrect = false;
24680 continue;
24681 }
24682 ExprResult St, St1;
24683 if (D.Range.Step) {
24684 St = D.Range.Step;
24685 // (Endi - Begini) + Stepi
24686 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
24687 St.get());
24688 if (!Res.isUsable()) {
24689 IsCorrect = false;
24690 continue;
24691 }
24692 // (Endi - Begini) + Stepi - 1
24694 D.AssignmentLoc, BO_Sub, Res.get(),
24695 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24696 if (!Res.isUsable()) {
24697 IsCorrect = false;
24698 continue;
24699 }
24700 // ((Endi - Begini) + Stepi - 1) / Stepi
24701 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
24702 St.get());
24703 if (!Res.isUsable()) {
24704 IsCorrect = false;
24705 continue;
24706 }
24707 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
24708 D.Range.Step);
24709 // (Begini - Endi)
24711 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
24712 if (!Res1.isUsable()) {
24713 IsCorrect = false;
24714 continue;
24715 }
24716 // (Begini - Endi) - Stepi
24717 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
24718 St1.get());
24719 if (!Res1.isUsable()) {
24720 IsCorrect = false;
24721 continue;
24722 }
24723 // (Begini - Endi) - Stepi - 1
24725 D.AssignmentLoc, BO_Sub, Res1.get(),
24726 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24727 if (!Res1.isUsable()) {
24728 IsCorrect = false;
24729 continue;
24730 }
24731 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24732 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
24733 St1.get());
24734 if (!Res1.isUsable()) {
24735 IsCorrect = false;
24736 continue;
24737 }
24738 // Stepi > 0.
24740 D.AssignmentLoc, BO_GT, D.Range.Step,
24741 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
24742 if (!CmpRes.isUsable()) {
24743 IsCorrect = false;
24744 continue;
24745 }
24746 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
24747 CmpRes.get(), Res.get(), Res1.get());
24748 if (!Res.isUsable()) {
24749 IsCorrect = false;
24750 continue;
24751 }
24752 }
24753 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
24754 if (!Res.isUsable()) {
24755 IsCorrect = false;
24756 continue;
24757 }
24758
24759 // Build counter update.
24760 // Build counter.
24761 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
24762 D.IteratorDecl->getBeginLoc(),
24763 D.IteratorDecl->getBeginLoc(), nullptr,
24764 Res.get()->getType(), nullptr, SC_None);
24765 CounterVD->setImplicit();
24766 ExprResult RefRes =
24767 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
24768 D.IteratorDecl->getBeginLoc());
24769 // Build counter update.
24770 // I = Begini + counter * Stepi;
24771 ExprResult UpdateRes;
24772 if (D.Range.Step) {
24773 UpdateRes = SemaRef.CreateBuiltinBinOp(
24774 D.AssignmentLoc, BO_Mul,
24775 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
24776 } else {
24777 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
24778 }
24779 if (!UpdateRes.isUsable()) {
24780 IsCorrect = false;
24781 continue;
24782 }
24783 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
24784 D.Range.Begin, UpdateRes.get());
24785 if (!UpdateRes.isUsable()) {
24786 IsCorrect = false;
24787 continue;
24788 }
24789 ExprResult VDRes =
24790 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
24791 cast<VarDecl>(D.IteratorDecl)->getType(),
24792 VK_LValue, D.IteratorDecl->getBeginLoc());
24793 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
24794 VDRes.get(), UpdateRes.get());
24795 if (!UpdateRes.isUsable()) {
24796 IsCorrect = false;
24797 continue;
24798 }
24799 UpdateRes =
24800 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
24801 if (!UpdateRes.isUsable()) {
24802 IsCorrect = false;
24803 continue;
24804 }
24805 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24806 D.AssignmentLoc, UO_PreInc, RefRes.get());
24807 if (!CounterUpdateRes.isUsable()) {
24808 IsCorrect = false;
24809 continue;
24810 }
24811 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
24812 /*DiscardedValue=*/true);
24813 if (!CounterUpdateRes.isUsable()) {
24814 IsCorrect = false;
24815 continue;
24816 }
24817 OMPIteratorHelperData &HD = Helpers.emplace_back();
24818 HD.CounterVD = CounterVD;
24819 HD.Upper = Res.get();
24820 HD.Update = UpdateRes.get();
24821 HD.CounterUpdate = CounterUpdateRes.get();
24822 }
24823 } else {
24824 Helpers.assign(ID.size(), {});
24825 }
24826 if (!IsCorrect) {
24827 // Invalidate all created iterator declarations if error is found.
24828 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24829 if (Decl *ID = D.IteratorDecl)
24830 ID->setInvalidDecl();
24831 }
24832 return ExprError();
24833 }
24834 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
24835 LLoc, RLoc, ID, Helpers);
24836}
24837
24838/// Check if \p AssumptionStr is a known assumption and warn if not.
24840 StringRef AssumptionStr) {
24841 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
24842 return;
24843
24844 unsigned BestEditDistance = 3;
24845 StringRef Suggestion;
24846 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
24847 unsigned EditDistance =
24848 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24849 if (EditDistance < BestEditDistance) {
24850 Suggestion = KnownAssumptionIt.getKey();
24851 BestEditDistance = EditDistance;
24852 }
24853 }
24854
24855 if (!Suggestion.empty())
24856 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24857 << AssumptionStr << Suggestion;
24858 else
24859 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
24860 << AssumptionStr;
24861}
24862
24864 // Handle the case where the attribute has a text message.
24865 StringRef Str;
24866 SourceLocation AttrStrLoc;
24867 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
24868 return;
24869
24870 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
24871
24872 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24873}
24874
24876 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3597
NodeId Parent
Definition: ASTDiff.cpp:191
DynTypedNode Node
StringRef P
const Decl * D
enum clang::sema::@1840::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:3181
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:145
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:1179
CastType
Definition: SemaCast.cpp:49
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:753
SourceLocation Loc
Definition: SemaObjC.cpp:754
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 Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
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 std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
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
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:489
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 mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:744
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
Definition: ASTContext.h:1360
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2851
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2867
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:1263
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1249
void Deallocate(void *Ptr) const
Definition: ASTContext.h:820
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:1250
CanQualType OMPIteratorTy
Definition: ASTContext.h:1263
IdentifierTable & Idents
Definition: ASTContext.h:740
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:1262
CanQualType BoolTy
Definition: ASTContext.h:1223
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 BoundMemberTy
Definition: ASTContext.h:1250
CanQualType IntTy
Definition: ASTContext.h:1231
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return a non-unique reference to the type for a variable array of the specified element type.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2898
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1222
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:1750
QualType getMemberPointerType(QualType T, NestedNameSpecifier Qualifier, const CXXRecordDecl *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:859
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:168
PtrTy get() const
Definition: Ownership.h:171
bool isInvalid() const
Definition: Ownership.h:167
bool isUsable() const
Definition: Ownership.h:169
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition: Expr.h:7092
Expr * getBase()
Get base of the array section.
Definition: Expr.h:7158
Expr * getLength()
Get length of array section.
Definition: Expr.h:7168
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5224
Expr * getLowerBound()
Get lower bound of array section.
Definition: Expr.h:7162
SourceLocation getColonLocFirst() const
Definition: Expr.h:7189
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2723
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: TypeBase.h:3738
QualType getElementType() const
Definition: TypeBase.h:3750
Attr - This represents one attribute.
Definition: Attr.h:44
Represents an attribute applied to a statement.
Definition: Stmt.h:2203
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:3974
Expr * getLHS() const
Definition: Expr.h:4024
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2175
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition: Expr.h:4121
bool isRelationalOp() const
Definition: Expr.h:4069
SourceLocation getOperatorLoc() const
Definition: Expr.h:4016
SourceLocation getExprLoc() const
Definition: Expr.h:4015
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:4093
Expr * getRHS() const
Definition: Expr.h:4026
Opcode getOpcode() const
Definition: Expr.h:4019
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2137
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:2604
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2937
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:84
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition: DeclCXX.h:1233
bool hasDefinition() const
Definition: DeclCXX.h:561
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:73
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition: DeclSpec.h:185
SourceLocation getBeginLoc() const
Definition: DeclSpec.h:83
bool isSet() const
Deprecated.
Definition: DeclSpec.h:198
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition: DeclSpec.cpp:123
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition: DeclSpec.h:183
Represents the this expression in C++.
Definition: ExprCXX.h:1155
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2879
SourceLocation getBeginLoc() const
Definition: Expr.h:3213
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:1513
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3062
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:346
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition: Decl.h:4906
unsigned getNumParams() const
Definition: Decl.h:4944
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5570
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4946
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition: Stmt.h:3899
This captures a statement into a function.
Definition: Stmt.h:3886
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1451
SourceRange getSourceRange() const LLVM_READONLY
Definition: Stmt.h:4089
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3990
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition: Stmt.cpp:1475
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:4081
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3612
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition: TypeBase.h:3293
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1720
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:4327
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:196
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:1382
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1449
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2109
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2238
bool isFileContext() const
Definition: DeclBase.h:2180
ASTContext & getParentASTContext() const
Definition: DeclBase.h:2138
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1424
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1358
bool isNamespace() const
Definition: DeclBase.h:2198
bool isTranslationUnit() const
Definition: DeclBase.h:2185
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1793
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2373
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1409
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context semantically encloses the declaration context DC.
Definition: DeclBase.cpp:1428
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1767
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition: DeclGroup.h:64
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1272
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:484
ValueDecl * getDecl()
Definition: Expr.h:1340
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Expr.cpp:547
SourceLocation getBeginLoc() const
Definition: Expr.h:1351
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1611
SourceLocation getEndLoc() const
Definition: Stmt.h:1634
const DeclGroupRef getDeclGroup() const
Definition: Stmt.h:1629
const Decl * getSingleDecl() const
Definition: Stmt.h:1626
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:1637
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:573
bool hasAttrs() const
Definition: DeclBase.h:518
void addAttr(Attr *A)
Definition: DeclBase.cpp:1022
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:593
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:156
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition: DeclBase.cpp:568
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition: DeclBase.cpp:578
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition: DeclBase.h:984
bool isInvalidDecl() const
Definition: DeclBase.h:588
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:559
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:502
SourceLocation getLocation() const
Definition: DeclBase.h:439
void setImplicit(bool I=true)
Definition: DeclBase.h:594
void setReferenced(bool R=true)
Definition: DeclBase.h:623
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: DeclBase.h:1049
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition: DeclBase.cpp:553
DeclContext * getDeclContext()
Definition: DeclBase.h:448
AccessSpecifier getAccess() const
Definition: DeclBase.h:507
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:431
AttrVec & getAttrs()
Definition: DeclBase.h:524
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition: DeclBase.cpp:360
bool hasAttr() const
Definition: DeclBase.h:577
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:364
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:978
Kind getKind() const
Definition: DeclBase.h:442
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:427
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:1874
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:337
This represents one expression.
Definition: Expr.h:112
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 isIntegerConstantExpr(const ASTContext &Ctx) const
bool isGLValue() const
Definition: Expr.h:287
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition: Expr.h:674
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3078
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:177
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition: Expr.h:444
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:194
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition: Expr.h:241
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:3090
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3073
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3061
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition: Expr.h:246
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3069
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:284
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:451
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:223
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3053
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:273
QualType getType() const
Definition: Expr.h:144
Represents difference between two FPOptions values.
Definition: LangOptions.h:919
Represents a member of a struct/union/class.
Definition: Decl.h:3157
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3260
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4767
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3404
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1072
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2888
Stmt * getBody()
Definition: Stmt.h:2932
Represents a function declaration or definition.
Definition: Decl.h:1999
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2794
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2771
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2469
bool isConsteval() const
Definition: Decl.h:2481
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3767
Represents a prototype with parameter type info, e.g.
Definition: TypeBase.h:5282
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2259
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition: Expr.h:1733
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2068
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition: Overload.h:615
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:7739
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:971
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:434
A class for iterating through a result set and possibly filtering out results.
Definition: Lookup.h:677
Represents the results of name lookup.
Definition: Lookup.h:147
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition: Lookup.h:607
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:751
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition: Lookup.h:569
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:576
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition: Lookup.h:636
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:3300
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3383
Expr * getBase() const
Definition: Expr.h:3377
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:3361
This represents a decl that may have a name.
Definition: Decl.h:273
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:294
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:300
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:339
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:316
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:1834
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:664
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:408
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:5305
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
Definition: StmtOpenMP.cpp:825
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:993
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:857
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:913
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Definition: StmtOpenMP.cpp:899
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:642
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:944
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:842
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:555
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:779
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:929
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:512
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:676
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:491
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:5432
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:682
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:959
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:627
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 the 'message' clause in the '#pragma omp error' and the '#pragma omp parallel' direct...
Expr * getMessageString() const
Returns message string of the clause.
std::optional< std::string > tryEvaluateString(ASTContext &Ctx) const
Try to evaluate the message string at compile time.
This represents the 'no_openmp' clause in the '#pragma omp assume' directive.
This represents the 'no_openmp_constructs' clause in the.
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:825
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:974
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:658
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:703
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:763
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:747
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:779
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, ArrayRef< bool > IsPrivateVarReduction, OpenMPOriginalSharingModifier OriginalSharingModifier)
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, unsigned NumLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp reverse'.
Definition: StmtOpenMP.cpp:472
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:891
Expr * getSafelen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:911
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:959
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:593
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
Definition: StmtOpenMP.cpp:575
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:555
This represents 'self_maps' clause in the '#pragma omp requires' directive.
This represents 'seq_cst' clause in the '#pragma omp atomic|flush' directives.
This represents the 'severity' clause in the '#pragma omp error' and the '#pragma omp parallel' direc...
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:926
Expr * getSimdlen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:946
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:610
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
static OMPStripeDirective * 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 stripe'.
Definition: StmtOpenMP.cpp:429
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.
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:798
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:883
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
Definition: StmtOpenMP.cpp:869
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:814
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:450
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:318
SourceLocation getLParenLoc() const
Returns the location of '('.
Definition: OpenMPClause.h:334
unsigned varlist_size() const
Definition: OpenMPClause.h:315
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:51
void * getAsOpaquePtr() const
Definition: Ownership.h:91
PtrTy get() const
Definition: Ownership.h:81
static OpaquePtr make(PtrTy P)
Definition: Ownership.h:61
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1180
void setIsUnique(bool V)
Definition: Expr.h:1232
Represents a parameter to a function.
Definition: Decl.h:1789
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:2946
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:119
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
Definition: Expr.cpp:5032
A (possibly-)qualified type.
Definition: TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition: Type.cpp:2871
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: TypeBase.h:8432
QualType withRestrict() const
Definition: TypeBase.h:1175
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition: Type.cpp:3591
QualType withConst() const
Definition: TypeBase.h:1159
void addConst()
Add the const type qualifier to this QualType.
Definition: TypeBase.h:1156
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: TypeBase.h:8343
bool isConstant(const ASTContext &Ctx) const
Definition: TypeBase.h:1097
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: TypeBase.h:8528
QualType getCanonicalType() const
Definition: TypeBase.h:8395
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: TypeBase.h:8437
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: TypeBase.h:8497
const Type * getTypePtrOrNull() const
Definition: TypeBase.h:8347
Represents a struct/union/class.
Definition: Decl.h:4309
field_range fields() const
Definition: Decl.h:4512
field_iterator field_begin() const
Definition: Decl.cpp:5154
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Definition: Redeclarable.h:201
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Definition: Redeclarable.h:223
Base for LValueReferenceType and RValueReferenceType.
Definition: TypeBase.h:3589
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:398
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition: Scope.h:322
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition: Scope.h:558
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition: Scope.h:287
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition: Scope.h:551
@ 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:111
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:61
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition: SemaBase.cpp:33
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...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
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.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' 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)
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< Expr * > AdjustArgsNeedDeviceAddr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
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...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
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.
StmtResult ActOnOpenMPStripeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
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
void setOpenMPDeviceNumID(StringRef ID)
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.
int getOpenMPDeviceNum() const
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 * ActOnOpenMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
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 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 * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers, 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 * 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 for '#pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
Definition: Sema.h:1283
Expr * get() const
Definition: Sema.h:7717
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:12401
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:7668
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:850
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
Definition: SemaType.cpp:6383
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:1113
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:1617
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15759
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:9281
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:9322
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:9324
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:9326
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
Definition: SemaExpr.cpp:15069
SemaOpenMP & OpenMP()
Definition: Sema.h:1498
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:20514
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition: Sema.h:4721
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17664
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:20730
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:1216
@ AR_inaccessible
Definition: Sema.h:1652
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:2442
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition: Sema.cpp:2311
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:6393
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:2042
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:1647
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ASTContext & Context
Definition: Sema.h:1276
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4759
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:75
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1555
void CleanupVarDeclMarking()
Definition: SemaExpr.cpp:19998
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:748
ASTContext & getASTContext() const
Definition: Sema.h:918
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:16038
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:19252
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:20253
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:18155
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:1184
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2298
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:2330
const LangOptions & getLangOpts() const
Definition: Sema.h:911
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:1275
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:6572
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:1274
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2557
DeclContext * getCurLexicalContext() const
Definition: Sema.h:1117
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3441
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
Definition: SemaStmt.cpp:4661
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:1307
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:633
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition: Sema.h:15324
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20751
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2512
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1411
bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, CXXRecordDecl *Base, CXXBasePaths &Paths)
Determine whether the type Derived is a C++ class that is derived from the type Base.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4774
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4154
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:21316
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:13791
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:11376
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:8916
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:15279
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2497
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:11169
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=AllowFoldKind::No)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
Definition: SemaExpr.cpp:17422
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:270
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5197
@ 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:5693
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:75
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9241
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:1239
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:18228
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1366
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
Definition: SemaExpr.cpp:15609
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
Definition: SemaExpr.cpp:3635
void PopDeclContext()
Definition: SemaDecl.cpp:1373
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:1637
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:14214
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13696
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition: Sema.cpp:2096
sema::FunctionScopeInfo * getEnclosingFunction() const
Definition: Sema.cpp:2527
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2886
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:2773
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:436
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:7731
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:8599
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:186
Stmt - This represents one statement.
Definition: Stmt.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:358
child_range children()
Definition: Stmt.cpp:295
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:334
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:205
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:346
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4834
bool isTLSSupported() const
Whether the target supports thread-local storage.
Definition: TargetInfo.h:1616
bool isVLASupported() const
Whether target supports variable-length arrays.
Definition: TargetInfo.h:1627
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition: Decl.h:3510
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:193
A container of type source information.
Definition: TypeBase.h:8314
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:272
QualType getType() const
Return the type wrapped by this type source info.
Definition: TypeBase.h:8325
The base class of the type hierarchy.
Definition: TypeBase.h:1833
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition: TypeBase.h:9116
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.h:26
bool isConstantArrayType() const
Definition: TypeBase.h:8683
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.h:41
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:2070
bool isArrayType() const
Definition: TypeBase.h:8679
bool isArithmeticType() const
Definition: Type.cpp:2341
bool isPointerType() const
Definition: TypeBase.h:8580
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: TypeBase.h:8980
const T * castAs() const
Member-template castAs<specific type>.
Definition: TypeBase.h:9226
bool isReferenceType() const
Definition: TypeBase.h:8604
bool isEnumeralType() const
Definition: TypeBase.h:8711
bool isScalarType() const
Definition: TypeBase.h:9038
bool isVariableArrayType() const
Definition: TypeBase.h:8691
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2107
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2295
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition: Type.cpp:2172
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: TypeBase.h:8930
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: TypeBase.h:2808
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: TypeBase.h:8905
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: TypeBase.h:2800
RecordDecl * castAsRecordDecl() const
Definition: Type.h:48
bool isAnyComplexType() const
Definition: TypeBase.h:8715
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: TypeBase.h:2423
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2247
bool isFunctionProtoType() const
Definition: TypeBase.h:2619
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition: TypeBase.h:9079
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: TypeBase.h:2818
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: TypeBase.h:9212
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition: Type.cpp:2440
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition: TypeBase.h:9176
bool isFunctionType() const
Definition: TypeBase.h:8576
bool isStructureOrClassType() const
Definition: Type.cpp:706
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2324
bool isFloatingType() const
Definition: Type.cpp:2308
bool isAnyPointerType() const
Definition: TypeBase.h:8588
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
bool isRecordType() const
Definition: TypeBase.h:8707
bool isUnionType() const
Definition: Type.cpp:718
bool isFunctionNoProtoType() const
Definition: TypeBase.h:2618
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:2246
Expr * getSubExpr() const
Definition: Expr.h:2287
Opcode getOpcode() const
Definition: Expr.h:2282
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:432
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
Definition: UnresolvedSet.h:91
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:711
void setType(QualType newType)
Definition: Decl.h:723
QualType getType() const
Definition: Decl.h:722
VarDecl * getPotentiallyDecomposedVarDecl()
Definition: DeclCXX.cpp:3566
Represents a variable declaration or definition.
Definition: Decl.h:925
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition: Decl.cpp:2151
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition: Decl.h:1266
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1568
TLSKind getTLSKind() const
Definition: Decl.cpp:2168
bool hasInit() const
Definition: Decl.cpp:2398
void setInitStyle(InitializationStyle Style)
Definition: Decl.h:1451
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition: Decl.h:1465
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition: Decl.cpp:2260
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:2190
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:2257
@ CInit
C-style initialization with assignment.
Definition: Decl.h:930
@ CallInit
Call-style initialization (C++98)
Definition: Decl.h:933
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition: Decl.h:1282
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1225
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:1207
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition: Decl.h:1341
const Expr * getInit() const
Definition: Decl.h:1367
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1183
@ TLS_None
Not a TLS variable.
Definition: Decl.h:945
void setInit(Expr *I)
Definition: Decl.cpp:2477
@ DeclarationOnly
This declaration is only a declaration.
Definition: Decl.h:1294
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition: Decl.h:1252
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition: Decl.h:1470
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition: Decl.h:1228
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1167
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:2528
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition: Decl.h:1261
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition: Decl.h:1357
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:36
#define bool
Definition: gpuintrin.h:32
Defines the clang::TargetInfo interface.
Definition: SPIR.cpp:47
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1274
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.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
Definition: OpenMPKinds.h:194
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:275
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
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
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:5347
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
Definition: OpenMPKinds.h:233
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:272
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
StmtResult StmtError()
Definition: Ownership.h:266
@ SD_Static
Static storage duration.
Definition: Specifiers.h:343
@ 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:208
@ OMPC_BIND_unknown
Definition: OpenMPKinds.h:211
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:214
@ OMPC_GRAINSIZE_unknown
Definition: OpenMPKinds.h:217
OpenMPNumTasksClauseModifier
Definition: OpenMPKinds.h:220
@ OMPC_NUMTASKS_unknown
Definition: OpenMPKinds.h:223
ActionResult< Expr * > ExprResult
Definition: Ownership.h:249
ExprResult ExprError()
Definition: Ownership.h:265
bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
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:240
@ OMPC_ALLOCATE_unknown
Definition: OpenMPKinds.h:243
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.
OpenMPNumThreadsClauseModifier
Definition: OpenMPKinds.h:226
@ OMPC_NUMTHREADS_unknown
Definition: OpenMPKinds.h:229
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:255
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
@ None
No keyword precedes the qualified type name.
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
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
int const char * function
Definition: c++config.h:31
#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:313
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition: ExprCXX.h:309
const Expr * LHS
The original left-hand side.
Definition: ExprCXX.h:311
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:645
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:647
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:633
Extra information about a function prototype.
Definition: TypeBase.h:5367
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:257
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:735
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:709
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Definition: StmtOpenMP.h:719
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:728
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Definition: StmtOpenMP.h:715
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:712
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:725
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Definition: StmtOpenMP.h:731
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:722
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Definition: StmtOpenMP.h:740
Expr * LastIteration
Loop last iteration number.
Definition: StmtOpenMP.h:744
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:802
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Definition: StmtOpenMP.h:792
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Definition: StmtOpenMP.h:786
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Definition: StmtOpenMP.h:780
Expr * IL
IsLastIteration - local flag variable passed to runtime.
Definition: StmtOpenMP.h:758
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
Definition: StmtOpenMP.h:790
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Definition: StmtOpenMP.h:814
Expr * CalcLastIteration
Calculation of last iteration.
Definition: StmtOpenMP.h:748
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Definition: StmtOpenMP.h:794
Expr * ST
Stride - local variable passed to runtime.
Definition: StmtOpenMP.h:764
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
Definition: StmtOpenMP.h:796
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:805
Expr * PreCond
Loop pre-condition.
Definition: StmtOpenMP.h:750
Stmt * PreInits
Init statement for all captured expressions.
Definition: StmtOpenMP.h:807
Expr * IterationVarRef
Loop iteration variable.
Definition: StmtOpenMP.h:742
Expr * NumIterations
Loop number of iterations.
Definition: StmtOpenMP.h:746
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Definition: StmtOpenMP.h:788
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:768
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:776
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
Definition: StmtOpenMP.h:810
void clear(unsigned Size)
Initialize all the fields to null.
Definition: StmtOpenMP.h:824
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Definition: StmtOpenMP.h:766
Expr * UB
UpperBound - local variable passed to runtime.
Definition: StmtOpenMP.h:762
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:770
Expr * LB
LowerBound - local variable passed to runtime.
Definition: StmtOpenMP.h:760
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:773
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:799
Expr * Init
Loop iteration variable init.
Definition: StmtOpenMP.h:754
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:1417
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1141
Data for list of allocators.
Definition: SemaOpenMP.h:1357
Clang specific specialization of the OMPContext to lookup target features.