clang 20.0.0git
SemaOpenMP.cpp
Go to the documentation of this file.
1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenMP directives and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
15
16#include "TreeTransform.h"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclCXX.h"
24#include "clang/AST/StmtCXX.h"
34#include "clang/Sema/Lookup.h"
36#include "clang/Sema/Scope.h"
38#include "clang/Sema/Sema.h"
40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.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#include <set>
51
52using namespace clang;
53using namespace llvm::omp;
54
55//===----------------------------------------------------------------------===//
56// Stack of data-sharing attributes for variables
57//===----------------------------------------------------------------------===//
58
60 Sema &SemaRef, Expr *E,
62 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
63
64namespace {
65/// Default data sharing attributes, which can be applied to directive.
66enum DefaultDataSharingAttributes {
67 DSA_unspecified = 0, /// Data sharing attribute not specified.
68 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
69 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
70 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
71 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
72};
73
74/// Stack for tracking declarations used in OpenMP directives and
75/// clauses and their data-sharing attributes.
76class DSAStackTy {
77public:
78 struct DSAVarData {
79 OpenMPDirectiveKind DKind = OMPD_unknown;
80 OpenMPClauseKind CKind = OMPC_unknown;
81 unsigned Modifier = 0;
82 const Expr *RefExpr = nullptr;
83 DeclRefExpr *PrivateCopy = nullptr;
84 SourceLocation ImplicitDSALoc;
85 bool AppliedToPointee = false;
86 DSAVarData() = default;
87 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
88 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
89 SourceLocation ImplicitDSALoc, unsigned Modifier,
90 bool AppliedToPointee)
91 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
92 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
93 AppliedToPointee(AppliedToPointee) {}
94 };
95 using OperatorOffsetTy =
97 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
98 /// Kind of the declaration used in the uses_allocators clauses.
99 enum class UsesAllocatorsDeclKind {
100 /// Predefined allocator
101 PredefinedAllocator,
102 /// User-defined allocator
103 UserDefinedAllocator,
104 /// The declaration that represent allocator trait
105 AllocatorTrait,
106 };
107
108private:
109 struct DSAInfo {
110 OpenMPClauseKind Attributes = OMPC_unknown;
111 unsigned Modifier = 0;
112 /// Pointer to a reference expression and a flag which shows that the
113 /// variable is marked as lastprivate(true) or not (false).
114 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
115 DeclRefExpr *PrivateCopy = nullptr;
116 /// true if the attribute is applied to the pointee, not the variable
117 /// itself.
118 bool AppliedToPointee = false;
119 };
120 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
121 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
122 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
123 using LoopControlVariablesMapTy =
124 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
125 /// Struct that associates a component with the clause kind where they are
126 /// found.
127 struct MappedExprComponentTy {
129 OpenMPClauseKind Kind = OMPC_unknown;
130 };
131 using MappedExprComponentsTy =
132 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
133 using CriticalsWithHintsTy =
134 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
135 struct ReductionData {
136 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
137 SourceRange ReductionRange;
138 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
139 ReductionData() = default;
140 void set(BinaryOperatorKind BO, SourceRange RR) {
141 ReductionRange = RR;
142 ReductionOp = BO;
143 }
144 void set(const Expr *RefExpr, SourceRange RR) {
145 ReductionRange = RR;
146 ReductionOp = RefExpr;
147 }
148 };
149 using DeclReductionMapTy =
150 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
151 struct DefaultmapInfo {
152 OpenMPDefaultmapClauseModifier ImplicitBehavior =
154 SourceLocation SLoc;
155 DefaultmapInfo() = default;
157 : ImplicitBehavior(M), SLoc(Loc) {}
158 };
159
160 struct SharingMapTy {
161 DeclSAMapTy SharingMap;
162 DeclReductionMapTy ReductionMap;
163 UsedRefMapTy AlignedMap;
164 UsedRefMapTy NontemporalMap;
165 MappedExprComponentsTy MappedExprComponents;
166 LoopControlVariablesMapTy LCVMap;
167 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
168 SourceLocation DefaultAttrLoc;
169 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
170 OpenMPDirectiveKind Directive = OMPD_unknown;
171 DeclarationNameInfo DirectiveName;
172 Scope *CurScope = nullptr;
173 DeclContext *Context = nullptr;
174 SourceLocation ConstructLoc;
175 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
176 /// get the data (loop counters etc.) about enclosing loop-based construct.
177 /// This data is required during codegen.
178 DoacrossClauseMapTy DoacrossDepends;
179 /// First argument (Expr *) contains optional argument of the
180 /// 'ordered' clause, the second one is true if the regions has 'ordered'
181 /// clause, false otherwise.
182 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
183 bool RegionHasOrderConcurrent = false;
184 unsigned AssociatedLoops = 1;
185 bool HasMutipleLoops = false;
186 const Decl *PossiblyLoopCounter = nullptr;
187 bool NowaitRegion = false;
188 bool UntiedRegion = false;
189 bool CancelRegion = false;
190 bool LoopStart = false;
191 bool BodyComplete = false;
192 SourceLocation PrevScanLocation;
193 SourceLocation PrevOrderedLocation;
194 SourceLocation InnerTeamsRegionLoc;
195 /// Reference to the taskgroup task_reduction reference expression.
196 Expr *TaskgroupReductionRef = nullptr;
197 llvm::DenseSet<QualType> MappedClassesQualTypes;
198 SmallVector<Expr *, 4> InnerUsedAllocators;
199 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
200 /// List of globals marked as declare target link in this target region
201 /// (isOpenMPTargetExecutionDirective(Directive) == true).
202 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
203 /// List of decls used in inclusive/exclusive clauses of the scan directive.
204 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
205 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
206 UsesAllocatorsDecls;
207 /// Data is required on creating capture fields for implicit
208 /// default first|private clause.
209 struct ImplicitDefaultFDInfoTy {
210 /// Field decl.
211 const FieldDecl *FD = nullptr;
212 /// Nesting stack level
213 size_t StackLevel = 0;
214 /// Capture variable decl.
215 VarDecl *VD = nullptr;
216 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
217 VarDecl *VD)
218 : FD(FD), StackLevel(StackLevel), VD(VD) {}
219 };
220 /// List of captured fields
222 ImplicitDefaultFirstprivateFDs;
223 Expr *DeclareMapperVar = nullptr;
224 SmallVector<VarDecl *, 16> IteratorVarDecls;
225 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
226 Scope *CurScope, SourceLocation Loc)
227 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
228 ConstructLoc(Loc) {}
229 SharingMapTy() = default;
230 };
231
232 using StackTy = SmallVector<SharingMapTy, 4>;
233
234 /// Stack of used declaration and their data-sharing attributes.
235 DeclSAMapTy Threadprivates;
236 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
238 /// true, if check for DSA must be from parent directive, false, if
239 /// from current directive.
240 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
241 Sema &SemaRef;
242 bool ForceCapturing = false;
243 /// true if all the variables in the target executable directives must be
244 /// captured by reference.
245 bool ForceCaptureByReferenceInTargetExecutable = false;
246 CriticalsWithHintsTy Criticals;
247 unsigned IgnoredStackElements = 0;
248
249 /// Iterators over the stack iterate in order from innermost to outermost
250 /// directive.
251 using const_iterator = StackTy::const_reverse_iterator;
252 const_iterator begin() const {
253 return Stack.empty() ? const_iterator()
254 : Stack.back().first.rbegin() + IgnoredStackElements;
255 }
256 const_iterator end() const {
257 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
258 }
259 using iterator = StackTy::reverse_iterator;
260 iterator begin() {
261 return Stack.empty() ? iterator()
262 : Stack.back().first.rbegin() + IgnoredStackElements;
263 }
264 iterator end() {
265 return Stack.empty() ? iterator() : Stack.back().first.rend();
266 }
267
268 // Convenience operations to get at the elements of the stack.
269
270 bool isStackEmpty() const {
271 return Stack.empty() ||
272 Stack.back().second != CurrentNonCapturingFunctionScope ||
273 Stack.back().first.size() <= IgnoredStackElements;
274 }
275 size_t getStackSize() const {
276 return isStackEmpty() ? 0
277 : Stack.back().first.size() - IgnoredStackElements;
278 }
279
280 SharingMapTy *getTopOfStackOrNull() {
281 size_t Size = getStackSize();
282 if (Size == 0)
283 return nullptr;
284 return &Stack.back().first[Size - 1];
285 }
286 const SharingMapTy *getTopOfStackOrNull() const {
287 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
288 }
289 SharingMapTy &getTopOfStack() {
290 assert(!isStackEmpty() && "no current directive");
291 return *getTopOfStackOrNull();
292 }
293 const SharingMapTy &getTopOfStack() const {
294 return const_cast<DSAStackTy &>(*this).getTopOfStack();
295 }
296
297 SharingMapTy *getSecondOnStackOrNull() {
298 size_t Size = getStackSize();
299 if (Size <= 1)
300 return nullptr;
301 return &Stack.back().first[Size - 2];
302 }
303 const SharingMapTy *getSecondOnStackOrNull() const {
304 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
305 }
306
307 /// Get the stack element at a certain level (previously returned by
308 /// \c getNestingLevel).
309 ///
310 /// Note that nesting levels count from outermost to innermost, and this is
311 /// the reverse of our iteration order where new inner levels are pushed at
312 /// the front of the stack.
313 SharingMapTy &getStackElemAtLevel(unsigned Level) {
314 assert(Level < getStackSize() && "no such stack element");
315 return Stack.back().first[Level];
316 }
317 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
318 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
319 }
320
321 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
322
323 /// Checks if the variable is a local for OpenMP region.
324 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
325
326 /// Vector of previously declared requires directives
328 /// omp_allocator_handle_t type.
329 QualType OMPAllocatorHandleT;
330 /// omp_depend_t type.
331 QualType OMPDependT;
332 /// omp_event_handle_t type.
333 QualType OMPEventHandleT;
334 /// omp_alloctrait_t type.
335 QualType OMPAlloctraitT;
336 /// Expression for the predefined allocators.
337 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
338 nullptr};
339 /// Vector of previously encountered target directives
340 SmallVector<SourceLocation, 2> TargetLocations;
341 SourceLocation AtomicLocation;
342 /// Vector of declare variant construct traits.
344
345public:
346 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
347
348 /// Sets omp_allocator_handle_t type.
349 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
350 /// Gets omp_allocator_handle_t type.
351 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
352 /// Sets omp_alloctrait_t type.
353 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
354 /// Gets omp_alloctrait_t type.
355 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
356 /// Sets the given default allocator.
357 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
358 Expr *Allocator) {
359 OMPPredefinedAllocators[AllocatorKind] = Allocator;
360 }
361 /// Returns the specified default allocator.
362 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
363 return OMPPredefinedAllocators[AllocatorKind];
364 }
365 /// Sets omp_depend_t type.
366 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
367 /// Gets omp_depend_t type.
368 QualType getOMPDependT() const { return OMPDependT; }
369
370 /// Sets omp_event_handle_t type.
371 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
372 /// Gets omp_event_handle_t type.
373 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
374
375 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
376 OpenMPClauseKind getClauseParsingMode() const {
377 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
378 return ClauseKindMode;
379 }
380 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
381
382 bool isBodyComplete() const {
383 const SharingMapTy *Top = getTopOfStackOrNull();
384 return Top && Top->BodyComplete;
385 }
386 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
387
388 bool isForceVarCapturing() const { return ForceCapturing; }
389 void setForceVarCapturing(bool V) { ForceCapturing = V; }
390
391 void setForceCaptureByReferenceInTargetExecutable(bool V) {
392 ForceCaptureByReferenceInTargetExecutable = V;
393 }
394 bool isForceCaptureByReferenceInTargetExecutable() const {
395 return ForceCaptureByReferenceInTargetExecutable;
396 }
397
398 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
399 Scope *CurScope, SourceLocation Loc) {
400 assert(!IgnoredStackElements &&
401 "cannot change stack while ignoring elements");
402 if (Stack.empty() ||
403 Stack.back().second != CurrentNonCapturingFunctionScope)
404 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
405 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
406 Stack.back().first.back().DefaultAttrLoc = Loc;
407 }
408
409 void pop() {
410 assert(!IgnoredStackElements &&
411 "cannot change stack while ignoring elements");
412 assert(!Stack.back().first.empty() &&
413 "Data-sharing attributes stack is empty!");
414 Stack.back().first.pop_back();
415 }
416
417 /// RAII object to temporarily leave the scope of a directive when we want to
418 /// logically operate in its parent.
419 class ParentDirectiveScope {
420 DSAStackTy &Self;
421 bool Active;
422
423 public:
424 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
425 : Self(Self), Active(false) {
426 if (Activate)
427 enable();
428 }
429 ~ParentDirectiveScope() { disable(); }
430 void disable() {
431 if (Active) {
432 --Self.IgnoredStackElements;
433 Active = false;
434 }
435 }
436 void enable() {
437 if (!Active) {
438 ++Self.IgnoredStackElements;
439 Active = true;
440 }
441 }
442 };
443
444 /// Marks that we're started loop parsing.
445 void loopInit() {
446 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
447 "Expected loop-based directive.");
448 getTopOfStack().LoopStart = true;
449 }
450 /// Start capturing of the variables in the loop context.
451 void loopStart() {
452 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
453 "Expected loop-based directive.");
454 getTopOfStack().LoopStart = false;
455 }
456 /// true, if variables are captured, false otherwise.
457 bool isLoopStarted() const {
458 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
459 "Expected loop-based directive.");
460 return !getTopOfStack().LoopStart;
461 }
462 /// Marks (or clears) declaration as possibly loop counter.
463 void resetPossibleLoopCounter(const Decl *D = nullptr) {
464 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
465 }
466 /// Gets the possible loop counter decl.
467 const Decl *getPossiblyLoopCounter() const {
468 return getTopOfStack().PossiblyLoopCounter;
469 }
470 /// Start new OpenMP region stack in new non-capturing function.
471 void pushFunction() {
472 assert(!IgnoredStackElements &&
473 "cannot change stack while ignoring elements");
474 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
475 assert(!isa<CapturingScopeInfo>(CurFnScope));
476 CurrentNonCapturingFunctionScope = CurFnScope;
477 }
478 /// Pop region stack for non-capturing function.
479 void popFunction(const FunctionScopeInfo *OldFSI) {
480 assert(!IgnoredStackElements &&
481 "cannot change stack while ignoring elements");
482 if (!Stack.empty() && Stack.back().second == OldFSI) {
483 assert(Stack.back().first.empty());
484 Stack.pop_back();
485 }
486 CurrentNonCapturingFunctionScope = nullptr;
487 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
488 if (!isa<CapturingScopeInfo>(FSI)) {
489 CurrentNonCapturingFunctionScope = FSI;
490 break;
491 }
492 }
493 }
494
495 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
496 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
497 }
498 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
499 getCriticalWithHint(const DeclarationNameInfo &Name) const {
500 auto I = Criticals.find(Name.getAsString());
501 if (I != Criticals.end())
502 return I->second;
503 return std::make_pair(nullptr, llvm::APSInt());
504 }
505 /// If 'aligned' declaration for given variable \a D was not seen yet,
506 /// add it and return NULL; otherwise return previous occurrence's expression
507 /// for diagnostics.
508 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
509 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
510 /// add it and return NULL; otherwise return previous occurrence's expression
511 /// for diagnostics.
512 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
513
514 /// Register specified variable as loop control variable.
515 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
516 /// Check if the specified variable is a loop control variable for
517 /// current region.
518 /// \return The index of the loop control variable in the list of associated
519 /// for-loops (from outer to inner).
520 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
521 /// Check if the specified variable is a loop control variable for
522 /// parent region.
523 /// \return The index of the loop control variable in the list of associated
524 /// for-loops (from outer to inner).
525 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
526 /// Check if the specified variable is a loop control variable for
527 /// current region.
528 /// \return The index of the loop control variable in the list of associated
529 /// for-loops (from outer to inner).
530 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
531 unsigned Level) const;
532 /// Get the loop control variable for the I-th loop (or nullptr) in
533 /// parent directive.
534 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
535
536 /// Marks the specified decl \p D as used in scan directive.
537 void markDeclAsUsedInScanDirective(ValueDecl *D) {
538 if (SharingMapTy *Stack = getSecondOnStackOrNull())
539 Stack->UsedInScanDirective.insert(D);
540 }
541
542 /// Checks if the specified declaration was used in the inner scan directive.
543 bool isUsedInScanDirective(ValueDecl *D) const {
544 if (const SharingMapTy *Stack = getTopOfStackOrNull())
545 return Stack->UsedInScanDirective.contains(D);
546 return false;
547 }
548
549 /// Adds explicit data sharing attribute to the specified declaration.
550 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
551 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
552 bool AppliedToPointee = false);
553
554 /// Adds additional information for the reduction items with the reduction id
555 /// represented as an operator.
556 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
558 /// Adds additional information for the reduction items with the reduction id
559 /// represented as reduction identifier.
560 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
561 const Expr *ReductionRef);
562 /// Returns the location and reduction operation from the innermost parent
563 /// region for the given \p D.
564 const DSAVarData
565 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
567 Expr *&TaskgroupDescriptor) const;
568 /// Returns the location and reduction operation from the innermost parent
569 /// region for the given \p D.
570 const DSAVarData
571 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
572 const Expr *&ReductionRef,
573 Expr *&TaskgroupDescriptor) const;
574 /// Return reduction reference expression for the current taskgroup or
575 /// parallel/worksharing directives with task reductions.
576 Expr *getTaskgroupReductionRef() const {
577 assert((getTopOfStack().Directive == OMPD_taskgroup ||
578 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
579 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
580 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
581 "taskgroup reference expression requested for non taskgroup or "
582 "parallel/worksharing directive.");
583 return getTopOfStack().TaskgroupReductionRef;
584 }
585 /// Checks if the given \p VD declaration is actually a taskgroup reduction
586 /// descriptor variable at the \p Level of OpenMP regions.
587 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
588 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
589 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
590 ->getDecl() == VD;
591 }
592
593 /// Returns data sharing attributes from top of the stack for the
594 /// specified declaration.
595 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
596 /// Returns data-sharing attributes for the specified declaration.
597 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
598 /// Returns data-sharing attributes for the specified declaration.
599 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
600 /// Checks if the specified variables has data-sharing attributes which
601 /// match specified \a CPred predicate in any directive which matches \a DPred
602 /// predicate.
603 const DSAVarData
604 hasDSA(ValueDecl *D,
605 const llvm::function_ref<bool(OpenMPClauseKind, bool,
606 DefaultDataSharingAttributes)>
607 CPred,
608 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
609 bool FromParent) const;
610 /// Checks if the specified variables has data-sharing attributes which
611 /// match specified \a CPred predicate in any innermost directive which
612 /// matches \a DPred predicate.
613 const DSAVarData
614 hasInnermostDSA(ValueDecl *D,
615 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
616 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
617 bool FromParent) const;
618 /// Checks if the specified variables has explicit data-sharing
619 /// attributes which match specified \a CPred predicate at the specified
620 /// OpenMP region.
621 bool
622 hasExplicitDSA(const ValueDecl *D,
623 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
624 unsigned Level, bool NotLastprivate = false) const;
625
626 /// Returns true if the directive at level \Level matches in the
627 /// specified \a DPred predicate.
628 bool hasExplicitDirective(
629 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
630 unsigned Level) const;
631
632 /// Finds a directive which matches specified \a DPred predicate.
633 bool hasDirective(
634 const llvm::function_ref<bool(
636 DPred,
637 bool FromParent) const;
638
639 /// Returns currently analyzed directive.
640 OpenMPDirectiveKind getCurrentDirective() const {
641 const SharingMapTy *Top = getTopOfStackOrNull();
642 return Top ? Top->Directive : OMPD_unknown;
643 }
644 /// Returns directive kind at specified level.
645 OpenMPDirectiveKind getDirective(unsigned Level) const {
646 assert(!isStackEmpty() && "No directive at specified level.");
647 return getStackElemAtLevel(Level).Directive;
648 }
649 /// Returns the capture region at the specified level.
650 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
651 unsigned OpenMPCaptureLevel) const {
653 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
654 return CaptureRegions[OpenMPCaptureLevel];
655 }
656 /// Returns parent directive.
657 OpenMPDirectiveKind getParentDirective() const {
658 const SharingMapTy *Parent = getSecondOnStackOrNull();
659 return Parent ? Parent->Directive : OMPD_unknown;
660 }
661
662 /// Add requires decl to internal vector
663 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
664
665 /// Checks if the defined 'requires' directive has specified type of clause.
666 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
667 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
668 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
669 return isa<ClauseType>(C);
670 });
671 });
672 }
673
674 /// Checks for a duplicate clause amongst previously declared requires
675 /// directives
676 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
677 bool IsDuplicate = false;
678 for (OMPClause *CNew : ClauseList) {
679 for (const OMPRequiresDecl *D : RequiresDecls) {
680 for (const OMPClause *CPrev : D->clauselists()) {
681 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
682 SemaRef.Diag(CNew->getBeginLoc(),
683 diag::err_omp_requires_clause_redeclaration)
684 << getOpenMPClauseName(CNew->getClauseKind());
685 SemaRef.Diag(CPrev->getBeginLoc(),
686 diag::note_omp_requires_previous_clause)
687 << getOpenMPClauseName(CPrev->getClauseKind());
688 IsDuplicate = true;
689 }
690 }
691 }
692 }
693 return IsDuplicate;
694 }
695
696 /// Add location of previously encountered target to internal vector
697 void addTargetDirLocation(SourceLocation LocStart) {
698 TargetLocations.push_back(LocStart);
699 }
700
701 /// Add location for the first encountered atomic directive.
702 void addAtomicDirectiveLoc(SourceLocation Loc) {
703 if (AtomicLocation.isInvalid())
704 AtomicLocation = Loc;
705 }
706
707 /// Returns the location of the first encountered atomic directive in the
708 /// module.
709 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
710
711 // Return previously encountered target region locations.
712 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
713 return TargetLocations;
714 }
715
716 /// Set default data sharing attribute to none.
717 void setDefaultDSANone(SourceLocation Loc) {
718 getTopOfStack().DefaultAttr = DSA_none;
719 getTopOfStack().DefaultAttrLoc = Loc;
720 }
721 /// Set default data sharing attribute to shared.
722 void setDefaultDSAShared(SourceLocation Loc) {
723 getTopOfStack().DefaultAttr = DSA_shared;
724 getTopOfStack().DefaultAttrLoc = Loc;
725 }
726 /// Set default data sharing attribute to private.
727 void setDefaultDSAPrivate(SourceLocation Loc) {
728 getTopOfStack().DefaultAttr = DSA_private;
729 getTopOfStack().DefaultAttrLoc = Loc;
730 }
731 /// Set default data sharing attribute to firstprivate.
732 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
733 getTopOfStack().DefaultAttr = DSA_firstprivate;
734 getTopOfStack().DefaultAttrLoc = Loc;
735 }
736 /// Set default data mapping attribute to Modifier:Kind
737 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
739 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
740 DMI.ImplicitBehavior = M;
741 DMI.SLoc = Loc;
742 }
743 /// Check whether the implicit-behavior has been set in defaultmap
744 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
745 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
746 return getTopOfStack()
747 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
748 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
749 getTopOfStack()
750 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
751 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
752 getTopOfStack()
753 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
754 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
755 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
757 }
758
759 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
760 return ConstructTraits;
761 }
762 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
763 bool ScopeEntry) {
764 if (ScopeEntry)
765 ConstructTraits.append(Traits.begin(), Traits.end());
766 else
767 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
768 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
769 assert(Top == Trait && "Something left a trait on the stack!");
770 (void)Trait;
771 (void)Top;
772 }
773 }
774
775 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
776 return getStackSize() <= Level ? DSA_unspecified
777 : getStackElemAtLevel(Level).DefaultAttr;
778 }
779 DefaultDataSharingAttributes getDefaultDSA() const {
780 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
781 }
782 SourceLocation getDefaultDSALocation() const {
783 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
784 }
786 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
787 return isStackEmpty()
789 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
790 }
792 getDefaultmapModifierAtLevel(unsigned Level,
793 OpenMPDefaultmapClauseKind Kind) const {
794 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
795 }
796 bool isDefaultmapCapturedByRef(unsigned Level,
797 OpenMPDefaultmapClauseKind Kind) const {
799 getDefaultmapModifierAtLevel(Level, Kind);
800 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
801 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
802 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_present);
806 }
807 return true;
808 }
809 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
811 switch (Kind) {
812 case OMPC_DEFAULTMAP_scalar:
813 case OMPC_DEFAULTMAP_pointer:
814 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
815 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
816 (M == OMPC_DEFAULTMAP_MODIFIER_default);
817 case OMPC_DEFAULTMAP_aggregate:
818 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
819 default:
820 break;
821 }
822 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
823 }
824 bool mustBeFirstprivateAtLevel(unsigned Level,
825 OpenMPDefaultmapClauseKind Kind) const {
827 getDefaultmapModifierAtLevel(Level, Kind);
828 return mustBeFirstprivateBase(M, Kind);
829 }
830 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
831 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
832 return mustBeFirstprivateBase(M, Kind);
833 }
834
835 /// Checks if the specified variable is a threadprivate.
836 bool isThreadPrivate(VarDecl *D) {
837 const DSAVarData DVar = getTopDSA(D, false);
838 return isOpenMPThreadPrivate(DVar.CKind);
839 }
840
841 /// Marks current region as ordered (it has an 'ordered' clause).
842 void setOrderedRegion(bool IsOrdered, const Expr *Param,
843 OMPOrderedClause *Clause) {
844 if (IsOrdered)
845 getTopOfStack().OrderedRegion.emplace(Param, Clause);
846 else
847 getTopOfStack().OrderedRegion.reset();
848 }
849 /// Returns true, if region is ordered (has associated 'ordered' clause),
850 /// false - otherwise.
851 bool isOrderedRegion() const {
852 if (const SharingMapTy *Top = getTopOfStackOrNull())
853 return Top->OrderedRegion.has_value();
854 return false;
855 }
856 /// Returns optional parameter for the ordered region.
857 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
858 if (const SharingMapTy *Top = getTopOfStackOrNull())
859 if (Top->OrderedRegion)
860 return *Top->OrderedRegion;
861 return std::make_pair(nullptr, nullptr);
862 }
863 /// Returns true, if parent region is ordered (has associated
864 /// 'ordered' clause), false - otherwise.
865 bool isParentOrderedRegion() const {
866 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
867 return Parent->OrderedRegion.has_value();
868 return false;
869 }
870 /// Returns optional parameter for the ordered region.
871 std::pair<const Expr *, OMPOrderedClause *>
872 getParentOrderedRegionParam() const {
873 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
874 if (Parent->OrderedRegion)
875 return *Parent->OrderedRegion;
876 return std::make_pair(nullptr, nullptr);
877 }
878 /// Marks current region as having an 'order' clause.
879 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
880 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
881 }
882 /// Returns true, if parent region is order (has associated
883 /// 'order' clause), false - otherwise.
884 bool isParentOrderConcurrent() const {
885 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
886 return Parent->RegionHasOrderConcurrent;
887 return false;
888 }
889 /// Marks current region as nowait (it has a 'nowait' clause).
890 void setNowaitRegion(bool IsNowait = true) {
891 getTopOfStack().NowaitRegion = IsNowait;
892 }
893 /// Returns true, if parent region is nowait (has associated
894 /// 'nowait' clause), false - otherwise.
895 bool isParentNowaitRegion() const {
896 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
897 return Parent->NowaitRegion;
898 return false;
899 }
900 /// Marks current region as untied (it has a 'untied' clause).
901 void setUntiedRegion(bool IsUntied = true) {
902 getTopOfStack().UntiedRegion = IsUntied;
903 }
904 /// Return true if current region is untied.
905 bool isUntiedRegion() const {
906 const SharingMapTy *Top = getTopOfStackOrNull();
907 return Top ? Top->UntiedRegion : false;
908 }
909 /// Marks parent region as cancel region.
910 void setParentCancelRegion(bool Cancel = true) {
911 if (SharingMapTy *Parent = getSecondOnStackOrNull())
912 Parent->CancelRegion |= Cancel;
913 }
914 /// Return true if current region has inner cancel construct.
915 bool isCancelRegion() const {
916 const SharingMapTy *Top = getTopOfStackOrNull();
917 return Top ? Top->CancelRegion : false;
918 }
919
920 /// Mark that parent region already has scan directive.
921 void setParentHasScanDirective(SourceLocation Loc) {
922 if (SharingMapTy *Parent = getSecondOnStackOrNull())
923 Parent->PrevScanLocation = Loc;
924 }
925 /// Return true if current region has inner cancel construct.
926 bool doesParentHasScanDirective() const {
927 const SharingMapTy *Top = getSecondOnStackOrNull();
928 return Top ? Top->PrevScanLocation.isValid() : false;
929 }
930 /// Return true if current region has inner cancel construct.
931 SourceLocation getParentScanDirectiveLoc() const {
932 const SharingMapTy *Top = getSecondOnStackOrNull();
933 return Top ? Top->PrevScanLocation : SourceLocation();
934 }
935 /// Mark that parent region already has ordered directive.
936 void setParentHasOrderedDirective(SourceLocation Loc) {
937 if (SharingMapTy *Parent = getSecondOnStackOrNull())
938 Parent->PrevOrderedLocation = Loc;
939 }
940 /// Return true if current region has inner ordered construct.
941 bool doesParentHasOrderedDirective() const {
942 const SharingMapTy *Top = getSecondOnStackOrNull();
943 return Top ? Top->PrevOrderedLocation.isValid() : false;
944 }
945 /// Returns the location of the previously specified ordered directive.
946 SourceLocation getParentOrderedDirectiveLoc() const {
947 const SharingMapTy *Top = getSecondOnStackOrNull();
948 return Top ? Top->PrevOrderedLocation : SourceLocation();
949 }
950
951 /// Set collapse value for the region.
952 void setAssociatedLoops(unsigned Val) {
953 getTopOfStack().AssociatedLoops = Val;
954 if (Val > 1)
955 getTopOfStack().HasMutipleLoops = true;
956 }
957 /// Return collapse value for region.
958 unsigned getAssociatedLoops() const {
959 const SharingMapTy *Top = getTopOfStackOrNull();
960 return Top ? Top->AssociatedLoops : 0;
961 }
962 /// Returns true if the construct is associated with multiple loops.
963 bool hasMutipleLoops() const {
964 const SharingMapTy *Top = getTopOfStackOrNull();
965 return Top ? Top->HasMutipleLoops : false;
966 }
967
968 /// Marks current target region as one with closely nested teams
969 /// region.
970 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
971 if (SharingMapTy *Parent = getSecondOnStackOrNull())
972 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
973 }
974 /// Returns true, if current region has closely nested teams region.
975 bool hasInnerTeamsRegion() const {
976 return getInnerTeamsRegionLoc().isValid();
977 }
978 /// Returns location of the nested teams region (if any).
979 SourceLocation getInnerTeamsRegionLoc() const {
980 const SharingMapTy *Top = getTopOfStackOrNull();
981 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
982 }
983
984 Scope *getCurScope() const {
985 const SharingMapTy *Top = getTopOfStackOrNull();
986 return Top ? Top->CurScope : nullptr;
987 }
988 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
989 SourceLocation getConstructLoc() const {
990 const SharingMapTy *Top = getTopOfStackOrNull();
991 return Top ? Top->ConstructLoc : SourceLocation();
992 }
993
994 /// Do the check specified in \a Check to all component lists and return true
995 /// if any issue is found.
996 bool checkMappableExprComponentListsForDecl(
997 const ValueDecl *VD, bool CurrentRegionOnly,
998 const llvm::function_ref<
1001 Check) const {
1002 if (isStackEmpty())
1003 return false;
1004 auto SI = begin();
1005 auto SE = end();
1006
1007 if (SI == SE)
1008 return false;
1009
1010 if (CurrentRegionOnly)
1011 SE = std::next(SI);
1012 else
1013 std::advance(SI, 1);
1014
1015 for (; SI != SE; ++SI) {
1016 auto MI = SI->MappedExprComponents.find(VD);
1017 if (MI != SI->MappedExprComponents.end())
1019 MI->second.Components)
1020 if (Check(L, MI->second.Kind))
1021 return true;
1022 }
1023 return false;
1024 }
1025
1026 /// Do the check specified in \a Check to all component lists at a given level
1027 /// and return true if any issue is found.
1028 bool checkMappableExprComponentListsForDeclAtLevel(
1029 const ValueDecl *VD, unsigned Level,
1030 const llvm::function_ref<
1033 Check) const {
1034 if (getStackSize() <= Level)
1035 return false;
1036
1037 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1038 auto MI = StackElem.MappedExprComponents.find(VD);
1039 if (MI != StackElem.MappedExprComponents.end())
1041 MI->second.Components)
1042 if (Check(L, MI->second.Kind))
1043 return true;
1044 return false;
1045 }
1046
1047 /// Create a new mappable expression component list associated with a given
1048 /// declaration and initialize it with the provided list of components.
1049 void addMappableExpressionComponents(
1050 const ValueDecl *VD,
1052 OpenMPClauseKind WhereFoundClauseKind) {
1053 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1054 // Create new entry and append the new components there.
1055 MEC.Components.resize(MEC.Components.size() + 1);
1056 MEC.Components.back().append(Components.begin(), Components.end());
1057 MEC.Kind = WhereFoundClauseKind;
1058 }
1059
1060 unsigned getNestingLevel() const {
1061 assert(!isStackEmpty());
1062 return getStackSize() - 1;
1063 }
1064 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1065 SharingMapTy *Parent = getSecondOnStackOrNull();
1066 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1067 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1068 }
1069 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1070 getDoacrossDependClauses() const {
1071 const SharingMapTy &StackElem = getTopOfStack();
1072 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1073 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1074 return llvm::make_range(Ref.begin(), Ref.end());
1075 }
1076 return llvm::make_range(StackElem.DoacrossDepends.end(),
1077 StackElem.DoacrossDepends.end());
1078 }
1079
1080 // Store types of classes which have been explicitly mapped
1081 void addMappedClassesQualTypes(QualType QT) {
1082 SharingMapTy &StackElem = getTopOfStack();
1083 StackElem.MappedClassesQualTypes.insert(QT);
1084 }
1085
1086 // Return set of mapped classes types
1087 bool isClassPreviouslyMapped(QualType QT) const {
1088 const SharingMapTy &StackElem = getTopOfStack();
1089 return StackElem.MappedClassesQualTypes.contains(QT);
1090 }
1091
1092 /// Adds global declare target to the parent target region.
1093 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1094 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1095 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1096 "Expected declare target link global.");
1097 for (auto &Elem : *this) {
1098 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1099 Elem.DeclareTargetLinkVarDecls.push_back(E);
1100 return;
1101 }
1102 }
1103 }
1104
1105 /// Returns the list of globals with declare target link if current directive
1106 /// is target.
1107 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1108 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1109 "Expected target executable directive.");
1110 return getTopOfStack().DeclareTargetLinkVarDecls;
1111 }
1112
1113 /// Adds list of allocators expressions.
1114 void addInnerAllocatorExpr(Expr *E) {
1115 getTopOfStack().InnerUsedAllocators.push_back(E);
1116 }
1117 /// Return list of used allocators.
1118 ArrayRef<Expr *> getInnerAllocators() const {
1119 return getTopOfStack().InnerUsedAllocators;
1120 }
1121 /// Marks the declaration as implicitly firstprivate nin the task-based
1122 /// regions.
1123 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1124 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1125 }
1126 /// Checks if the decl is implicitly firstprivate in the task-based region.
1127 bool isImplicitTaskFirstprivate(Decl *D) const {
1128 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1129 }
1130
1131 /// Marks decl as used in uses_allocators clause as the allocator.
1132 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1133 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1134 }
1135 /// Checks if specified decl is used in uses allocator clause as the
1136 /// allocator.
1137 std::optional<UsesAllocatorsDeclKind>
1138 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1139 const SharingMapTy &StackElem = getTopOfStack();
1140 auto I = StackElem.UsesAllocatorsDecls.find(D);
1141 if (I == StackElem.UsesAllocatorsDecls.end())
1142 return std::nullopt;
1143 return I->getSecond();
1144 }
1145 std::optional<UsesAllocatorsDeclKind>
1146 isUsesAllocatorsDecl(const Decl *D) const {
1147 const SharingMapTy &StackElem = getTopOfStack();
1148 auto I = StackElem.UsesAllocatorsDecls.find(D);
1149 if (I == StackElem.UsesAllocatorsDecls.end())
1150 return std::nullopt;
1151 return I->getSecond();
1152 }
1153
1154 void addDeclareMapperVarRef(Expr *Ref) {
1155 SharingMapTy &StackElem = getTopOfStack();
1156 StackElem.DeclareMapperVar = Ref;
1157 }
1158 const Expr *getDeclareMapperVarRef() const {
1159 const SharingMapTy *Top = getTopOfStackOrNull();
1160 return Top ? Top->DeclareMapperVar : nullptr;
1161 }
1162
1163 /// Add a new iterator variable.
1164 void addIteratorVarDecl(VarDecl *VD) {
1165 SharingMapTy &StackElem = getTopOfStack();
1166 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1167 }
1168 /// Check if variable declaration is an iterator VarDecl.
1169 bool isIteratorVarDecl(const VarDecl *VD) const {
1170 const SharingMapTy *Top = getTopOfStackOrNull();
1171 if (!Top)
1172 return false;
1173
1174 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1175 }
1176 /// get captured field from ImplicitDefaultFirstprivateFDs
1177 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1178 const_iterator I = begin();
1179 const_iterator EndI = end();
1180 size_t StackLevel = getStackSize();
1181 for (; I != EndI; ++I) {
1182 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1183 break;
1184 StackLevel--;
1185 }
1186 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1187 if (I == EndI)
1188 return nullptr;
1189 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1190 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1191 return IFD.VD;
1192 return nullptr;
1193 }
1194 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1195 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1196 const_iterator I = begin();
1197 const_iterator EndI = end();
1198 for (; I != EndI; ++I)
1199 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1200 break;
1201 if (I == EndI)
1202 return false;
1203 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1204 if (IFD.VD == VD)
1205 return true;
1206 return false;
1207 }
1208 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1209 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1210 iterator I = begin();
1211 const_iterator EndI = end();
1212 size_t StackLevel = getStackSize();
1213 for (; I != EndI; ++I) {
1214 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1215 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1216 break;
1217 }
1218 StackLevel--;
1219 }
1220 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1221 }
1222};
1223
1224bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1225 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1226}
1227
1228bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1229 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1230 DKind == OMPD_unknown;
1231}
1232
1233} // namespace
1234
1235static const Expr *getExprAsWritten(const Expr *E) {
1236 if (const auto *FE = dyn_cast<FullExpr>(E))
1237 E = FE->getSubExpr();
1238
1239 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1240 E = MTE->getSubExpr();
1241
1242 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1243 E = Binder->getSubExpr();
1244
1245 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1246 E = ICE->getSubExprAsWritten();
1247 return E->IgnoreParens();
1248}
1249
1251 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1252}
1253
1254static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1255 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1256 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1257 D = ME->getMemberDecl();
1258 const auto *VD = dyn_cast<VarDecl>(D);
1259 const auto *FD = dyn_cast<FieldDecl>(D);
1260 if (VD != nullptr) {
1261 VD = VD->getCanonicalDecl();
1262 D = VD;
1263 } else {
1264 assert(FD);
1265 FD = FD->getCanonicalDecl();
1266 D = FD;
1267 }
1268 return D;
1269}
1270
1272 return const_cast<ValueDecl *>(
1273 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1274}
1275
1276DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1277 ValueDecl *D) const {
1278 D = getCanonicalDecl(D);
1279 auto *VD = dyn_cast<VarDecl>(D);
1280 const auto *FD = dyn_cast<FieldDecl>(D);
1281 DSAVarData DVar;
1282 if (Iter == end()) {
1283 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1284 // in a region but not in construct]
1285 // File-scope or namespace-scope variables referenced in called routines
1286 // in the region are shared unless they appear in a threadprivate
1287 // directive.
1288 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1289 DVar.CKind = OMPC_shared;
1290
1291 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1292 // in a region but not in construct]
1293 // Variables with static storage duration that are declared in called
1294 // routines in the region are shared.
1295 if (VD && VD->hasGlobalStorage())
1296 DVar.CKind = OMPC_shared;
1297
1298 // Non-static data members are shared by default.
1299 if (FD)
1300 DVar.CKind = OMPC_shared;
1301
1302 return DVar;
1303 }
1304
1305 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1306 // in a Construct, C/C++, predetermined, p.1]
1307 // Variables with automatic storage duration that are declared in a scope
1308 // inside the construct are private.
1309 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1310 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1311 DVar.CKind = OMPC_private;
1312 return DVar;
1313 }
1314
1315 DVar.DKind = Iter->Directive;
1316 // Explicitly specified attributes and local variables with predetermined
1317 // attributes.
1318 if (Iter->SharingMap.count(D)) {
1319 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1320 DVar.RefExpr = Data.RefExpr.getPointer();
1321 DVar.PrivateCopy = Data.PrivateCopy;
1322 DVar.CKind = Data.Attributes;
1323 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1324 DVar.Modifier = Data.Modifier;
1325 DVar.AppliedToPointee = Data.AppliedToPointee;
1326 return DVar;
1327 }
1328
1329 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1330 // in a Construct, C/C++, implicitly determined, p.1]
1331 // In a parallel or task construct, the data-sharing attributes of these
1332 // variables are determined by the default clause, if present.
1333 switch (Iter->DefaultAttr) {
1334 case DSA_shared:
1335 DVar.CKind = OMPC_shared;
1336 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1337 return DVar;
1338 case DSA_none:
1339 return DVar;
1340 case DSA_firstprivate:
1341 if (VD && VD->getStorageDuration() == SD_Static &&
1342 VD->getDeclContext()->isFileContext()) {
1343 DVar.CKind = OMPC_unknown;
1344 } else {
1345 DVar.CKind = OMPC_firstprivate;
1346 }
1347 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1348 return DVar;
1349 case DSA_private:
1350 // each variable with static storage duration that is declared
1351 // in a namespace or global scope and referenced in the construct,
1352 // and that does not have a predetermined data-sharing attribute
1353 if (VD && VD->getStorageDuration() == SD_Static &&
1354 VD->getDeclContext()->isFileContext()) {
1355 DVar.CKind = OMPC_unknown;
1356 } else {
1357 DVar.CKind = OMPC_private;
1358 }
1359 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1360 return DVar;
1361 case DSA_unspecified:
1362 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1363 // in a Construct, implicitly determined, p.2]
1364 // In a parallel construct, if no default clause is present, these
1365 // variables are shared.
1366 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1367 if ((isOpenMPParallelDirective(DVar.DKind) &&
1368 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1369 isOpenMPTeamsDirective(DVar.DKind)) {
1370 DVar.CKind = OMPC_shared;
1371 return DVar;
1372 }
1373
1374 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1375 // in a Construct, implicitly determined, p.4]
1376 // In a task construct, if no default clause is present, a variable that in
1377 // the enclosing context is determined to be shared by all implicit tasks
1378 // bound to the current team is shared.
1379 if (isOpenMPTaskingDirective(DVar.DKind)) {
1380 DSAVarData DVarTemp;
1381 const_iterator I = Iter, E = end();
1382 do {
1383 ++I;
1384 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1385 // Referenced in a Construct, implicitly determined, p.6]
1386 // In a task construct, if no default clause is present, a variable
1387 // whose data-sharing attribute is not determined by the rules above is
1388 // firstprivate.
1389 DVarTemp = getDSA(I, D);
1390 if (DVarTemp.CKind != OMPC_shared) {
1391 DVar.RefExpr = nullptr;
1392 DVar.CKind = OMPC_firstprivate;
1393 return DVar;
1394 }
1395 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1396 DVar.CKind =
1397 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1398 return DVar;
1399 }
1400 }
1401 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1402 // in a Construct, implicitly determined, p.3]
1403 // For constructs other than task, if no default clause is present, these
1404 // variables inherit their data-sharing attributes from the enclosing
1405 // context.
1406 return getDSA(++Iter, D);
1407}
1408
1409const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1410 const Expr *NewDE) {
1411 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1412 D = getCanonicalDecl(D);
1413 SharingMapTy &StackElem = getTopOfStack();
1414 auto It = StackElem.AlignedMap.find(D);
1415 if (It == StackElem.AlignedMap.end()) {
1416 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1417 StackElem.AlignedMap[D] = NewDE;
1418 return nullptr;
1419 }
1420 assert(It->second && "Unexpected nullptr expr in the aligned map");
1421 return It->second;
1422}
1423
1424const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1425 const Expr *NewDE) {
1426 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1427 D = getCanonicalDecl(D);
1428 SharingMapTy &StackElem = getTopOfStack();
1429 auto It = StackElem.NontemporalMap.find(D);
1430 if (It == StackElem.NontemporalMap.end()) {
1431 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1432 StackElem.NontemporalMap[D] = NewDE;
1433 return nullptr;
1434 }
1435 assert(It->second && "Unexpected nullptr expr in the aligned map");
1436 return It->second;
1437}
1438
1439void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1440 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1441 D = getCanonicalDecl(D);
1442 SharingMapTy &StackElem = getTopOfStack();
1443 StackElem.LCVMap.try_emplace(
1444 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1445}
1446
1447const DSAStackTy::LCDeclInfo
1448DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1449 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1450 D = getCanonicalDecl(D);
1451 const SharingMapTy &StackElem = getTopOfStack();
1452 auto It = StackElem.LCVMap.find(D);
1453 if (It != StackElem.LCVMap.end())
1454 return It->second;
1455 return {0, nullptr};
1456}
1457
1458const DSAStackTy::LCDeclInfo
1459DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1460 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1461 D = getCanonicalDecl(D);
1462 for (unsigned I = Level + 1; I > 0; --I) {
1463 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1464 auto It = StackElem.LCVMap.find(D);
1465 if (It != StackElem.LCVMap.end())
1466 return It->second;
1467 }
1468 return {0, nullptr};
1469}
1470
1471const DSAStackTy::LCDeclInfo
1472DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1473 const SharingMapTy *Parent = getSecondOnStackOrNull();
1474 assert(Parent && "Data-sharing attributes stack is empty");
1475 D = getCanonicalDecl(D);
1476 auto It = Parent->LCVMap.find(D);
1477 if (It != Parent->LCVMap.end())
1478 return It->second;
1479 return {0, nullptr};
1480}
1481
1482const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1483 const SharingMapTy *Parent = getSecondOnStackOrNull();
1484 assert(Parent && "Data-sharing attributes stack is empty");
1485 if (Parent->LCVMap.size() < I)
1486 return nullptr;
1487 for (const auto &Pair : Parent->LCVMap)
1488 if (Pair.second.first == I)
1489 return Pair.first;
1490 return nullptr;
1491}
1492
1493void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1494 DeclRefExpr *PrivateCopy, unsigned Modifier,
1495 bool AppliedToPointee) {
1496 D = getCanonicalDecl(D);
1497 if (A == OMPC_threadprivate) {
1498 DSAInfo &Data = Threadprivates[D];
1499 Data.Attributes = A;
1500 Data.RefExpr.setPointer(E);
1501 Data.PrivateCopy = nullptr;
1502 Data.Modifier = Modifier;
1503 } else {
1504 DSAInfo &Data = getTopOfStack().SharingMap[D];
1505 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1506 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1507 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1508 (isLoopControlVariable(D).first && A == OMPC_private));
1509 Data.Modifier = Modifier;
1510 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1511 Data.RefExpr.setInt(/*IntVal=*/true);
1512 return;
1513 }
1514 const bool IsLastprivate =
1515 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1516 Data.Attributes = A;
1517 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1518 Data.PrivateCopy = PrivateCopy;
1519 Data.AppliedToPointee = AppliedToPointee;
1520 if (PrivateCopy) {
1521 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1522 Data.Modifier = Modifier;
1523 Data.Attributes = A;
1524 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1525 Data.PrivateCopy = nullptr;
1526 Data.AppliedToPointee = AppliedToPointee;
1527 }
1528 }
1529}
1530
1531/// Build a variable declaration for OpenMP loop iteration variable.
1533 StringRef Name, const AttrVec *Attrs = nullptr,
1534 DeclRefExpr *OrigRef = nullptr) {
1535 DeclContext *DC = SemaRef.CurContext;
1536 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1538 auto *Decl =
1539 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1540 if (Attrs) {
1541 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1542 I != E; ++I)
1543 Decl->addAttr(*I);
1544 }
1545 Decl->setImplicit();
1546 if (OrigRef) {
1547 Decl->addAttr(
1548 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1549 }
1550 return Decl;
1551}
1552
1555 bool RefersToCapture = false) {
1556 D->setReferenced();
1557 D->markUsed(S.Context);
1559 SourceLocation(), D, RefersToCapture, Loc, Ty,
1560 VK_LValue);
1561}
1562
1563void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1564 BinaryOperatorKind BOK) {
1565 D = getCanonicalDecl(D);
1566 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1567 assert(
1568 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1569 "Additional reduction info may be specified only for reduction items.");
1570 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1571 assert(ReductionData.ReductionRange.isInvalid() &&
1572 (getTopOfStack().Directive == OMPD_taskgroup ||
1573 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1574 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1575 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1576 "Additional reduction info may be specified only once for reduction "
1577 "items.");
1578 ReductionData.set(BOK, SR);
1579 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1580 if (!TaskgroupReductionRef) {
1581 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1582 SemaRef.Context.VoidPtrTy, ".task_red.");
1583 TaskgroupReductionRef =
1584 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1585 }
1586}
1587
1588void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1589 const Expr *ReductionRef) {
1590 D = getCanonicalDecl(D);
1591 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1592 assert(
1593 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1594 "Additional reduction info may be specified only for reduction items.");
1595 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1596 assert(ReductionData.ReductionRange.isInvalid() &&
1597 (getTopOfStack().Directive == OMPD_taskgroup ||
1598 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1599 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1600 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1601 "Additional reduction info may be specified only once for reduction "
1602 "items.");
1603 ReductionData.set(ReductionRef, SR);
1604 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1605 if (!TaskgroupReductionRef) {
1606 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1607 SemaRef.Context.VoidPtrTy, ".task_red.");
1608 TaskgroupReductionRef =
1609 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1610 }
1611}
1612
1613const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1614 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1615 Expr *&TaskgroupDescriptor) const {
1616 D = getCanonicalDecl(D);
1617 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1618 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1619 const DSAInfo &Data = I->SharingMap.lookup(D);
1620 if (Data.Attributes != OMPC_reduction ||
1621 Data.Modifier != OMPC_REDUCTION_task)
1622 continue;
1623 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1624 if (!ReductionData.ReductionOp ||
1625 ReductionData.ReductionOp.is<const Expr *>())
1626 return DSAVarData();
1627 SR = ReductionData.ReductionRange;
1628 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1629 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1630 "expression for the descriptor is not "
1631 "set.");
1632 TaskgroupDescriptor = I->TaskgroupReductionRef;
1633 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1634 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1635 /*AppliedToPointee=*/false);
1636 }
1637 return DSAVarData();
1638}
1639
1640const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1641 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1642 Expr *&TaskgroupDescriptor) const {
1643 D = getCanonicalDecl(D);
1644 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1645 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1646 const DSAInfo &Data = I->SharingMap.lookup(D);
1647 if (Data.Attributes != OMPC_reduction ||
1648 Data.Modifier != OMPC_REDUCTION_task)
1649 continue;
1650 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1651 if (!ReductionData.ReductionOp ||
1652 !ReductionData.ReductionOp.is<const Expr *>())
1653 return DSAVarData();
1654 SR = ReductionData.ReductionRange;
1655 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1656 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1657 "expression for the descriptor is not "
1658 "set.");
1659 TaskgroupDescriptor = I->TaskgroupReductionRef;
1660 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1661 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1662 /*AppliedToPointee=*/false);
1663 }
1664 return DSAVarData();
1665}
1666
1667bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1668 D = D->getCanonicalDecl();
1669 for (const_iterator E = end(); I != E; ++I) {
1670 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1671 isOpenMPTargetExecutionDirective(I->Directive)) {
1672 if (I->CurScope) {
1673 Scope *TopScope = I->CurScope->getParent();
1674 Scope *CurScope = getCurScope();
1675 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1676 CurScope = CurScope->getParent();
1677 return CurScope != TopScope;
1678 }
1679 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1680 if (I->Context == DC)
1681 return true;
1682 return false;
1683 }
1684 }
1685 return false;
1686}
1687
1689 bool AcceptIfMutable = true,
1690 bool *IsClassType = nullptr) {
1691 ASTContext &Context = SemaRef.getASTContext();
1692 Type = Type.getNonReferenceType().getCanonicalType();
1693 bool IsConstant = Type.isConstant(Context);
1694 Type = Context.getBaseElementType(Type);
1695 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1697 : nullptr;
1698 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1699 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1700 RD = CTD->getTemplatedDecl();
1701 if (IsClassType)
1702 *IsClassType = RD;
1703 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1704 RD->hasDefinition() && RD->hasMutableFields());
1705}
1706
1707static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1709 SourceLocation ELoc,
1710 bool AcceptIfMutable = true,
1711 bool ListItemNotVar = false) {
1712 ASTContext &Context = SemaRef.getASTContext();
1713 bool IsClassType;
1714 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1715 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1716 : IsClassType ? diag::err_omp_const_not_mutable_variable
1717 : diag::err_omp_const_variable;
1718 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1719 if (!ListItemNotVar && D) {
1720 const VarDecl *VD = dyn_cast<VarDecl>(D);
1721 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1723 SemaRef.Diag(D->getLocation(),
1724 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1725 << D;
1726 }
1727 return true;
1728 }
1729 return false;
1730}
1731
1732const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1733 bool FromParent) {
1734 D = getCanonicalDecl(D);
1735 DSAVarData DVar;
1736
1737 auto *VD = dyn_cast<VarDecl>(D);
1738 auto TI = Threadprivates.find(D);
1739 if (TI != Threadprivates.end()) {
1740 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1741 DVar.CKind = OMPC_threadprivate;
1742 DVar.Modifier = TI->getSecond().Modifier;
1743 return DVar;
1744 }
1745 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1746 DVar.RefExpr = buildDeclRefExpr(
1747 SemaRef, VD, D->getType().getNonReferenceType(),
1748 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1749 DVar.CKind = OMPC_threadprivate;
1750 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1751 return DVar;
1752 }
1753 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1754 // in a Construct, C/C++, predetermined, p.1]
1755 // Variables appearing in threadprivate directives are threadprivate.
1756 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1757 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1758 SemaRef.getLangOpts().OpenMPUseTLS &&
1759 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1760 (VD && VD->getStorageClass() == SC_Register &&
1761 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1762 DVar.RefExpr = buildDeclRefExpr(
1763 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1764 DVar.CKind = OMPC_threadprivate;
1765 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1766 return DVar;
1767 }
1768 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1769 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1770 !isLoopControlVariable(D).first) {
1771 const_iterator IterTarget =
1772 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1773 return isOpenMPTargetExecutionDirective(Data.Directive);
1774 });
1775 if (IterTarget != end()) {
1776 const_iterator ParentIterTarget = IterTarget + 1;
1777 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1778 if (isOpenMPLocal(VD, Iter)) {
1779 DVar.RefExpr =
1780 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1781 D->getLocation());
1782 DVar.CKind = OMPC_threadprivate;
1783 return DVar;
1784 }
1785 }
1786 if (!isClauseParsingMode() || IterTarget != begin()) {
1787 auto DSAIter = IterTarget->SharingMap.find(D);
1788 if (DSAIter != IterTarget->SharingMap.end() &&
1789 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1790 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1791 DVar.CKind = OMPC_threadprivate;
1792 return DVar;
1793 }
1794 const_iterator End = end();
1795 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1796 D, std::distance(ParentIterTarget, End),
1797 /*OpenMPCaptureLevel=*/0)) {
1798 DVar.RefExpr =
1799 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1800 IterTarget->ConstructLoc);
1801 DVar.CKind = OMPC_threadprivate;
1802 return DVar;
1803 }
1804 }
1805 }
1806 }
1807
1808 if (isStackEmpty())
1809 // Not in OpenMP execution region and top scope was already checked.
1810 return DVar;
1811
1812 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1813 // in a Construct, C/C++, predetermined, p.4]
1814 // Static data members are shared.
1815 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1816 // in a Construct, C/C++, predetermined, p.7]
1817 // Variables with static storage duration that are declared in a scope
1818 // inside the construct are shared.
1819 if (VD && VD->isStaticDataMember()) {
1820 // Check for explicitly specified attributes.
1821 const_iterator I = begin();
1822 const_iterator EndI = end();
1823 if (FromParent && I != EndI)
1824 ++I;
1825 if (I != EndI) {
1826 auto It = I->SharingMap.find(D);
1827 if (It != I->SharingMap.end()) {
1828 const DSAInfo &Data = It->getSecond();
1829 DVar.RefExpr = Data.RefExpr.getPointer();
1830 DVar.PrivateCopy = Data.PrivateCopy;
1831 DVar.CKind = Data.Attributes;
1832 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1833 DVar.DKind = I->Directive;
1834 DVar.Modifier = Data.Modifier;
1835 DVar.AppliedToPointee = Data.AppliedToPointee;
1836 return DVar;
1837 }
1838 }
1839
1840 DVar.CKind = OMPC_shared;
1841 return DVar;
1842 }
1843
1844 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1845 // The predetermined shared attribute for const-qualified types having no
1846 // mutable members was removed after OpenMP 3.1.
1847 if (SemaRef.LangOpts.OpenMP <= 31) {
1848 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1849 // in a Construct, C/C++, predetermined, p.6]
1850 // Variables with const qualified type having no mutable member are
1851 // shared.
1852 if (isConstNotMutableType(SemaRef, D->getType())) {
1853 // Variables with const-qualified type having no mutable member may be
1854 // listed in a firstprivate clause, even if they are static data members.
1855 DSAVarData DVarTemp = hasInnermostDSA(
1856 D,
1857 [](OpenMPClauseKind C, bool) {
1858 return C == OMPC_firstprivate || C == OMPC_shared;
1859 },
1860 MatchesAlways, FromParent);
1861 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1862 return DVarTemp;
1863
1864 DVar.CKind = OMPC_shared;
1865 return DVar;
1866 }
1867 }
1868
1869 // Explicitly specified attributes and local variables with predetermined
1870 // attributes.
1871 const_iterator I = begin();
1872 const_iterator EndI = end();
1873 if (FromParent && I != EndI)
1874 ++I;
1875 if (I == EndI)
1876 return DVar;
1877 auto It = I->SharingMap.find(D);
1878 if (It != I->SharingMap.end()) {
1879 const DSAInfo &Data = It->getSecond();
1880 DVar.RefExpr = Data.RefExpr.getPointer();
1881 DVar.PrivateCopy = Data.PrivateCopy;
1882 DVar.CKind = Data.Attributes;
1883 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1884 DVar.DKind = I->Directive;
1885 DVar.Modifier = Data.Modifier;
1886 DVar.AppliedToPointee = Data.AppliedToPointee;
1887 }
1888
1889 return DVar;
1890}
1891
1892const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1893 bool FromParent) const {
1894 if (isStackEmpty()) {
1895 const_iterator I;
1896 return getDSA(I, D);
1897 }
1898 D = getCanonicalDecl(D);
1899 const_iterator StartI = begin();
1900 const_iterator EndI = end();
1901 if (FromParent && StartI != EndI)
1902 ++StartI;
1903 return getDSA(StartI, D);
1904}
1905
1906const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1907 unsigned Level) const {
1908 if (getStackSize() <= Level)
1909 return DSAVarData();
1910 D = getCanonicalDecl(D);
1911 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1912 return getDSA(StartI, D);
1913}
1914
1915const DSAStackTy::DSAVarData
1916DSAStackTy::hasDSA(ValueDecl *D,
1917 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1918 DefaultDataSharingAttributes)>
1919 CPred,
1920 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1921 bool FromParent) const {
1922 if (isStackEmpty())
1923 return {};
1924 D = getCanonicalDecl(D);
1925 const_iterator I = begin();
1926 const_iterator EndI = end();
1927 if (FromParent && I != EndI)
1928 ++I;
1929 for (; I != EndI; ++I) {
1930 if (!DPred(I->Directive) &&
1931 !isImplicitOrExplicitTaskingRegion(I->Directive))
1932 continue;
1933 const_iterator NewI = I;
1934 DSAVarData DVar = getDSA(NewI, D);
1935 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1936 return DVar;
1937 }
1938 return {};
1939}
1940
1941const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1942 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1943 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1944 bool FromParent) const {
1945 if (isStackEmpty())
1946 return {};
1947 D = getCanonicalDecl(D);
1948 const_iterator StartI = begin();
1949 const_iterator EndI = end();
1950 if (FromParent && StartI != EndI)
1951 ++StartI;
1952 if (StartI == EndI || !DPred(StartI->Directive))
1953 return {};
1954 const_iterator NewI = StartI;
1955 DSAVarData DVar = getDSA(NewI, D);
1956 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1957 ? DVar
1958 : DSAVarData();
1959}
1960
1961bool DSAStackTy::hasExplicitDSA(
1962 const ValueDecl *D,
1963 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1964 unsigned Level, bool NotLastprivate) const {
1965 if (getStackSize() <= Level)
1966 return false;
1967 D = getCanonicalDecl(D);
1968 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1969 auto I = StackElem.SharingMap.find(D);
1970 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1971 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1972 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1973 return true;
1974 // Check predetermined rules for the loop control variables.
1975 auto LI = StackElem.LCVMap.find(D);
1976 if (LI != StackElem.LCVMap.end())
1977 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1978 return false;
1979}
1980
1981bool DSAStackTy::hasExplicitDirective(
1982 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1983 unsigned Level) const {
1984 if (getStackSize() <= Level)
1985 return false;
1986 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1987 return DPred(StackElem.Directive);
1988}
1989
1990bool DSAStackTy::hasDirective(
1991 const llvm::function_ref<bool(OpenMPDirectiveKind,
1993 DPred,
1994 bool FromParent) const {
1995 // We look only in the enclosing region.
1996 size_t Skip = FromParent ? 2 : 1;
1997 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1998 I != E; ++I) {
1999 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2000 return true;
2001 }
2002 return false;
2003}
2004
2005void SemaOpenMP::InitDataSharingAttributesStack() {
2006 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2007}
2008
2009#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2010
2011void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2012
2013void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2014 DSAStack->popFunction(OldFSI);
2015}
2016
2018 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2019 "Expected OpenMP device compilation.");
2021}
2022
2023namespace {
2024/// Status of the function emission on the host/device.
2025enum class FunctionEmissionStatus {
2026 Emitted,
2027 Discarded,
2028 Unknown,
2029};
2030} // anonymous namespace
2031
2034 const FunctionDecl *FD) {
2035 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2036 "Expected OpenMP device compilation.");
2037
2038 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2039 if (FD) {
2041 switch (FES) {
2043 Kind = SemaDiagnosticBuilder::K_Immediate;
2044 break;
2046 // TODO: We should always delay diagnostics here in case a target
2047 // region is in a function we do not emit. However, as the
2048 // current diagnostics are associated with the function containing
2049 // the target region and we do not emit that one, we would miss out
2050 // on diagnostics for the target region itself. We need to anchor
2051 // the diagnostics with the new generated function *or* ensure we
2052 // emit diagnostics associated with the surrounding function.
2054 ? SemaDiagnosticBuilder::K_Deferred
2055 : SemaDiagnosticBuilder::K_Immediate;
2056 break;
2059 Kind = SemaDiagnosticBuilder::K_Nop;
2060 break;
2062 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2063 break;
2064 }
2065 }
2066
2067 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2068}
2069
2072 const FunctionDecl *FD) {
2073 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2074 "Expected OpenMP host compilation.");
2075
2076 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2077 if (FD) {
2079 switch (FES) {
2081 Kind = SemaDiagnosticBuilder::K_Immediate;
2082 break;
2084 Kind = SemaDiagnosticBuilder::K_Deferred;
2085 break;
2089 Kind = SemaDiagnosticBuilder::K_Nop;
2090 break;
2091 }
2092 }
2093
2094 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2095}
2096
2099 if (LO.OpenMP <= 45) {
2101 return OMPC_DEFAULTMAP_scalar;
2102 return OMPC_DEFAULTMAP_aggregate;
2103 }
2105 return OMPC_DEFAULTMAP_pointer;
2107 return OMPC_DEFAULTMAP_scalar;
2108 return OMPC_DEFAULTMAP_aggregate;
2109}
2110
2112 unsigned OpenMPCaptureLevel) const {
2113 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2114
2115 ASTContext &Ctx = getASTContext();
2116 bool IsByRef = true;
2117
2118 // Find the directive that is associated with the provided scope.
2119 D = cast<ValueDecl>(D->getCanonicalDecl());
2120 QualType Ty = D->getType();
2121
2122 bool IsVariableUsedInMapClause = false;
2123 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2124 // This table summarizes how a given variable should be passed to the device
2125 // given its type and the clauses where it appears. This table is based on
2126 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2127 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2128 //
2129 // =========================================================================
2130 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2131 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2132 // =========================================================================
2133 // | scl | | | | - | | bycopy|
2134 // | scl | | - | x | - | - | bycopy|
2135 // | scl | | x | - | - | - | null |
2136 // | scl | x | | | - | | byref |
2137 // | scl | x | - | x | - | - | bycopy|
2138 // | scl | x | x | - | - | - | null |
2139 // | scl | | - | - | - | x | byref |
2140 // | scl | x | - | - | - | x | byref |
2141 //
2142 // | agg | n.a. | | | - | | byref |
2143 // | agg | n.a. | - | x | - | - | byref |
2144 // | agg | n.a. | x | - | - | - | null |
2145 // | agg | n.a. | - | - | - | x | byref |
2146 // | agg | n.a. | - | - | - | x[] | byref |
2147 //
2148 // | ptr | n.a. | | | - | | bycopy|
2149 // | ptr | n.a. | - | x | - | - | bycopy|
2150 // | ptr | n.a. | x | - | - | - | null |
2151 // | ptr | n.a. | - | - | - | x | byref |
2152 // | ptr | n.a. | - | - | - | x[] | bycopy|
2153 // | ptr | n.a. | - | - | x | | bycopy|
2154 // | ptr | n.a. | - | - | x | x | bycopy|
2155 // | ptr | n.a. | - | - | x | x[] | bycopy|
2156 // =========================================================================
2157 // Legend:
2158 // scl - scalar
2159 // ptr - pointer
2160 // agg - aggregate
2161 // x - applies
2162 // - - invalid in this combination
2163 // [] - mapped with an array section
2164 // byref - should be mapped by reference
2165 // byval - should be mapped by value
2166 // null - initialize a local variable to null on the device
2167 //
2168 // Observations:
2169 // - All scalar declarations that show up in a map clause have to be passed
2170 // by reference, because they may have been mapped in the enclosing data
2171 // environment.
2172 // - If the scalar value does not fit the size of uintptr, it has to be
2173 // passed by reference, regardless the result in the table above.
2174 // - For pointers mapped by value that have either an implicit map or an
2175 // array section, the runtime library may pass the NULL value to the
2176 // device instead of the value passed to it by the compiler.
2177
2178 if (Ty->isReferenceType())
2179 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2180
2181 // Locate map clauses and see if the variable being captured is referred to
2182 // in any of those clauses. Here we only care about variables, not fields,
2183 // because fields are part of aggregates.
2184 bool IsVariableAssociatedWithSection = false;
2185
2186 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2187 D, Level,
2188 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2190 MapExprComponents,
2191 OpenMPClauseKind WhereFoundClauseKind) {
2192 // Both map and has_device_addr clauses information influences how a
2193 // variable is captured. E.g. is_device_ptr does not require changing
2194 // the default behavior.
2195 if (WhereFoundClauseKind != OMPC_map &&
2196 WhereFoundClauseKind != OMPC_has_device_addr)
2197 return false;
2198
2199 auto EI = MapExprComponents.rbegin();
2200 auto EE = MapExprComponents.rend();
2201
2202 assert(EI != EE && "Invalid map expression!");
2203
2204 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2205 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2206
2207 ++EI;
2208 if (EI == EE)
2209 return false;
2210 auto Last = std::prev(EE);
2211 const auto *UO =
2212 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2213 if ((UO && UO->getOpcode() == UO_Deref) ||
2214 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2215 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2216 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2217 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2218 IsVariableAssociatedWithSection = true;
2219 // There is nothing more we need to know about this variable.
2220 return true;
2221 }
2222
2223 // Keep looking for more map info.
2224 return false;
2225 });
2226
2227 if (IsVariableUsedInMapClause) {
2228 // If variable is identified in a map clause it is always captured by
2229 // reference except if it is a pointer that is dereferenced somehow.
2230 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2231 } else {
2232 // By default, all the data that has a scalar type is mapped by copy
2233 // (except for reduction variables).
2234 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2235 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2236 !Ty->isAnyPointerType()) ||
2237 !Ty->isScalarType() ||
2238 DSAStack->isDefaultmapCapturedByRef(
2240 DSAStack->hasExplicitDSA(
2241 D,
2242 [](OpenMPClauseKind K, bool AppliedToPointee) {
2243 return K == OMPC_reduction && !AppliedToPointee;
2244 },
2245 Level);
2246 }
2247 }
2248
2249 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2250 IsByRef =
2251 ((IsVariableUsedInMapClause &&
2252 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2253 OMPD_target) ||
2254 !(DSAStack->hasExplicitDSA(
2255 D,
2256 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2257 return K == OMPC_firstprivate ||
2258 (K == OMPC_reduction && AppliedToPointee);
2259 },
2260 Level, /*NotLastprivate=*/true) ||
2261 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2262 // If the variable is artificial and must be captured by value - try to
2263 // capture by value.
2264 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2265 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2266 // If the variable is implicitly firstprivate and scalar - capture by
2267 // copy
2268 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2269 DSAStack->getDefaultDSA() == DSA_private) &&
2270 !DSAStack->hasExplicitDSA(
2271 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2272 Level) &&
2273 !DSAStack->isLoopControlVariable(D, Level).first);
2274 }
2275
2276 // When passing data by copy, we need to make sure it fits the uintptr size
2277 // and alignment, because the runtime library only deals with uintptr types.
2278 // If it does not fit the uintptr size, we need to pass the data by reference
2279 // instead.
2280 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2282 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2283 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2284 IsByRef = true;
2285 }
2286
2287 return IsByRef;
2288}
2289
2290unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2291 assert(getLangOpts().OpenMP);
2292 return DSAStack->getNestingLevel();
2293}
2294
2296 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2297 DSAStack->isUntiedRegion();
2298}
2299
2301 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2302 !DSAStack->isClauseParsingMode()) ||
2303 DSAStack->hasDirective(
2305 SourceLocation) -> bool {
2307 },
2308 false);
2309}
2310
2312 // Only rebuild for Field.
2313 if (!dyn_cast<FieldDecl>(D))
2314 return false;
2315 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2316 D,
2317 [](OpenMPClauseKind C, bool AppliedToPointee,
2318 DefaultDataSharingAttributes DefaultAttr) {
2319 return isOpenMPPrivate(C) && !AppliedToPointee &&
2320 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2321 },
2322 [](OpenMPDirectiveKind) { return true; },
2323 DSAStack->isClauseParsingMode());
2324 if (DVarPrivate.CKind != OMPC_unknown)
2325 return true;
2326 return false;
2327}
2328
2330 Expr *CaptureExpr, bool WithInit,
2331 DeclContext *CurContext,
2332 bool AsExpression);
2333
2335 unsigned StopAt) {
2336 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2337 D = getCanonicalDecl(D);
2338
2339 auto *VD = dyn_cast<VarDecl>(D);
2340 // Do not capture constexpr variables.
2341 if (VD && VD->isConstexpr())
2342 return nullptr;
2343
2344 // If we want to determine whether the variable should be captured from the
2345 // perspective of the current capturing scope, and we've already left all the
2346 // capturing scopes of the top directive on the stack, check from the
2347 // perspective of its parent directive (if any) instead.
2348 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2349 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2350
2351 // If we are attempting to capture a global variable in a directive with
2352 // 'target' we return true so that this global is also mapped to the device.
2353 //
2354 if (VD && !VD->hasLocalStorage() &&
2356 SemaRef.getCurLambda())) {
2358 DSAStackTy::DSAVarData DVarTop =
2359 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2360 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2361 return VD;
2362 // If the declaration is enclosed in a 'declare target' directive,
2363 // then it should not be captured.
2364 //
2365 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2366 return nullptr;
2367 CapturedRegionScopeInfo *CSI = nullptr;
2368 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2369 llvm::reverse(SemaRef.FunctionScopes),
2370 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2371 : 0)) {
2372 if (!isa<CapturingScopeInfo>(FSI))
2373 return nullptr;
2374 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2375 if (RSI->CapRegionKind == CR_OpenMP) {
2376 CSI = RSI;
2377 break;
2378 }
2379 }
2380 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2383 DSAStack->getDirective(CSI->OpenMPLevel));
2384 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2385 return VD;
2386 }
2388 // Try to mark variable as declare target if it is used in capturing
2389 // regions.
2390 if (getLangOpts().OpenMP <= 45 &&
2391 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2393 return nullptr;
2394 }
2395 }
2396
2397 if (CheckScopeInfo) {
2398 bool OpenMPFound = false;
2399 for (unsigned I = StopAt + 1; I > 0; --I) {
2401 if (!isa<CapturingScopeInfo>(FSI))
2402 return nullptr;
2403 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2404 if (RSI->CapRegionKind == CR_OpenMP) {
2405 OpenMPFound = true;
2406 break;
2407 }
2408 }
2409 if (!OpenMPFound)
2410 return nullptr;
2411 }
2412
2413 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2414 (!DSAStack->isClauseParsingMode() ||
2415 DSAStack->getParentDirective() != OMPD_unknown)) {
2416 auto &&Info = DSAStack->isLoopControlVariable(D);
2417 if (Info.first ||
2418 (VD && VD->hasLocalStorage() &&
2419 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2420 (VD && DSAStack->isForceVarCapturing()))
2421 return VD ? VD : Info.second;
2422 DSAStackTy::DSAVarData DVarTop =
2423 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2424 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2425 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2426 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2427 // Threadprivate variables must not be captured.
2428 if (isOpenMPThreadPrivate(DVarTop.CKind))
2429 return nullptr;
2430 // The variable is not private or it is the variable in the directive with
2431 // default(none) clause and not used in any clause.
2432 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2433 D,
2434 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2435 return isOpenMPPrivate(C) && !AppliedToPointee;
2436 },
2437 [](OpenMPDirectiveKind) { return true; },
2438 DSAStack->isClauseParsingMode());
2439 // Global shared must not be captured.
2440 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2441 ((DSAStack->getDefaultDSA() != DSA_none &&
2442 DSAStack->getDefaultDSA() != DSA_private &&
2443 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2444 DVarTop.CKind == OMPC_shared))
2445 return nullptr;
2446 auto *FD = dyn_cast<FieldDecl>(D);
2447 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2448 !DVarPrivate.PrivateCopy) {
2449 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2450 D,
2451 [](OpenMPClauseKind C, bool AppliedToPointee,
2452 DefaultDataSharingAttributes DefaultAttr) {
2453 return isOpenMPPrivate(C) && !AppliedToPointee &&
2454 (DefaultAttr == DSA_firstprivate ||
2455 DefaultAttr == DSA_private);
2456 },
2457 [](OpenMPDirectiveKind) { return true; },
2458 DSAStack->isClauseParsingMode());
2459 if (DVarPrivate.CKind == OMPC_unknown)
2460 return nullptr;
2461
2462 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2463 if (VD)
2464 return VD;
2466 return nullptr;
2469 /*IsImplicit=*/true);
2470 const CXXScopeSpec CS = CXXScopeSpec();
2472 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2475 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2478 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2479 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2480 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2482 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2483 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2484 return VD;
2485 }
2486 if (DVarPrivate.CKind != OMPC_unknown ||
2487 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2488 DSAStack->getDefaultDSA() == DSA_private ||
2489 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2490 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2491 }
2492 return nullptr;
2493}
2494
2495void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2496 unsigned Level) const {
2497 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2498}
2499
2501 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2502 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2503 DSAStack->loopInit();
2504}
2505
2507 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2508 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2509 DSAStack->resetPossibleLoopCounter();
2510 DSAStack->loopStart();
2511 }
2512}
2513
2515 unsigned CapLevel) const {
2516 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2517 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2518 (!DSAStack->isClauseParsingMode() ||
2519 DSAStack->getParentDirective() != OMPD_unknown)) {
2520 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2521 D,
2522 [](OpenMPClauseKind C, bool AppliedToPointee,
2523 DefaultDataSharingAttributes DefaultAttr) {
2524 return isOpenMPPrivate(C) && !AppliedToPointee &&
2525 DefaultAttr == DSA_private;
2526 },
2527 [](OpenMPDirectiveKind) { return true; },
2528 DSAStack->isClauseParsingMode());
2529 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2530 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2531 !DSAStack->isLoopControlVariable(D).first)
2532 return OMPC_private;
2533 }
2534 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2535 bool IsTriviallyCopyable =
2536 D->getType().getNonReferenceType().isTriviallyCopyableType(
2537 getASTContext()) &&
2538 !D->getType()
2539 .getNonReferenceType()
2540 .getCanonicalType()
2541 ->getAsCXXRecordDecl();
2542 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2544 getOpenMPCaptureRegions(CaptureRegions, DKind);
2545 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2546 (IsTriviallyCopyable ||
2547 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2548 if (DSAStack->hasExplicitDSA(
2549 D,
2550 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2551 Level, /*NotLastprivate=*/true))
2552 return OMPC_firstprivate;
2553 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2554 if (DVar.CKind != OMPC_shared &&
2555 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2556 DSAStack->addImplicitTaskFirstprivate(Level, D);
2557 return OMPC_firstprivate;
2558 }
2559 }
2560 }
2561 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2562 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2563 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2564 DSAStack->resetPossibleLoopCounter(D);
2565 DSAStack->loopStart();
2566 return OMPC_private;
2567 }
2568 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2569 DSAStack->isLoopControlVariable(D).first) &&
2570 !DSAStack->hasExplicitDSA(
2571 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2572 Level) &&
2573 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2574 return OMPC_private;
2575 }
2576 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2577 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2578 DSAStack->isForceVarCapturing() &&
2579 !DSAStack->hasExplicitDSA(
2580 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2581 Level))
2582 return OMPC_private;
2583 }
2584 // User-defined allocators are private since they must be defined in the
2585 // context of target region.
2586 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2587 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2588 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2589 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2590 return OMPC_private;
2591 return (DSAStack->hasExplicitDSA(
2592 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2593 Level) ||
2594 (DSAStack->isClauseParsingMode() &&
2595 DSAStack->getClauseParsingMode() == OMPC_private) ||
2596 // Consider taskgroup reduction descriptor variable a private
2597 // to avoid possible capture in the region.
2598 (DSAStack->hasExplicitDirective(
2599 [](OpenMPDirectiveKind K) {
2600 return K == OMPD_taskgroup ||
2601 ((isOpenMPParallelDirective(K) ||
2602 isOpenMPWorksharingDirective(K)) &&
2603 !isOpenMPSimdDirective(K));
2604 },
2605 Level) &&
2606 DSAStack->isTaskgroupReductionRef(D, Level)))
2607 ? OMPC_private
2608 : OMPC_unknown;
2609}
2610
2612 unsigned Level) {
2613 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2614 D = getCanonicalDecl(D);
2615 OpenMPClauseKind OMPC = OMPC_unknown;
2616 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2617 const unsigned NewLevel = I - 1;
2618 if (DSAStack->hasExplicitDSA(
2619 D,
2620 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2621 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2622 OMPC = K;
2623 return true;
2624 }
2625 return false;
2626 },
2627 NewLevel))
2628 break;
2629 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2630 D, NewLevel,
2632 OpenMPClauseKind) { return true; })) {
2633 OMPC = OMPC_map;
2634 break;
2635 }
2636 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2637 NewLevel)) {
2638 OMPC = OMPC_map;
2639 if (DSAStack->mustBeFirstprivateAtLevel(
2641 OMPC = OMPC_firstprivate;
2642 break;
2643 }
2644 }
2645 if (OMPC != OMPC_unknown)
2646 FD->addAttr(
2647 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2648}
2649
2651 unsigned CaptureLevel) const {
2652 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2653 // Return true if the current level is no longer enclosed in a target region.
2654
2656 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2657 const auto *VD = dyn_cast<VarDecl>(D);
2658 return VD && !VD->hasLocalStorage() &&
2659 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2660 Level) &&
2661 Regions[CaptureLevel] != OMPD_task;
2662}
2663
2665 unsigned CaptureLevel) const {
2666 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2667 // Return true if the current level is no longer enclosed in a target region.
2668
2669 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2670 if (!VD->hasLocalStorage()) {
2672 return true;
2673 DSAStackTy::DSAVarData TopDVar =
2674 DSAStack->getTopDSA(D, /*FromParent=*/false);
2675 unsigned NumLevels =
2676 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2677 if (Level == 0)
2678 // non-file scope static variable with default(firstprivate)
2679 // should be global captured.
2680 return (NumLevels == CaptureLevel + 1 &&
2681 (TopDVar.CKind != OMPC_shared ||
2682 DSAStack->getDefaultDSA() == DSA_firstprivate));
2683 do {
2684 --Level;
2685 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2686 if (DVar.CKind != OMPC_shared)
2687 return true;
2688 } while (Level > 0);
2689 }
2690 }
2691 return true;
2692}
2693
2694void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2695
2697 OMPTraitInfo &TI) {
2698 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2699}
2700
2703 "Not in OpenMP declare variant scope!");
2704
2705 OMPDeclareVariantScopes.pop_back();
2706}
2707
2709 const FunctionDecl *Callee,
2711 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2712 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2713 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2714 // Ignore host functions during device analysis.
2715 if (getLangOpts().OpenMPIsTargetDevice &&
2716 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2717 return;
2718 // Ignore nohost functions during host analysis.
2719 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2720 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2721 return;
2722 const FunctionDecl *FD = Callee->getMostRecentDecl();
2723 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2724 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2725 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2726 // Diagnose host function called during device codegen.
2727 StringRef HostDevTy =
2728 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2729 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2730 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2731 diag::note_omp_marked_device_type_here)
2732 << HostDevTy;
2733 return;
2734 }
2735 if (!getLangOpts().OpenMPIsTargetDevice &&
2736 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2737 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2738 // In OpenMP 5.2 or later, if the function has a host variant then allow
2739 // that to be called instead
2740 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2741 for (OMPDeclareVariantAttr *A :
2742 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2743 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2744 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2745 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2746 OMPDeclareTargetDeclAttr::getDeviceType(
2747 VariantFD->getMostRecentDecl());
2748 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2749 return true;
2750 }
2751 return false;
2752 };
2753 if (getLangOpts().OpenMP >= 52 &&
2754 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2755 return;
2756 // Diagnose nohost function called during host codegen.
2757 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2758 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2759 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2760 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2761 diag::note_omp_marked_device_type_here)
2762 << NoHostDevTy;
2763 }
2764}
2765
2767 const DeclarationNameInfo &DirName,
2768 Scope *CurScope, SourceLocation Loc) {
2769 DSAStack->push(DKind, DirName, CurScope, Loc);
2772}
2773
2775 DSAStack->setClauseParsingMode(K);
2776}
2777
2779 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2781}
2782
2783static std::pair<ValueDecl *, bool>
2784getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2785 SourceRange &ERange, bool AllowArraySection = false,
2786 StringRef DiagType = "");
2787
2788/// Check consistency of the reduction clauses.
2789static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2790 ArrayRef<OMPClause *> Clauses) {
2791 bool InscanFound = false;
2792 SourceLocation InscanLoc;
2793 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2794 // A reduction clause without the inscan reduction-modifier may not appear on
2795 // a construct on which a reduction clause with the inscan reduction-modifier
2796 // appears.
2797 for (OMPClause *C : Clauses) {
2798 if (C->getClauseKind() != OMPC_reduction)
2799 continue;
2800 auto *RC = cast<OMPReductionClause>(C);
2801 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2802 InscanFound = true;
2803 InscanLoc = RC->getModifierLoc();
2804 continue;
2805 }
2806 if (RC->getModifier() == OMPC_REDUCTION_task) {
2807 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2808 // A reduction clause with the task reduction-modifier may only appear on
2809 // a parallel construct, a worksharing construct or a combined or
2810 // composite construct for which any of the aforementioned constructs is a
2811 // constituent construct and simd or loop are not constituent constructs.
2812 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2813 if (!(isOpenMPParallelDirective(CurDir) ||
2815 isOpenMPSimdDirective(CurDir))
2816 S.Diag(RC->getModifierLoc(),
2817 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2818 continue;
2819 }
2820 }
2821 if (InscanFound) {
2822 for (OMPClause *C : Clauses) {
2823 if (C->getClauseKind() != OMPC_reduction)
2824 continue;
2825 auto *RC = cast<OMPReductionClause>(C);
2826 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2827 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2828 ? RC->getBeginLoc()
2829 : RC->getModifierLoc(),
2830 diag::err_omp_inscan_reduction_expected);
2831 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2832 continue;
2833 }
2834 for (Expr *Ref : RC->varlist()) {
2835 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2836 SourceLocation ELoc;
2837 SourceRange ERange;
2838 Expr *SimpleRefExpr = Ref;
2839 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2840 /*AllowArraySection=*/true);
2841 ValueDecl *D = Res.first;
2842 if (!D)
2843 continue;
2844 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2845 S.Diag(Ref->getExprLoc(),
2846 diag::err_omp_reduction_not_inclusive_exclusive)
2847 << Ref->getSourceRange();
2848 }
2849 }
2850 }
2851 }
2852}
2853
2854static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2855 ArrayRef<OMPClause *> Clauses);
2856static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2857 bool WithInit);
2858
2859static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2860 const ValueDecl *D,
2861 const DSAStackTy::DSAVarData &DVar,
2862 bool IsLoopIterVar = false);
2863
2865 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2866 // A variable of class type (or array thereof) that appears in a lastprivate
2867 // clause requires an accessible, unambiguous default constructor for the
2868 // class type, unless the list item is also specified in a firstprivate
2869 // clause.
2870 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2871 for (OMPClause *C : D->clauses()) {
2872 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2873 SmallVector<Expr *, 8> PrivateCopies;
2874 for (Expr *DE : Clause->varlist()) {
2875 if (DE->isValueDependent() || DE->isTypeDependent()) {
2876 PrivateCopies.push_back(nullptr);
2877 continue;
2878 }
2879 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2880 auto *VD = cast<VarDecl>(DRE->getDecl());
2882 const DSAStackTy::DSAVarData DVar =
2883 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2884 if (DVar.CKind == OMPC_lastprivate) {
2885 // Generate helper private variable and initialize it with the
2886 // default value. The address of the original variable is replaced
2887 // by the address of the new private variable in CodeGen. This new
2888 // variable is not added to IdResolver, so the code in the OpenMP
2889 // region uses original variable for proper diagnostics.
2890 VarDecl *VDPrivate = buildVarDecl(
2891 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(),
2892 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2894 if (VDPrivate->isInvalidDecl()) {
2895 PrivateCopies.push_back(nullptr);
2896 continue;
2897 }
2898 PrivateCopies.push_back(buildDeclRefExpr(
2899 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2900 } else {
2901 // The variable is also a firstprivate, so initialization sequence
2902 // for private copy is generated already.
2903 PrivateCopies.push_back(nullptr);
2904 }
2905 }
2906 Clause->setPrivateCopies(PrivateCopies);
2907 continue;
2908 }
2909 // Finalize nontemporal clause by handling private copies, if any.
2910 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2911 SmallVector<Expr *, 8> PrivateRefs;
2912 for (Expr *RefExpr : Clause->varlist()) {
2913 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2914 SourceLocation ELoc;
2915 SourceRange ERange;
2916 Expr *SimpleRefExpr = RefExpr;
2917 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2918 if (Res.second)
2919 // It will be analyzed later.
2920 PrivateRefs.push_back(RefExpr);
2921 ValueDecl *D = Res.first;
2922 if (!D)
2923 continue;
2924
2925 const DSAStackTy::DSAVarData DVar =
2926 DSAStack->getTopDSA(D, /*FromParent=*/false);
2927 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2928 : SimpleRefExpr);
2929 }
2930 Clause->setPrivateRefs(PrivateRefs);
2931 continue;
2932 }
2933 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2934 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2935 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2936 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2937 if (!DRE)
2938 continue;
2939 ValueDecl *VD = DRE->getDecl();
2940 if (!VD || !isa<VarDecl>(VD))
2941 continue;
2942 DSAStackTy::DSAVarData DVar =
2943 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2944 // OpenMP [2.12.5, target Construct]
2945 // Memory allocators that appear in a uses_allocators clause cannot
2946 // appear in other data-sharing attribute clauses or data-mapping
2947 // attribute clauses in the same construct.
2948 Expr *MapExpr = nullptr;
2949 if (DVar.RefExpr ||
2950 DSAStack->checkMappableExprComponentListsForDecl(
2951 VD, /*CurrentRegionOnly=*/true,
2952 [VD, &MapExpr](
2954 MapExprComponents,
2956 auto MI = MapExprComponents.rbegin();
2957 auto ME = MapExprComponents.rend();
2958 if (MI != ME &&
2959 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2960 VD->getCanonicalDecl()) {
2961 MapExpr = MI->getAssociatedExpression();
2962 return true;
2963 }
2964 return false;
2965 })) {
2966 Diag(D.Allocator->getExprLoc(),
2967 diag::err_omp_allocator_used_in_clauses)
2968 << D.Allocator->getSourceRange();
2969 if (DVar.RefExpr)
2971 else
2972 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2973 << MapExpr->getSourceRange();
2974 }
2975 }
2976 continue;
2977 }
2978 }
2979 // Check allocate clauses.
2981 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
2983 }
2984
2985 DSAStack->pop();
2988}
2989
2991 Expr *NumIterations, Sema &SemaRef,
2992 Scope *S, DSAStackTy *Stack);
2993
2994static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
2996 DSAStackTy *Stack) {
2997 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
2998 "loop exprs were not built");
2999
3000 if (SemaRef.CurContext->isDependentContext())
3001 return false;
3002
3003 // Finalize the clauses that need pre-built expressions for CodeGen.
3004 for (OMPClause *C : Clauses) {
3005 auto *LC = dyn_cast<OMPLinearClause>(C);
3006 if (!LC)
3007 continue;
3008 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3009 B.NumIterations, SemaRef,
3010 SemaRef.getCurScope(), Stack))
3011 return true;
3012 }
3013
3014 return false;
3015}
3016
3017namespace {
3018
3019class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3020private:
3021 Sema &SemaRef;
3022
3023public:
3024 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3025 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3026 NamedDecl *ND = Candidate.getCorrectionDecl();
3027 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3028 return VD->hasGlobalStorage() &&
3029 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3030 SemaRef.getCurScope());
3031 }
3032 return false;
3033 }
3034
3035 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3036 return std::make_unique<VarDeclFilterCCC>(*this);
3037 }
3038};
3039
3040class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3041private:
3042 Sema &SemaRef;
3043
3044public:
3045 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3046 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3047 NamedDecl *ND = Candidate.getCorrectionDecl();
3048 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3049 isa<FunctionDecl>(ND))) {
3050 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3051 SemaRef.getCurScope());
3052 }
3053 return false;
3054 }
3055
3056 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3057 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3058 }
3059};
3060
3061} // namespace
3062
3064 CXXScopeSpec &ScopeSpec,
3065 const DeclarationNameInfo &Id,
3066 OpenMPDirectiveKind Kind) {
3067 ASTContext &Context = getASTContext();
3069 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3070 /*ObjectType=*/QualType(),
3071 /*AllowBuiltinCreation=*/true);
3072
3073 if (Lookup.isAmbiguous())
3074 return ExprError();
3075
3076 VarDecl *VD;
3077 if (!Lookup.isSingleResult()) {
3078 VarDeclFilterCCC CCC(SemaRef);
3079 if (TypoCorrection Corrected =
3080 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3083 Corrected,
3084 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3085 : diag::err_omp_expected_var_arg_suggest)
3086 << Id.getName());
3087 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3088 } else {
3089 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3090 : diag::err_omp_expected_var_arg)
3091 << Id.getName();
3092 return ExprError();
3093 }
3094 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3095 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3096 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3097 return ExprError();
3098 }
3099 Lookup.suppressDiagnostics();
3100
3101 // OpenMP [2.9.2, Syntax, C/C++]
3102 // Variables must be file-scope, namespace-scope, or static block-scope.
3103 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3104 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3105 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3106 bool IsDecl =
3108 Diag(VD->getLocation(),
3109 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3110 << VD;
3111 return ExprError();
3112 }
3113
3114 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3115 NamedDecl *ND = CanonicalVD;
3116 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3117 // A threadprivate directive for file-scope variables must appear outside
3118 // any definition or declaration.
3119 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3121 Diag(Id.getLoc(), diag::err_omp_var_scope)
3122 << getOpenMPDirectiveName(Kind) << VD;
3123 bool IsDecl =
3125 Diag(VD->getLocation(),
3126 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3127 << VD;
3128 return ExprError();
3129 }
3130 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3131 // A threadprivate directive for static class member variables must appear
3132 // in the class definition, in the same scope in which the member
3133 // variables are declared.
3134 if (CanonicalVD->isStaticDataMember() &&
3135 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3136 Diag(Id.getLoc(), diag::err_omp_var_scope)
3137 << getOpenMPDirectiveName(Kind) << VD;
3138 bool IsDecl =
3140 Diag(VD->getLocation(),
3141 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3142 << VD;
3143 return ExprError();
3144 }
3145 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3146 // A threadprivate directive for namespace-scope variables must appear
3147 // outside any definition or declaration other than the namespace
3148 // definition itself.
3149 if (CanonicalVD->getDeclContext()->isNamespace() &&
3152 CanonicalVD->getDeclContext()))) {
3153 Diag(Id.getLoc(), diag::err_omp_var_scope)
3154 << getOpenMPDirectiveName(Kind) << VD;
3155 bool IsDecl =
3157 Diag(VD->getLocation(),
3158 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3159 << VD;
3160 return ExprError();
3161 }
3162 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3163 // A threadprivate directive for static block-scope variables must appear
3164 // in the scope of the variable and not in a nested scope.
3165 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3167 Diag(Id.getLoc(), diag::err_omp_var_scope)
3168 << getOpenMPDirectiveName(Kind) << VD;
3169 bool IsDecl =
3171 Diag(VD->getLocation(),
3172 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3173 << VD;
3174 return ExprError();
3175 }
3176
3177 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3178 // A threadprivate directive must lexically precede all references to any
3179 // of the variables in its list.
3180 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3181 !DSAStack->isThreadPrivate(VD)) {
3182 Diag(Id.getLoc(), diag::err_omp_var_used)
3183 << getOpenMPDirectiveName(Kind) << VD;
3184 return ExprError();
3185 }
3186
3187 QualType ExprType = VD->getType().getNonReferenceType();
3189 SourceLocation(), VD,
3190 /*RefersToEnclosingVariableOrCapture=*/false,
3191 Id.getLoc(), ExprType, VK_LValue);
3192}
3193
3196 ArrayRef<Expr *> VarList) {
3200 }
3201 return nullptr;
3202}
3203
3204namespace {
3205class LocalVarRefChecker final
3206 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3207 Sema &SemaRef;
3208
3209public:
3210 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3211 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3212 if (VD->hasLocalStorage()) {
3213 SemaRef.Diag(E->getBeginLoc(),
3214 diag::err_omp_local_var_in_threadprivate_init)
3215 << E->getSourceRange();
3216 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3217 << VD << VD->getSourceRange();
3218 return true;
3219 }
3220 }
3221 return false;
3222 }
3223 bool VisitStmt(const Stmt *S) {
3224 for (const Stmt *Child : S->children()) {
3225 if (Child && Visit(Child))
3226 return true;
3227 }
3228 return false;
3229 }
3230 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3231};
3232} // namespace
3233
3236 ArrayRef<Expr *> VarList) {
3237 ASTContext &Context = getASTContext();
3239 for (Expr *RefExpr : VarList) {
3240 auto *DE = cast<DeclRefExpr>(RefExpr);
3241 auto *VD = cast<VarDecl>(DE->getDecl());
3242 SourceLocation ILoc = DE->getExprLoc();
3243
3244 // Mark variable as used.
3245 VD->setReferenced();
3246 VD->markUsed(Context);
3247
3248 QualType QType = VD->getType();
3249 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3250 // It will be analyzed later.
3251 Vars.push_back(DE);
3252 continue;
3253 }
3254
3255 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3256 // A threadprivate variable must not have an incomplete type.
3258 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3259 continue;
3260 }
3261
3262 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3263 // A threadprivate variable must not have a reference type.
3264 if (VD->getType()->isReferenceType()) {
3265 Diag(ILoc, diag::err_omp_ref_type_arg)
3266 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3267 bool IsDecl =
3269 Diag(VD->getLocation(),
3270 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3271 << VD;
3272 continue;
3273 }
3274
3275 // Check if this is a TLS variable. If TLS is not being supported, produce
3276 // the corresponding diagnostic.
3277 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3278 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3279 getLangOpts().OpenMPUseTLS &&
3280 getASTContext().getTargetInfo().isTLSSupported())) ||
3281 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3282 !VD->isLocalVarDecl())) {
3283 Diag(ILoc, diag::err_omp_var_thread_local)
3284 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3285 bool IsDecl =
3287 Diag(VD->getLocation(),
3288 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3289 << VD;
3290 continue;
3291 }
3292
3293 // Check if initial value of threadprivate variable reference variable with
3294 // local storage (it is not supported by runtime).
3295 if (const Expr *Init = VD->getAnyInitializer()) {
3296 LocalVarRefChecker Checker(SemaRef);
3297 if (Checker.Visit(Init))
3298 continue;
3299 }
3300
3301 Vars.push_back(RefExpr);
3302 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3303 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3304 Context, SourceRange(Loc, Loc)));
3305 if (ASTMutationListener *ML = Context.getASTMutationListener())
3306 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3307 }
3308 OMPThreadPrivateDecl *D = nullptr;
3309 if (!Vars.empty()) {
3311 Loc, Vars);
3313 }
3314 return D;
3315}
3316
3317static OMPAllocateDeclAttr::AllocatorTypeTy
3318getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3319 if (!Allocator)
3320 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3321 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3322 Allocator->isInstantiationDependent() ||
3323 Allocator->containsUnexpandedParameterPack())
3324 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3325 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3326 llvm::FoldingSetNodeID AEId;
3327 const Expr *AE = Allocator->IgnoreParenImpCasts();
3328 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3329 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3330 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3331 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3332 llvm::FoldingSetNodeID DAEId;
3333 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3334 /*Canonical=*/true);
3335 if (AEId == DAEId) {
3336 AllocatorKindRes = AllocatorKind;
3337 break;
3338 }
3339 }
3340 return AllocatorKindRes;
3341}
3342
3344 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3345 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3346 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3347 return false;
3348 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3349 Expr *PrevAllocator = A->getAllocator();
3350 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3351 getAllocatorKind(S, Stack, PrevAllocator);
3352 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3353 if (AllocatorsMatch &&
3354 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3355 Allocator && PrevAllocator) {
3356 const Expr *AE = Allocator->IgnoreParenImpCasts();
3357 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3358 llvm::FoldingSetNodeID AEId, PAEId;
3359 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3360 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3361 AllocatorsMatch = AEId == PAEId;
3362 }
3363 if (!AllocatorsMatch) {
3364 SmallString<256> AllocatorBuffer;
3365 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3366 if (Allocator)
3367 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3368 SmallString<256> PrevAllocatorBuffer;
3369 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3370 if (PrevAllocator)
3371 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3372 S.getPrintingPolicy());
3373
3374 SourceLocation AllocatorLoc =
3375 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3376 SourceRange AllocatorRange =
3377 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3378 SourceLocation PrevAllocatorLoc =
3379 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3380 SourceRange PrevAllocatorRange =
3381 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3382 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3383 << (Allocator ? 1 : 0) << AllocatorStream.str()
3384 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3385 << AllocatorRange;
3386 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3387 << PrevAllocatorRange;
3388 return true;
3389 }
3390 return false;
3391}
3392
3393static void
3395 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3396 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3397 if (VD->hasAttr<OMPAllocateDeclAttr>())
3398 return;
3399 if (Alignment &&
3400 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3401 Alignment->isInstantiationDependent() ||
3402 Alignment->containsUnexpandedParameterPack()))
3403 // Apply later when we have a usable value.
3404 return;
3405 if (Allocator &&
3406 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3407 Allocator->isInstantiationDependent() ||
3408 Allocator->containsUnexpandedParameterPack()))
3409 return;
3410 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3411 Allocator, Alignment, SR);
3412 VD->addAttr(A);
3414 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3415}
3416
3419 DeclContext *Owner) {
3420 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3421 Expr *Alignment = nullptr;
3422 Expr *Allocator = nullptr;
3423 if (Clauses.empty()) {
3424 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3425 // allocate directives that appear in a target region must specify an
3426 // allocator clause unless a requires directive with the dynamic_allocators
3427 // clause is present in the same compilation unit.
3428 if (getLangOpts().OpenMPIsTargetDevice &&
3429 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3430 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3431 } else {
3432 for (const OMPClause *C : Clauses)
3433 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3434 Allocator = AC->getAllocator();
3435 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3436 Alignment = AC->getAlignment();
3437 else
3438 llvm_unreachable("Unexpected clause on allocate directive");
3439 }
3440 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3441 getAllocatorKind(SemaRef, DSAStack, Allocator);
3443 for (Expr *RefExpr : VarList) {
3444 auto *DE = cast<DeclRefExpr>(RefExpr);
3445 auto *VD = cast<VarDecl>(DE->getDecl());
3446
3447 // Check if this is a TLS variable or global register.
3448 if (VD->getTLSKind() != VarDecl::TLS_None ||
3449 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3450 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3451 !VD->isLocalVarDecl()))
3452 continue;
3453
3454 // If the used several times in the allocate directive, the same allocator
3455 // must be used.
3457 AllocatorKind, Allocator))
3458 continue;
3459
3460 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3461 // If a list item has a static storage type, the allocator expression in the
3462 // allocator clause must be a constant expression that evaluates to one of
3463 // the predefined memory allocator values.
3464 if (Allocator && VD->hasGlobalStorage()) {
3465 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3466 Diag(Allocator->getExprLoc(),
3467 diag::err_omp_expected_predefined_allocator)
3468 << Allocator->getSourceRange();
3469 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3471 Diag(VD->getLocation(),
3472 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3473 << VD;
3474 continue;
3475 }
3476 }
3477
3478 Vars.push_back(RefExpr);
3479 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3480 DE->getSourceRange());
3481 }
3482 if (Vars.empty())
3483 return nullptr;
3484 if (!Owner)
3485 Owner = SemaRef.getCurLexicalContext();
3486 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3488 Owner->addDecl(D);
3490}
3491
3494 ArrayRef<OMPClause *> ClauseList) {
3495 OMPRequiresDecl *D = nullptr;
3497 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3498 } else {
3499 D = CheckOMPRequiresDecl(Loc, ClauseList);
3500 if (D) {
3502 DSAStack->addRequiresDecl(D);
3503 }
3504 }
3506}
3507
3509 OpenMPDirectiveKind DKind,
3510 ArrayRef<std::string> Assumptions,
3511 bool SkippedClauses) {
3512 if (!SkippedClauses && Assumptions.empty())
3513 Diag(Loc, diag::err_omp_no_clause_for_directive)
3514 << llvm::omp::getAllAssumeClauseOptions()
3515 << llvm::omp::getOpenMPDirectiveName(DKind);
3516
3517 auto *AA =
3518 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3519 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3520 OMPAssumeScoped.push_back(AA);
3521 return;
3522 }
3523
3524 // Global assumes without assumption clauses are ignored.
3525 if (Assumptions.empty())
3526 return;
3527
3528 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3529 "Unexpected omp assumption directive!");
3530 OMPAssumeGlobal.push_back(AA);
3531
3532 // The OMPAssumeGlobal scope above will take care of new declarations but
3533 // we also want to apply the assumption to existing ones, e.g., to
3534 // declarations in included headers. To this end, we traverse all existing
3535 // declaration contexts and annotate function declarations here.
3536 SmallVector<DeclContext *, 8> DeclContexts;
3537 auto *Ctx = SemaRef.CurContext;
3538 while (Ctx->getLexicalParent())
3539 Ctx = Ctx->getLexicalParent();
3540 DeclContexts.push_back(Ctx);
3541 while (!DeclContexts.empty()) {
3542 DeclContext *DC = DeclContexts.pop_back_val();
3543 for (auto *SubDC : DC->decls()) {
3544 if (SubDC->isInvalidDecl())
3545 continue;
3546 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3547 DeclContexts.push_back(CTD->getTemplatedDecl());
3548 llvm::append_range(DeclContexts, CTD->specializations());
3549 continue;
3550 }
3551 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3552 DeclContexts.push_back(DC);
3553 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3554 F->addAttr(AA);
3555 continue;
3556 }
3557 }
3558 }
3559}
3560
3562 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3563 OMPAssumeScoped.pop_back();
3564}
3565
3567 Stmt *AStmt,
3568 SourceLocation StartLoc,
3569 SourceLocation EndLoc) {
3570 if (!AStmt)
3571 return StmtError();
3572
3573 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3574 AStmt);
3575}
3576
3579 ArrayRef<OMPClause *> ClauseList) {
3580 /// For target specific clauses, the requires directive cannot be
3581 /// specified after the handling of any of the target regions in the
3582 /// current compilation unit.
3583 ArrayRef<SourceLocation> TargetLocations =
3584 DSAStack->getEncounteredTargetLocs();
3585 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3586 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3587 for (const OMPClause *CNew : ClauseList) {
3588 // Check if any of the requires clauses affect target regions.
3589 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3590 isa<OMPUnifiedAddressClause>(CNew) ||
3591 isa<OMPReverseOffloadClause>(CNew) ||
3592 isa<OMPDynamicAllocatorsClause>(CNew)) {
3593 Diag(Loc, diag::err_omp_directive_before_requires)
3594 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3595 for (SourceLocation TargetLoc : TargetLocations) {
3596 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3597 << "target";
3598 }
3599 } else if (!AtomicLoc.isInvalid() &&
3600 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3601 Diag(Loc, diag::err_omp_directive_before_requires)
3602 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3603 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3604 << "atomic";
3605 }
3606 }
3607 }
3608
3609 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3611 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3612 return nullptr;
3613}
3614
3615static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3616 const ValueDecl *D,
3617 const DSAStackTy::DSAVarData &DVar,
3618 bool IsLoopIterVar) {
3619 if (DVar.RefExpr) {
3620 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3621 << getOpenMPClauseName(DVar.CKind);
3622 return;
3623 }
3624 enum {
3625 PDSA_StaticMemberShared,
3626 PDSA_StaticLocalVarShared,
3627 PDSA_LoopIterVarPrivate,
3628 PDSA_LoopIterVarLinear,
3629 PDSA_LoopIterVarLastprivate,
3630 PDSA_ConstVarShared,
3631 PDSA_GlobalVarShared,
3632 PDSA_TaskVarFirstprivate,
3633 PDSA_LocalVarPrivate,
3634 PDSA_Implicit
3635 } Reason = PDSA_Implicit;
3636 bool ReportHint = false;
3637 auto ReportLoc = D->getLocation();
3638 auto *VD = dyn_cast<VarDecl>(D);
3639 if (IsLoopIterVar) {
3640 if (DVar.CKind == OMPC_private)
3641 Reason = PDSA_LoopIterVarPrivate;
3642 else if (DVar.CKind == OMPC_lastprivate)
3643 Reason = PDSA_LoopIterVarLastprivate;
3644 else
3645 Reason = PDSA_LoopIterVarLinear;
3646 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3647 DVar.CKind == OMPC_firstprivate) {
3648 Reason = PDSA_TaskVarFirstprivate;
3649 ReportLoc = DVar.ImplicitDSALoc;
3650 } else if (VD && VD->isStaticLocal())
3651 Reason = PDSA_StaticLocalVarShared;
3652 else if (VD && VD->isStaticDataMember())
3653 Reason = PDSA_StaticMemberShared;
3654 else if (VD && VD->isFileVarDecl())
3655 Reason = PDSA_GlobalVarShared;
3656 else if (D->getType().isConstant(SemaRef.getASTContext()))
3657 Reason = PDSA_ConstVarShared;
3658 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3659 ReportHint = true;
3660 Reason = PDSA_LocalVarPrivate;
3661 }
3662 if (Reason != PDSA_Implicit) {
3663 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3664 << Reason << ReportHint
3665 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3666 } else if (DVar.ImplicitDSALoc.isValid()) {
3667 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3668 << getOpenMPClauseName(DVar.CKind);
3669 }
3670}
3671
3674 bool IsAggregateOrDeclareTarget) {
3676 switch (M) {
3677 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3678 Kind = OMPC_MAP_alloc;
3679 break;
3680 case OMPC_DEFAULTMAP_MODIFIER_to:
3681 Kind = OMPC_MAP_to;
3682 break;
3683 case OMPC_DEFAULTMAP_MODIFIER_from:
3684 Kind = OMPC_MAP_from;
3685 break;
3686 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3687 Kind = OMPC_MAP_tofrom;
3688 break;
3689 case OMPC_DEFAULTMAP_MODIFIER_present:
3690 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3691 // If implicit-behavior is present, each variable referenced in the
3692 // construct in the category specified by variable-category is treated as if
3693 // it had been listed in a map clause with the map-type of alloc and
3694 // map-type-modifier of present.
3695 Kind = OMPC_MAP_alloc;
3696 break;
3697 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3699 llvm_unreachable("Unexpected defaultmap implicit behavior");
3700 case OMPC_DEFAULTMAP_MODIFIER_none:
3701 case OMPC_DEFAULTMAP_MODIFIER_default:
3703 // IsAggregateOrDeclareTarget could be true if:
3704 // 1. the implicit behavior for aggregate is tofrom
3705 // 2. it's a declare target link
3706 if (IsAggregateOrDeclareTarget) {
3707 Kind = OMPC_MAP_tofrom;
3708 break;
3709 }
3710 llvm_unreachable("Unexpected defaultmap implicit behavior");
3711 }
3712 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3713 return Kind;
3714}
3715
3716namespace {
3717class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3718 DSAStackTy *Stack;
3719 Sema &SemaRef;
3720 bool ErrorFound = false;
3721 bool TryCaptureCXXThisMembers = false;
3722 CapturedStmt *CS = nullptr;
3723 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3724 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3725 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3726 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3728 ImplicitMapModifier[DefaultmapKindNum];
3729 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3730 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3731
3732 void VisitSubCaptures(OMPExecutableDirective *S) {
3733 // Check implicitly captured variables.
3734 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3735 return;
3736 if (S->getDirectiveKind() == OMPD_atomic ||
3737 S->getDirectiveKind() == OMPD_critical ||
3738 S->getDirectiveKind() == OMPD_section ||
3739 S->getDirectiveKind() == OMPD_master ||
3740 S->getDirectiveKind() == OMPD_masked ||
3741 S->getDirectiveKind() == OMPD_scope ||
3742 S->getDirectiveKind() == OMPD_assume ||
3743 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3744 Visit(S->getAssociatedStmt());
3745 return;
3746 }
3747 visitSubCaptures(S->getInnermostCapturedStmt());
3748 // Try to capture inner this->member references to generate correct mappings
3749 // and diagnostics.
3750 if (TryCaptureCXXThisMembers ||
3751 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3752 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3753 [](const CapturedStmt::Capture &C) {
3754 return C.capturesThis();
3755 }))) {
3756 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3757 TryCaptureCXXThisMembers = true;
3758 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3759 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3760 }
3761 // In tasks firstprivates are not captured anymore, need to analyze them
3762 // explicitly.
3763 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3764 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3765 for (OMPClause *C : S->clauses())
3766 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3767 for (Expr *Ref : FC->varlist())
3768 Visit(Ref);
3769 }
3770 }
3771 }
3772
3773public:
3774 void VisitDeclRefExpr(DeclRefExpr *E) {
3775 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3778 E->isNonOdrUse() == clang::NOUR_Unevaluated)
3779 return;
3780 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3781 // Check the datasharing rules for the expressions in the clauses.
3782 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3783 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3784 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3785 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3786 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3787 Visit(CED->getInit());
3788 return;
3789 }
3790 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3791 // Do not analyze internal variables and do not enclose them into
3792 // implicit clauses.
3793 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3794 return;
3795 VD = VD->getCanonicalDecl();
3796 // Skip internally declared variables.
3797 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3798 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3799 !Stack->isImplicitTaskFirstprivate(VD))
3800 return;
3801 // Skip allocators in uses_allocators clauses.
3802 if (Stack->isUsesAllocatorsDecl(VD))
3803 return;
3804
3805 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3806 // Check if the variable has explicit DSA set and stop analysis if it so.
3807 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3808 return;
3809
3810 // Skip internally declared static variables.
3811 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3812 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3813 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3814 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3815 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3816 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3817 !Stack->isImplicitTaskFirstprivate(VD))
3818 return;
3819
3820 SourceLocation ELoc = E->getExprLoc();
3821 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3822 // The default(none) clause requires that each variable that is referenced
3823 // in the construct, and does not have a predetermined data-sharing
3824 // attribute, must have its data-sharing attribute explicitly determined
3825 // by being listed in a data-sharing attribute clause.
3826 if (DVar.CKind == OMPC_unknown &&
3827 (Stack->getDefaultDSA() == DSA_none ||
3828 Stack->getDefaultDSA() == DSA_private ||
3829 Stack->getDefaultDSA() == DSA_firstprivate) &&
3830 isImplicitOrExplicitTaskingRegion(DKind) &&
3831 VarsWithInheritedDSA.count(VD) == 0) {
3832 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3833 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3834 Stack->getDefaultDSA() == DSA_private)) {
3835 DSAStackTy::DSAVarData DVar =
3836 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3837 InheritedDSA = DVar.CKind == OMPC_unknown;
3838 }
3839 if (InheritedDSA)
3840 VarsWithInheritedDSA[VD] = E;
3841 if (Stack->getDefaultDSA() == DSA_none)
3842 return;
3843 }
3844
3845 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3846 // If implicit-behavior is none, each variable referenced in the
3847 // construct that does not have a predetermined data-sharing attribute
3848 // and does not appear in a to or link clause on a declare target
3849 // directive must be listed in a data-mapping attribute clause, a
3850 // data-sharing attribute clause (including a data-sharing attribute
3851 // clause on a combined construct where target. is one of the
3852 // constituent constructs), or an is_device_ptr clause.
3853 OpenMPDefaultmapClauseKind ClauseKind =
3855 if (SemaRef.getLangOpts().OpenMP >= 50) {
3856 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3857 OMPC_DEFAULTMAP_MODIFIER_none;
3858 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3859 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3860 // Only check for data-mapping attribute and is_device_ptr here
3861 // since we have already make sure that the declaration does not
3862 // have a data-sharing attribute above
3863 if (!Stack->checkMappableExprComponentListsForDecl(
3864 VD, /*CurrentRegionOnly=*/true,
3866 MapExprComponents,
3868 auto MI = MapExprComponents.rbegin();
3869 auto ME = MapExprComponents.rend();
3870 return MI != ME && MI->getAssociatedDeclaration() == VD;
3871 })) {
3872 VarsWithInheritedDSA[VD] = E;
3873 return;
3874 }
3875 }
3876 }
3877 if (SemaRef.getLangOpts().OpenMP > 50) {
3878 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3879 OMPC_DEFAULTMAP_MODIFIER_present;
3880 if (IsModifierPresent) {
3881 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3882 OMPC_MAP_MODIFIER_present)) {
3883 ImplicitMapModifier[ClauseKind].push_back(
3884 OMPC_MAP_MODIFIER_present);
3885 }
3886 }
3887 }
3888
3890 !Stack->isLoopControlVariable(VD).first) {
3891 if (!Stack->checkMappableExprComponentListsForDecl(
3892 VD, /*CurrentRegionOnly=*/true,
3894 StackComponents,
3896 if (SemaRef.LangOpts.OpenMP >= 50)
3897 return !StackComponents.empty();
3898 // Variable is used if it has been marked as an array, array
3899 // section, array shaping or the variable itself.
3900 return StackComponents.size() == 1 ||
3901 llvm::all_of(
3902 llvm::drop_begin(llvm::reverse(StackComponents)),
3903 [](const OMPClauseMappableExprCommon::
3904 MappableComponent &MC) {
3905 return MC.getAssociatedDeclaration() ==
3906 nullptr &&
3907 (isa<ArraySectionExpr>(
3908 MC.getAssociatedExpression()) ||
3909 isa<OMPArrayShapingExpr>(
3910 MC.getAssociatedExpression()) ||
3911 isa<ArraySubscriptExpr>(
3912 MC.getAssociatedExpression()));
3913 });
3914 })) {
3915 bool IsFirstprivate = false;
3916 // By default lambdas are captured as firstprivates.
3917 if (const auto *RD =
3919 IsFirstprivate = RD->isLambda();
3920 IsFirstprivate =
3921 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3922 if (IsFirstprivate) {
3923 ImplicitFirstprivate.emplace_back(E);
3924 } else {
3926 Stack->getDefaultmapModifier(ClauseKind);
3928 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3929 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3930 }
3931 return;
3932 }
3933 }
3934
3935 // OpenMP [2.9.3.6, Restrictions, p.2]
3936 // A list item that appears in a reduction clause of the innermost
3937 // enclosing worksharing or parallel construct may not be accessed in an
3938 // explicit task.
3939 DVar = Stack->hasInnermostDSA(
3940 VD,
3941 [](OpenMPClauseKind C, bool AppliedToPointee) {
3942 return C == OMPC_reduction && !AppliedToPointee;
3943 },
3944 [](OpenMPDirectiveKind K) {
3945 return isOpenMPParallelDirective(K) ||
3947 },
3948 /*FromParent=*/true);
3949 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3950 ErrorFound = true;
3951 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3952 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3953 return;
3954 }
3955
3956 // Define implicit data-sharing attributes for task.
3957 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3958 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3959 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3960 DVar.CKind == OMPC_firstprivate) ||
3961 (Stack->getDefaultDSA() == DSA_private &&
3962 DVar.CKind == OMPC_private)) &&
3963 !DVar.RefExpr)) &&
3964 !Stack->isLoopControlVariable(VD).first) {
3965 if (Stack->getDefaultDSA() == DSA_private)
3966 ImplicitPrivate.push_back(E);
3967 else
3968 ImplicitFirstprivate.push_back(E);
3969 return;
3970 }
3971
3972 // Store implicitly used globals with declare target link for parent
3973 // target.
3974 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3975 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3976 Stack->addToParentTargetRegionLinkGlobals(E);
3977 return;
3978 }
3979 }
3980 }
3981 void VisitMemberExpr(MemberExpr *E) {
3982 if (E->isTypeDependent() || E->isValueDependent() ||
3984 return;
3985 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3986 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3987 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3988 if (!FD)
3989 return;
3990 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3991 // Check if the variable has explicit DSA set and stop analysis if it
3992 // so.
3993 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3994 return;
3995
3997 !Stack->isLoopControlVariable(FD).first &&
3998 !Stack->checkMappableExprComponentListsForDecl(
3999 FD, /*CurrentRegionOnly=*/true,
4001 StackComponents,
4003 return isa<CXXThisExpr>(
4004 cast<MemberExpr>(
4005 StackComponents.back().getAssociatedExpression())
4006 ->getBase()
4007 ->IgnoreParens());
4008 })) {
4009 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4010 // A bit-field cannot appear in a map clause.
4011 //
4012 if (FD->isBitField())
4013 return;
4014
4015 // Check to see if the member expression is referencing a class that
4016 // has already been explicitly mapped
4017 if (Stack->isClassPreviouslyMapped(TE->getType()))
4018 return;
4019
4021 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4022 OpenMPDefaultmapClauseKind ClauseKind =
4025 Modifier, /*IsAggregateOrDeclareTarget*/ true);
4026 ImplicitMap[ClauseKind][Kind].emplace_back(E);
4027 return;
4028 }
4029
4030 SourceLocation ELoc = E->getExprLoc();
4031 // OpenMP [2.9.3.6, Restrictions, p.2]
4032 // A list item that appears in a reduction clause of the innermost
4033 // enclosing worksharing or parallel construct may not be accessed in
4034 // an explicit task.
4035 DVar = Stack->hasInnermostDSA(
4036 FD,
4037 [](OpenMPClauseKind C, bool AppliedToPointee) {
4038 return C == OMPC_reduction && !AppliedToPointee;
4039 },
4040 [](OpenMPDirectiveKind K) {
4041 return isOpenMPParallelDirective(K) ||
4043 },
4044 /*FromParent=*/true);
4045 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4046 ErrorFound = true;
4047 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4048 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4049 return;
4050 }
4051
4052 // Define implicit data-sharing attributes for task.
4053 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4054 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4055 !Stack->isLoopControlVariable(FD).first) {
4056 // Check if there is a captured expression for the current field in the
4057 // region. Do not mark it as firstprivate unless there is no captured
4058 // expression.
4059 // TODO: try to make it firstprivate.
4060 if (DVar.CKind != OMPC_unknown)
4061 ImplicitFirstprivate.push_back(E);
4062 }
4063 return;
4064 }
4067 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4068 Stack->getCurrentDirective(),
4069 /*NoDiagnose=*/true))
4070 return;
4071 const auto *VD = cast<ValueDecl>(
4072 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4073 if (!Stack->checkMappableExprComponentListsForDecl(
4074 VD, /*CurrentRegionOnly=*/true,
4075 [&CurComponents](
4077 StackComponents,
4079 auto CCI = CurComponents.rbegin();
4080 auto CCE = CurComponents.rend();
4081 for (const auto &SC : llvm::reverse(StackComponents)) {
4082 // Do both expressions have the same kind?
4083 if (CCI->getAssociatedExpression()->getStmtClass() !=
4084 SC.getAssociatedExpression()->getStmtClass())
4085 if (!((isa<ArraySectionExpr>(
4086 SC.getAssociatedExpression()) ||
4087 isa<OMPArrayShapingExpr>(
4088 SC.getAssociatedExpression())) &&
4089 isa<ArraySubscriptExpr>(
4090 CCI->getAssociatedExpression())))
4091 return false;
4092
4093 const Decl *CCD = CCI->getAssociatedDeclaration();
4094 const Decl *SCD = SC.getAssociatedDeclaration();
4095 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4096 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4097 if (SCD != CCD)
4098 return false;
4099 std::advance(CCI, 1);
4100 if (CCI == CCE)
4101 break;
4102 }
4103 return true;
4104 })) {
4105 Visit(E->getBase());
4106 }
4107 } else if (!TryCaptureCXXThisMembers) {
4108 Visit(E->getBase());
4109 }
4110 }
4111 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4112 for (OMPClause *C : S->clauses()) {
4113 // Skip analysis of arguments of private clauses for task|target
4114 // directives.
4115 if (isa_and_nonnull<OMPPrivateClause>(C))
4116 continue;
4117 // Skip analysis of arguments of implicitly defined firstprivate clause
4118 // for task|target directives.
4119 // Skip analysis of arguments of implicitly defined map clause for target
4120 // directives.
4121 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4122 C->isImplicit() &&
4123 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4124 for (Stmt *CC : C->children()) {
4125 if (CC)
4126 Visit(CC);
4127 }
4128 }
4129 }
4130 // Check implicitly captured variables.
4131 VisitSubCaptures(S);
4132 }
4133
4134 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4135 // Loop transformation directives do not introduce data sharing
4136 VisitStmt(S);
4137 }
4138
4139 void VisitCallExpr(CallExpr *S) {
4140 for (Stmt *C : S->arguments()) {
4141 if (C) {
4142 // Check implicitly captured variables in the task-based directives to
4143 // check if they must be firstprivatized.
4144 Visit(C);
4145 }
4146 }
4147 if (Expr *Callee = S->getCallee()) {
4148 auto *CI = Callee->IgnoreParenImpCasts();
4149 if (auto *CE = dyn_cast<MemberExpr>(CI))
4150 Visit(CE->getBase());
4151 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4152 Visit(CE);
4153 }
4154 }
4155 void VisitStmt(Stmt *S) {
4156 for (Stmt *C : S->children()) {
4157 if (C) {
4158 // Check implicitly captured variables in the task-based directives to
4159 // check if they must be firstprivatized.
4160 Visit(C);
4161 }
4162 }
4163 }
4164
4165 void visitSubCaptures(CapturedStmt *S) {
4166 for (const CapturedStmt::Capture &Cap : S->captures()) {
4167 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4168 continue;
4169 VarDecl *VD = Cap.getCapturedVar();
4170 // Do not try to map the variable if it or its sub-component was mapped
4171 // already.
4172 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4173 Stack->checkMappableExprComponentListsForDecl(
4174 VD, /*CurrentRegionOnly=*/true,
4176 OpenMPClauseKind) { return true; }))
4177 continue;
4179 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4180 Cap.getLocation(), /*RefersToCapture=*/true);
4181 Visit(DRE);
4182 }
4183 }
4184 bool isErrorFound() const { return ErrorFound; }
4185 ArrayRef<Expr *> getImplicitFirstprivate() const {
4186 return ImplicitFirstprivate;
4187 }
4188 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4190 OpenMPMapClauseKind MK) const {
4191 return ImplicitMap[DK][MK];
4192 }
4194 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4195 return ImplicitMapModifier[Kind];
4196 }
4197 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4198 return VarsWithInheritedDSA;
4199 }
4200
4201 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4202 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4203 // Process declare target link variables for the target directives.
4204 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4205 for (DeclRefExpr *E : Stack->getLinkGlobals())
4206 Visit(E);
4207 }
4208 }
4209};
4210} // namespace
4211
4212static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4213 OpenMPDirectiveKind DKind,
4214 bool ScopeEntry) {
4217 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4218 if (isOpenMPTeamsDirective(DKind))
4219 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4220 if (isOpenMPParallelDirective(DKind))
4221 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4223 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4224 if (isOpenMPSimdDirective(DKind))
4225 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4226 Stack->handleConstructTrait(Traits, ScopeEntry);
4227}
4228
4230getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4231 ASTContext &Context = SemaRef.getASTContext();
4232 QualType KmpInt32Ty =
4233 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4234 QualType KmpInt32PtrTy =
4235 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4237 std::make_pair(".global_tid.", KmpInt32PtrTy),
4238 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4239 };
4240 if (LoopBoundSharing) {
4241 QualType KmpSizeTy = Context.getSizeType().withConst();
4242 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4243 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4244 }
4245
4246 // __context with shared vars
4247 Params.push_back(std::make_pair(StringRef(), QualType()));
4248 return Params;
4249}
4250
4253 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4254}
4255
4258 ASTContext &Context = SemaRef.getASTContext();
4259 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4260 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4261 QualType KmpInt32PtrTy =
4262 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4263 QualType Args[] = {VoidPtrTy};
4265 EPI.Variadic = true;
4266 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4268 std::make_pair(".global_tid.", KmpInt32Ty),
4269 std::make_pair(".part_id.", KmpInt32PtrTy),
4270 std::make_pair(".privates.", VoidPtrTy),
4271 std::make_pair(
4272 ".copy_fn.",
4273 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4274 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4275 std::make_pair(StringRef(), QualType()) // __context with shared vars
4276 };
4277 return Params;
4278}
4279
4282 ASTContext &Context = SemaRef.getASTContext();
4284 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4285 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4286 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4287 }
4288 // __context with shared vars
4289 Params.push_back(std::make_pair(StringRef(), QualType()));
4290 return Params;
4291}
4292
4296 std::make_pair(StringRef(), QualType()) // __context with shared vars
4297 };
4298 return Params;
4299}
4300
4303 ASTContext &Context = SemaRef.getASTContext();
4304 QualType KmpInt32Ty =
4305 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4306 QualType KmpUInt64Ty =
4307 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4308 QualType KmpInt64Ty =
4309 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4310 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4311 QualType KmpInt32PtrTy =
4312 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4313 QualType Args[] = {VoidPtrTy};
4315 EPI.Variadic = true;
4316 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4318 std::make_pair(".global_tid.", KmpInt32Ty),
4319 std::make_pair(".part_id.", KmpInt32PtrTy),
4320 std::make_pair(".privates.", VoidPtrTy),
4321 std::make_pair(
4322 ".copy_fn.",
4323 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4324 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4325 std::make_pair(".lb.", KmpUInt64Ty),
4326 std::make_pair(".ub.", KmpUInt64Ty),
4327 std::make_pair(".st.", KmpInt64Ty),
4328 std::make_pair(".liter.", KmpInt32Ty),
4329 std::make_pair(".reductions.", VoidPtrTy),
4330 std::make_pair(StringRef(), QualType()) // __context with shared vars
4331 };
4332 return Params;
4333}
4334
4336 Scope *CurScope, SourceLocation Loc) {
4338 getOpenMPCaptureRegions(Regions, DKind);
4339
4340 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4341
4342 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4343 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4344 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4345 };
4346
4347 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4348 switch (RKind) {
4349 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4350 // are listed here.
4351 case OMPD_parallel:
4353 Loc, CurScope, CR_OpenMP,
4354 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4355 break;
4356 case OMPD_teams:
4357 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4358 getTeamsRegionParams(SemaRef), Level);
4359 break;
4360 case OMPD_task:
4361 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4362 getTaskRegionParams(SemaRef), Level);
4363 // Mark this captured region as inlined, because we don't use outlined
4364 // function directly.
4365 MarkAsInlined(SemaRef.getCurCapturedRegion());
4366 break;
4367 case OMPD_taskloop:
4368 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4369 getTaskloopRegionParams(SemaRef), Level);
4370 // Mark this captured region as inlined, because we don't use outlined
4371 // function directly.
4372 MarkAsInlined(SemaRef.getCurCapturedRegion());
4373 break;
4374 case OMPD_target:
4375 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4376 getTargetRegionParams(SemaRef), Level);
4377 break;
4378 case OMPD_unknown:
4379 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4380 getUnknownRegionParams(SemaRef));
4381 break;
4382 case OMPD_metadirective:
4383 case OMPD_nothing:
4384 default:
4385 llvm_unreachable("Unexpected capture region");
4386 }
4387 }
4388}
4389
4391 Scope *CurScope) {
4392 switch (DKind) {
4393 case OMPD_atomic:
4394 case OMPD_critical:
4395 case OMPD_masked:
4396 case OMPD_master:
4397 case OMPD_section:
4398 case OMPD_tile:
4399 case OMPD_unroll:
4400 case OMPD_reverse:
4401 case OMPD_interchange:
4402 case OMPD_assume:
4403 break;
4404 default:
4405 processCapturedRegions(SemaRef, DKind, CurScope,
4406 DSAStack->getConstructLoc());
4407 break;
4408 }
4409
4410 DSAStack->setContext(SemaRef.CurContext);
4411 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4412}
4413
4414int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4415 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4416}
4417
4420 getOpenMPCaptureRegions(CaptureRegions, DKind);
4421 return CaptureRegions.size();
4422}
4423
4425 Expr *CaptureExpr, bool WithInit,
4426 DeclContext *CurContext,
4427 bool AsExpression) {
4428 assert(CaptureExpr);
4429 ASTContext &C = S.getASTContext();
4430 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4431 QualType Ty = Init->getType();
4432 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4433 if (S.getLangOpts().CPlusPlus) {
4434 Ty = C.getLValueReferenceType(Ty);
4435 } else {
4436 Ty = C.getPointerType(Ty);
4437 ExprResult Res =
4438 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4439 if (!Res.isUsable())
4440 return nullptr;
4441 Init = Res.get();
4442 }
4443 WithInit = true;
4444 }
4445 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4446 CaptureExpr->getBeginLoc());
4447 if (!WithInit)
4448 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4449 CurContext->addHiddenDecl(CED);
4451 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4452 return CED;
4453}
4454
4455static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4456 bool WithInit) {
4458 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4459 CD = cast<OMPCapturedExprDecl>(VD);
4460 else
4461 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4462 S.CurContext,
4463 /*AsExpression=*/false);
4464 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4465 CaptureExpr->getExprLoc());
4466}
4467
4468static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4469 StringRef Name) {
4470 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4471 if (!Ref) {
4473 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4474 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4475 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4476 CaptureExpr->getExprLoc());
4477 }
4478 ExprResult Res = Ref;
4479 if (!S.getLangOpts().CPlusPlus &&
4480 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4481 Ref->getType()->isPointerType()) {
4482 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4483 if (!Res.isUsable())
4484 return ExprError();
4485 }
4486 return S.DefaultLvalueConversion(Res.get());
4487}
4488
4489namespace {
4490// OpenMP directives parsed in this section are represented as a
4491// CapturedStatement with an associated statement. If a syntax error
4492// is detected during the parsing of the associated statement, the
4493// compiler must abort processing and close the CapturedStatement.
4494//
4495// Combined directives such as 'target parallel' have more than one
4496// nested CapturedStatements. This RAII ensures that we unwind out
4497// of all the nested CapturedStatements when an error is found.
4498class CaptureRegionUnwinderRAII {
4499private:
4500 Sema &S;
4501 bool &ErrorFound;
4502 OpenMPDirectiveKind DKind = OMPD_unknown;
4503
4504public:
4505 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4506 OpenMPDirectiveKind DKind)
4507 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4508 ~CaptureRegionUnwinderRAII() {
4509 if (ErrorFound) {
4510 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4511 while (--ThisCaptureLevel >= 0)
4513 }
4514 }
4515};
4516} // namespace
4517
4519 // Capture variables captured by reference in lambdas for target-based
4520 // directives.
4522 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4524 DSAStack->getCurrentDirective()))) {
4525 QualType Type = V->getType();
4526 if (const auto *RD = Type.getCanonicalType()
4527 .getNonReferenceType()
4528 ->getAsCXXRecordDecl()) {
4529 bool SavedForceCaptureByReferenceInTargetExecutable =
4530 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4531 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4532 /*V=*/true);
4533 if (RD->isLambda()) {
4534 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4535 FieldDecl *ThisCapture;
4536 RD->getCaptureFields(Captures, ThisCapture);
4537 for (const LambdaCapture &LC : RD->captures()) {
4538 if (LC.getCaptureKind() == LCK_ByRef) {
4539 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4540 DeclContext *VDC = VD->getDeclContext();
4541 if (!VDC->Encloses(SemaRef.CurContext))
4542 continue;
4543 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4544 } else if (LC.getCaptureKind() == LCK_This) {
4546 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4547 ThisTy, ThisCapture->getType()))
4548 SemaRef.CheckCXXThisCapture(LC.getLocation());
4549 }
4550 }
4551 }
4552 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4553 SavedForceCaptureByReferenceInTargetExecutable);
4554 }
4555 }
4556}
4557
4559 const ArrayRef<OMPClause *> Clauses) {
4560 const OMPOrderedClause *Ordered = nullptr;
4561 const OMPOrderClause *Order = nullptr;
4562
4563 for (const OMPClause *Clause : Clauses) {
4564 if (Clause->getClauseKind() == OMPC_ordered)
4565 Ordered = cast<OMPOrderedClause>(Clause);
4566 else if (Clause->getClauseKind() == OMPC_order) {
4567 Order = cast<OMPOrderClause>(Clause);
4568 if (Order->getKind() != OMPC_ORDER_concurrent)
4569 Order = nullptr;
4570 }
4571 if (Ordered && Order)
4572 break;
4573 }
4574
4575 if (Ordered && Order) {
4576 S.Diag(Order->getKindKwLoc(),
4577 diag::err_omp_simple_clause_incompatible_with_ordered)
4578 << getOpenMPClauseName(OMPC_order)
4579 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4580 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4581 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4582 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4583 return true;
4584 }
4585 return false;
4586}
4587
4589 ArrayRef<OMPClause *> Clauses) {
4591 /* ScopeEntry */ false);
4592 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4593 return S;
4594
4595 bool ErrorFound = false;
4596 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4597 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4598 if (!S.isUsable()) {
4599 ErrorFound = true;
4600 return StmtError();
4601 }
4602
4604 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4605 OMPOrderedClause *OC = nullptr;
4606 OMPScheduleClause *SC = nullptr;
4609 // This is required for proper codegen.
4610 for (OMPClause *Clause : Clauses) {
4611 if (!getLangOpts().OpenMPSimd &&
4612 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4613 DSAStack->getCurrentDirective() == OMPD_target) &&
4614 Clause->getClauseKind() == OMPC_in_reduction) {
4615 // Capture taskgroup task_reduction descriptors inside the tasking regions
4616 // with the corresponding in_reduction items.
4617 auto *IRC = cast<OMPInReductionClause>(Clause);
4618 for (Expr *E : IRC->taskgroup_descriptors())
4619 if (E)
4621 }
4622 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4623 Clause->getClauseKind() == OMPC_copyprivate ||
4624 (getLangOpts().OpenMPUseTLS &&
4625 getASTContext().getTargetInfo().isTLSSupported() &&
4626 Clause->getClauseKind() == OMPC_copyin)) {
4627 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4628 // Mark all variables in private list clauses as used in inner region.
4629 for (Stmt *VarRef : Clause->children()) {
4630 if (auto *E = cast_or_null<Expr>(VarRef)) {
4632 }
4633 }
4634 DSAStack->setForceVarCapturing(/*V=*/false);
4635 } else if (CaptureRegions.size() > 1 ||
4636 CaptureRegions.back() != OMPD_unknown) {
4637 if (auto *C = OMPClauseWithPreInit::get(Clause))
4638 PICs.push_back(C);
4639 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4640 if (Expr *E = C->getPostUpdateExpr())
4642 }
4643 }
4644 if (Clause->getClauseKind() == OMPC_schedule)
4645 SC = cast<OMPScheduleClause>(Clause);
4646 else if (Clause->getClauseKind() == OMPC_ordered)
4647 OC = cast<OMPOrderedClause>(Clause);
4648 else if (Clause->getClauseKind() == OMPC_linear)
4649 LCs.push_back(cast<OMPLinearClause>(Clause));
4650 }
4651 // Capture allocator expressions if used.
4652 for (Expr *E : DSAStack->getInnerAllocators())
4654 // OpenMP, 2.7.1 Loop Construct, Restrictions
4655 // The nonmonotonic modifier cannot be specified if an ordered clause is
4656 // specified.
4657 if (SC &&
4658 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4660 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4661 OC) {
4662 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4665 diag::err_omp_simple_clause_incompatible_with_ordered)
4666 << getOpenMPClauseName(OMPC_schedule)
4667 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4668 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4669 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4670 ErrorFound = true;
4671 }
4672 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4673 // If an order(concurrent) clause is present, an ordered clause may not appear
4674 // on the same directive.
4675 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4676 ErrorFound = true;
4677 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4678 for (const OMPLinearClause *C : LCs) {
4679 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4680 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4681 }
4682 ErrorFound = true;
4683 }
4684 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4685 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4686 OC->getNumForLoops()) {
4687 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4688 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4689 ErrorFound = true;
4690 }
4691 if (ErrorFound) {
4692 return StmtError();
4693 }
4694 StmtResult SR = S;
4695 unsigned CompletedRegions = 0;
4696 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4697 // Mark all variables in private list clauses as used in inner region.
4698 // Required for proper codegen of combined directives.
4699 // TODO: add processing for other clauses.
4700 if (ThisCaptureRegion != OMPD_unknown) {
4701 for (const clang::OMPClauseWithPreInit *C : PICs) {
4702 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4703 // Find the particular capture region for the clause if the
4704 // directive is a combined one with multiple capture regions.
4705 // If the directive is not a combined one, the capture region
4706 // associated with the clause is OMPD_unknown and is generated
4707 // only once.
4708 if (CaptureRegion == ThisCaptureRegion ||
4709 CaptureRegion == OMPD_unknown) {
4710 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4711 for (Decl *D : DS->decls())
4713 cast<VarDecl>(D));
4714 }
4715 }
4716 }
4717 }
4718 if (ThisCaptureRegion == OMPD_target) {
4719 // Capture allocator traits in the target region. They are used implicitly
4720 // and, thus, are not captured by default.
4721 for (OMPClause *C : Clauses) {
4722 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4723 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4724 ++I) {
4725 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4726 if (Expr *E = D.AllocatorTraits)
4728 }
4729 continue;
4730 }
4731 }
4732 }
4733 if (ThisCaptureRegion == OMPD_parallel) {
4734 // Capture temp arrays for inscan reductions and locals in aligned
4735 // clauses.
4736 for (OMPClause *C : Clauses) {
4737 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4738 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4739 continue;
4740 for (Expr *E : RC->copy_array_temps())
4741 if (E)
4743 }
4744 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4745 for (Expr *E : AC->varlist())
4747 }
4748 }
4749 }
4750 if (++CompletedRegions == CaptureRegions.size())
4751 DSAStack->setBodyComplete();
4753 }
4754 return SR;
4755}
4756
4757static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4758 OpenMPDirectiveKind CancelRegion,
4759 SourceLocation StartLoc) {
4760 // CancelRegion is only needed for cancel and cancellation_point.
4761 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4762 return false;
4763
4764 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4765 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4766 return false;
4767
4768 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4769 << getOpenMPDirectiveName(CancelRegion);
4770 return true;
4771}
4772
4773static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4774 OpenMPDirectiveKind CurrentRegion,
4775 const DeclarationNameInfo &CurrentName,
4776 OpenMPDirectiveKind CancelRegion,
4777 OpenMPBindClauseKind BindKind,
4778 SourceLocation StartLoc) {
4779 if (!Stack->getCurScope())
4780 return false;
4781
4782 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4783 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4784 bool NestingProhibited = false;
4785 bool CloseNesting = true;
4786 bool OrphanSeen = false;
4787 enum {
4788 NoRecommend,
4789 ShouldBeInParallelRegion,
4790 ShouldBeInOrderedRegion,
4791 ShouldBeInTargetRegion,
4792 ShouldBeInTeamsRegion,
4793 ShouldBeInLoopSimdRegion,
4794 } Recommend = NoRecommend;
4795
4798 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4799 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4800
4801 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4802 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4803 CurrentRegion != OMPD_parallel &&
4804 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
4805 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4806 << getOpenMPDirectiveName(CurrentRegion);
4807 return true;
4808 }
4809 if (isOpenMPSimdDirective(ParentRegion) &&
4810 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4811 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4812 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4813 CurrentRegion != OMPD_scan))) {
4814 // OpenMP [2.16, Nesting of Regions]
4815 // OpenMP constructs may not be nested inside a simd region.
4816 // OpenMP [2.8.1,simd Construct, Restrictions]
4817 // An ordered construct with the simd clause is the only OpenMP
4818 // construct that can appear in the simd region.
4819 // Allowing a SIMD construct nested in another SIMD construct is an
4820 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4821 // message.
4822 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4823 // The only OpenMP constructs that can be encountered during execution of
4824 // a simd region are the atomic construct, the loop construct, the simd
4825 // construct and the ordered construct with the simd clause.
4826 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4827 ? diag::err_omp_prohibited_region_simd
4828 : diag::warn_omp_nesting_simd)
4829 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4830 return CurrentRegion != OMPD_simd;
4831 }
4832 if (EnclosingConstruct == OMPD_atomic) {
4833 // OpenMP [2.16, Nesting of Regions]
4834 // OpenMP constructs may not be nested inside an atomic region.
4835 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4836 return true;
4837 }
4838 if (CurrentRegion == OMPD_section) {
4839 // OpenMP [2.7.2, sections Construct, Restrictions]
4840 // Orphaned section directives are prohibited. That is, the section
4841 // directives must appear within the sections construct and must not be
4842 // encountered elsewhere in the sections region.
4843 if (EnclosingConstruct != OMPD_sections) {
4844 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4845 << (ParentRegion != OMPD_unknown)
4846 << getOpenMPDirectiveName(ParentRegion);
4847 return true;
4848 }
4849 return false;
4850 }
4851 // Allow some constructs (except teams and cancellation constructs) to be
4852 // orphaned (they could be used in functions, called from OpenMP regions
4853 // with the required preconditions).
4854 if (ParentRegion == OMPD_unknown &&
4855 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4856 CurrentRegion != OMPD_cancellation_point &&
4857 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4858 return false;
4859 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4860 // for a detailed explanation
4861 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4862 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4863 (isOpenMPWorksharingDirective(ParentRegion) ||
4864 EnclosingConstruct == OMPD_loop)) {
4865 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4866 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4867 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4868 << getOpenMPDirectiveName(CurrentRegion);
4869 return true;
4870 }
4871 if (CurrentRegion == OMPD_cancellation_point ||
4872 CurrentRegion == OMPD_cancel) {
4873 // OpenMP [2.16, Nesting of Regions]
4874 // A cancellation point construct for which construct-type-clause is
4875 // taskgroup must be nested inside a task construct. A cancellation
4876 // point construct for which construct-type-clause is not taskgroup must
4877 // be closely nested inside an OpenMP construct that matches the type
4878 // specified in construct-type-clause.
4879 // A cancel construct for which construct-type-clause is taskgroup must be
4880 // nested inside a task construct. A cancel construct for which
4881 // construct-type-clause is not taskgroup must be closely nested inside an
4882 // OpenMP construct that matches the type specified in
4883 // construct-type-clause.
4884 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4885 if (CancelRegion == OMPD_taskgroup) {
4886 NestingProhibited = EnclosingConstruct != OMPD_task &&
4887 (SemaRef.getLangOpts().OpenMP < 50 ||
4888 EnclosingConstruct != OMPD_taskloop);
4889 } else if (CancelRegion == OMPD_sections) {
4890 NestingProhibited = EnclosingConstruct != OMPD_section &&
4891 EnclosingConstruct != OMPD_sections;
4892 } else {
4893 NestingProhibited = CancelRegion != Leafs.back();
4894 }
4895 OrphanSeen = ParentRegion == OMPD_unknown;
4896 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4897 // OpenMP 5.1 [2.22, Nesting of Regions]
4898 // A masked region may not be closely nested inside a worksharing, loop,
4899 // atomic, task, or taskloop region.
4900 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4901 isOpenMPGenericLoopDirective(ParentRegion) ||
4902 isOpenMPTaskingDirective(ParentRegion);
4903 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4904 // OpenMP [2.16, Nesting of Regions]
4905 // A critical region may not be nested (closely or otherwise) inside a
4906 // critical region with the same name. Note that this restriction is not
4907 // sufficient to prevent deadlock.
4908 SourceLocation PreviousCriticalLoc;
4909 bool DeadLock = Stack->hasDirective(
4910 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4911 const DeclarationNameInfo &DNI,
4913 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4914 PreviousCriticalLoc = Loc;
4915 return true;
4916 }
4917 return false;
4918 },
4919 false /* skip top directive */);
4920 if (DeadLock) {
4921 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4922 << CurrentName.getName();
4923 if (PreviousCriticalLoc.isValid())
4924 SemaRef.Diag(PreviousCriticalLoc,
4925 diag::note_omp_previous_critical_region);
4926 return true;
4927 }
4928 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4929 // OpenMP 5.1 [2.22, Nesting of Regions]
4930 // A scope region may not be closely nested inside a worksharing, loop,
4931 // task, taskloop, critical, ordered, atomic, or masked region.
4932 // OpenMP 5.1 [2.22, Nesting of Regions]
4933 // A barrier region may not be closely nested inside a worksharing, loop,
4934 // task, taskloop, critical, ordered, atomic, or masked region.
4935 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4936 isOpenMPGenericLoopDirective(ParentRegion) ||
4937 isOpenMPTaskingDirective(ParentRegion) ||
4938 llvm::is_contained({OMPD_masked, OMPD_master,
4939 OMPD_critical, OMPD_ordered},
4940 EnclosingConstruct);
4941 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4942 !isOpenMPParallelDirective(CurrentRegion) &&
4943 !isOpenMPTeamsDirective(CurrentRegion)) {
4944 // OpenMP 5.1 [2.22, Nesting of Regions]
4945 // A loop region that binds to a parallel region or a worksharing region
4946 // may not be closely nested inside a worksharing, loop, task, taskloop,
4947 // critical, ordered, atomic, or masked region.
4948 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4949 isOpenMPGenericLoopDirective(ParentRegion) ||
4950 isOpenMPTaskingDirective(ParentRegion) ||
4951 llvm::is_contained({OMPD_masked, OMPD_master,
4952 OMPD_critical, OMPD_ordered},
4953 EnclosingConstruct);
4954 Recommend = ShouldBeInParallelRegion;
4955 } else if (CurrentRegion == OMPD_ordered) {
4956 // OpenMP [2.16, Nesting of Regions]
4957 // An ordered region may not be closely nested inside a critical,
4958 // atomic, or explicit task region.
4959 // An ordered region must be closely nested inside a loop region (or
4960 // parallel loop region) with an ordered clause.
4961 // OpenMP [2.8.1,simd Construct, Restrictions]
4962 // An ordered construct with the simd clause is the only OpenMP construct
4963 // that can appear in the simd region.
4964 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4965 isOpenMPTaskingDirective(ParentRegion) ||
4966 !(isOpenMPSimdDirective(ParentRegion) ||
4967 Stack->isParentOrderedRegion());
4968 Recommend = ShouldBeInOrderedRegion;
4969 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4970 // OpenMP [2.16, Nesting of Regions]
4971 // If specified, a teams construct must be contained within a target
4972 // construct.
4973 NestingProhibited =
4974 (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4975 (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4976 EnclosingConstruct != OMPD_target);
4977 OrphanSeen = ParentRegion == OMPD_unknown;
4978 Recommend = ShouldBeInTargetRegion;
4979 } else if (CurrentRegion == OMPD_scan) {
4980 if (SemaRef.LangOpts.OpenMP >= 50) {
4981 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4982 // simd, or for simd. This has to take into account combined directives.
4983 // In 5.2 this seems to be implied by the fact that the specified
4984 // separated constructs are do, for, and simd.
4985 NestingProhibited = !llvm::is_contained(
4986 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4987 } else {
4988 NestingProhibited = true;
4989 }
4990 OrphanSeen = ParentRegion == OMPD_unknown;
4991 Recommend = ShouldBeInLoopSimdRegion;
4992 }
4993 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
4994 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
4995 EnclosingConstruct == OMPD_teams) {
4996 // OpenMP [5.1, 2.22, Nesting of Regions]
4997 // distribute, distribute simd, distribute parallel worksharing-loop,
4998 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
4999 // including any parallel regions arising from combined constructs,
5000 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5001 // only OpenMP regions that may be strictly nested inside the teams
5002 // region.
5003 //
5004 // As an extension, we permit atomic within teams as well.
5005 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5006 !isOpenMPDistributeDirective(CurrentRegion) &&
5007 CurrentRegion != OMPD_loop &&
5008 !(SemaRef.getLangOpts().OpenMPExtensions &&
5009 CurrentRegion == OMPD_atomic);
5010 Recommend = ShouldBeInParallelRegion;
5011 }
5012 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5013 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5014 // If the bind clause is present on the loop construct and binding is
5015 // teams then the corresponding loop region must be strictly nested inside
5016 // a teams region.
5017 NestingProhibited =
5018 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5019 Recommend = ShouldBeInTeamsRegion;
5020 }
5021 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5022 // OpenMP 4.5 [2.17 Nesting of Regions]
5023 // The region associated with the distribute construct must be strictly
5024 // nested inside a teams region
5025 NestingProhibited = EnclosingConstruct != OMPD_teams;
5026 Recommend = ShouldBeInTeamsRegion;
5027 }
5028 if (!NestingProhibited &&
5029 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5030 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5031 // OpenMP 4.5 [2.17 Nesting of Regions]
5032 // If a target, target update, target data, target enter data, or
5033 // target exit data construct is encountered during execution of a
5034 // target region, the behavior is unspecified.
5035 NestingProhibited = Stack->hasDirective(
5036 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5039 OffendingRegion = K;
5040 return true;
5041 }
5042 return false;
5043 },
5044 false /* don't skip top directive */);
5045 CloseNesting = false;
5046 }
5047 if (NestingProhibited) {
5048 if (OrphanSeen) {
5049 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5050 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5051 } else {
5052 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5053 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5054 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5055 }
5056 return true;
5057 }
5058 return false;
5059}
5060
5063 unsigned operator()(argument_type DK) { return unsigned(DK); }
5064};
5066 ArrayRef<OMPClause *> Clauses,
5067 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5068 bool ErrorFound = false;
5069 unsigned NamedModifiersNumber = 0;
5070 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5071 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5072 SmallVector<SourceLocation, 4> NameModifierLoc;
5073 for (const OMPClause *C : Clauses) {
5074 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5075 // At most one if clause without a directive-name-modifier can appear on
5076 // the directive.
5077 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5078 if (FoundNameModifiers[CurNM]) {
5079 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5080 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5081 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5082 ErrorFound = true;
5083 } else if (CurNM != OMPD_unknown) {
5084 NameModifierLoc.push_back(IC->getNameModifierLoc());
5085 ++NamedModifiersNumber;
5086 }
5087 FoundNameModifiers[CurNM] = IC;
5088 if (CurNM == OMPD_unknown)
5089 continue;
5090 // Check if the specified name modifier is allowed for the current
5091 // directive.
5092 // At most one if clause with the particular directive-name-modifier can
5093 // appear on the directive.
5094 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5095 S.Diag(IC->getNameModifierLoc(),
5096 diag::err_omp_wrong_if_directive_name_modifier)
5097 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5098 ErrorFound = true;
5099 }
5100 }
5101 }
5102 // If any if clause on the directive includes a directive-name-modifier then
5103 // all if clauses on the directive must include a directive-name-modifier.
5104 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5105 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5106 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5107 diag::err_omp_no_more_if_clause);
5108 } else {
5109 std::string Values;
5110 std::string Sep(", ");
5111 unsigned AllowedCnt = 0;
5112 unsigned TotalAllowedNum =
5113 AllowedNameModifiers.size() - NamedModifiersNumber;
5114 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5115 ++Cnt) {
5116 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5117 if (!FoundNameModifiers[NM]) {
5118 Values += "'";
5119 Values += getOpenMPDirectiveName(NM);
5120 Values += "'";
5121 if (AllowedCnt + 2 == TotalAllowedNum)
5122 Values += " or ";
5123 else if (AllowedCnt + 1 != TotalAllowedNum)
5124 Values += Sep;
5125 ++AllowedCnt;
5126 }
5127 }
5128 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5129 diag::err_omp_unnamed_if_clause)
5130 << (TotalAllowedNum > 1) << Values;
5131 }
5132 for (SourceLocation Loc : NameModifierLoc) {
5133 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5134 }
5135 ErrorFound = true;
5136 }
5137 return ErrorFound;
5138}
5139
5140static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5141 SourceLocation &ELoc,
5142 SourceRange &ERange,
5143 bool AllowArraySection,
5144 StringRef DiagType) {
5145 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5147 return std::make_pair(nullptr, true);
5148
5149 // OpenMP [3.1, C/C++]
5150 // A list item is a variable name.
5151 // OpenMP [2.9.3.3, Restrictions, p.1]
5152 // A variable that is part of another variable (as an array or
5153 // structure element) cannot appear in a private clause.
5154 RefExpr = RefExpr->IgnoreParens();
5155 enum {
5156 NoArrayExpr = -1,
5157 ArraySubscript = 0,
5158 OMPArraySection = 1
5159 } IsArrayExpr = NoArrayExpr;
5160 if (AllowArraySection) {
5161 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5162 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5163 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5164 Base = TempASE->getBase()->IgnoreParenImpCasts();
5165 RefExpr = Base;
5166 IsArrayExpr = ArraySubscript;
5167 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5168 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5169 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5170 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5171 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5172 Base = TempASE->getBase()->IgnoreParenImpCasts();
5173 RefExpr = Base;
5174 IsArrayExpr = OMPArraySection;
5175 }
5176 }
5177 ELoc = RefExpr->getExprLoc();
5178 ERange = RefExpr->getSourceRange();
5179 RefExpr = RefExpr->IgnoreParenImpCasts();
5180 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5181 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5182 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5183 (S.getCurrentThisType().isNull() || !ME ||
5184 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5185 !isa<FieldDecl>(ME->getMemberDecl()))) {
5186 if (IsArrayExpr != NoArrayExpr) {
5187 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5188 << IsArrayExpr << ERange;
5189 } else if (!DiagType.empty()) {
5190 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5191 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5192 : 0;
5193 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5194 << DiagSelect << DiagType << ERange;
5195 } else {
5196 S.Diag(ELoc,
5197 AllowArraySection
5198 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5199 : diag::err_omp_expected_var_name_member_expr)
5200 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5201 }
5202 return std::make_pair(nullptr, false);
5203 }
5204 return std::make_pair(
5205 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5206}
5207
5208namespace {
5209/// Checks if the allocator is used in uses_allocators clause to be allowed in
5210/// target regions.
5211class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5212 DSAStackTy *S = nullptr;
5213
5214public:
5215 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5216 return S->isUsesAllocatorsDecl(E->getDecl())
5217 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5218 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5219 }
5220 bool VisitStmt(const Stmt *S) {
5221 for (const Stmt *Child : S->children()) {
5222 if (Child && Visit(Child))
5223 return true;
5224 }
5225 return false;
5226 }
5227 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5228};
5229} // namespace
5230
5231static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5232 ArrayRef<OMPClause *> Clauses) {
5233 assert(!S.CurContext->isDependentContext() &&
5234 "Expected non-dependent context.");
5235 auto AllocateRange =
5236 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5237 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5238 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5239 return isOpenMPPrivate(C->getClauseKind());
5240 });
5241 for (OMPClause *Cl : PrivateRange) {
5243 if (Cl->getClauseKind() == OMPC_private) {
5244 auto *PC = cast<OMPPrivateClause>(Cl);
5245 I = PC->private_copies().begin();
5246 It = PC->varlist_begin();
5247 Et = PC->varlist_end();
5248 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5249 auto *PC = cast<OMPFirstprivateClause>(Cl);
5250 I = PC->private_copies().begin();
5251 It = PC->varlist_begin();
5252 Et = PC->varlist_end();
5253 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5254 auto *PC = cast<OMPLastprivateClause>(Cl);
5255 I = PC->private_copies().begin();
5256 It = PC->varlist_begin();
5257 Et = PC->varlist_end();
5258 } else if (Cl->getClauseKind() == OMPC_linear) {
5259 auto *PC = cast<OMPLinearClause>(Cl);
5260 I = PC->privates().begin();
5261 It = PC->varlist_begin();
5262 Et = PC->varlist_end();
5263 } else if (Cl->getClauseKind() == OMPC_reduction) {
5264 auto *PC = cast<OMPReductionClause>(Cl);
5265 I = PC->privates().begin();
5266 It = PC->varlist_begin();
5267 Et = PC->varlist_end();
5268 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5269 auto *PC = cast<OMPTaskReductionClause>(Cl);
5270 I = PC->privates().begin();
5271 It = PC->varlist_begin();
5272 Et = PC->varlist_end();
5273 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5274 auto *PC = cast<OMPInReductionClause>(Cl);
5275 I = PC->privates().begin();
5276 It = PC->varlist_begin();
5277 Et = PC->varlist_end();
5278 } else {
5279 llvm_unreachable("Expected private clause.");
5280 }
5281 for (Expr *E : llvm::make_range(It, Et)) {
5282 if (!*I) {
5283 ++I;
5284 continue;
5285 }
5286 SourceLocation ELoc;
5287 SourceRange ERange;
5288 Expr *SimpleRefExpr = E;
5289 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5290 /*AllowArraySection=*/true);
5291 DeclToCopy.try_emplace(Res.first,
5292 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5293 ++I;
5294 }
5295 }
5296 for (OMPClause *C : AllocateRange) {
5297 auto *AC = cast<OMPAllocateClause>(C);
5298 if (S.getLangOpts().OpenMP >= 50 &&
5299 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5300 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5301 AC->getAllocator()) {
5302 Expr *Allocator = AC->getAllocator();
5303 // OpenMP, 2.12.5 target Construct
5304 // Memory allocators that do not appear in a uses_allocators clause cannot
5305 // appear as an allocator in an allocate clause or be used in the target
5306 // region unless a requires directive with the dynamic_allocators clause
5307 // is present in the same compilation unit.
5308 AllocatorChecker Checker(Stack);
5309 if (Checker.Visit(Allocator))
5310 S.Diag(Allocator->getExprLoc(),
5311 diag::err_omp_allocator_not_in_uses_allocators)
5312 << Allocator->getSourceRange();
5313 }
5314 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5315 getAllocatorKind(S, Stack, AC->getAllocator());
5316 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5317 // For task, taskloop or target directives, allocation requests to memory
5318 // allocators with the trait access set to thread result in unspecified
5319 // behavior.
5320 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5321 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5322 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5323 S.Diag(AC->getAllocator()->getExprLoc(),
5324 diag::warn_omp_allocate_thread_on_task_target_directive)
5325 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5326 }
5327 for (Expr *E : AC->varlist()) {
5328 SourceLocation ELoc;
5329 SourceRange ERange;
5330 Expr *SimpleRefExpr = E;
5331 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5332 ValueDecl *VD = Res.first;
5333 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5334 if (!isOpenMPPrivate(Data.CKind)) {
5335 S.Diag(E->getExprLoc(),
5336 diag::err_omp_expected_private_copy_for_allocate);
5337 continue;
5338 }
5339 VarDecl *PrivateVD = DeclToCopy[VD];
5340 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5341 AllocatorKind, AC->getAllocator()))
5342 continue;
5343 // Placeholder until allocate clause supports align modifier.
5344 Expr *Alignment = nullptr;
5345 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5346 Alignment, E->getSourceRange());
5347 }
5348 }
5349}
5350
5351namespace {
5352/// Rewrite statements and expressions for Sema \p Actions CurContext.
5353///
5354/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5355/// context. DeclRefExpr used inside the new context are changed to refer to the
5356/// captured variable instead.
5357class CaptureVars : public TreeTransform<CaptureVars> {
5358 using BaseTransform = TreeTransform<CaptureVars>;
5359
5360public:
5361 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5362
5363 bool AlwaysRebuild() { return true; }
5364};
5365} // namespace
5366
5367static VarDecl *precomputeExpr(Sema &Actions,
5368 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5369 StringRef Name) {
5370 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5371 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5372 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5373 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5374 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5375 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5376 BodyStmts.push_back(NewDeclStmt);
5377 return NewVar;
5378}
5379
5380/// Create a closure that computes the number of iterations of a loop.
5381///
5382/// \param Actions The Sema object.
5383/// \param LogicalTy Type for the logical iteration number.
5384/// \param Rel Comparison operator of the loop condition.
5385/// \param StartExpr Value of the loop counter at the first iteration.
5386/// \param StopExpr Expression the loop counter is compared against in the loop
5387/// condition. \param StepExpr Amount of increment after each iteration.
5388///
5389/// \return Closure (CapturedStmt) of the distance calculation.
5390static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5392 Expr *StartExpr, Expr *StopExpr,
5393 Expr *StepExpr) {
5394 ASTContext &Ctx = Actions.getASTContext();
5395 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5396
5397 // Captured regions currently don't support return values, we use an
5398 // out-parameter instead. All inputs are implicit captures.
5399 // TODO: Instead of capturing each DeclRefExpr occurring in
5400 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5401 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5402 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5403 {StringRef(), QualType()}};
5404 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5405
5406 Stmt *Body;
5407 {
5408 Sema::CompoundScopeRAII CompoundScope(Actions);
5409 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5410
5411 // Get the LValue expression for the result.
5412 ImplicitParamDecl *DistParam = CS->getParam(0);
5413 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5414 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5415
5416 SmallVector<Stmt *, 4> BodyStmts;
5417
5418 // Capture all referenced variable references.
5419 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5420 // CapturedStmt, we could compute them before and capture the result, to be
5421 // used jointly with the LoopVar function.
5422 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5423 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5424 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5425 auto BuildVarRef = [&](VarDecl *VD) {
5426 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5427 };
5428
5430 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5432 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5433 Expr *Dist;
5434 if (Rel == BO_NE) {
5435 // When using a != comparison, the increment can be +1 or -1. This can be
5436 // dynamic at runtime, so we need to check for the direction.
5437 Expr *IsNegStep = AssertSuccess(
5438 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5439
5440 // Positive increment.
5441 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5442 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5443 ForwardRange = AssertSuccess(
5444 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5445 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5446 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5447
5448 // Negative increment.
5449 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5450 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5451 BackwardRange = AssertSuccess(
5452 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5453 Expr *NegIncAmount = AssertSuccess(
5454 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5455 Expr *BackwardDist = AssertSuccess(
5456 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5457
5458 // Use the appropriate case.
5459 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5460 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5461 } else {
5462 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5463 "Expected one of these relational operators");
5464
5465 // We can derive the direction from any other comparison operator. It is
5466 // non well-formed OpenMP if Step increments/decrements in the other
5467 // directions. Whether at least the first iteration passes the loop
5468 // condition.
5469 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5470 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5471
5472 // Compute the range between first and last counter value.
5473 Expr *Range;
5474 if (Rel == BO_GE || Rel == BO_GT)
5475 Range = AssertSuccess(Actions.BuildBinOp(
5476 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5477 else
5478 Range = AssertSuccess(Actions.BuildBinOp(
5479 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5480
5481 // Ensure unsigned range space.
5482 Range =
5483 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5484
5485 if (Rel == BO_LE || Rel == BO_GE) {
5486 // Add one to the range if the relational operator is inclusive.
5487 Range =
5488 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5489 }
5490
5491 // Divide by the absolute step amount. If the range is not a multiple of
5492 // the step size, rounding-up the effective upper bound ensures that the
5493 // last iteration is included.
5494 // Note that the rounding-up may cause an overflow in a temporary that
5495 // could be avoided, but would have occurred in a C-style for-loop as
5496 // well.
5497 Expr *Divisor = BuildVarRef(NewStep);
5498 if (Rel == BO_GE || Rel == BO_GT)
5499 Divisor =
5500 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5501 Expr *DivisorMinusOne =
5502 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5503 Expr *RangeRoundUp = AssertSuccess(
5504 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5505 Dist = AssertSuccess(
5506 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5507
5508 // If there is not at least one iteration, the range contains garbage. Fix
5509 // to zero in this case.
5510 Dist = AssertSuccess(
5511 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5512 }
5513
5514 // Assign the result to the out-parameter.
5515 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5516 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5517 BodyStmts.push_back(ResultAssign);
5518
5519 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5520 }
5521
5522 return cast<CapturedStmt>(
5523 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5524}
5525
5526/// Create a closure that computes the loop variable from the logical iteration
5527/// number.
5528///
5529/// \param Actions The Sema object.
5530/// \param LoopVarTy Type for the loop variable used for result value.
5531/// \param LogicalTy Type for the logical iteration number.
5532/// \param StartExpr Value of the loop counter at the first iteration.
5533/// \param Step Amount of increment after each iteration.
5534/// \param Deref Whether the loop variable is a dereference of the loop
5535/// counter variable.
5536///
5537/// \return Closure (CapturedStmt) of the loop value calculation.
5538static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5539 QualType LogicalTy,
5540 DeclRefExpr *StartExpr, Expr *Step,
5541 bool Deref) {
5542 ASTContext &Ctx = Actions.getASTContext();
5543
5544 // Pass the result as an out-parameter. Passing as return value would require
5545 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5546 // invoke a copy constructor.
5547 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5548 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5549 {"Logical", LogicalTy},
5550 {StringRef(), QualType()}};
5551 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5552
5553 // Capture the initial iterator which represents the LoopVar value at the
5554 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5555 // it in every iteration, capture it by value before it is modified.
5556 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5557 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5559 (void)Invalid;
5560 assert(!Invalid && "Expecting capture-by-value to work.");
5561
5562 Expr *Body;
5563 {
5564 Sema::CompoundScopeRAII CompoundScope(Actions);
5565 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5566
5567 ImplicitParamDecl *TargetParam = CS->getParam(0);
5568 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5569 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5570 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5571 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5572 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5573
5574 // Capture the Start expression.
5575 CaptureVars Recap(Actions);
5576 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5577 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5578
5579 Expr *Skip = AssertSuccess(
5580 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5581 // TODO: Explicitly cast to the iterator's difference_type instead of
5582 // relying on implicit conversion.
5583 Expr *Advanced =
5584 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5585
5586 if (Deref) {
5587 // For range-based for-loops convert the loop counter value to a concrete
5588 // loop variable value by dereferencing the iterator.
5589 Advanced =
5590 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5591 }
5592
5593 // Assign the result to the output parameter.
5594 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5595 BO_Assign, TargetRef, Advanced));
5596 }
5597 return cast<CapturedStmt>(
5598 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5599}
5600
5602 ASTContext &Ctx = getASTContext();
5603
5604 // Extract the common elements of ForStmt and CXXForRangeStmt:
5605 // Loop variable, repeat condition, increment
5606 Expr *Cond, *Inc;
5607 VarDecl *LIVDecl, *LUVDecl;
5608 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5609 Stmt *Init = For->getInit();
5610 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5611 // For statement declares loop variable.
5612 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5613 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5614 // For statement reuses variable.
5615 assert(LCAssign->getOpcode() == BO_Assign &&
5616 "init part must be a loop variable assignment");
5617 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5618 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5619 } else
5620 llvm_unreachable("Cannot determine loop variable");
5621 LUVDecl = LIVDecl;
5622
5623 Cond = For->getCond();
5624 Inc = For->getInc();
5625 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5626 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5627 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5628 LUVDecl = RangeFor->getLoopVariable();
5629
5630 Cond = RangeFor->getCond();
5631 Inc = RangeFor->getInc();
5632 } else
5633 llvm_unreachable("unhandled kind of loop");
5634
5635 QualType CounterTy = LIVDecl->getType();
5636 QualType LVTy = LUVDecl->getType();
5637
5638 // Analyze the loop condition.
5639 Expr *LHS, *RHS;
5640 BinaryOperator::Opcode CondRel;
5641 Cond = Cond->IgnoreImplicit();
5642 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5643 LHS = CondBinExpr->getLHS();
5644 RHS = CondBinExpr->getRHS();
5645 CondRel = CondBinExpr->getOpcode();
5646 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5647 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5648 LHS = CondCXXOp->getArg(0);
5649 RHS = CondCXXOp->getArg(1);
5650 switch (CondCXXOp->getOperator()) {
5651 case OO_ExclaimEqual:
5652 CondRel = BO_NE;
5653 break;
5654 case OO_Less:
5655 CondRel = BO_LT;
5656 break;
5657 case OO_LessEqual:
5658 CondRel = BO_LE;
5659 break;
5660 case OO_Greater:
5661 CondRel = BO_GT;
5662 break;
5663 case OO_GreaterEqual:
5664 CondRel = BO_GE;
5665 break;
5666 default:
5667 llvm_unreachable("unexpected iterator operator");
5668 }
5669 } else
5670 llvm_unreachable("unexpected loop condition");
5671
5672 // Normalize such that the loop counter is on the LHS.
5673 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5674 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5675 std::swap(LHS, RHS);
5676 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5677 }
5678 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5679
5680 // Decide the bit width for the logical iteration counter. By default use the
5681 // unsigned ptrdiff_t integer size (for iterators and pointers).
5682 // TODO: For iterators, use iterator::difference_type,
5683 // std::iterator_traits<>::difference_type or decltype(it - end).
5684 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5685 if (CounterTy->isIntegerType()) {
5686 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5687 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5688 }
5689
5690 // Analyze the loop increment.
5691 Expr *Step;
5692 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5693 int Direction;
5694 switch (IncUn->getOpcode()) {
5695 case UO_PreInc:
5696 case UO_PostInc:
5697 Direction = 1;
5698 break;
5699 case UO_PreDec:
5700 case UO_PostDec:
5701 Direction = -1;
5702 break;
5703 default:
5704 llvm_unreachable("unhandled unary increment operator");
5705 }
5707 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5708 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5709 if (IncBin->getOpcode() == BO_AddAssign) {
5710 Step = IncBin->getRHS();
5711 } else if (IncBin->getOpcode() == BO_SubAssign) {
5712 Step = AssertSuccess(
5713 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5714 } else
5715 llvm_unreachable("unhandled binary increment operator");
5716 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5717 switch (CondCXXOp->getOperator()) {
5718 case OO_PlusPlus:
5720 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5721 break;
5722 case OO_MinusMinus:
5724 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5725 break;
5726 case OO_PlusEqual:
5727 Step = CondCXXOp->getArg(1);
5728 break;
5729 case OO_MinusEqual:
5730 Step = AssertSuccess(
5731 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5732 break;
5733 default:
5734 llvm_unreachable("unhandled overloaded increment operator");
5735 }
5736 } else
5737 llvm_unreachable("unknown increment expression");
5738
5739 CapturedStmt *DistanceFunc =
5740 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5741 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5742 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5743 DeclRefExpr *LVRef =
5744 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5745 nullptr, nullptr, {}, nullptr);
5746 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5747 LoopVarFunc, LVRef);
5748}
5749
5751 // Handle a literal loop.
5752 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5753 return ActOnOpenMPCanonicalLoop(AStmt);
5754
5755 // If not a literal loop, it must be the result of a loop transformation.
5756 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5757 assert(
5759 "Loop transformation directive expected");
5760 return LoopTransform;
5761}
5762
5764 CXXScopeSpec &MapperIdScopeSpec,
5765 const DeclarationNameInfo &MapperId,
5766 QualType Type,
5767 Expr *UnresolvedMapper);
5768
5769/// Perform DFS through the structure/class data members trying to find
5770/// member(s) with user-defined 'default' mapper and generate implicit map
5771/// clauses for such members with the found 'default' mapper.
5772static void
5775 // Check for the default mapper for data members.
5776 if (S.getLangOpts().OpenMP < 50)
5777 return;
5778 SmallVector<OMPClause *, 4> ImplicitMaps;
5779 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5780 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5781 if (!C)
5782 continue;
5783 SmallVector<Expr *, 4> SubExprs;
5784 auto *MI = C->mapperlist_begin();
5785 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5786 ++I, ++MI) {
5787 // Expression is mapped using mapper - skip it.
5788 if (*MI)
5789 continue;
5790 Expr *E = *I;
5791 // Expression is dependent - skip it, build the mapper when it gets
5792 // instantiated.
5793 if (E->isTypeDependent() || E->isValueDependent() ||
5795 continue;
5796 // Array section - need to check for the mapping of the array section
5797 // element.
5798 QualType CanonType = E->getType().getCanonicalType();
5799 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5800 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5801 QualType BaseType =
5803 QualType ElemType;
5804 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5805 ElemType = ATy->getElementType();
5806 else
5807 ElemType = BaseType->getPointeeType();
5808 CanonType = ElemType;
5809 }
5810
5811 // DFS over data members in structures/classes.
5813 1, {CanonType, nullptr});
5814 llvm::DenseMap<const Type *, Expr *> Visited;
5816 1, {nullptr, 1});
5817 while (!Types.empty()) {
5818 QualType BaseType;
5819 FieldDecl *CurFD;
5820 std::tie(BaseType, CurFD) = Types.pop_back_val();
5821 while (ParentChain.back().second == 0)
5822 ParentChain.pop_back();
5823 --ParentChain.back().second;
5824 if (BaseType.isNull())
5825 continue;
5826 // Only structs/classes are allowed to have mappers.
5827 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5828 if (!RD)
5829 continue;
5830 auto It = Visited.find(BaseType.getTypePtr());
5831 if (It == Visited.end()) {
5832 // Try to find the associated user-defined mapper.
5833 CXXScopeSpec MapperIdScopeSpec;
5834 DeclarationNameInfo DefaultMapperId;
5836 &S.Context.Idents.get("default")));
5837 DefaultMapperId.setLoc(E->getExprLoc());
5839 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5840 BaseType, /*UnresolvedMapper=*/nullptr);
5841 if (ER.isInvalid())
5842 continue;
5843 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5844 }
5845 // Found default mapper.
5846 if (It->second) {
5847 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5849 OE->setIsUnique(/*V=*/true);
5850 Expr *BaseExpr = OE;
5851 for (const auto &P : ParentChain) {
5852 if (P.first) {
5853 BaseExpr = S.BuildMemberExpr(
5854 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5856 DeclAccessPair::make(P.first, P.first->getAccess()),
5857 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5858 P.first->getType(), VK_LValue, OK_Ordinary);
5859 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5860 }
5861 }
5862 if (CurFD)
5863 BaseExpr = S.BuildMemberExpr(
5864 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5866 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5867 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5868 CurFD->getType(), VK_LValue, OK_Ordinary);
5869 SubExprs.push_back(BaseExpr);
5870 continue;
5871 }
5872 // Check for the "default" mapper for data members.
5873 bool FirstIter = true;
5874 for (FieldDecl *FD : RD->fields()) {
5875 if (!FD)
5876 continue;
5877 QualType FieldTy = FD->getType();
5878 if (FieldTy.isNull() ||
5879 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5880 continue;
5881 if (FirstIter) {
5882 FirstIter = false;
5883 ParentChain.emplace_back(CurFD, 1);
5884 } else {
5885 ++ParentChain.back().second;
5886 }
5887 Types.emplace_back(FieldTy, FD);
5888 }
5889 }
5890 }
5891 if (SubExprs.empty())
5892 continue;
5893 CXXScopeSpec MapperIdScopeSpec;
5894 DeclarationNameInfo MapperId;
5895 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5896 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
5897 MapperIdScopeSpec, MapperId, C->getMapType(),
5898 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
5899 SubExprs, OMPVarListLocTy()))
5900 Clauses.push_back(NewClause);
5901 }
5902}
5903
5904namespace {
5905/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5906/// call in the associated loop-nest cannot be a 'parallel for'.
5907class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5908 Sema &SemaRef;
5909
5910public:
5911 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5912
5913 // Is there a nested OpenMP loop bind(parallel)
5914 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5915 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5916 if (const auto *C = D->getSingleClause<OMPBindClause>())
5917 if (C->getBindKind() == OMPC_BIND_parallel) {
5918 TeamsLoopCanBeParallelFor = false;
5919 // No need to continue visiting any more
5920 return;
5921 }
5922 }
5923 for (const Stmt *Child : D->children())
5924 if (Child)
5925 Visit(Child);
5926 }
5927
5928 void VisitCallExpr(const CallExpr *C) {
5929 // Function calls inhibit parallel loop translation of 'target teams loop'
5930 // unless the assume-no-nested-parallelism flag has been specified.
5931 // OpenMP API runtime library calls do not inhibit parallel loop
5932 // translation, regardless of the assume-no-nested-parallelism.
5933 bool IsOpenMPAPI = false;
5934 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
5935 if (FD) {
5936 std::string Name = FD->getNameInfo().getAsString();
5937 IsOpenMPAPI = Name.find("omp_") == 0;
5938 }
5939 TeamsLoopCanBeParallelFor =
5940 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5941 if (!TeamsLoopCanBeParallelFor)
5942 return;
5943
5944 for (const Stmt *Child : C->children())
5945 if (Child)
5946 Visit(Child);
5947 }
5948
5949 void VisitCapturedStmt(const CapturedStmt *S) {
5950 if (!S)
5951 return;
5952 Visit(S->getCapturedDecl()->getBody());
5953 }
5954
5955 void VisitStmt(const Stmt *S) {
5956 if (!S)
5957 return;
5958 for (const Stmt *Child : S->children())
5959 if (Child)
5960 Visit(Child);
5961 }
5962 explicit TeamsLoopChecker(Sema &SemaRef)
5963 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5964
5965private:
5966 bool TeamsLoopCanBeParallelFor;
5967};
5968} // namespace
5969
5970static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5971 TeamsLoopChecker Checker(SemaRef);
5972 Checker.Visit(AStmt);
5973 return Checker.teamsLoopCanBeParallelFor();
5974}
5975
5977 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5978 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5979 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5980 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5981
5982 StmtResult Res = StmtError();
5984 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5985
5986 if (const OMPBindClause *BC =
5987 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5988 BindKind = BC->getBindKind();
5989
5990 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
5991 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
5992
5993 // Setting the enclosing teams or parallel construct for the loop
5994 // directive without bind clause.
5995 // [5.0:129:25-28] If the bind clause is not present on the construct and
5996 // the loop construct is closely nested inside a teams or parallel
5997 // construct, the binding region is the corresponding teams or parallel
5998 // region. If none of those conditions hold, the binding region is not
5999 // defined.
6000 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6001 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6002 getLeafConstructsOrSelf(ParentDirective);
6003
6004 if (ParentDirective == OMPD_unknown) {
6005 Diag(DSAStack->getDefaultDSALocation(),
6006 diag::err_omp_bind_required_on_loop);
6007 } else if (ParentLeafs.back() == OMPD_parallel) {
6008 BindKind = OMPC_BIND_parallel;
6009 } else if (ParentLeafs.back() == OMPD_teams) {
6010 BindKind = OMPC_BIND_teams;
6011 }
6012
6013 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6014
6015 OMPClause *C =
6018 ClausesWithImplicit.push_back(C);
6019 }
6020
6021 // Diagnose "loop bind(teams)" with "reduction".
6022 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6023 for (OMPClause *C : Clauses) {
6024 if (C->getClauseKind() == OMPC_reduction)
6025 Diag(DSAStack->getDefaultDSALocation(),
6026 diag::err_omp_loop_reduction_clause);
6027 }
6028 }
6029
6030 // First check CancelRegion which is then used in checkNestingOfRegions.
6031 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6032 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6033 BindKind, StartLoc)) {
6034 return StmtError();
6035 }
6036
6037 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6040 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6041
6042 VarsWithInheritedDSAType VarsWithInheritedDSA;
6043 bool ErrorFound = false;
6044 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6045
6046 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6048 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6049
6050 // Check default data sharing attributes for referenced variables.
6051 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6052 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6053 Stmt *S = AStmt;
6054 while (--ThisCaptureLevel >= 0)
6055 S = cast<CapturedStmt>(S)->getCapturedStmt();
6056 DSAChecker.Visit(S);
6058 !isOpenMPTaskingDirective(Kind)) {
6059 // Visit subcaptures to generate implicit clauses for captured vars.
6060 auto *CS = cast<CapturedStmt>(AStmt);
6062 getOpenMPCaptureRegions(CaptureRegions, Kind);
6063 // Ignore outer tasking regions for target directives.
6064 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6065 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6066 DSAChecker.visitSubCaptures(CS);
6067 }
6068 if (DSAChecker.isErrorFound())
6069 return StmtError();
6070 // Generate list of implicitly defined firstprivate variables.
6071 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6072
6073 SmallVector<Expr *, 4> ImplicitFirstprivates(
6074 DSAChecker.getImplicitFirstprivate());
6075 SmallVector<Expr *, 4> ImplicitPrivates(DSAChecker.getImplicitPrivate());
6076 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6077 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6079 ImplicitMapModifiers[DefaultmapKindNum];
6081 ImplicitMapModifiersLoc[DefaultmapKindNum];
6082 // Get the original location of present modifier from Defaultmap clause.
6083 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6084 for (OMPClause *C : Clauses) {
6085 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6086 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6087 PresentModifierLocs[DMC->getDefaultmapKind()] =
6088 DMC->getDefaultmapModifierLoc();
6089 }
6090 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6091 auto K = static_cast<OpenMPDefaultmapClauseKind>(VC);
6092 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6093 ArrayRef<Expr *> ImplicitMap =
6094 DSAChecker.getImplicitMap(K, static_cast<OpenMPMapClauseKind>(I));
6095 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6096 }
6097 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6098 DSAChecker.getImplicitMapModifier(K);
6099 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6100 ImplicitModifier.end());
6101 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6102 ImplicitModifier.size(), PresentModifierLocs[VC]);
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 ImplicitFirstprivates.emplace_back(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 ImplicitFirstprivates.push_back(DC->getEventHandler());
6116 }
6117 if (!ImplicitFirstprivates.empty()) {
6119 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6120 SourceLocation())) {
6121 ClausesWithImplicit.push_back(Implicit);
6122 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6123 ImplicitFirstprivates.size();
6124 } else {
6125 ErrorFound = true;
6126 }
6127 }
6128 if (!ImplicitPrivates.empty()) {
6129 if (OMPClause *Implicit =
6130 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6132 ClausesWithImplicit.push_back(Implicit);
6133 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6134 ImplicitPrivates.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, E = DefaultmapKindNum; I < E; ++I) {
6165 int ClauseKindCnt = -1;
6166 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6167 ++ClauseKindCnt;
6168 if (ImplicitMap.empty())
6169 continue;
6170 CXXScopeSpec MapperIdScopeSpec;
6171 DeclarationNameInfo MapperId;
6172 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6174 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6175 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6176 SourceLocation(), SourceLocation(), ImplicitMap,
6177 OMPVarListLocTy())) {
6178 ClausesWithImplicit.emplace_back(Implicit);
6179 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6180 ImplicitMap.size();
6181 } else {
6182 ErrorFound = true;
6183 }
6184 }
6185 }
6186 // Build expressions for implicit maps of data members with 'default'
6187 // mappers.
6188 if (getLangOpts().OpenMP >= 50)
6190 ClausesWithImplicit);
6191 }
6192
6193 switch (Kind) {
6194 case OMPD_parallel:
6195 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6196 EndLoc);
6197 break;
6198 case OMPD_simd:
6199 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6200 VarsWithInheritedDSA);
6201 break;
6202 case OMPD_tile:
6203 Res =
6204 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6205 break;
6206 case OMPD_unroll:
6207 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6208 EndLoc);
6209 break;
6210 case OMPD_reverse:
6211 assert(ClausesWithImplicit.empty() &&
6212 "reverse directive does not support any clauses");
6213 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6214 break;
6215 case OMPD_interchange:
6216 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6217 EndLoc);
6218 break;
6219 case OMPD_for:
6220 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6221 VarsWithInheritedDSA);
6222 break;
6223 case OMPD_for_simd:
6224 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6225 EndLoc, VarsWithInheritedDSA);
6226 break;
6227 case OMPD_sections:
6228 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6229 EndLoc);
6230 break;
6231 case OMPD_section:
6232 assert(ClausesWithImplicit.empty() &&
6233 "No clauses are allowed for 'omp section' directive");
6234 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6235 break;
6236 case OMPD_single:
6237 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6238 EndLoc);
6239 break;
6240 case OMPD_master:
6241 assert(ClausesWithImplicit.empty() &&
6242 "No clauses are allowed for 'omp master' directive");
6243 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6244 break;
6245 case OMPD_masked:
6246 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6247 EndLoc);
6248 break;
6249 case OMPD_critical:
6250 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6251 StartLoc, EndLoc);
6252 break;
6253 case OMPD_parallel_for:
6254 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6255 EndLoc, VarsWithInheritedDSA);
6256 break;
6257 case OMPD_parallel_for_simd:
6259 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6260 break;
6261 case OMPD_scope:
6262 Res =
6263 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6264 break;
6265 case OMPD_parallel_master:
6266 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6267 StartLoc, EndLoc);
6268 break;
6269 case OMPD_parallel_masked:
6270 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6271 StartLoc, EndLoc);
6272 break;
6273 case OMPD_parallel_sections:
6274 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6275 StartLoc, EndLoc);
6276 break;
6277 case OMPD_task:
6278 Res =
6279 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6280 break;
6281 case OMPD_taskyield:
6282 assert(ClausesWithImplicit.empty() &&
6283 "No clauses are allowed for 'omp taskyield' directive");
6284 assert(AStmt == nullptr &&
6285 "No associated statement allowed for 'omp taskyield' directive");
6286 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6287 break;
6288 case OMPD_error:
6289 assert(AStmt == nullptr &&
6290 "No associated statement allowed for 'omp error' directive");
6291 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6292 break;
6293 case OMPD_barrier:
6294 assert(ClausesWithImplicit.empty() &&
6295 "No clauses are allowed for 'omp barrier' directive");
6296 assert(AStmt == nullptr &&
6297 "No associated statement allowed for 'omp barrier' directive");
6298 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6299 break;
6300 case OMPD_taskwait:
6301 assert(AStmt == nullptr &&
6302 "No associated statement allowed for 'omp taskwait' directive");
6303 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6304 break;
6305 case OMPD_taskgroup:
6306 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6307 EndLoc);
6308 break;
6309 case OMPD_flush:
6310 assert(AStmt == nullptr &&
6311 "No associated statement allowed for 'omp flush' directive");
6312 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6313 break;
6314 case OMPD_depobj:
6315 assert(AStmt == nullptr &&
6316 "No associated statement allowed for 'omp depobj' directive");
6317 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6318 break;
6319 case OMPD_scan:
6320 assert(AStmt == nullptr &&
6321 "No associated statement allowed for 'omp scan' directive");
6322 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6323 break;
6324 case OMPD_ordered:
6325 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6326 EndLoc);
6327 break;
6328 case OMPD_atomic:
6329 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6330 EndLoc);
6331 break;
6332 case OMPD_teams:
6333 Res =
6334 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6335 break;
6336 case OMPD_target:
6337 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6338 EndLoc);
6339 break;
6340 case OMPD_target_parallel:
6341 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6342 StartLoc, EndLoc);
6343 break;
6344 case OMPD_target_parallel_for:
6346 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6347 break;
6348 case OMPD_cancellation_point:
6349 assert(ClausesWithImplicit.empty() &&
6350 "No clauses are allowed for 'omp cancellation point' directive");
6351 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6352 "cancellation point' directive");
6353 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6354 break;
6355 case OMPD_cancel:
6356 assert(AStmt == nullptr &&
6357 "No associated statement allowed for 'omp cancel' directive");
6358 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6359 CancelRegion);
6360 break;
6361 case OMPD_target_data:
6362 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6363 EndLoc);
6364 break;
6365 case OMPD_target_enter_data:
6366 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6367 EndLoc, AStmt);
6368 break;
6369 case OMPD_target_exit_data:
6370 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6371 EndLoc, AStmt);
6372 break;
6373 case OMPD_taskloop:
6374 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6375 EndLoc, VarsWithInheritedDSA);
6376 break;
6377 case OMPD_taskloop_simd:
6378 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6379 EndLoc, VarsWithInheritedDSA);
6380 break;
6381 case OMPD_master_taskloop:
6383 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6384 break;
6385 case OMPD_masked_taskloop:
6387 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6388 break;
6389 case OMPD_master_taskloop_simd:
6391 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6392 break;
6393 case OMPD_masked_taskloop_simd:
6395 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6396 break;
6397 case OMPD_parallel_master_taskloop:
6399 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6400 break;
6401 case OMPD_parallel_masked_taskloop:
6403 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6404 break;
6405 case OMPD_parallel_master_taskloop_simd:
6407 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6408 break;
6409 case OMPD_parallel_masked_taskloop_simd:
6411 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6412 break;
6413 case OMPD_distribute:
6414 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6415 EndLoc, VarsWithInheritedDSA);
6416 break;
6417 case OMPD_target_update:
6418 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6419 EndLoc, AStmt);
6420 break;
6421 case OMPD_distribute_parallel_for:
6423 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6424 break;
6425 case OMPD_distribute_parallel_for_simd:
6427 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6428 break;
6429 case OMPD_distribute_simd:
6431 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6432 break;
6433 case OMPD_target_parallel_for_simd:
6435 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6436 break;
6437 case OMPD_target_simd:
6438 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6439 EndLoc, VarsWithInheritedDSA);
6440 break;
6441 case OMPD_teams_distribute:
6443 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6444 break;
6445 case OMPD_teams_distribute_simd:
6447 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6448 break;
6449 case OMPD_teams_distribute_parallel_for_simd:
6451 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6452 break;
6453 case OMPD_teams_distribute_parallel_for:
6455 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6456 break;
6457 case OMPD_target_teams:
6458 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6459 EndLoc);
6460 break;
6461 case OMPD_target_teams_distribute:
6463 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6464 break;
6465 case OMPD_target_teams_distribute_parallel_for:
6467 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6468 break;
6469 case OMPD_target_teams_distribute_parallel_for_simd:
6471 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6472 break;
6473 case OMPD_target_teams_distribute_simd:
6475 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6476 break;
6477 case OMPD_interop:
6478 assert(AStmt == nullptr &&
6479 "No associated statement allowed for 'omp interop' directive");
6480 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6481 break;
6482 case OMPD_dispatch:
6483 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6484 EndLoc);
6485 break;
6486 case OMPD_loop:
6487 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6488 EndLoc, VarsWithInheritedDSA);
6489 break;
6490 case OMPD_teams_loop:
6492 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6493 break;
6494 case OMPD_target_teams_loop:
6496 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6497 break;
6498 case OMPD_parallel_loop:
6500 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6501 break;
6502 case OMPD_target_parallel_loop:
6504 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6505 break;
6506 case OMPD_declare_target:
6507 case OMPD_end_declare_target:
6508 case OMPD_threadprivate:
6509 case OMPD_allocate:
6510 case OMPD_declare_reduction:
6511 case OMPD_declare_mapper:
6512 case OMPD_declare_simd:
6513 case OMPD_requires:
6514 case OMPD_declare_variant:
6515 case OMPD_begin_declare_variant:
6516 case OMPD_end_declare_variant:
6517 llvm_unreachable("OpenMP Directive is not allowed");
6518 case OMPD_unknown:
6519 default:
6520 llvm_unreachable("Unknown OpenMP directive");
6521 }
6522
6523 ErrorFound = Res.isInvalid() || ErrorFound;
6524
6525 // Check variables in the clauses if default(none) or
6526 // default(firstprivate) was specified.
6527 if (DSAStack->getDefaultDSA() == DSA_none ||
6528 DSAStack->getDefaultDSA() == DSA_private ||
6529 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6530 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6531 for (OMPClause *C : Clauses) {
6532 switch (C->getClauseKind()) {
6533 case OMPC_num_threads:
6534 case OMPC_dist_schedule:
6535 // Do not analyze if no parent teams directive.
6536 if (isOpenMPTeamsDirective(Kind))
6537 break;
6538 continue;
6539 case OMPC_if:
6540 if (isOpenMPTeamsDirective(Kind) &&
6541 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6542 break;
6543 if (isOpenMPParallelDirective(Kind) &&
6545 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6546 break;
6547 continue;
6548 case OMPC_schedule:
6549 case OMPC_detach:
6550 break;
6551 case OMPC_grainsize:
6552 case OMPC_num_tasks:
6553 case OMPC_final:
6554 case OMPC_priority:
6555 case OMPC_novariants:
6556 case OMPC_nocontext:
6557 // Do not analyze if no parent parallel directive.
6558 if (isOpenMPParallelDirective(Kind))
6559 break;
6560 continue;
6561 case OMPC_ordered:
6562 case OMPC_device:
6563 case OMPC_num_teams:
6564 case OMPC_thread_limit:
6565 case OMPC_hint:
6566 case OMPC_collapse:
6567 case OMPC_safelen:
6568 case OMPC_simdlen:
6569 case OMPC_sizes:
6570 case OMPC_default:
6571 case OMPC_proc_bind:
6572 case OMPC_private:
6573 case OMPC_firstprivate:
6574 case OMPC_lastprivate:
6575 case OMPC_shared:
6576 case OMPC_reduction:
6577 case OMPC_task_reduction:
6578 case OMPC_in_reduction:
6579 case OMPC_linear:
6580 case OMPC_aligned:
6581 case OMPC_copyin:
6582 case OMPC_copyprivate:
6583 case OMPC_nowait:
6584 case OMPC_untied:
6585 case OMPC_mergeable:
6586 case OMPC_allocate:
6587 case OMPC_read:
6588 case OMPC_write:
6589 case OMPC_update:
6590 case OMPC_capture:
6591 case OMPC_compare:
6592 case OMPC_seq_cst:
6593 case OMPC_acq_rel:
6594 case OMPC_acquire:
6595 case OMPC_release:
6596 case OMPC_relaxed:
6597 case OMPC_depend:
6598 case OMPC_threads:
6599 case OMPC_simd:
6600 case OMPC_map:
6601 case OMPC_nogroup:
6602 case OMPC_defaultmap:
6603 case OMPC_to:
6604 case OMPC_from:
6605 case OMPC_use_device_ptr:
6606 case OMPC_use_device_addr:
6607 case OMPC_is_device_ptr:
6608 case OMPC_has_device_addr:
6609 case OMPC_nontemporal:
6610 case OMPC_order:
6611 case OMPC_destroy:
6612 case OMPC_inclusive:
6613 case OMPC_exclusive:
6614 case OMPC_uses_allocators:
6615 case OMPC_affinity:
6616 case OMPC_bind:
6617 case OMPC_filter:
6618 continue;
6619 case OMPC_allocator:
6620 case OMPC_flush:
6621 case OMPC_depobj:
6622 case OMPC_threadprivate:
6623 case OMPC_uniform:
6624 case OMPC_unknown:
6625 case OMPC_unified_address:
6626 case OMPC_unified_shared_memory:
6627 case OMPC_reverse_offload:
6628 case OMPC_dynamic_allocators:
6629 case OMPC_atomic_default_mem_order:
6630 case OMPC_device_type:
6631 case OMPC_match:
6632 case OMPC_when:
6633 case OMPC_at:
6634 case OMPC_severity:
6635 case OMPC_message:
6636 default:
6637 llvm_unreachable("Unexpected clause");
6638 }
6639 for (Stmt *CC : C->children()) {
6640 if (CC)
6641 DSAChecker.Visit(CC);
6642 }
6643 }
6644 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6645 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6646 }
6647 for (const auto &P : VarsWithInheritedDSA) {
6648 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6649 continue;
6650 ErrorFound = true;
6651 if (DSAStack->getDefaultDSA() == DSA_none ||
6652 DSAStack->getDefaultDSA() == DSA_private ||
6653 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6654 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6655 << P.first << P.second->getSourceRange();
6656 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6657 } else if (getLangOpts().OpenMP >= 50) {
6658 Diag(P.second->getExprLoc(),
6659 diag::err_omp_defaultmap_no_attr_for_variable)
6660 << P.first << P.second->getSourceRange();
6661 Diag(DSAStack->getDefaultDSALocation(),
6662 diag::note_omp_defaultmap_attr_none);
6663 }
6664 }
6665
6666 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6667 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6668 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6669 AllowedNameModifiers.push_back(D);
6670 }
6671 if (!AllowedNameModifiers.empty())
6672 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6673 ErrorFound;
6674
6675 if (ErrorFound)
6676 return StmtError();
6677
6680 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6681 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6682 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6683 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6684 // Register target to DSA Stack.
6685 DSAStack->addTargetDirLocation(StartLoc);
6686 }
6687
6688 return Res;
6689}
6690
6692 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6693 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6694 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6695 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6696 assert(Aligneds.size() == Alignments.size());
6697 assert(Linears.size() == LinModifiers.size());
6698 assert(Linears.size() == Steps.size());
6699 if (!DG || DG.get().isNull())
6700 return DeclGroupPtrTy();
6701
6702 const int SimdId = 0;
6703 if (!DG.get().isSingleDecl()) {
6704 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6705 << SimdId;
6706 return DG;
6707 }
6708 Decl *ADecl = DG.get().getSingleDecl();
6709 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6710 ADecl = FTD->getTemplatedDecl();
6711
6712 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6713 if (!FD) {
6714 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6715 return DeclGroupPtrTy();
6716 }
6717
6718 // OpenMP [2.8.2, declare simd construct, Description]
6719 // The parameter of the simdlen clause must be a constant positive integer
6720 // expression.
6721 ExprResult SL;
6722 if (Simdlen)
6723 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6724 // OpenMP [2.8.2, declare simd construct, Description]
6725 // The special this pointer can be used as if was one of the arguments to the
6726 // function in any of the linear, aligned, or uniform clauses.
6727 // The uniform clause declares one or more arguments to have an invariant
6728 // value for all concurrent invocations of the function in the execution of a
6729 // single SIMD loop.
6730 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6731 const Expr *UniformedLinearThis = nullptr;
6732 for (const Expr *E : Uniforms) {
6733 E = E->IgnoreParenImpCasts();
6734 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6735 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6736 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6737 FD->getParamDecl(PVD->getFunctionScopeIndex())
6738 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6739 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6740 continue;
6741 }
6742 if (isa<CXXThisExpr>(E)) {
6743 UniformedLinearThis = E;
6744 continue;
6745 }
6746 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6747 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6748 }
6749 // OpenMP [2.8.2, declare simd construct, Description]
6750 // The aligned clause declares that the object to which each list item points
6751 // is aligned to the number of bytes expressed in the optional parameter of
6752 // the aligned clause.
6753 // The special this pointer can be used as if was one of the arguments to the
6754 // function in any of the linear, aligned, or uniform clauses.
6755 // The type of list items appearing in the aligned clause must be array,
6756 // pointer, reference to array, or reference to pointer.
6757 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6758 const Expr *AlignedThis = nullptr;
6759 for (const Expr *E : Aligneds) {
6760 E = E->IgnoreParenImpCasts();
6761 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6762 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6763 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6764 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6765 FD->getParamDecl(PVD->getFunctionScopeIndex())
6766 ->getCanonicalDecl() == CanonPVD) {
6767 // OpenMP [2.8.1, simd construct, Restrictions]
6768 // A list-item cannot appear in more than one aligned clause.
6769 if (AlignedArgs.count(CanonPVD) > 0) {
6770 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6771 << 1 << getOpenMPClauseName(OMPC_aligned)
6772 << E->getSourceRange();
6773 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6774 diag::note_omp_explicit_dsa)
6775 << getOpenMPClauseName(OMPC_aligned);
6776 continue;
6777 }
6778 AlignedArgs[CanonPVD] = E;
6779 QualType QTy = PVD->getType()
6780 .getNonReferenceType()
6781 .getUnqualifiedType()
6782 .getCanonicalType();
6783 const Type *Ty = QTy.getTypePtrOrNull();
6784 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6785 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6786 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6787 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6788 }
6789 continue;
6790 }
6791 }
6792 if (isa<CXXThisExpr>(E)) {
6793 if (AlignedThis) {
6794 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6795 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6796 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6797 << getOpenMPClauseName(OMPC_aligned);
6798 }
6799 AlignedThis = E;
6800 continue;
6801 }
6802 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6803 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6804 }
6805 // The optional parameter of the aligned clause, alignment, must be a constant
6806 // positive integer expression. If no optional parameter is specified,
6807 // implementation-defined default alignments for SIMD instructions on the
6808 // target platforms are assumed.
6810 for (Expr *E : Alignments) {
6811 ExprResult Align;
6812 if (E)
6813 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6814 NewAligns.push_back(Align.get());
6815 }
6816 // OpenMP [2.8.2, declare simd construct, Description]
6817 // The linear clause declares one or more list items to be private to a SIMD
6818 // lane and to have a linear relationship with respect to the iteration space
6819 // of a loop.
6820 // The special this pointer can be used as if was one of the arguments to the
6821 // function in any of the linear, aligned, or uniform clauses.
6822 // When a linear-step expression is specified in a linear clause it must be
6823 // either a constant integer expression or an integer-typed parameter that is
6824 // specified in a uniform clause on the directive.
6825 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6826 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6827 auto MI = LinModifiers.begin();
6828 for (const Expr *E : Linears) {
6829 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6830 ++MI;
6831 E = E->IgnoreParenImpCasts();
6832 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6833 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6834 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6835 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6836 FD->getParamDecl(PVD->getFunctionScopeIndex())
6837 ->getCanonicalDecl() == CanonPVD) {
6838 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6839 // A list-item cannot appear in more than one linear clause.
6840 if (LinearArgs.count(CanonPVD) > 0) {
6841 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6842 << getOpenMPClauseName(OMPC_linear)
6843 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6844 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6845 diag::note_omp_explicit_dsa)
6846 << getOpenMPClauseName(OMPC_linear);
6847 continue;
6848 }
6849 // Each argument can appear in at most one uniform or linear clause.
6850 if (UniformedArgs.count(CanonPVD) > 0) {
6851 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6852 << getOpenMPClauseName(OMPC_linear)
6853 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
6854 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6855 diag::note_omp_explicit_dsa)
6856 << getOpenMPClauseName(OMPC_uniform);
6857 continue;
6858 }
6859 LinearArgs[CanonPVD] = E;
6860 if (E->isValueDependent() || E->isTypeDependent() ||
6863 continue;
6864 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6865 PVD->getOriginalType(),
6866 /*IsDeclareSimd=*/true);
6867 continue;
6868 }
6869 }
6870 if (isa<CXXThisExpr>(E)) {
6871 if (UniformedLinearThis) {
6872 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6873 << getOpenMPClauseName(OMPC_linear)
6874 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6875 << E->getSourceRange();
6876 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6877 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6878 : OMPC_linear);
6879 continue;
6880 }
6881 UniformedLinearThis = E;
6882 if (E->isValueDependent() || E->isTypeDependent() ||
6884 continue;
6885 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6886 E->getType(), /*IsDeclareSimd=*/true);
6887 continue;
6888 }
6889 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6890 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6891 }
6892 Expr *Step = nullptr;
6893 Expr *NewStep = nullptr;
6894 SmallVector<Expr *, 4> NewSteps;
6895 for (Expr *E : Steps) {
6896 // Skip the same step expression, it was checked already.
6897 if (Step == E || !E) {
6898 NewSteps.push_back(E ? NewStep : nullptr);
6899 continue;
6900 }
6901 Step = E;
6902 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6903 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6904 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6905 if (UniformedArgs.count(CanonPVD) == 0) {
6906 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6907 << Step->getSourceRange();
6908 } else if (E->isValueDependent() || E->isTypeDependent() ||
6911 CanonPVD->getType()->hasIntegerRepresentation()) {
6912 NewSteps.push_back(Step);
6913 } else {
6914 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6915 << Step->getSourceRange();
6916 }
6917 continue;
6918 }
6919 NewStep = Step;
6920 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6921 !Step->isInstantiationDependent() &&
6923 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6924 .get();
6925 if (NewStep)
6926 NewStep = SemaRef
6928 NewStep, /*FIXME*/ Sema::AllowFold)
6929 .get();
6930 }
6931 NewSteps.push_back(NewStep);
6932 }
6933 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6934 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
6935 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
6936 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
6937 const_cast<Expr **>(Linears.data()), Linears.size(),
6938 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
6939 NewSteps.data(), NewSteps.size(), SR);
6940 ADecl->addAttr(NewAttr);
6941 return DG;
6942}
6943
6945 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6946 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
6947 SourceLocation EndLoc) {
6948 assert(isOpenMPInformationalDirective(Kind) &&
6949 "Unexpected directive category");
6950
6951 StmtResult Res = StmtError();
6952
6953 switch (Kind) {
6954 case OMPD_assume:
6955 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
6956 break;
6957 default:
6958 llvm_unreachable("Unknown OpenMP directive");
6959 }
6960
6961 return Res;
6962}
6963
6964static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6965 QualType NewType) {
6966 assert(NewType->isFunctionProtoType() &&
6967 "Expected function type with prototype.");
6968 assert(FD->getType()->isFunctionNoProtoType() &&
6969 "Expected function with type with no prototype.");
6970 assert(FDWithProto->getType()->isFunctionProtoType() &&
6971 "Expected function with prototype.");
6972 // Synthesize parameters with the same types.
6973 FD->setType(NewType);
6975 for (const ParmVarDecl *P : FDWithProto->parameters()) {
6976 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
6977 SourceLocation(), nullptr, P->getType(),
6978 /*TInfo=*/nullptr, SC_None, nullptr);
6979 Param->setScopeInfo(0, Params.size());
6980 Param->setImplicit();
6981 Params.push_back(Param);
6982 }
6983
6984 FD->setParams(Params);
6985}
6986
6988 if (D->isInvalidDecl())
6989 return;
6990 FunctionDecl *FD = nullptr;
6991 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
6992 FD = UTemplDecl->getTemplatedDecl();
6993 else
6994 FD = cast<FunctionDecl>(D);
6995 assert(FD && "Expected a function declaration!");
6996
6997 // If we are instantiating templates we do *not* apply scoped assumptions but
6998 // only global ones. We apply scoped assumption to the template definition
6999 // though.
7001 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7002 FD->addAttr(AA);
7003 }
7004 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7005 FD->addAttr(AA);
7006}
7007
7008SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7009 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7010
7012 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7014 if (!D.getIdentifier())
7015 return;
7016
7017 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7018
7019 // Template specialization is an extension, check if we do it.
7020 bool IsTemplated = !TemplateParamLists.empty();
7021 if (IsTemplated &&
7022 !DVScope.TI->isExtensionActive(
7023 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7024 return;
7025
7026 const IdentifierInfo *BaseII = D.getIdentifier();
7027 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7029 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7030 /*ObjectType=*/QualType());
7031
7033 QualType FType = TInfo->getType();
7034
7035 bool IsConstexpr =
7036 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7037 bool IsConsteval =
7038 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7039
7040 for (auto *Candidate : Lookup) {
7041 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7042 FunctionDecl *UDecl = nullptr;
7043 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7044 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7045 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7046 UDecl = FTD->getTemplatedDecl();
7047 } else if (!IsTemplated)
7048 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7049 if (!UDecl)
7050 continue;
7051
7052 // Don't specialize constexpr/consteval functions with
7053 // non-constexpr/consteval functions.
7054 if (UDecl->isConstexpr() && !IsConstexpr)
7055 continue;
7056 if (UDecl->isConsteval() && !IsConsteval)
7057 continue;
7058
7059 QualType UDeclTy = UDecl->getType();
7060 if (!UDeclTy->isDependentType()) {
7062 FType, UDeclTy, /* OfBlockPointer */ false,
7063 /* Unqualified */ false, /* AllowCXX */ true);
7064 if (NewType.isNull())
7065 continue;
7066 }
7067
7068 // Found a base!
7069 Bases.push_back(UDecl);
7070 }
7071
7072 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7073 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7074 // If no base was found we create a declaration that we use as base.
7075 if (Bases.empty() && UseImplicitBase) {
7076 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7077 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7078 BaseD->setImplicit(true);
7079 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7080 Bases.push_back(BaseTemplD->getTemplatedDecl());
7081 else
7082 Bases.push_back(cast<FunctionDecl>(BaseD));
7083 }
7084
7085 std::string MangledName;
7086 MangledName += D.getIdentifier()->getName();
7087 MangledName += getOpenMPVariantManglingSeparatorStr();
7088 MangledName += DVScope.NameSuffix;
7089 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7090
7091 VariantII.setMangledOpenMPVariantName(true);
7092 D.SetIdentifier(&VariantII, D.getBeginLoc());
7093}
7094
7097 // Do not mark function as is used to prevent its emission if this is the
7098 // only place where it is used.
7101
7102 FunctionDecl *FD = nullptr;
7103 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7104 FD = UTemplDecl->getTemplatedDecl();
7105 else
7106 FD = cast<FunctionDecl>(D);
7107 auto *VariantFuncRef = DeclRefExpr::Create(
7109 /* RefersToEnclosingVariableOrCapture */ false,
7110 /* NameLoc */ FD->getLocation(), FD->getType(),
7112
7113 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7114 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7115 getASTContext(), VariantFuncRef, DVScope.TI,
7116 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7117 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7118 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7119 for (FunctionDecl *BaseFD : Bases)
7120 BaseFD->addAttr(OMPDeclareVariantA);
7121}
7122
7124 SourceLocation LParenLoc,
7125 MultiExprArg ArgExprs,
7126 SourceLocation RParenLoc,
7127 Expr *ExecConfig) {
7128 // The common case is a regular call we do not want to specialize at all. Try
7129 // to make that case fast by bailing early.
7130 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7131 if (!CE)
7132 return Call;
7133
7134 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7135 if (!CalleeFnDecl)
7136 return Call;
7137
7138 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7139 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7140 // checking for any calls inside an Order region
7142 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7143 }
7144
7145 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7146 return Call;
7147
7148 ASTContext &Context = getASTContext();
7149 std::function<void(StringRef)> DiagUnknownTrait = [this,
7150 CE](StringRef ISATrait) {
7151 // TODO Track the selector locations in a way that is accessible here to
7152 // improve the diagnostic location.
7153 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7154 << ISATrait;
7155 };
7156 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7158 DSAStack->getConstructTraits());
7159
7160 QualType CalleeFnType = CalleeFnDecl->getType();
7161
7164 while (CalleeFnDecl) {
7165 for (OMPDeclareVariantAttr *A :
7166 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7167 Expr *VariantRef = A->getVariantFuncRef();
7168
7169 VariantMatchInfo VMI;
7170 OMPTraitInfo &TI = A->getTraitInfo();
7171 TI.getAsVariantMatchInfo(Context, VMI);
7172 if (!isVariantApplicableInContext(VMI, OMPCtx,
7173 /* DeviceSetOnly */ false))
7174 continue;
7175
7176 VMIs.push_back(VMI);
7177 Exprs.push_back(VariantRef);
7178 }
7179
7180 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7181 }
7182
7183 ExprResult NewCall;
7184 do {
7185 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7186 if (BestIdx < 0)
7187 return Call;
7188 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7189 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7190
7191 {
7192 // Try to build a (member) call expression for the current best applicable
7193 // variant expression. We allow this to fail in which case we continue
7194 // with the next best variant expression. The fail case is part of the
7195 // implementation defined behavior in the OpenMP standard when it talks
7196 // about what differences in the function prototypes: "Any differences
7197 // that the specific OpenMP context requires in the prototype of the
7198 // variant from the base function prototype are implementation defined."
7199 // This wording is there to allow the specialized variant to have a
7200 // different type than the base function. This is intended and OK but if
7201 // we cannot create a call the difference is not in the "implementation
7202 // defined range" we allow.
7204
7205 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7206 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7207 BestExpr = MemberExpr::CreateImplicit(
7208 Context, MemberCall->getImplicitObjectArgument(),
7209 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7210 MemberCall->getValueKind(), MemberCall->getObjectKind());
7211 }
7212 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7213 RParenLoc, ExecConfig);
7214 if (NewCall.isUsable()) {
7215 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7216 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7218 CalleeFnType, NewCalleeFnDecl->getType(),
7219 /* OfBlockPointer */ false,
7220 /* Unqualified */ false, /* AllowCXX */ true);
7221 if (!NewType.isNull())
7222 break;
7223 // Don't use the call if the function type was not compatible.
7224 NewCall = nullptr;
7225 }
7226 }
7227 }
7228
7229 VMIs.erase(VMIs.begin() + BestIdx);
7230 Exprs.erase(Exprs.begin() + BestIdx);
7231 } while (!VMIs.empty());
7232
7233 if (!NewCall.isUsable())
7234 return Call;
7235 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7236}
7237
7238std::optional<std::pair<FunctionDecl *, Expr *>>
7240 Expr *VariantRef,
7241 OMPTraitInfo &TI,
7242 unsigned NumAppendArgs,
7243 SourceRange SR) {
7244 ASTContext &Context = getASTContext();
7245 if (!DG || DG.get().isNull())
7246 return std::nullopt;
7247
7248 const int VariantId = 1;
7249 // Must be applied only to single decl.
7250 if (!DG.get().isSingleDecl()) {
7251 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7252 << VariantId << SR;
7253 return std::nullopt;
7254 }
7255 Decl *ADecl = DG.get().getSingleDecl();
7256 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7257 ADecl = FTD->getTemplatedDecl();
7258
7259 // Decl must be a function.
7260 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7261 if (!FD) {
7262 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7263 << VariantId << SR;
7264 return std::nullopt;
7265 }
7266
7267 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7268 // The 'target' attribute needs to be separately checked because it does
7269 // not always signify a multiversion function declaration.
7270 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7271 };
7272 // OpenMP is not compatible with multiversion function attributes.
7273 if (HasMultiVersionAttributes(FD)) {
7274 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7275 << SR;
7276 return std::nullopt;
7277 }
7278
7279 // Allow #pragma omp declare variant only if the function is not used.
7280 if (FD->isUsed(false))
7281 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7282 << FD->getLocation();
7283
7284 // Check if the function was emitted already.
7285 const FunctionDecl *Definition;
7286 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7287 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7288 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7289 << FD->getLocation();
7290
7291 // The VariantRef must point to function.
7292 if (!VariantRef) {
7293 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7294 return std::nullopt;
7295 }
7296
7297 auto ShouldDelayChecks = [](Expr *&E, bool) {
7298 return E && (E->isTypeDependent() || E->isValueDependent() ||
7301 };
7302 // Do not check templates, wait until instantiation.
7303 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7304 TI.anyScoreOrCondition(ShouldDelayChecks))
7305 return std::make_pair(FD, VariantRef);
7306
7307 // Deal with non-constant score and user condition expressions.
7308 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7309 bool IsScore) -> bool {
7311 return false;
7312
7313 if (IsScore) {
7314 // We warn on non-constant scores and pretend they were not present.
7315 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7316 << E;
7317 E = nullptr;
7318 } else {
7319 // We could replace a non-constant user condition with "false" but we
7320 // will soon need to handle these anyway for the dynamic version of
7321 // OpenMP context selectors.
7322 Diag(E->getExprLoc(),
7323 diag::err_omp_declare_variant_user_condition_not_constant)
7324 << E;
7325 }
7326 return true;
7327 };
7328 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7329 return std::nullopt;
7330
7331 QualType AdjustedFnType = FD->getType();
7332 if (NumAppendArgs) {
7333 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7334 if (!PTy) {
7335 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7336 << SR;
7337 return std::nullopt;
7338 }
7339 // Adjust the function type to account for an extra omp_interop_t for each
7340 // specified in the append_args clause.
7341 const TypeDecl *TD = nullptr;
7342 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7345 NamedDecl *ND = Result.getFoundDecl();
7346 TD = dyn_cast_or_null<TypeDecl>(ND);
7347 }
7348 if (!TD) {
7349 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7350 return std::nullopt;
7351 }
7352 QualType InteropType = Context.getTypeDeclType(TD);
7353 if (PTy->isVariadic()) {
7354 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7355 return std::nullopt;
7356 }
7358 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7359 Params.insert(Params.end(), NumAppendArgs, InteropType);
7360 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7361 PTy->getExtProtoInfo());
7362 }
7363
7364 // Convert VariantRef expression to the type of the original function to
7365 // resolve possible conflicts.
7366 ExprResult VariantRefCast = VariantRef;
7367 if (getLangOpts().CPlusPlus) {
7368 QualType FnPtrType;
7369 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7370 if (Method && !Method->isStatic()) {
7371 const Type *ClassType =
7372 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7373 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7374 ExprResult ER;
7375 {
7376 // Build addr_of unary op to correctly handle type checks for member
7377 // functions.
7379 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7380 VariantRef);
7381 }
7382 if (!ER.isUsable()) {
7383 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7384 << VariantId << VariantRef->getSourceRange();
7385 return std::nullopt;
7386 }
7387 VariantRef = ER.get();
7388 } else {
7389 FnPtrType = Context.getPointerType(AdjustedFnType);
7390 }
7391 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7392 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7394 VariantRef, FnPtrType.getUnqualifiedType(),
7395 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7396 /*InOverloadResolution=*/false,
7397 /*CStyle=*/false,
7398 /*AllowObjCWritebackConversion=*/false);
7399 if (ICS.isFailure()) {
7400 Diag(VariantRef->getExprLoc(),
7401 diag::err_omp_declare_variant_incompat_types)
7402 << VariantRef->getType()
7403 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7404 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7405 return std::nullopt;
7406 }
7407 VariantRefCast = SemaRef.PerformImplicitConversion(
7408 VariantRef, FnPtrType.getUnqualifiedType(), Sema::AA_Converting);
7409 if (!VariantRefCast.isUsable())
7410 return std::nullopt;
7411 }
7412 // Drop previously built artificial addr_of unary op for member functions.
7413 if (Method && !Method->isStatic()) {
7414 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7415 if (auto *UO = dyn_cast<UnaryOperator>(
7416 PossibleAddrOfVariantRef->IgnoreImplicit()))
7417 VariantRefCast = UO->getSubExpr();
7418 }
7419 }
7420
7421 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7422 if (!ER.isUsable() ||
7424 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7425 << VariantId << VariantRef->getSourceRange();
7426 return std::nullopt;
7427 }
7428
7429 // The VariantRef must point to function.
7430 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7431 if (!DRE) {
7432 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7433 << VariantId << VariantRef->getSourceRange();
7434 return std::nullopt;
7435 }
7436 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7437 if (!NewFD) {
7438 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7439 << VariantId << VariantRef->getSourceRange();
7440 return std::nullopt;
7441 }
7442
7443 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7444 Diag(VariantRef->getExprLoc(),
7445 diag::err_omp_declare_variant_same_base_function)
7446 << VariantRef->getSourceRange();
7447 return std::nullopt;
7448 }
7449
7450 // Check if function types are compatible in C.
7451 if (!getLangOpts().CPlusPlus) {
7452 QualType NewType =
7453 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7454 if (NewType.isNull()) {
7455 Diag(VariantRef->getExprLoc(),
7456 diag::err_omp_declare_variant_incompat_types)
7457 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7458 << VariantRef->getSourceRange();
7459 return std::nullopt;
7460 }
7461 if (NewType->isFunctionProtoType()) {
7462 if (FD->getType()->isFunctionNoProtoType())
7463 setPrototype(SemaRef, FD, NewFD, NewType);
7464 else if (NewFD->getType()->isFunctionNoProtoType())
7465 setPrototype(SemaRef, NewFD, FD, NewType);
7466 }
7467 }
7468
7469 // Check if variant function is not marked with declare variant directive.
7470 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7471 Diag(VariantRef->getExprLoc(),
7472 diag::warn_omp_declare_variant_marked_as_declare_variant)
7473 << VariantRef->getSourceRange();
7474 SourceRange SR =
7475 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7476 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7477 return std::nullopt;
7478 }
7479
7480 enum DoesntSupport {
7481 VirtFuncs = 1,
7482 Constructors = 3,
7483 Destructors = 4,
7484 DeletedFuncs = 5,
7485 DefaultedFuncs = 6,
7486 ConstexprFuncs = 7,
7487 ConstevalFuncs = 8,
7488 };
7489 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7490 if (CXXFD->isVirtual()) {
7491 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7492 << VirtFuncs;
7493 return std::nullopt;
7494 }
7495
7496 if (isa<CXXConstructorDecl>(FD)) {
7497 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7498 << Constructors;
7499 return std::nullopt;
7500 }
7501
7502 if (isa<CXXDestructorDecl>(FD)) {
7503 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7504 << Destructors;
7505 return std::nullopt;
7506 }
7507 }
7508
7509 if (FD->isDeleted()) {
7510 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7511 << DeletedFuncs;
7512 return std::nullopt;
7513 }
7514
7515 if (FD->isDefaulted()) {
7516 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7517 << DefaultedFuncs;
7518 return std::nullopt;
7519 }
7520
7521 if (FD->isConstexpr()) {
7522 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7523 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7524 return std::nullopt;
7525 }
7526
7527 // Check general compatibility.
7533 VariantRef->getExprLoc(),
7534 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7535 PartialDiagnosticAt(VariantRef->getExprLoc(),
7536 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7537 << FD->getLocation()),
7538 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7539 /*CLinkageMayDiffer=*/true))
7540 return std::nullopt;
7541 return std::make_pair(FD, cast<Expr>(DRE));
7542}
7543
7545 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7546 ArrayRef<Expr *> AdjustArgsNothing,
7547 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7548 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7549 SourceLocation AppendArgsLoc, SourceRange SR) {
7550
7551 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7552 // An adjust_args clause or append_args clause can only be specified if the
7553 // dispatch selector of the construct selector set appears in the match
7554 // clause.
7555
7556 SmallVector<Expr *, 8> AllAdjustArgs;
7557 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7558 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7559
7560 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7561 VariantMatchInfo VMI;
7563 if (!llvm::is_contained(
7564 VMI.ConstructTraits,
7565 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7566 if (!AllAdjustArgs.empty())
7567 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7568 << getOpenMPClauseName(OMPC_adjust_args);
7569 if (!AppendArgs.empty())
7570 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7571 << getOpenMPClauseName(OMPC_append_args);
7572 return;
7573 }
7574 }
7575
7576 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7577 // Each argument can only appear in a single adjust_args clause for each
7578 // declare variant directive.
7580
7581 for (Expr *E : AllAdjustArgs) {
7582 E = E->IgnoreParenImpCasts();
7583 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7584 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7585 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7586 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7587 FD->getParamDecl(PVD->getFunctionScopeIndex())
7588 ->getCanonicalDecl() == CanonPVD) {
7589 // It's a parameter of the function, check duplicates.
7590 if (!AdjustVars.insert(CanonPVD).second) {
7591 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7592 << PVD;
7593 return;
7594 }
7595 continue;
7596 }
7597 }
7598 }
7599 // Anything that is not a function parameter is an error.
7600 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7601 return;
7602 }
7603
7604 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7605 getASTContext(), VariantRef, &TI,
7606 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7607 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7608 AdjustArgsNeedDevicePtr.size(),
7609 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7610 FD->addAttr(NewAttr);
7611}
7612
7613static CapturedStmt *
7615 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7616 assert(CS && "Captured statement expected");
7617 // 1.2.2 OpenMP Language Terminology
7618 // Structured block - An executable statement with a single entry at the
7619 // top and a single exit at the bottom.
7620 // The point of exit cannot be a branch out of the structured block.
7621 // longjmp() and throw() must not violate the entry/exit criteria.
7622 CS->getCapturedDecl()->setNothrow();
7623
7624 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7625 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7626 CS = cast<CapturedStmt>(CS->getCapturedStmt());
7627 // 1.2.2 OpenMP Language Terminology
7628 // Structured block - An executable statement with a single entry at the
7629 // top and a single exit at the bottom.
7630 // The point of exit cannot be a branch out of the structured block.
7631 // longjmp() and throw() must not violate the entry/exit criteria.
7632 CS->getCapturedDecl()->setNothrow();
7633 }
7635 return CS;
7636}
7637
7640 Stmt *AStmt, SourceLocation StartLoc,
7641 SourceLocation EndLoc) {
7642 if (!AStmt)
7643 return StmtError();
7644
7645 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7646
7648 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7649 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7650}
7651
7652namespace {
7653/// Iteration space of a single for loop.
7654struct LoopIterationSpace final {
7655 /// True if the condition operator is the strict compare operator (<, > or
7656 /// !=).
7657 bool IsStrictCompare = false;
7658 /// Condition of the loop.
7659 Expr *PreCond = nullptr;
7660 /// This expression calculates the number of iterations in the loop.
7661 /// It is always possible to calculate it before starting the loop.
7662 Expr *NumIterations = nullptr;
7663 /// The loop counter variable.
7664 Expr *CounterVar = nullptr;
7665 /// Private loop counter variable.
7666 Expr *PrivateCounterVar = nullptr;
7667 /// This is initializer for the initial value of #CounterVar.
7668 Expr *CounterInit = nullptr;
7669 /// This is step for the #CounterVar used to generate its update:
7670 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7671 Expr *CounterStep = nullptr;
7672 /// Should step be subtracted?
7673 bool Subtract = false;
7674 /// Source range of the loop init.
7675 SourceRange InitSrcRange;
7676 /// Source range of the loop condition.
7677 SourceRange CondSrcRange;
7678 /// Source range of the loop increment.
7679 SourceRange IncSrcRange;
7680 /// Minimum value that can have the loop control variable. Used to support
7681 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7682 /// since only such variables can be used in non-loop invariant expressions.
7683 Expr *MinValue = nullptr;
7684 /// Maximum value that can have the loop control variable. Used to support
7685 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7686 /// since only such variables can be used in non-loop invariant expressions.
7687 Expr *MaxValue = nullptr;
7688 /// true, if the lower bound depends on the outer loop control var.
7689 bool IsNonRectangularLB = false;
7690 /// true, if the upper bound depends on the outer loop control var.
7691 bool IsNonRectangularUB = false;
7692 /// Index of the loop this loop depends on and forms non-rectangular loop
7693 /// nest.
7694 unsigned LoopDependentIdx = 0;
7695 /// Final condition for the non-rectangular loop nest support. It is used to
7696 /// check that the number of iterations for this particular counter must be
7697 /// finished.
7698 Expr *FinalCondition = nullptr;
7699};
7700
7701/// Helper class for checking canonical form of the OpenMP loops and
7702/// extracting iteration space of each loop in the loop nest, that will be used
7703/// for IR generation.
7704class OpenMPIterationSpaceChecker {
7705 /// Reference to Sema.
7706 Sema &SemaRef;
7707 /// Does the loop associated directive support non-rectangular loops?
7708 bool SupportsNonRectangular;
7709 /// Data-sharing stack.
7710 DSAStackTy &Stack;
7711 /// A location for diagnostics (when there is no some better location).
7712 SourceLocation DefaultLoc;
7713 /// A location for diagnostics (when increment is not compatible).
7714 SourceLocation ConditionLoc;
7715 /// A source location for referring to loop init later.
7716 SourceRange InitSrcRange;
7717 /// A source location for referring to condition later.
7718 SourceRange ConditionSrcRange;
7719 /// A source location for referring to increment later.
7720 SourceRange IncrementSrcRange;
7721 /// Loop variable.
7722 ValueDecl *LCDecl = nullptr;
7723 /// Reference to loop variable.
7724 Expr *LCRef = nullptr;
7725 /// Lower bound (initializer for the var).
7726 Expr *LB = nullptr;
7727 /// Upper bound.
7728 Expr *UB = nullptr;
7729 /// Loop step (increment).
7730 Expr *Step = nullptr;
7731 /// This flag is true when condition is one of:
7732 /// Var < UB
7733 /// Var <= UB
7734 /// UB > Var
7735 /// UB >= Var
7736 /// This will have no value when the condition is !=
7737 std::optional<bool> TestIsLessOp;
7738 /// This flag is true when condition is strict ( < or > ).
7739 bool TestIsStrictOp = false;
7740 /// This flag is true when step is subtracted on each iteration.
7741 bool SubtractStep = false;
7742 /// The outer loop counter this loop depends on (if any).
7743 const ValueDecl *DepDecl = nullptr;
7744 /// Contains number of loop (starts from 1) on which loop counter init
7745 /// expression of this loop depends on.
7746 std::optional<unsigned> InitDependOnLC;
7747 /// Contains number of loop (starts from 1) on which loop counter condition
7748 /// expression of this loop depends on.
7749 std::optional<unsigned> CondDependOnLC;
7750 /// Checks if the provide statement depends on the loop counter.
7751 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7752 bool IsInitializer);
7753 /// Original condition required for checking of the exit condition for
7754 /// non-rectangular loop.
7755 Expr *Condition = nullptr;
7756
7757public:
7758 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7759 DSAStackTy &Stack, SourceLocation DefaultLoc)
7760 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7761 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7762 /// Check init-expr for canonical loop form and save loop counter
7763 /// variable - #Var and its initialization value - #LB.
7764 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7765 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7766 /// for less/greater and for strict/non-strict comparison.
7767 bool checkAndSetCond(Expr *S);
7768 /// Check incr-expr for canonical loop form and return true if it
7769 /// does not conform, otherwise save loop step (#Step).
7770 bool checkAndSetInc(Expr *S);
7771 /// Return the loop counter variable.
7772 ValueDecl *getLoopDecl() const { return LCDecl; }
7773 /// Return the reference expression to loop counter variable.
7774 Expr *getLoopDeclRefExpr() const { return LCRef; }
7775 /// Source range of the loop init.
7776 SourceRange getInitSrcRange() const { return InitSrcRange; }
7777 /// Source range of the loop condition.
7778 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7779 /// Source range of the loop increment.
7780 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7781 /// True if the step should be subtracted.
7782 bool shouldSubtractStep() const { return SubtractStep; }
7783 /// True, if the compare operator is strict (<, > or !=).
7784 bool isStrictTestOp() const { return TestIsStrictOp; }
7785 /// Build the expression to calculate the number of iterations.
7786 Expr *buildNumIterations(
7787 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7788 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7789 /// Build the precondition expression for the loops.
7790 Expr *
7791 buildPreCond(Scope *S, Expr *Cond,
7792 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7793 /// Build reference expression to the counter be used for codegen.
7794 DeclRefExpr *
7795 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7796 DSAStackTy &DSA) const;
7797 /// Build reference expression to the private counter be used for
7798 /// codegen.
7799 Expr *buildPrivateCounterVar() const;
7800 /// Build initialization of the counter be used for codegen.
7801 Expr *buildCounterInit() const;
7802 /// Build step of the counter be used for codegen.
7803 Expr *buildCounterStep() const;
7804 /// Build loop data with counter value for depend clauses in ordered
7805 /// directives.
7806 Expr *
7807 buildOrderedLoopData(Scope *S, Expr *Counter,
7808 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7809 SourceLocation Loc, Expr *Inc = nullptr,
7810 OverloadedOperatorKind OOK = OO_Amp);
7811 /// Builds the minimum value for the loop counter.
7812 std::pair<Expr *, Expr *> buildMinMaxValues(
7813 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7814 /// Builds final condition for the non-rectangular loops.
7815 Expr *buildFinalCondition(Scope *S) const;
7816 /// Return true if any expression is dependent.
7817 bool dependent() const;
7818 /// Returns true if the initializer forms non-rectangular loop.
7819 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7820 /// Returns true if the condition forms non-rectangular loop.
7821 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7822 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7823 unsigned getLoopDependentIdx() const {
7824 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7825 }
7826
7827private:
7828 /// Check the right-hand side of an assignment in the increment
7829 /// expression.
7830 bool checkAndSetIncRHS(Expr *RHS);
7831 /// Helper to set loop counter variable and its initializer.
7832 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7833 bool EmitDiags);
7834 /// Helper to set upper bound.
7835 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7837 /// Helper to set loop increment.
7838 bool setStep(Expr *NewStep, bool Subtract);
7839};
7840
7841bool OpenMPIterationSpaceChecker::dependent() const {
7842 if (!LCDecl) {
7843 assert(!LB && !UB && !Step);
7844 return false;
7845 }
7846 return LCDecl->getType()->isDependentType() ||
7847 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7848 (Step && Step->isValueDependent());
7849}
7850
7851bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7852 Expr *NewLCRefExpr,
7853 Expr *NewLB, bool EmitDiags) {
7854 // State consistency checking to ensure correct usage.
7855 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7856 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7857 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7858 return true;
7859 LCDecl = getCanonicalDecl(NewLCDecl);
7860 LCRef = NewLCRefExpr;
7861 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7862 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7863 if ((Ctor->isCopyOrMoveConstructor() ||
7864 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7865 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7866 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7867 LB = NewLB;
7868 if (EmitDiags)
7869 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7870 return false;
7871}
7872
7873bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7874 bool StrictOp, SourceRange SR,
7875 SourceLocation SL) {
7876 // State consistency checking to ensure correct usage.
7877 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7878 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7879 if (!NewUB || NewUB->containsErrors())
7880 return true;
7881 UB = NewUB;
7882 if (LessOp)
7883 TestIsLessOp = LessOp;
7884 TestIsStrictOp = StrictOp;
7885 ConditionSrcRange = SR;
7886 ConditionLoc = SL;
7887 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7888 return false;
7889}
7890
7891bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7892 // State consistency checking to ensure correct usage.
7893 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7894 if (!NewStep || NewStep->containsErrors())
7895 return true;
7896 if (!NewStep->isValueDependent()) {
7897 // Check that the step is integer expression.
7898 SourceLocation StepLoc = NewStep->getBeginLoc();
7900 StepLoc, getExprAsWritten(NewStep));
7901 if (Val.isInvalid())
7902 return true;
7903 NewStep = Val.get();
7904
7905 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7906 // If test-expr is of form var relational-op b and relational-op is < or
7907 // <= then incr-expr must cause var to increase on each iteration of the
7908 // loop. If test-expr is of form var relational-op b and relational-op is
7909 // > or >= then incr-expr must cause var to decrease on each iteration of
7910 // the loop.
7911 // If test-expr is of form b relational-op var and relational-op is < or
7912 // <= then incr-expr must cause var to decrease on each iteration of the
7913 // loop. If test-expr is of form b relational-op var and relational-op is
7914 // > or >= then incr-expr must cause var to increase on each iteration of
7915 // the loop.
7916 std::optional<llvm::APSInt> Result =
7917 NewStep->getIntegerConstantExpr(SemaRef.Context);
7918 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7919 bool IsConstNeg =
7920 Result && Result->isSigned() && (Subtract != Result->isNegative());
7921 bool IsConstPos =
7922 Result && Result->isSigned() && (Subtract == Result->isNegative());
7923 bool IsConstZero = Result && !Result->getBoolValue();
7924
7925 // != with increment is treated as <; != with decrement is treated as >
7926 if (!TestIsLessOp)
7927 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7928 if (UB && (IsConstZero ||
7929 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7930 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7931 SemaRef.Diag(NewStep->getExprLoc(),
7932 diag::err_omp_loop_incr_not_compatible)
7933 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7934 SemaRef.Diag(ConditionLoc,
7935 diag::note_omp_loop_cond_requires_compatible_incr)
7936 << *TestIsLessOp << ConditionSrcRange;
7937 return true;
7938 }
7939 if (*TestIsLessOp == Subtract) {
7940 NewStep =
7941 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
7942 .get();
7943 Subtract = !Subtract;
7944 }
7945 }
7946
7947 Step = NewStep;
7948 SubtractStep = Subtract;
7949 return false;
7950}
7951
7952namespace {
7953/// Checker for the non-rectangular loops. Checks if the initializer or
7954/// condition expression references loop counter variable.
7955class LoopCounterRefChecker final
7956 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
7957 Sema &SemaRef;
7958 DSAStackTy &Stack;
7959 const ValueDecl *CurLCDecl = nullptr;
7960 const ValueDecl *DepDecl = nullptr;
7961 const ValueDecl *PrevDepDecl = nullptr;
7962 bool IsInitializer = true;
7963 bool SupportsNonRectangular;
7964 unsigned BaseLoopId = 0;
7965 bool checkDecl(const Expr *E, const ValueDecl *VD) {
7966 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
7967 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7968 << (IsInitializer ? 0 : 1);
7969 return false;
7970 }
7971 const auto &&Data = Stack.isLoopControlVariable(VD);
7972 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
7973 // The type of the loop iterator on which we depend may not have a random
7974 // access iterator type.
7975 if (Data.first && VD->getType()->isRecordType()) {
7976 SmallString<128> Name;
7977 llvm::raw_svector_ostream OS(Name);
7978 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
7979 /*Qualified=*/true);
7980 SemaRef.Diag(E->getExprLoc(),
7981 diag::err_omp_wrong_dependency_iterator_type)
7982 << OS.str();
7983 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
7984 return false;
7985 }
7986 if (Data.first && !SupportsNonRectangular) {
7987 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
7988 return false;
7989 }
7990 if (Data.first &&
7991 (DepDecl || (PrevDepDecl &&
7992 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
7993 if (!DepDecl && PrevDepDecl)
7994 DepDecl = PrevDepDecl;
7995 SmallString<128> Name;
7996 llvm::raw_svector_ostream OS(Name);
7997 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
7998 /*Qualified=*/true);
7999 SemaRef.Diag(E->getExprLoc(),
8000 diag::err_omp_invariant_or_linear_dependency)
8001 << OS.str();
8002 return false;
8003 }
8004 if (Data.first) {
8005 DepDecl = VD;
8006 BaseLoopId = Data.first;
8007 }
8008 return Data.first;
8009 }
8010
8011public:
8012 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8013 const ValueDecl *VD = E->getDecl();
8014 if (isa<VarDecl>(VD))
8015 return checkDecl(E, VD);
8016 return false;
8017 }
8018 bool VisitMemberExpr(const MemberExpr *E) {
8019 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8020 const ValueDecl *VD = E->getMemberDecl();
8021 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8022 return checkDecl(E, VD);
8023 }
8024 return false;
8025 }
8026 bool VisitStmt(const Stmt *S) {
8027 bool Res = false;
8028 for (const Stmt *Child : S->children())
8029 Res = (Child && Visit(Child)) || Res;
8030 return Res;
8031 }
8032 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8033 const ValueDecl *CurLCDecl, bool IsInitializer,
8034 const ValueDecl *PrevDepDecl = nullptr,
8035 bool SupportsNonRectangular = true)
8036 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8037 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8038 SupportsNonRectangular(SupportsNonRectangular) {}
8039 unsigned getBaseLoopId() const {
8040 assert(CurLCDecl && "Expected loop dependency.");
8041 return BaseLoopId;
8042 }
8043 const ValueDecl *getDepDecl() const {
8044 assert(CurLCDecl && "Expected loop dependency.");
8045 return DepDecl;
8046 }
8047};
8048} // namespace
8049
8050std::optional<unsigned>
8051OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8052 bool IsInitializer) {
8053 // Check for the non-rectangular loops.
8054 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8055 DepDecl, SupportsNonRectangular);
8056 if (LoopStmtChecker.Visit(S)) {
8057 DepDecl = LoopStmtChecker.getDepDecl();
8058 return LoopStmtChecker.getBaseLoopId();
8059 }
8060 return std::nullopt;
8061}
8062
8063bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8064 // Check init-expr for canonical loop form and save loop counter
8065 // variable - #Var and its initialization value - #LB.
8066 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8067 // var = lb
8068 // integer-type var = lb
8069 // random-access-iterator-type var = lb
8070 // pointer-type var = lb
8071 //
8072 if (!S) {
8073 if (EmitDiags) {
8074 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8075 }
8076 return true;
8077 }
8078 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8079 if (!ExprTemp->cleanupsHaveSideEffects())
8080 S = ExprTemp->getSubExpr();
8081
8082 InitSrcRange = S->getSourceRange();
8083 if (Expr *E = dyn_cast<Expr>(S))
8084 S = E->IgnoreParens();
8085 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8086 if (BO->getOpcode() == BO_Assign) {
8087 Expr *LHS = BO->getLHS()->IgnoreParens();
8088 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8089 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8090 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8091 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8092 EmitDiags);
8093 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8094 }
8095 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8096 if (ME->isArrow() &&
8097 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8098 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8099 EmitDiags);
8100 }
8101 }
8102 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8103 if (DS->isSingleDecl()) {
8104 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8105 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8106 // Accept non-canonical init form here but emit ext. warning.
8107 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8108 SemaRef.Diag(S->getBeginLoc(),
8109 diag::ext_omp_loop_not_canonical_init)
8110 << S->getSourceRange();
8111 return setLCDeclAndLB(
8112 Var,
8113 buildDeclRefExpr(SemaRef, Var,
8114 Var->getType().getNonReferenceType(),
8115 DS->getBeginLoc()),
8116 Var->getInit(), EmitDiags);
8117 }
8118 }
8119 }
8120 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8121 if (CE->getOperator() == OO_Equal) {
8122 Expr *LHS = CE->getArg(0);
8123 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8124 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8125 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8126 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8127 EmitDiags);
8128 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8129 }
8130 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8131 if (ME->isArrow() &&
8132 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8133 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8134 EmitDiags);
8135 }
8136 }
8137 }
8138
8139 if (dependent() || SemaRef.CurContext->isDependentContext())
8140 return false;
8141 if (EmitDiags) {
8142 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8143 << S->getSourceRange();
8144 }
8145 return true;
8146}
8147
8148/// Ignore parenthesizes, implicit casts, copy constructor and return the
8149/// variable (which may be the loop variable) if possible.
8150static const ValueDecl *getInitLCDecl(const Expr *E) {
8151 if (!E)
8152 return nullptr;
8153 E = getExprAsWritten(E);
8154 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8155 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8156 if ((Ctor->isCopyOrMoveConstructor() ||
8157 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8158 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8159 E = CE->getArg(0)->IgnoreParenImpCasts();
8160 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8161 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8162 return getCanonicalDecl(VD);
8163 }
8164 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8165 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8166 return getCanonicalDecl(ME->getMemberDecl());
8167 return nullptr;
8168}
8169
8170bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8171 // Check test-expr for canonical form, save upper-bound UB, flags for
8172 // less/greater and for strict/non-strict comparison.
8173 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8174 // var relational-op b
8175 // b relational-op var
8176 //
8177 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8178 if (!S) {
8179 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8180 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8181 return true;
8182 }
8183 Condition = S;
8184 S = getExprAsWritten(S);
8185 SourceLocation CondLoc = S->getBeginLoc();
8186 auto &&CheckAndSetCond =
8187 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8188 const Expr *RHS, SourceRange SR,
8189 SourceLocation OpLoc) -> std::optional<bool> {
8190 if (BinaryOperator::isRelationalOp(Opcode)) {
8191 if (getInitLCDecl(LHS) == LCDecl)
8192 return setUB(const_cast<Expr *>(RHS),
8193 (Opcode == BO_LT || Opcode == BO_LE),
8194 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8195 if (getInitLCDecl(RHS) == LCDecl)
8196 return setUB(const_cast<Expr *>(LHS),
8197 (Opcode == BO_GT || Opcode == BO_GE),
8198 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8199 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8200 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8201 /*LessOp=*/std::nullopt,
8202 /*StrictOp=*/true, SR, OpLoc);
8203 }
8204 return std::nullopt;
8205 };
8206 std::optional<bool> Res;
8207 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8208 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8209 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8210 RBO->getOperatorLoc());
8211 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8212 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8213 BO->getSourceRange(), BO->getOperatorLoc());
8214 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8215 if (CE->getNumArgs() == 2) {
8216 Res = CheckAndSetCond(
8217 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8218 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8219 }
8220 }
8221 if (Res)
8222 return *Res;
8223 if (dependent() || SemaRef.CurContext->isDependentContext())
8224 return false;
8225 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8226 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8227 return true;
8228}
8229
8230bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8231 // RHS of canonical loop form increment can be:
8232 // var + incr
8233 // incr + var
8234 // var - incr
8235 //
8236 RHS = RHS->IgnoreParenImpCasts();
8237 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8238 if (BO->isAdditiveOp()) {
8239 bool IsAdd = BO->getOpcode() == BO_Add;
8240 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8241 return setStep(BO->getRHS(), !IsAdd);
8242 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8243 return setStep(BO->getLHS(), /*Subtract=*/false);
8244 }
8245 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8246 bool IsAdd = CE->getOperator() == OO_Plus;
8247 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8248 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8249 return setStep(CE->getArg(1), !IsAdd);
8250 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8251 return setStep(CE->getArg(0), /*Subtract=*/false);
8252 }
8253 }
8254 if (dependent() || SemaRef.CurContext->isDependentContext())
8255 return false;
8256 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8257 << RHS->getSourceRange() << LCDecl;
8258 return true;
8259}
8260
8261bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8262 // Check incr-expr for canonical loop form and return true if it
8263 // does not conform.
8264 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8265 // ++var
8266 // var++
8267 // --var
8268 // var--
8269 // var += incr
8270 // var -= incr
8271 // var = var + incr
8272 // var = incr + var
8273 // var = var - incr
8274 //
8275 if (!S) {
8276 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8277 return true;
8278 }
8279 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8280 if (!ExprTemp->cleanupsHaveSideEffects())
8281 S = ExprTemp->getSubExpr();
8282
8283 IncrementSrcRange = S->getSourceRange();
8284 S = S->IgnoreParens();
8285 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8286 if (UO->isIncrementDecrementOp() &&
8287 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8288 return setStep(SemaRef
8289 .ActOnIntegerConstant(UO->getBeginLoc(),
8290 (UO->isDecrementOp() ? -1 : 1))
8291 .get(),
8292 /*Subtract=*/false);
8293 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8294 switch (BO->getOpcode()) {
8295 case BO_AddAssign:
8296 case BO_SubAssign:
8297 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8298 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8299 break;
8300 case BO_Assign:
8301 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8302 return checkAndSetIncRHS(BO->getRHS());
8303 break;
8304 default:
8305 break;
8306 }
8307 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8308 switch (CE->getOperator()) {
8309 case OO_PlusPlus:
8310 case OO_MinusMinus:
8311 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8312 return setStep(SemaRef
8313 .ActOnIntegerConstant(
8314 CE->getBeginLoc(),
8315 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8316 .get(),
8317 /*Subtract=*/false);
8318 break;
8319 case OO_PlusEqual:
8320 case OO_MinusEqual:
8321 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8322 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8323 break;
8324 case OO_Equal:
8325 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8326 return checkAndSetIncRHS(CE->getArg(1));
8327 break;
8328 default:
8329 break;
8330 }
8331 }
8332 if (dependent() || SemaRef.CurContext->isDependentContext())
8333 return false;
8334 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8335 << S->getSourceRange() << LCDecl;
8336 return true;
8337}
8338
8339static ExprResult
8340tryBuildCapture(Sema &SemaRef, Expr *Capture,
8341 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8342 StringRef Name = ".capture_expr.") {
8343 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8344 return Capture;
8345 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8346 return SemaRef.PerformImplicitConversion(
8347 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8348 /*AllowExplicit=*/true);
8349 auto I = Captures.find(Capture);
8350 if (I != Captures.end())
8351 return buildCapture(SemaRef, Capture, I->second, Name);
8352 DeclRefExpr *Ref = nullptr;
8353 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8354 Captures[Capture] = Ref;
8355 return Res;
8356}
8357
8358/// Calculate number of iterations, transforming to unsigned, if number of
8359/// iterations may be larger than the original type.
8360static Expr *
8361calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8362 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8363 bool TestIsStrictOp, bool RoundToStep,
8364 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8365 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8366 if (!NewStep.isUsable())
8367 return nullptr;
8368 llvm::APSInt LRes, SRes;
8369 bool IsLowerConst = false, IsStepConst = false;
8370 if (std::optional<llvm::APSInt> Res =
8371 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8372 LRes = *Res;
8373 IsLowerConst = true;
8374 }
8375 if (std::optional<llvm::APSInt> Res =
8376 Step->getIntegerConstantExpr(SemaRef.Context)) {
8377 SRes = *Res;
8378 IsStepConst = true;
8379 }
8380 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8381 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8382 (TestIsStrictOp && LRes.isStrictlyPositive()));
8383 bool NeedToReorganize = false;
8384 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8385 if (!NoNeedToConvert && IsLowerConst &&
8386 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8387 NoNeedToConvert = true;
8388 if (RoundToStep) {
8389 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8390 ? LRes.getBitWidth()
8391 : SRes.getBitWidth();
8392 LRes = LRes.extend(BW + 1);
8393 LRes.setIsSigned(true);
8394 SRes = SRes.extend(BW + 1);
8395 SRes.setIsSigned(true);
8396 LRes -= SRes;
8397 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8398 LRes = LRes.trunc(BW);
8399 }
8400 if (TestIsStrictOp) {
8401 unsigned BW = LRes.getBitWidth();
8402 LRes = LRes.extend(BW + 1);
8403 LRes.setIsSigned(true);
8404 ++LRes;
8405 NoNeedToConvert =
8406 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8407 // truncate to the original bitwidth.
8408 LRes = LRes.trunc(BW);
8409 }
8410 NeedToReorganize = NoNeedToConvert;
8411 }
8412 llvm::APSInt URes;
8413 bool IsUpperConst = false;
8414 if (std::optional<llvm::APSInt> Res =
8415 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8416 URes = *Res;
8417 IsUpperConst = true;
8418 }
8419 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8420 (!RoundToStep || IsStepConst)) {
8421 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8422 : URes.getBitWidth();
8423 LRes = LRes.extend(BW + 1);
8424 LRes.setIsSigned(true);
8425 URes = URes.extend(BW + 1);
8426 URes.setIsSigned(true);
8427 URes -= LRes;
8428 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8429 NeedToReorganize = NoNeedToConvert;
8430 }
8431 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8432 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8433 // unsigned.
8434 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8435 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8436 QualType LowerTy = Lower->getType();
8437 QualType UpperTy = Upper->getType();
8438 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8439 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8440 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8441 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8443 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8444 Upper =
8445 SemaRef
8447 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8449 .get();
8450 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8451 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8452 }
8453 }
8454 if (!Lower || !Upper || NewStep.isInvalid())
8455 return nullptr;
8456
8457 ExprResult Diff;
8458 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8459 // 1]).
8460 if (NeedToReorganize) {
8461 Diff = Lower;
8462
8463 if (RoundToStep) {
8464 // Lower - Step
8465 Diff =
8466 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8467 if (!Diff.isUsable())
8468 return nullptr;
8469 }
8470
8471 // Lower - Step [+ 1]
8472 if (TestIsStrictOp)
8473 Diff = SemaRef.BuildBinOp(
8474 S, DefaultLoc, BO_Add, Diff.get(),
8475 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8476 if (!Diff.isUsable())
8477 return nullptr;
8478
8479 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8480 if (!Diff.isUsable())
8481 return nullptr;
8482
8483 // Upper - (Lower - Step [+ 1]).
8484 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8485 if (!Diff.isUsable())
8486 return nullptr;
8487 } else {
8488 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8489
8490 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8491 // BuildBinOp already emitted error, this one is to point user to upper
8492 // and lower bound, and to tell what is passed to 'operator-'.
8493 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8494 << Upper->getSourceRange() << Lower->getSourceRange();
8495 return nullptr;
8496 }
8497
8498 if (!Diff.isUsable())
8499 return nullptr;
8500
8501 // Upper - Lower [- 1]
8502 if (TestIsStrictOp)
8503 Diff = SemaRef.BuildBinOp(
8504 S, DefaultLoc, BO_Sub, Diff.get(),
8505 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8506 if (!Diff.isUsable())
8507 return nullptr;
8508
8509 if (RoundToStep) {
8510 // Upper - Lower [- 1] + Step
8511 Diff =
8512 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8513 if (!Diff.isUsable())
8514 return nullptr;
8515 }
8516 }
8517
8518 // Parentheses (for dumping/debugging purposes only).
8519 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8520 if (!Diff.isUsable())
8521 return nullptr;
8522
8523 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8524 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8525 if (!Diff.isUsable())
8526 return nullptr;
8527
8528 return Diff.get();
8529}
8530
8531/// Build the expression to calculate the number of iterations.
8532Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8533 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8534 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8535 QualType VarType = LCDecl->getType().getNonReferenceType();
8536 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8537 !SemaRef.getLangOpts().CPlusPlus)
8538 return nullptr;
8539 Expr *LBVal = LB;
8540 Expr *UBVal = UB;
8541 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8542 // max(LB(MinVal), LB(MaxVal)))
8543 if (InitDependOnLC) {
8544 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8545 if (!IS.MinValue || !IS.MaxValue)
8546 return nullptr;
8547 // OuterVar = Min
8548 ExprResult MinValue =
8549 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8550 if (!MinValue.isUsable())
8551 return nullptr;
8552
8553 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8554 IS.CounterVar, MinValue.get());
8555 if (!LBMinVal.isUsable())
8556 return nullptr;
8557 // OuterVar = Min, LBVal
8558 LBMinVal =
8559 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8560 if (!LBMinVal.isUsable())
8561 return nullptr;
8562 // (OuterVar = Min, LBVal)
8563 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8564 if (!LBMinVal.isUsable())
8565 return nullptr;
8566
8567 // OuterVar = Max
8568 ExprResult MaxValue =
8569 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8570 if (!MaxValue.isUsable())
8571 return nullptr;
8572
8573 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8574 IS.CounterVar, MaxValue.get());
8575 if (!LBMaxVal.isUsable())
8576 return nullptr;
8577 // OuterVar = Max, LBVal
8578 LBMaxVal =
8579 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8580 if (!LBMaxVal.isUsable())
8581 return nullptr;
8582 // (OuterVar = Max, LBVal)
8583 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8584 if (!LBMaxVal.isUsable())
8585 return nullptr;
8586
8587 Expr *LBMin =
8588 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8589 Expr *LBMax =
8590 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8591 if (!LBMin || !LBMax)
8592 return nullptr;
8593 // LB(MinVal) < LB(MaxVal)
8594 ExprResult MinLessMaxRes =
8595 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8596 if (!MinLessMaxRes.isUsable())
8597 return nullptr;
8598 Expr *MinLessMax =
8599 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8600 .get();
8601 if (!MinLessMax)
8602 return nullptr;
8603 if (*TestIsLessOp) {
8604 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8605 // LB(MaxVal))
8606 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8607 MinLessMax, LBMin, LBMax);
8608 if (!MinLB.isUsable())
8609 return nullptr;
8610 LBVal = MinLB.get();
8611 } else {
8612 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8613 // LB(MaxVal))
8614 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8615 MinLessMax, LBMax, LBMin);
8616 if (!MaxLB.isUsable())
8617 return nullptr;
8618 LBVal = MaxLB.get();
8619 }
8620 // OuterVar = LB
8621 LBMinVal =
8622 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8623 if (!LBMinVal.isUsable())
8624 return nullptr;
8625 LBVal = LBMinVal.get();
8626 }
8627 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8628 // min(UB(MinVal), UB(MaxVal))
8629 if (CondDependOnLC) {
8630 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8631 if (!IS.MinValue || !IS.MaxValue)
8632 return nullptr;
8633 // OuterVar = Min
8634 ExprResult MinValue =
8635 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8636 if (!MinValue.isUsable())
8637 return nullptr;
8638
8639 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8640 IS.CounterVar, MinValue.get());
8641 if (!UBMinVal.isUsable())
8642 return nullptr;
8643 // OuterVar = Min, UBVal
8644 UBMinVal =
8645 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8646 if (!UBMinVal.isUsable())
8647 return nullptr;
8648 // (OuterVar = Min, UBVal)
8649 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8650 if (!UBMinVal.isUsable())
8651 return nullptr;
8652
8653 // OuterVar = Max
8654 ExprResult MaxValue =
8655 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8656 if (!MaxValue.isUsable())
8657 return nullptr;
8658
8659 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8660 IS.CounterVar, MaxValue.get());
8661 if (!UBMaxVal.isUsable())
8662 return nullptr;
8663 // OuterVar = Max, UBVal
8664 UBMaxVal =
8665 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8666 if (!UBMaxVal.isUsable())
8667 return nullptr;
8668 // (OuterVar = Max, UBVal)
8669 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8670 if (!UBMaxVal.isUsable())
8671 return nullptr;
8672
8673 Expr *UBMin =
8674 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8675 Expr *UBMax =
8676 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8677 if (!UBMin || !UBMax)
8678 return nullptr;
8679 // UB(MinVal) > UB(MaxVal)
8680 ExprResult MinGreaterMaxRes =
8681 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8682 if (!MinGreaterMaxRes.isUsable())
8683 return nullptr;
8684 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8685 Captures, ".min_greater_max")
8686 .get();
8687 if (!MinGreaterMax)
8688 return nullptr;
8689 if (*TestIsLessOp) {
8690 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8691 // UB(MaxVal))
8692 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8693 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8694 if (!MaxUB.isUsable())
8695 return nullptr;
8696 UBVal = MaxUB.get();
8697 } else {
8698 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8699 // UB(MaxVal))
8700 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8701 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8702 if (!MinUB.isUsable())
8703 return nullptr;
8704 UBVal = MinUB.get();
8705 }
8706 }
8707 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8708 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8709 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8710 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8711 if (!Upper || !Lower)
8712 return nullptr;
8713
8714 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8715 Step, VarType, TestIsStrictOp,
8716 /*RoundToStep=*/true, Captures);
8717 if (!Diff.isUsable())
8718 return nullptr;
8719
8720 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8721 QualType Type = Diff.get()->getType();
8722 ASTContext &C = SemaRef.Context;
8723 bool UseVarType = VarType->hasIntegerRepresentation() &&
8724 C.getTypeSize(Type) > C.getTypeSize(VarType);
8725 if (!Type->isIntegerType() || UseVarType) {
8726 unsigned NewSize =
8727 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8728 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8730 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8731 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8732 Diff = SemaRef.PerformImplicitConversion(
8733 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8734 if (!Diff.isUsable())
8735 return nullptr;
8736 }
8737 }
8738 if (LimitedType) {
8739 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8740 if (NewSize != C.getTypeSize(Type)) {
8741 if (NewSize < C.getTypeSize(Type)) {
8742 assert(NewSize == 64 && "incorrect loop var size");
8743 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8744 << InitSrcRange << ConditionSrcRange;
8745 }
8746 QualType NewType = C.getIntTypeForBitwidth(
8748 C.getTypeSize(Type) < NewSize);
8749 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8750 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8751 Sema::AA_Converting, true);
8752 if (!Diff.isUsable())
8753 return nullptr;
8754 }
8755 }
8756 }
8757
8758 return Diff.get();
8759}
8760
8761std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8762 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8763 // Do not build for iterators, they cannot be used in non-rectangular loop
8764 // nests.
8765 if (LCDecl->getType()->isRecordType())
8766 return std::make_pair(nullptr, nullptr);
8767 // If we subtract, the min is in the condition, otherwise the min is in the
8768 // init value.
8769 Expr *MinExpr = nullptr;
8770 Expr *MaxExpr = nullptr;
8771 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8772 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8773 bool LBNonRect =
8774 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8775 bool UBNonRect =
8776 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8777 Expr *Lower =
8778 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8779 Expr *Upper =
8780 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8781 if (!Upper || !Lower)
8782 return std::make_pair(nullptr, nullptr);
8783
8784 if (*TestIsLessOp)
8785 MinExpr = Lower;
8786 else
8787 MaxExpr = Upper;
8788
8789 // Build minimum/maximum value based on number of iterations.
8790 QualType VarType = LCDecl->getType().getNonReferenceType();
8791
8792 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8793 Step, VarType, TestIsStrictOp,
8794 /*RoundToStep=*/false, Captures);
8795 if (!Diff.isUsable())
8796 return std::make_pair(nullptr, nullptr);
8797
8798 // ((Upper - Lower [- 1]) / Step) * Step
8799 // Parentheses (for dumping/debugging purposes only).
8800 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8801 if (!Diff.isUsable())
8802 return std::make_pair(nullptr, nullptr);
8803
8804 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8805 if (!NewStep.isUsable())
8806 return std::make_pair(nullptr, nullptr);
8807 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8808 if (!Diff.isUsable())
8809 return std::make_pair(nullptr, nullptr);
8810
8811 // Parentheses (for dumping/debugging purposes only).
8812 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8813 if (!Diff.isUsable())
8814 return std::make_pair(nullptr, nullptr);
8815
8816 // Convert to the ptrdiff_t, if original type is pointer.
8817 if (VarType->isAnyPointerType() &&
8818 !SemaRef.Context.hasSameType(
8819 Diff.get()->getType(),
8821 Diff = SemaRef.PerformImplicitConversion(
8822 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8823 Sema::AA_Converting, /*AllowExplicit=*/true);
8824 }
8825 if (!Diff.isUsable())
8826 return std::make_pair(nullptr, nullptr);
8827
8828 if (*TestIsLessOp) {
8829 // MinExpr = Lower;
8830 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8831 Diff = SemaRef.BuildBinOp(
8832 S, DefaultLoc, BO_Add,
8833 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8834 Diff.get());
8835 if (!Diff.isUsable())
8836 return std::make_pair(nullptr, nullptr);
8837 } else {
8838 // MaxExpr = Upper;
8839 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8840 Diff = SemaRef.BuildBinOp(
8841 S, DefaultLoc, BO_Sub,
8842 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8843 Diff.get());
8844 if (!Diff.isUsable())
8845 return std::make_pair(nullptr, nullptr);
8846 }
8847
8848 // Convert to the original type.
8849 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8850 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8852 /*AllowExplicit=*/true);
8853 if (!Diff.isUsable())
8854 return std::make_pair(nullptr, nullptr);
8855
8856 Sema::TentativeAnalysisScope Trap(SemaRef);
8857 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8858 if (!Diff.isUsable())
8859 return std::make_pair(nullptr, nullptr);
8860
8861 if (*TestIsLessOp)
8862 MaxExpr = Diff.get();
8863 else
8864 MinExpr = Diff.get();
8865
8866 return std::make_pair(MinExpr, MaxExpr);
8867}
8868
8869Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8870 if (InitDependOnLC || CondDependOnLC)
8871 return Condition;
8872 return nullptr;
8873}
8874
8875Expr *OpenMPIterationSpaceChecker::buildPreCond(
8876 Scope *S, Expr *Cond,
8877 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8878 // Do not build a precondition when the condition/initialization is dependent
8879 // to prevent pessimistic early loop exit.
8880 // TODO: this can be improved by calculating min/max values but not sure that
8881 // it will be very effective.
8882 if (CondDependOnLC || InitDependOnLC)
8883 return SemaRef
8885 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8886 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8887 /*AllowExplicit=*/true)
8888 .get();
8889
8890 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8891 Sema::TentativeAnalysisScope Trap(SemaRef);
8892
8893 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8894 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8895 if (!NewLB.isUsable() || !NewUB.isUsable())
8896 return nullptr;
8897
8898 ExprResult CondExpr =
8899 SemaRef.BuildBinOp(S, DefaultLoc,
8900 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8901 : (TestIsStrictOp ? BO_GT : BO_GE),
8902 NewLB.get(), NewUB.get());
8903 if (CondExpr.isUsable()) {
8904 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8905 SemaRef.Context.BoolTy))
8906 CondExpr = SemaRef.PerformImplicitConversion(
8907 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8908 /*AllowExplicit=*/true);
8909 }
8910
8911 // Otherwise use original loop condition and evaluate it in runtime.
8912 return CondExpr.isUsable() ? CondExpr.get() : Cond;
8913}
8914
8915/// Build reference expression to the counter be used for codegen.
8916DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8917 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8918 DSAStackTy &DSA) const {
8919 auto *VD = dyn_cast<VarDecl>(LCDecl);
8920 if (!VD) {
8921 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
8923 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
8924 const DSAStackTy::DSAVarData Data =
8925 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
8926 // If the loop control decl is explicitly marked as private, do not mark it
8927 // as captured again.
8928 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
8929 Captures.insert(std::make_pair(LCRef, Ref));
8930 return Ref;
8931 }
8932 return cast<DeclRefExpr>(LCRef);
8933}
8934
8935Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
8936 if (LCDecl && !LCDecl->isInvalidDecl()) {
8938 VarDecl *PrivateVar = buildVarDecl(
8939 SemaRef, DefaultLoc, Type, LCDecl->getName(),
8940 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
8941 isa<VarDecl>(LCDecl)
8942 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
8943 : nullptr);
8944 if (PrivateVar->isInvalidDecl())
8945 return nullptr;
8946 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
8947 }
8948 return nullptr;
8949}
8950
8951/// Build initialization of the counter to be used for codegen.
8952Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
8953
8954/// Build step of the counter be used for codegen.
8955Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
8956
8957Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
8958 Scope *S, Expr *Counter,
8959 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
8960 Expr *Inc, OverloadedOperatorKind OOK) {
8961 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
8962 if (!Cnt)
8963 return nullptr;
8964 if (Inc) {
8965 assert((OOK == OO_Plus || OOK == OO_Minus) &&
8966 "Expected only + or - operations for depend clauses.");
8967 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
8968 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
8969 if (!Cnt)
8970 return nullptr;
8971 }
8972 QualType VarType = LCDecl->getType().getNonReferenceType();
8973 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8974 !SemaRef.getLangOpts().CPlusPlus)
8975 return nullptr;
8976 // Upper - Lower
8977 Expr *Upper =
8978 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
8979 Expr *Lower =
8980 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
8981 if (!Upper || !Lower)
8982 return nullptr;
8983
8984 ExprResult Diff = calculateNumIters(
8985 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
8986 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
8987 if (!Diff.isUsable())
8988 return nullptr;
8989
8990 return Diff.get();
8991}
8992} // namespace
8993
8995 Stmt *Init) {
8996 assert(getLangOpts().OpenMP && "OpenMP is not active.");
8997 assert(Init && "Expected loop in canonical form.");
8998 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
8999 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9000 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9001 return;
9002
9003 DSAStack->loopStart();
9004 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9005 *DSAStack, ForLoc);
9006 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9007 if (ValueDecl *D = ISC.getLoopDecl()) {
9008 auto *VD = dyn_cast<VarDecl>(D);
9009 DeclRefExpr *PrivateRef = nullptr;
9010 if (!VD) {
9012 VD = Private;
9013 } else {
9014 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9015 /*WithInit=*/false);
9016 VD = cast<VarDecl>(PrivateRef->getDecl());
9017 }
9018 }
9019 DSAStack->addLoopControlVariable(D, VD);
9020 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9021 if (LD != D->getCanonicalDecl()) {
9022 DSAStack->resetPossibleLoopCounter();
9023 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9025 SemaRef, const_cast<VarDecl *>(Var),
9026 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9027 /*RefersToCapture=*/true));
9028 }
9029 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9030 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9031 // associated for-loop of a simd construct with just one associated
9032 // for-loop may be listed in a linear clause with a constant-linear-step
9033 // that is the increment of the associated for-loop. The loop iteration
9034 // variable(s) in the associated for-loop(s) of a for or parallel for
9035 // construct may be listed in a private or lastprivate clause.
9036 DSAStackTy::DSAVarData DVar =
9037 DSAStack->getTopDSA(D, /*FromParent=*/false);
9038 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9039 // is declared in the loop and it is predetermined as a private.
9040 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9041 OpenMPClauseKind PredeterminedCKind =
9043 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9044 : OMPC_private;
9045 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9046 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9047 };
9048 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9049 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9050 (getLangOpts().OpenMP <= 45 ||
9051 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9053 IsOpenMPTaskloopDirective(DKind) ||
9055 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9056 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9057 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9058 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9059 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9060 << getOpenMPClauseName(PredeterminedCKind);
9061 if (DVar.RefExpr == nullptr)
9062 DVar.CKind = PredeterminedCKind;
9063 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9064 } else if (LoopDeclRefExpr) {
9065 // Make the loop iteration variable private (for worksharing
9066 // constructs), linear (for simd directives with the only one
9067 // associated loop) or lastprivate (for simd directives with several
9068 // collapsed or ordered loops).
9069 if (DVar.CKind == OMPC_unknown)
9070 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9071 }
9072 }
9073 }
9074 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9075}
9076
9077namespace {
9078// Utility for OpenMP doacross clause kind
9079class OMPDoacrossKind {
9080public:
9081 bool isSource(const OMPDoacrossClause *C) {
9082 return C->getDependenceType() == OMPC_DOACROSS_source ||
9083 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9084 }
9085 bool isSink(const OMPDoacrossClause *C) {
9086 return C->getDependenceType() == OMPC_DOACROSS_sink;
9087 }
9088 bool isSinkIter(const OMPDoacrossClause *C) {
9089 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9090 }
9091};
9092} // namespace
9093/// Called on a for stmt to check and extract its iteration space
9094/// for further processing (such as collapsing).
9096 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9097 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9098 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9099 Expr *OrderedLoopCountExpr,
9100 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9102 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9103 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9104 // OpenMP [2.9.1, Canonical Loop Form]
9105 // for (init-expr; test-expr; incr-expr) structured-block
9106 // for (range-decl: range-expr) structured-block
9107 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9108 S = CanonLoop->getLoopStmt();
9109 auto *For = dyn_cast_or_null<ForStmt>(S);
9110 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9111 // Ranged for is supported only in OpenMP 5.0.
9112 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9113 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9114 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9115 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9116 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9117 if (TotalNestedLoopCount > 1) {
9118 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9119 SemaRef.Diag(DSA.getConstructLoc(),
9120 diag::note_omp_collapse_ordered_expr)
9121 << 2 << CollapseLoopCountExpr->getSourceRange()
9122 << OrderedLoopCountExpr->getSourceRange();
9123 else if (CollapseLoopCountExpr)
9124 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9125 diag::note_omp_collapse_ordered_expr)
9126 << 0 << CollapseLoopCountExpr->getSourceRange();
9127 else
9128 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9129 diag::note_omp_collapse_ordered_expr)
9130 << 1 << OrderedLoopCountExpr->getSourceRange();
9131 }
9132 return true;
9133 }
9134 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9135 "No loop body.");
9136 // Postpone analysis in dependent contexts for ranged for loops.
9137 if (CXXFor && SemaRef.CurContext->isDependentContext())
9138 return false;
9139
9140 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9141 For ? For->getForLoc() : CXXFor->getForLoc());
9142
9143 // Check init.
9144 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9145 if (ISC.checkAndSetInit(Init))
9146 return true;
9147
9148 bool HasErrors = false;
9149
9150 // Check loop variable's type.
9151 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9152 // OpenMP [2.6, Canonical Loop Form]
9153 // Var is one of the following:
9154 // A variable of signed or unsigned integer type.
9155 // For C++, a variable of a random access iterator type.
9156 // For C, a variable of a pointer type.
9157 QualType VarType = LCDecl->getType().getNonReferenceType();
9158 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9159 !VarType->isPointerType() &&
9160 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9161 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9162 << SemaRef.getLangOpts().CPlusPlus;
9163 HasErrors = true;
9164 }
9165
9166 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9167 // a Construct
9168 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9169 // parallel for construct is (are) private.
9170 // The loop iteration variable in the associated for-loop of a simd
9171 // construct with just one associated for-loop is linear with a
9172 // constant-linear-step that is the increment of the associated for-loop.
9173 // Exclude loop var from the list of variables with implicitly defined data
9174 // sharing attributes.
9175 VarsWithImplicitDSA.erase(LCDecl);
9176
9177 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9178
9179 // Check test-expr.
9180 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9181
9182 // Check incr-expr.
9183 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9184 }
9185
9186 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9187 return HasErrors;
9188
9189 // Build the loop's iteration space representation.
9190 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9191 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9192 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9193 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9199 Captures);
9200 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9201 ISC.buildCounterVar(Captures, DSA);
9202 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9203 ISC.buildPrivateCounterVar();
9204 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9205 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9206 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9207 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9208 ISC.getConditionSrcRange();
9209 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9210 ISC.getIncrementSrcRange();
9211 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9212 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9213 ISC.isStrictTestOp();
9214 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9215 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9216 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9217 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9218 ISC.buildFinalCondition(DSA.getCurScope());
9219 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9220 ISC.doesInitDependOnLC();
9221 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9222 ISC.doesCondDependOnLC();
9223 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9224 ISC.getLoopDependentIdx();
9225
9226 HasErrors |=
9227 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9228 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9229 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9230 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9231 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9232 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9233 if (!HasErrors && DSA.isOrderedRegion()) {
9234 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9235 if (CurrentNestedLoopCount <
9236 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9237 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9238 CurrentNestedLoopCount,
9239 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9240 DSA.getOrderedRegionParam().second->setLoopCounter(
9241 CurrentNestedLoopCount,
9242 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9243 }
9244 }
9245 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9246 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9247 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9248 unsigned NumLoops =
9249 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9250 if (CurrentNestedLoopCount >= NumLoops) {
9251 // Erroneous case - clause has some problems.
9252 continue;
9253 }
9254 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9255 Pair.second.size() <= CurrentNestedLoopCount) {
9256 // Erroneous case - clause has some problems.
9257 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9258 continue;
9259 }
9260 OMPDoacrossKind ODK;
9261 if (DoacrossC && ODK.isSink(DoacrossC) &&
9262 Pair.second.size() <= CurrentNestedLoopCount) {
9263 // Erroneous case - clause has some problems.
9264 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9265 continue;
9266 }
9267 Expr *CntValue;
9268 SourceLocation DepLoc =
9269 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9270 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9271 (DoacrossC && ODK.isSource(DoacrossC)))
9272 CntValue = ISC.buildOrderedLoopData(
9273 DSA.getCurScope(),
9274 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9275 DepLoc);
9276 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9277 Expr *Cnt = SemaRef
9279 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9280 .get();
9281 if (!Cnt)
9282 continue;
9283 // build CounterVar - 1
9284 Expr *Inc =
9285 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9286 .get();
9287 CntValue = ISC.buildOrderedLoopData(
9288 DSA.getCurScope(),
9289 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9290 DepLoc, Inc, clang::OO_Minus);
9291 } else
9292 CntValue = ISC.buildOrderedLoopData(
9293 DSA.getCurScope(),
9294 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9295 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9296 Pair.second[CurrentNestedLoopCount].second);
9297 if (DependC)
9298 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9299 else
9300 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9301 }
9302 }
9303
9304 return HasErrors;
9305}
9306
9307/// Build 'VarRef = Start.
9308static ExprResult
9310 ExprResult Start, bool IsNonRectangularLB,
9311 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9312 // Build 'VarRef = Start.
9313 ExprResult NewStart = IsNonRectangularLB
9314 ? Start.get()
9315 : tryBuildCapture(SemaRef, Start.get(), Captures);
9316 if (!NewStart.isUsable())
9317 return ExprError();
9318 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9319 VarRef.get()->getType())) {
9320 NewStart = SemaRef.PerformImplicitConversion(
9321 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9322 /*AllowExplicit=*/true);
9323 if (!NewStart.isUsable())
9324 return ExprError();
9325 }
9326
9328 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9329 return Init;
9330}
9331
9332/// Build 'VarRef = Start + Iter * Step'.
9334 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9335 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9336 bool IsNonRectangularLB,
9337 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9338 // Add parentheses (for debugging purposes only).
9339 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9340 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9341 !Step.isUsable())
9342 return ExprError();
9343
9344 ExprResult NewStep = Step;
9345 if (Captures)
9346 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9347 if (NewStep.isInvalid())
9348 return ExprError();
9350 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9351 if (!Update.isUsable())
9352 return ExprError();
9353
9354 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9355 // 'VarRef = Start (+|-) Iter * Step'.
9356 if (!Start.isUsable())
9357 return ExprError();
9358 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9359 if (!NewStart.isUsable())
9360 return ExprError();
9361 if (Captures && !IsNonRectangularLB)
9362 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9363 if (NewStart.isInvalid())
9364 return ExprError();
9365
9366 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9367 ExprResult SavedUpdate = Update;
9368 ExprResult UpdateVal;
9369 if (VarRef.get()->getType()->isOverloadableType() ||
9370 NewStart.get()->getType()->isOverloadableType() ||
9371 Update.get()->getType()->isOverloadableType()) {
9372 Sema::TentativeAnalysisScope Trap(SemaRef);
9373
9374 Update =
9375 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9376 if (Update.isUsable()) {
9377 UpdateVal =
9378 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9379 VarRef.get(), SavedUpdate.get());
9380 if (UpdateVal.isUsable()) {
9381 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9382 UpdateVal.get());
9383 }
9384 }
9385 }
9386
9387 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9388 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9389 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9390 NewStart.get(), SavedUpdate.get());
9391 if (!Update.isUsable())
9392 return ExprError();
9393
9394 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9395 VarRef.get()->getType())) {
9397 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9398 if (!Update.isUsable())
9399 return ExprError();
9400 }
9401
9402 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9403 }
9404 return Update;
9405}
9406
9407/// Convert integer expression \a E to make it have at least \a Bits
9408/// bits.
9409static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9410 if (E == nullptr)
9411 return ExprError();
9412 ASTContext &C = SemaRef.Context;
9413 QualType OldType = E->getType();
9414 unsigned HasBits = C.getTypeSize(OldType);
9415 if (HasBits >= Bits)
9416 return ExprResult(E);
9417 // OK to convert to signed, because new type has more bits than old.
9418 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9419 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9420 true);
9421}
9422
9423/// Check if the given expression \a E is a constant integer that fits
9424/// into \a Bits bits.
9425static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9426 if (E == nullptr)
9427 return false;
9428 if (std::optional<llvm::APSInt> Result =
9430 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9431 return false;
9432}
9433
9434/// Build preinits statement for the given declarations.
9436 MutableArrayRef<Decl *> PreInits) {
9437 if (!PreInits.empty()) {
9438 return new (Context) DeclStmt(
9439 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9441 }
9442 return nullptr;
9443}
9444
9445/// Append the \p Item or the content of a CompoundStmt to the list \p
9446/// TargetList.
9447///
9448/// A CompoundStmt is used as container in case multiple statements need to be
9449/// stored in lieu of using an explicit list. Flattening is necessary because
9450/// contained DeclStmts need to be visible after the execution of the list. Used
9451/// for OpenMP pre-init declarations/statements.
9453 Stmt *Item) {
9454 // nullptr represents an empty list.
9455 if (!Item)
9456 return;
9457
9458 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9459 llvm::append_range(TargetList, CS->body());
9460 else
9461 TargetList.push_back(Item);
9462}
9463
9464/// Build preinits statement for the given declarations.
9465static Stmt *
9467 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9468 if (!Captures.empty()) {
9469 SmallVector<Decl *, 16> PreInits;
9470 for (const auto &Pair : Captures)
9471 PreInits.push_back(Pair.second->getDecl());
9472 return buildPreInits(Context, PreInits);
9473 }
9474 return nullptr;
9475}
9476
9477/// Build pre-init statement for the given statements.
9478static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9479 if (PreInits.empty())
9480 return nullptr;
9481
9482 SmallVector<Stmt *> Stmts;
9483 for (Stmt *S : PreInits)
9484 appendFlattenedStmtList(Stmts, S);
9485 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9486}
9487
9488/// Build postupdate expression for the given list of postupdates expressions.
9489static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9490 Expr *PostUpdate = nullptr;
9491 if (!PostUpdates.empty()) {
9492 for (Expr *E : PostUpdates) {
9493 Expr *ConvE = S.BuildCStyleCastExpr(
9494 E->getExprLoc(),
9496 E->getExprLoc(), E)
9497 .get();
9498 PostUpdate = PostUpdate
9499 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9500 PostUpdate, ConvE)
9501 .get()
9502 : ConvE;
9503 }
9504 }
9505 return PostUpdate;
9506}
9507
9508/// Called on a for stmt to check itself and nested loops (if any).
9509/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9510/// number of collapsed loops otherwise.
9511static unsigned
9512checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9513 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9514 DSAStackTy &DSA,
9515 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9517 unsigned NestedLoopCount = 1;
9518 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9520
9521 if (CollapseLoopCountExpr) {
9522 // Found 'collapse' clause - calculate collapse number.
9524 if (!CollapseLoopCountExpr->isValueDependent() &&
9525 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9526 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9527 } else {
9528 Built.clear(/*Size=*/1);
9529 return 1;
9530 }
9531 }
9532 unsigned OrderedLoopCount = 1;
9533 if (OrderedLoopCountExpr) {
9534 // Found 'ordered' clause - calculate collapse number.
9535 Expr::EvalResult EVResult;
9536 if (!OrderedLoopCountExpr->isValueDependent() &&
9537 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9538 SemaRef.getASTContext())) {
9539 llvm::APSInt Result = EVResult.Val.getInt();
9540 if (Result.getLimitedValue() < NestedLoopCount) {
9541 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9542 diag::err_omp_wrong_ordered_loop_count)
9543 << OrderedLoopCountExpr->getSourceRange();
9544 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9545 diag::note_collapse_loop_count)
9546 << CollapseLoopCountExpr->getSourceRange();
9547 }
9548 OrderedLoopCount = Result.getLimitedValue();
9549 } else {
9550 Built.clear(/*Size=*/1);
9551 return 1;
9552 }
9553 }
9554 // This is helper routine for loop directives (e.g., 'for', 'simd',
9555 // 'for simd', etc.).
9556 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9557 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9558 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9561 SupportsNonPerfectlyNested, NumLoops,
9562 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9563 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9564 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9566 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9567 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9568 VarsWithImplicitDSA, IterSpaces, Captures))
9569 return true;
9570 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9571 IterSpaces[Cnt].CounterVar) {
9572 // Handle initialization of captured loop iterator variables.
9573 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9574 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9575 Captures[DRE] = DRE;
9576 }
9577 }
9578 return false;
9579 },
9580 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9581 Stmt *DependentPreInits = Transform->getPreInits();
9582 if (!DependentPreInits)
9583 return;
9584
9585 // Search for pre-init declared variables that need to be captured
9586 // to be referenceable inside the directive.
9587 SmallVector<Stmt *> Constituents;
9588 appendFlattenedStmtList(Constituents, DependentPreInits);
9589 for (Stmt *S : Constituents) {
9590 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9591 for (Decl *C : DC->decls()) {
9592 auto *D = cast<VarDecl>(C);
9594 SemaRef, D, D->getType().getNonReferenceType(),
9595 Transform->getBeginLoc());
9596 Captures[Ref] = Ref;
9597 }
9598 }
9599 }
9600 }))
9601 return 0;
9602
9603 Built.clear(/* size */ NestedLoopCount);
9604
9605 if (SemaRef.CurContext->isDependentContext())
9606 return NestedLoopCount;
9607
9608 // An example of what is generated for the following code:
9609 //
9610 // #pragma omp simd collapse(2) ordered(2)
9611 // for (i = 0; i < NI; ++i)
9612 // for (k = 0; k < NK; ++k)
9613 // for (j = J0; j < NJ; j+=2) {
9614 // <loop body>
9615 // }
9616 //
9617 // We generate the code below.
9618 // Note: the loop body may be outlined in CodeGen.
9619 // Note: some counters may be C++ classes, operator- is used to find number of
9620 // iterations and operator+= to calculate counter value.
9621 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9622 // or i64 is currently supported).
9623 //
9624 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9625 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9626 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9627 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9628 // // similar updates for vars in clauses (e.g. 'linear')
9629 // <loop body (using local i and j)>
9630 // }
9631 // i = NI; // assign final values of counters
9632 // j = NJ;
9633 //
9634
9635 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9636 // the iteration counts of the collapsed for loops.
9637 // Precondition tests if there is at least one iteration (all conditions are
9638 // true).
9639 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9640 Expr *N0 = IterSpaces[0].NumIterations;
9641 ExprResult LastIteration32 =
9642 widenIterationCount(/*Bits=*/32,
9643 SemaRef
9644 .PerformImplicitConversion(
9645 N0->IgnoreImpCasts(), N0->getType(),
9646 Sema::AA_Converting, /*AllowExplicit=*/true)
9647 .get(),
9648 SemaRef);
9649 ExprResult LastIteration64 = widenIterationCount(
9650 /*Bits=*/64,
9651 SemaRef
9652 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9654 /*AllowExplicit=*/true)
9655 .get(),
9656 SemaRef);
9657
9658 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9659 return NestedLoopCount;
9660
9661 ASTContext &C = SemaRef.Context;
9662 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9663
9664 Scope *CurScope = DSA.getCurScope();
9665 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9666 if (PreCond.isUsable()) {
9667 PreCond =
9668 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9669 PreCond.get(), IterSpaces[Cnt].PreCond);
9670 }
9671 Expr *N = IterSpaces[Cnt].NumIterations;
9673 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9674 if (LastIteration32.isUsable())
9675 LastIteration32 = SemaRef.BuildBinOp(
9676 CurScope, Loc, BO_Mul, LastIteration32.get(),
9677 SemaRef
9680 /*AllowExplicit=*/true)
9681 .get());
9682 if (LastIteration64.isUsable())
9683 LastIteration64 = SemaRef.BuildBinOp(
9684 CurScope, Loc, BO_Mul, LastIteration64.get(),
9685 SemaRef
9688 /*AllowExplicit=*/true)
9689 .get());
9690 }
9691
9692 // Choose either the 32-bit or 64-bit version.
9693 ExprResult LastIteration = LastIteration64;
9694 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9695 (LastIteration32.isUsable() &&
9696 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9697 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9698 fitsInto(
9699 /*Bits=*/32,
9700 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9701 LastIteration64.get(), SemaRef))))
9702 LastIteration = LastIteration32;
9703 QualType VType = LastIteration.get()->getType();
9704 QualType RealVType = VType;
9705 QualType StrideVType = VType;
9706 if (isOpenMPTaskLoopDirective(DKind)) {
9707 VType =
9708 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9709 StrideVType =
9710 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9711 }
9712
9713 if (!LastIteration.isUsable())
9714 return 0;
9715
9716 // Save the number of iterations.
9717 ExprResult NumIterations = LastIteration;
9718 {
9719 LastIteration = SemaRef.BuildBinOp(
9720 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9721 LastIteration.get(),
9722 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9723 if (!LastIteration.isUsable())
9724 return 0;
9725 }
9726
9727 // Calculate the last iteration number beforehand instead of doing this on
9728 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9729 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9730 ExprResult CalcLastIteration;
9731 if (!IsConstant) {
9732 ExprResult SaveRef =
9733 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9734 LastIteration = SaveRef;
9735
9736 // Prepare SaveRef + 1.
9737 NumIterations = SemaRef.BuildBinOp(
9738 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9739 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9740 if (!NumIterations.isUsable())
9741 return 0;
9742 }
9743
9744 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9745
9746 // Build variables passed into runtime, necessary for worksharing directives.
9747 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9752 // Lower bound variable, initialized with zero.
9753 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9754 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9755 SemaRef.AddInitializerToDecl(LBDecl,
9756 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9757 /*DirectInit*/ false);
9758
9759 // Upper bound variable, initialized with last iteration number.
9760 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9761 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9762 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9763 /*DirectInit*/ false);
9764
9765 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9766 // This will be used to implement clause 'lastprivate'.
9767 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9768 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9769 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9770 SemaRef.AddInitializerToDecl(ILDecl,
9771 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9772 /*DirectInit*/ false);
9773
9774 // Stride variable returned by runtime (we initialize it to 1 by default).
9775 VarDecl *STDecl =
9776 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9777 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9778 SemaRef.AddInitializerToDecl(STDecl,
9779 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9780 /*DirectInit*/ false);
9781
9782 // Build expression: UB = min(UB, LastIteration)
9783 // It is necessary for CodeGen of directives with static scheduling.
9784 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9785 UB.get(), LastIteration.get());
9786 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9787 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9788 LastIteration.get(), UB.get());
9789 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9790 CondOp.get());
9791 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9792
9793 // If we have a combined directive that combines 'distribute', 'for' or
9794 // 'simd' we need to be able to access the bounds of the schedule of the
9795 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9796 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9798 // Lower bound variable, initialized with zero.
9799 VarDecl *CombLBDecl =
9800 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9801 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9802 SemaRef.AddInitializerToDecl(
9803 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9804 /*DirectInit*/ false);
9805
9806 // Upper bound variable, initialized with last iteration number.
9807 VarDecl *CombUBDecl =
9808 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9809 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9810 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9811 /*DirectInit*/ false);
9812
9813 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9814 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9815 ExprResult CombCondOp =
9816 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9817 LastIteration.get(), CombUB.get());
9818 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9819 CombCondOp.get());
9820 CombEUB =
9821 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
9822
9823 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9824 // We expect to have at least 2 more parameters than the 'parallel'
9825 // directive does - the lower and upper bounds of the previous schedule.
9826 assert(CD->getNumParams() >= 4 &&
9827 "Unexpected number of parameters in loop combined directive");
9828
9829 // Set the proper type for the bounds given what we learned from the
9830 // enclosed loops.
9831 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9832 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9833
9834 // Previous lower and upper bounds are obtained from the region
9835 // parameters.
9836 PrevLB =
9837 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9838 PrevUB =
9839 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9840 }
9841 }
9842
9843 // Build the iteration variable and its initialization before loop.
9844 ExprResult IV;
9845 ExprResult Init, CombInit;
9846 {
9847 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9848 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9849 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9854 ? LB.get()
9855 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9856 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9857 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
9858
9860 Expr *CombRHS =
9865 ? CombLB.get()
9866 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9867 CombInit =
9868 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9869 CombInit =
9870 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
9871 }
9872 }
9873
9874 bool UseStrictCompare =
9875 RealVType->hasUnsignedIntegerRepresentation() &&
9876 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9877 return LIS.IsStrictCompare;
9878 });
9879 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9880 // unsigned IV)) for worksharing loops.
9881 SourceLocation CondLoc = AStmt->getBeginLoc();
9882 Expr *BoundUB = UB.get();
9883 if (UseStrictCompare) {
9884 BoundUB =
9885 SemaRef
9886 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9887 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9888 .get();
9889 BoundUB =
9890 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
9891 }
9892 ExprResult Cond =
9897 ? SemaRef.BuildBinOp(CurScope, CondLoc,
9898 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
9899 BoundUB)
9900 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9901 NumIterations.get());
9902 ExprResult CombDistCond;
9904 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9905 NumIterations.get());
9906 }
9907
9908 ExprResult CombCond;
9910 Expr *BoundCombUB = CombUB.get();
9911 if (UseStrictCompare) {
9912 BoundCombUB =
9913 SemaRef
9914 .BuildBinOp(
9915 CurScope, CondLoc, BO_Add, BoundCombUB,
9916 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9917 .get();
9918 BoundCombUB =
9919 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
9920 .get();
9921 }
9922 CombCond =
9923 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9924 IV.get(), BoundCombUB);
9925 }
9926 // Loop increment (IV = IV + 1)
9927 SourceLocation IncLoc = AStmt->getBeginLoc();
9928 ExprResult Inc =
9929 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
9930 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
9931 if (!Inc.isUsable())
9932 return 0;
9933 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
9934 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
9935 if (!Inc.isUsable())
9936 return 0;
9937
9938 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
9939 // Used for directives with static scheduling.
9940 // In combined construct, add combined version that use CombLB and CombUB
9941 // base variables for the update
9942 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
9947 // LB + ST
9948 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
9949 if (!NextLB.isUsable())
9950 return 0;
9951 // LB = LB + ST
9952 NextLB =
9953 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
9954 NextLB =
9955 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
9956 if (!NextLB.isUsable())
9957 return 0;
9958 // UB + ST
9959 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
9960 if (!NextUB.isUsable())
9961 return 0;
9962 // UB = UB + ST
9963 NextUB =
9964 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
9965 NextUB =
9966 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
9967 if (!NextUB.isUsable())
9968 return 0;
9970 CombNextLB =
9971 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
9972 if (!NextLB.isUsable())
9973 return 0;
9974 // LB = LB + ST
9975 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
9976 CombNextLB.get());
9977 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
9978 /*DiscardedValue*/ false);
9979 if (!CombNextLB.isUsable())
9980 return 0;
9981 // UB + ST
9982 CombNextUB =
9983 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
9984 if (!CombNextUB.isUsable())
9985 return 0;
9986 // UB = UB + ST
9987 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
9988 CombNextUB.get());
9989 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
9990 /*DiscardedValue*/ false);
9991 if (!CombNextUB.isUsable())
9992 return 0;
9993 }
9994 }
9995
9996 // Create increment expression for distribute loop when combined in a same
9997 // directive with for as IV = IV + ST; ensure upper bound expression based
9998 // on PrevUB instead of NumIterations - used to implement 'for' when found
9999 // in combination with 'distribute', like in 'distribute parallel for'
10000 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10001 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10003 DistCond = SemaRef.BuildBinOp(
10004 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10005 assert(DistCond.isUsable() && "distribute cond expr was not built");
10006
10007 DistInc =
10008 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10009 assert(DistInc.isUsable() && "distribute inc expr was not built");
10010 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10011 DistInc.get());
10012 DistInc =
10013 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
10014 assert(DistInc.isUsable() && "distribute inc expr was not built");
10015
10016 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10017 // construct
10018 ExprResult NewPrevUB = PrevUB;
10019 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10020 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10021 PrevUB.get()->getType())) {
10022 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10023 DistEUBLoc,
10025 DistEUBLoc, NewPrevUB.get());
10026 if (!NewPrevUB.isUsable())
10027 return 0;
10028 }
10029 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10030 UB.get(), NewPrevUB.get());
10031 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10032 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10033 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10034 CondOp.get());
10035 PrevEUB =
10036 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10037
10038 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10039 // parallel for is in combination with a distribute directive with
10040 // schedule(static, 1)
10041 Expr *BoundPrevUB = PrevUB.get();
10042 if (UseStrictCompare) {
10043 BoundPrevUB =
10044 SemaRef
10045 .BuildBinOp(
10046 CurScope, CondLoc, BO_Add, BoundPrevUB,
10047 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10048 .get();
10049 BoundPrevUB =
10050 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10051 .get();
10052 }
10053 ParForInDistCond =
10054 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10055 IV.get(), BoundPrevUB);
10056 }
10057
10058 // Build updates and final values of the loop counters.
10059 bool HasErrors = false;
10060 Built.Counters.resize(NestedLoopCount);
10061 Built.Inits.resize(NestedLoopCount);
10062 Built.Updates.resize(NestedLoopCount);
10063 Built.Finals.resize(NestedLoopCount);
10064 Built.DependentCounters.resize(NestedLoopCount);
10065 Built.DependentInits.resize(NestedLoopCount);
10066 Built.FinalsConditions.resize(NestedLoopCount);
10067 {
10068 // We implement the following algorithm for obtaining the
10069 // original loop iteration variable values based on the
10070 // value of the collapsed loop iteration variable IV.
10071 //
10072 // Let n+1 be the number of collapsed loops in the nest.
10073 // Iteration variables (I0, I1, .... In)
10074 // Iteration counts (N0, N1, ... Nn)
10075 //
10076 // Acc = IV;
10077 //
10078 // To compute Ik for loop k, 0 <= k <= n, generate:
10079 // Prod = N(k+1) * N(k+2) * ... * Nn;
10080 // Ik = Acc / Prod;
10081 // Acc -= Ik * Prod;
10082 //
10083 ExprResult Acc = IV;
10084 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10085 LoopIterationSpace &IS = IterSpaces[Cnt];
10086 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10088
10089 // Compute prod
10090 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10091 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10092 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10093 IterSpaces[K].NumIterations);
10094
10095 // Iter = Acc / Prod
10096 // If there is at least one more inner loop to avoid
10097 // multiplication by 1.
10098 if (Cnt + 1 < NestedLoopCount)
10099 Iter =
10100 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10101 else
10102 Iter = Acc;
10103 if (!Iter.isUsable()) {
10104 HasErrors = true;
10105 break;
10106 }
10107
10108 // Update Acc:
10109 // Acc -= Iter * Prod
10110 // Check if there is at least one more inner loop to avoid
10111 // multiplication by 1.
10112 if (Cnt + 1 < NestedLoopCount)
10113 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10114 Prod.get());
10115 else
10116 Prod = Iter;
10117 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10118
10119 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10120 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10121 DeclRefExpr *CounterVar = buildDeclRefExpr(
10122 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10123 /*RefersToCapture=*/true);
10125 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10126 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10127 if (!Init.isUsable()) {
10128 HasErrors = true;
10129 break;
10130 }
10132 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10133 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10134 if (!Update.isUsable()) {
10135 HasErrors = true;
10136 break;
10137 }
10138
10139 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10140 ExprResult Final =
10141 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10142 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10143 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10144 if (!Final.isUsable()) {
10145 HasErrors = true;
10146 break;
10147 }
10148
10149 if (!Update.isUsable() || !Final.isUsable()) {
10150 HasErrors = true;
10151 break;
10152 }
10153 // Save results
10154 Built.Counters[Cnt] = IS.CounterVar;
10155 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10156 Built.Inits[Cnt] = Init.get();
10157 Built.Updates[Cnt] = Update.get();
10158 Built.Finals[Cnt] = Final.get();
10159 Built.DependentCounters[Cnt] = nullptr;
10160 Built.DependentInits[Cnt] = nullptr;
10161 Built.FinalsConditions[Cnt] = nullptr;
10162 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10163 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10164 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10165 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10166 }
10167 }
10168 }
10169
10170 if (HasErrors)
10171 return 0;
10172
10173 // Save results
10174 Built.IterationVarRef = IV.get();
10175 Built.LastIteration = LastIteration.get();
10176 Built.NumIterations = NumIterations.get();
10177 Built.CalcLastIteration = SemaRef
10178 .ActOnFinishFullExpr(CalcLastIteration.get(),
10179 /*DiscardedValue=*/false)
10180 .get();
10181 Built.PreCond = PreCond.get();
10182 Built.PreInits = buildPreInits(C, Captures);
10183 Built.Cond = Cond.get();
10184 Built.Init = Init.get();
10185 Built.Inc = Inc.get();
10186 Built.LB = LB.get();
10187 Built.UB = UB.get();
10188 Built.IL = IL.get();
10189 Built.ST = ST.get();
10190 Built.EUB = EUB.get();
10191 Built.NLB = NextLB.get();
10192 Built.NUB = NextUB.get();
10193 Built.PrevLB = PrevLB.get();
10194 Built.PrevUB = PrevUB.get();
10195 Built.DistInc = DistInc.get();
10196 Built.PrevEUB = PrevEUB.get();
10197 Built.DistCombinedFields.LB = CombLB.get();
10198 Built.DistCombinedFields.UB = CombUB.get();
10199 Built.DistCombinedFields.EUB = CombEUB.get();
10200 Built.DistCombinedFields.Init = CombInit.get();
10201 Built.DistCombinedFields.Cond = CombCond.get();
10202 Built.DistCombinedFields.NLB = CombNextLB.get();
10203 Built.DistCombinedFields.NUB = CombNextUB.get();
10204 Built.DistCombinedFields.DistCond = CombDistCond.get();
10205 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10206
10207 return NestedLoopCount;
10208}
10209
10211 auto CollapseClauses =
10212 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10213 if (CollapseClauses.begin() != CollapseClauses.end())
10214 return (*CollapseClauses.begin())->getNumForLoops();
10215 return nullptr;
10216}
10217
10219 auto OrderedClauses =
10220 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10221 if (OrderedClauses.begin() != OrderedClauses.end())
10222 return (*OrderedClauses.begin())->getNumForLoops();
10223 return nullptr;
10224}
10225
10227 const ArrayRef<OMPClause *> Clauses) {
10228 const OMPSafelenClause *Safelen = nullptr;
10229 const OMPSimdlenClause *Simdlen = nullptr;
10230
10231 for (const OMPClause *Clause : Clauses) {
10232 if (Clause->getClauseKind() == OMPC_safelen)
10233 Safelen = cast<OMPSafelenClause>(Clause);
10234 else if (Clause->getClauseKind() == OMPC_simdlen)
10235 Simdlen = cast<OMPSimdlenClause>(Clause);
10236 if (Safelen && Simdlen)
10237 break;
10238 }
10239
10240 if (Simdlen && Safelen) {
10241 const Expr *SimdlenLength = Simdlen->getSimdlen();
10242 const Expr *SafelenLength = Safelen->getSafelen();
10243 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10244 SimdlenLength->isInstantiationDependent() ||
10245 SimdlenLength->containsUnexpandedParameterPack())
10246 return false;
10247 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10248 SafelenLength->isInstantiationDependent() ||
10249 SafelenLength->containsUnexpandedParameterPack())
10250 return false;
10251 Expr::EvalResult SimdlenResult, SafelenResult;
10252 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10253 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10254 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10255 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10256 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10257 // If both simdlen and safelen clauses are specified, the value of the
10258 // simdlen parameter must be less than or equal to the value of the safelen
10259 // parameter.
10260 if (SimdlenRes > SafelenRes) {
10261 S.Diag(SimdlenLength->getExprLoc(),
10262 diag::err_omp_wrong_simdlen_safelen_values)
10263 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10264 return true;
10265 }
10266 }
10267 return false;
10268}
10269
10271 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10272 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10273 if (!AStmt)
10274 return StmtError();
10275
10276 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10277
10278 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10280 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10281 // define the nested loops number.
10282 unsigned NestedLoopCount = checkOpenMPLoop(
10283 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10284 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10285 if (NestedLoopCount == 0)
10286 return StmtError();
10287
10288 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10289 return StmtError();
10290
10292 return StmtError();
10293
10294 auto *SimdDirective = OMPSimdDirective::Create(
10295 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10296 return SimdDirective;
10297}
10298
10300 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10301 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10302 if (!AStmt)
10303 return StmtError();
10304
10305 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10307 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10308 // define the nested loops number.
10309 unsigned NestedLoopCount = checkOpenMPLoop(
10310 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10311 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10312 if (NestedLoopCount == 0)
10313 return StmtError();
10314
10315 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10316 return StmtError();
10317
10318 auto *ForDirective = OMPForDirective::Create(
10319 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10320 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10321 return ForDirective;
10322}
10323
10325 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10326 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10327 if (!AStmt)
10328 return StmtError();
10329
10330 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10331
10332 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10334 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10335 // define the nested loops number.
10336 unsigned NestedLoopCount =
10337 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10338 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10339 VarsWithImplicitDSA, B);
10340 if (NestedLoopCount == 0)
10341 return StmtError();
10342
10343 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10344 return StmtError();
10345
10347 return StmtError();
10348
10349 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10350 NestedLoopCount, Clauses, AStmt, B);
10351}
10352
10354 Stmt *AStmt, DSAStackTy *Stack) {
10355 if (!AStmt)
10356 return true;
10357
10358 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10359 auto BaseStmt = AStmt;
10360 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10361 BaseStmt = CS->getCapturedStmt();
10362 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10363 auto S = C->children();
10364 if (S.begin() == S.end())
10365 return true;
10366 // All associated statements must be '#pragma omp section' except for
10367 // the first one.
10368 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10369 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10370 if (SectionStmt)
10371 SemaRef.Diag(SectionStmt->getBeginLoc(),
10372 diag::err_omp_sections_substmt_not_section)
10373 << getOpenMPDirectiveName(DKind);
10374 return true;
10375 }
10376 cast<OMPSectionDirective>(SectionStmt)
10377 ->setHasCancel(Stack->isCancelRegion());
10378 }
10379 } else {
10380 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10381 << getOpenMPDirectiveName(DKind);
10382 return true;
10383 }
10384 return false;
10385}
10386
10389 Stmt *AStmt, SourceLocation StartLoc,
10390 SourceLocation EndLoc) {
10391 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10392 return StmtError();
10393
10395
10397 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10398 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10399}
10400
10402 SourceLocation StartLoc,
10403 SourceLocation EndLoc) {
10404 if (!AStmt)
10405 return StmtError();
10406
10408 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10409
10410 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10411 DSAStack->isCancelRegion());
10412}
10413
10416 if (auto *CE = dyn_cast<CallExpr>(E))
10417 if (CE->getDirectCallee())
10418 return E;
10419 return nullptr;
10420}
10421
10424 Stmt *AStmt, SourceLocation StartLoc,
10425 SourceLocation EndLoc) {
10426 if (!AStmt)
10427 return StmtError();
10428
10429 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10430
10431 // 5.1 OpenMP
10432 // expression-stmt : an expression statement with one of the following forms:
10433 // expression = target-call ( [expression-list] );
10434 // target-call ( [expression-list] );
10435
10436 SourceLocation TargetCallLoc;
10437
10439 Expr *TargetCall = nullptr;
10440
10441 auto *E = dyn_cast<Expr>(S);
10442 if (!E) {
10443 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10444 return StmtError();
10445 }
10446
10448
10449 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10450 if (BO->getOpcode() == BO_Assign)
10451 TargetCall = getDirectCallExpr(BO->getRHS());
10452 } else {
10453 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10454 if (COCE->getOperator() == OO_Equal)
10455 TargetCall = getDirectCallExpr(COCE->getArg(1));
10456 if (!TargetCall)
10457 TargetCall = getDirectCallExpr(E);
10458 }
10459 if (!TargetCall) {
10460 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10461 return StmtError();
10462 }
10463 TargetCallLoc = TargetCall->getExprLoc();
10464 }
10465
10467
10468 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10469 Clauses, AStmt, TargetCallLoc);
10470}
10471
10474 DSAStackTy *Stack) {
10475 bool ErrorFound = false;
10476 for (OMPClause *C : Clauses) {
10477 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10478 for (Expr *RefExpr : LPC->varlist()) {
10479 SourceLocation ELoc;
10480 SourceRange ERange;
10481 Expr *SimpleRefExpr = RefExpr;
10482 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10483 if (ValueDecl *D = Res.first) {
10484 auto &&Info = Stack->isLoopControlVariable(D);
10485 if (!Info.first) {
10486 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10487 << getOpenMPDirectiveName(K);
10488 ErrorFound = true;
10489 }
10490 }
10491 }
10492 }
10493 }
10494 return ErrorFound;
10495}
10496
10498 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10499 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10500 if (!AStmt)
10501 return StmtError();
10502
10503 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10504 // A list item may not appear in a lastprivate clause unless it is the
10505 // loop iteration variable of a loop that is associated with the construct.
10506 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10507 return StmtError();
10508
10509 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10510
10512 // In presence of clause 'collapse', it will define the nested loops number.
10513 unsigned NestedLoopCount = checkOpenMPLoop(
10514 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10515 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10516 if (NestedLoopCount == 0)
10517 return StmtError();
10518
10519 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10520 "omp loop exprs were not built");
10521
10522 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10523 NestedLoopCount, Clauses, AStmt, B);
10524}
10525
10527 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10528 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10529 if (!AStmt)
10530 return StmtError();
10531
10532 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10533 // A list item may not appear in a lastprivate clause unless it is the
10534 // loop iteration variable of a loop that is associated with the construct.
10535 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10536 return StmtError();
10537
10538 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10539
10541 // In presence of clause 'collapse', it will define the nested loops number.
10542 unsigned NestedLoopCount =
10543 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10544 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10545 VarsWithImplicitDSA, B);
10546 if (NestedLoopCount == 0)
10547 return StmtError();
10548
10549 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10550 "omp loop exprs were not built");
10551
10552 DSAStack->setParentTeamsRegionLoc(StartLoc);
10553
10555 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10556}
10557
10559 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10560 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10561 if (!AStmt)
10562 return StmtError();
10563
10564 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10565 // A list item may not appear in a lastprivate clause unless it is the
10566 // loop iteration variable of a loop that is associated with the construct.
10567 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10568 DSAStack))
10569 return StmtError();
10570
10571 CapturedStmt *CS =
10572 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10573
10575 // In presence of clause 'collapse', it will define the nested loops number.
10576 unsigned NestedLoopCount =
10577 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10578 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10579 VarsWithImplicitDSA, B);
10580 if (NestedLoopCount == 0)
10581 return StmtError();
10582
10583 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10584 "omp loop exprs were not built");
10585
10587 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10589}
10590
10592 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10593 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10594 if (!AStmt)
10595 return StmtError();
10596
10597 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10598 // A list item may not appear in a lastprivate clause unless it is the
10599 // loop iteration variable of a loop that is associated with the construct.
10600 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10601 DSAStack))
10602 return StmtError();
10603
10604 CapturedStmt *CS =
10605 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10606
10608 // In presence of clause 'collapse', it will define the nested loops number.
10609 unsigned NestedLoopCount =
10610 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10611 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10612 VarsWithImplicitDSA, B);
10613 if (NestedLoopCount == 0)
10614 return StmtError();
10615
10616 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10617 "omp loop exprs were not built");
10618
10620 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10621}
10622
10624 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10625 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10626 if (!AStmt)
10627 return StmtError();
10628
10629 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10630 // A list item may not appear in a lastprivate clause unless it is the
10631 // loop iteration variable of a loop that is associated with the construct.
10632 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10633 DSAStack))
10634 return StmtError();
10635
10636 CapturedStmt *CS =
10637 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
10638
10640 // In presence of clause 'collapse', it will define the nested loops number.
10641 unsigned NestedLoopCount =
10642 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10643 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10644 VarsWithImplicitDSA, B);
10645 if (NestedLoopCount == 0)
10646 return StmtError();
10647
10648 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10649 "omp loop exprs were not built");
10650
10652 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10653}
10654
10656 Stmt *AStmt,
10657 SourceLocation StartLoc,
10658 SourceLocation EndLoc) {
10659 if (!AStmt)
10660 return StmtError();
10661
10662 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10663
10665
10666 // OpenMP [2.7.3, single Construct, Restrictions]
10667 // The copyprivate clause must not be used with the nowait clause.
10668 const OMPClause *Nowait = nullptr;
10669 const OMPClause *Copyprivate = nullptr;
10670 for (const OMPClause *Clause : Clauses) {
10671 if (Clause->getClauseKind() == OMPC_nowait)
10672 Nowait = Clause;
10673 else if (Clause->getClauseKind() == OMPC_copyprivate)
10674 Copyprivate = Clause;
10675 if (Copyprivate && Nowait) {
10676 Diag(Copyprivate->getBeginLoc(),
10677 diag::err_omp_single_copyprivate_with_nowait);
10678 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10679 return StmtError();
10680 }
10681 }
10682
10683 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10684 AStmt);
10685}
10686
10688 SourceLocation StartLoc,
10689 SourceLocation EndLoc) {
10690 if (!AStmt)
10691 return StmtError();
10692
10694
10695 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
10696}
10697
10699 Stmt *AStmt,
10700 SourceLocation StartLoc,
10701 SourceLocation EndLoc) {
10702 if (!AStmt)
10703 return StmtError();
10704
10706
10707 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10708 AStmt);
10709}
10710
10712 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10713 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10714 if (!AStmt)
10715 return StmtError();
10716
10717 bool ErrorFound = false;
10718 llvm::APSInt Hint;
10719 SourceLocation HintLoc;
10720 bool DependentHint = false;
10721 for (const OMPClause *C : Clauses) {
10722 if (C->getClauseKind() == OMPC_hint) {
10723 if (!DirName.getName()) {
10724 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10725 ErrorFound = true;
10726 }
10727 Expr *E = cast<OMPHintClause>(C)->getHint();
10728 if (E->isTypeDependent() || E->isValueDependent() ||
10730 DependentHint = true;
10731 } else {
10733 HintLoc = C->getBeginLoc();
10734 }
10735 }
10736 }
10737 if (ErrorFound)
10738 return StmtError();
10739 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10740 if (Pair.first && DirName.getName() && !DependentHint) {
10741 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10742 Diag(StartLoc, diag::err_omp_critical_with_hint);
10743 if (HintLoc.isValid())
10744 Diag(HintLoc, diag::note_omp_critical_hint_here)
10745 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10746 else
10747 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10748 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10749 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10750 << 1
10751 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10752 /*Radix=*/10, /*Signed=*/false);
10753 } else {
10754 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10755 }
10756 }
10757 }
10758
10760
10761 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
10762 EndLoc, Clauses, AStmt);
10763 if (!Pair.first && DirName.getName() && !DependentHint)
10764 DSAStack->addCriticalWithHint(Dir, Hint);
10765 return Dir;
10766}
10767
10769 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10770 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10771 if (!AStmt)
10772 return StmtError();
10773
10774 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10775
10777 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10778 // define the nested loops number.
10779 unsigned NestedLoopCount =
10780 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10781 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10782 VarsWithImplicitDSA, B);
10783 if (NestedLoopCount == 0)
10784 return StmtError();
10785
10786 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10787 return StmtError();
10788
10790 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10791 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10792}
10793
10795 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10796 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10797 if (!AStmt)
10798 return StmtError();
10799
10800 CapturedStmt *CS =
10801 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10802
10804 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10805 // define the nested loops number.
10806 unsigned NestedLoopCount =
10807 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10808 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10809 VarsWithImplicitDSA, B);
10810 if (NestedLoopCount == 0)
10811 return StmtError();
10812
10813 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10814 return StmtError();
10815
10817 return StmtError();
10818
10820 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10821}
10822
10824 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10825 SourceLocation EndLoc) {
10826 if (!AStmt)
10827 return StmtError();
10828
10829 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
10830
10832 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10833 DSAStack->getTaskgroupReductionRef());
10834}
10835
10837 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10838 SourceLocation EndLoc) {
10839 if (!AStmt)
10840 return StmtError();
10841
10842 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
10843
10845 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10846 DSAStack->getTaskgroupReductionRef());
10847}
10848
10850 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10851 SourceLocation EndLoc) {
10852 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
10853 return StmtError();
10854
10856
10858 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10859 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10860}
10861
10862/// Find and diagnose mutually exclusive clause kinds.
10864 Sema &S, ArrayRef<OMPClause *> Clauses,
10865 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
10866 const OMPClause *PrevClause = nullptr;
10867 bool ErrorFound = false;
10868 for (const OMPClause *C : Clauses) {
10869 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
10870 if (!PrevClause) {
10871 PrevClause = C;
10872 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
10873 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10874 << getOpenMPClauseName(C->getClauseKind())
10875 << getOpenMPClauseName(PrevClause->getClauseKind());
10876 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
10877 << getOpenMPClauseName(PrevClause->getClauseKind());
10878 ErrorFound = true;
10879 }
10880 }
10881 }
10882 return ErrorFound;
10883}
10884
10886 Stmt *AStmt,
10887 SourceLocation StartLoc,
10888 SourceLocation EndLoc) {
10889 if (!AStmt)
10890 return StmtError();
10891
10892 // OpenMP 5.0, 2.10.1 task Construct
10893 // If a detach clause appears on the directive, then a mergeable clause cannot
10894 // appear on the same directive.
10896 {OMPC_detach, OMPC_mergeable}))
10897 return StmtError();
10898
10899 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
10900
10901 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10902 AStmt, DSAStack->isCancelRegion());
10903}
10904
10906 SourceLocation EndLoc) {
10907 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
10908}
10909
10911 SourceLocation EndLoc) {
10912 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
10913}
10914
10916 SourceLocation StartLoc,
10917 SourceLocation EndLoc,
10918 bool InExContext) {
10919 const OMPAtClause *AtC =
10920 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
10921
10922 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
10923 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
10924 return StmtError();
10925 }
10926
10927 const OMPSeverityClause *SeverityC =
10928 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
10929 const OMPMessageClause *MessageC =
10930 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
10931 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
10932
10933 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
10934 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
10935 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
10936 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
10937 else
10938 Diag(StartLoc, diag::err_diagnose_if_succeeded)
10939 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
10940 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
10941 return StmtError();
10942 }
10943 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
10944}
10945
10948 SourceLocation StartLoc,
10949 SourceLocation EndLoc) {
10950 const OMPNowaitClause *NowaitC =
10951 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
10952 bool HasDependC =
10953 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
10954 .empty();
10955 if (NowaitC && !HasDependC) {
10956 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
10957 return StmtError();
10958 }
10959
10960 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
10961 Clauses);
10962}
10963
10966 Stmt *AStmt, SourceLocation StartLoc,
10967 SourceLocation EndLoc) {
10968 if (!AStmt)
10969 return StmtError();
10970
10971 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10972
10974
10975 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
10976 Clauses, AStmt,
10977 DSAStack->getTaskgroupReductionRef());
10978}
10979
10981 SourceLocation StartLoc,
10982 SourceLocation EndLoc) {
10983 OMPFlushClause *FC = nullptr;
10984 OMPClause *OrderClause = nullptr;
10985 for (OMPClause *C : Clauses) {
10986 if (C->getClauseKind() == OMPC_flush)
10987 FC = cast<OMPFlushClause>(C);
10988 else
10989 OrderClause = C;
10990 }
10991 OpenMPClauseKind MemOrderKind = OMPC_unknown;
10992 SourceLocation MemOrderLoc;
10993 for (const OMPClause *C : Clauses) {
10994 if (C->getClauseKind() == OMPC_acq_rel ||
10995 C->getClauseKind() == OMPC_acquire ||
10996 C->getClauseKind() == OMPC_release) {
10997 if (MemOrderKind != OMPC_unknown) {
10998 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
10999 << getOpenMPDirectiveName(OMPD_flush) << 1
11000 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11001 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11002 << getOpenMPClauseName(MemOrderKind);
11003 } else {
11004 MemOrderKind = C->getClauseKind();
11005 MemOrderLoc = C->getBeginLoc();
11006 }
11007 }
11008 }
11009 if (FC && OrderClause) {
11010 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11011 << getOpenMPClauseName(OrderClause->getClauseKind());
11012 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11013 << getOpenMPClauseName(OrderClause->getClauseKind());
11014 return StmtError();
11015 }
11016 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11017}
11018
11020 SourceLocation StartLoc,
11021 SourceLocation EndLoc) {
11022 if (Clauses.empty()) {
11023 Diag(StartLoc, diag::err_omp_depobj_expected);
11024 return StmtError();
11025 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11026 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11027 return StmtError();
11028 }
11029 // Only depobj expression and another single clause is allowed.
11030 if (Clauses.size() > 2) {
11031 Diag(Clauses[2]->getBeginLoc(),
11032 diag::err_omp_depobj_single_clause_expected);
11033 return StmtError();
11034 } else if (Clauses.size() < 1) {
11035 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11036 return StmtError();
11037 }
11038 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11039}
11040
11042 SourceLocation StartLoc,
11043 SourceLocation EndLoc) {
11044 // Check that exactly one clause is specified.
11045 if (Clauses.size() != 1) {
11046 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11047 diag::err_omp_scan_single_clause_expected);
11048 return StmtError();
11049 }
11050 // Check that scan directive is used in the scope of the OpenMP loop body.
11051 if (Scope *S = DSAStack->getCurScope()) {
11052 Scope *ParentS = S->getParent();
11053 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11054 !ParentS->getBreakParent()->isOpenMPLoopScope())
11055 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11056 << getOpenMPDirectiveName(OMPD_scan) << 5);
11057 }
11058 // Check that only one instance of scan directives is used in the same outer
11059 // region.
11060 if (DSAStack->doesParentHasScanDirective()) {
11061 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11062 Diag(DSAStack->getParentScanDirectiveLoc(),
11063 diag::note_omp_previous_directive)
11064 << "scan";
11065 return StmtError();
11066 }
11067 DSAStack->setParentHasScanDirective(StartLoc);
11068 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11069}
11070
11073 Stmt *AStmt, SourceLocation StartLoc,
11074 SourceLocation EndLoc) {
11075 const OMPClause *DependFound = nullptr;
11076 const OMPClause *DependSourceClause = nullptr;
11077 const OMPClause *DependSinkClause = nullptr;
11078 const OMPClause *DoacrossFound = nullptr;
11079 const OMPClause *DoacrossSourceClause = nullptr;
11080 const OMPClause *DoacrossSinkClause = nullptr;
11081 bool ErrorFound = false;
11082 const OMPThreadsClause *TC = nullptr;
11083 const OMPSIMDClause *SC = nullptr;
11084 for (const OMPClause *C : Clauses) {
11085 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11086 auto DC = dyn_cast<OMPDependClause>(C);
11087 if (DC || DOC) {
11088 DependFound = DC ? C : nullptr;
11089 DoacrossFound = DOC ? C : nullptr;
11090 OMPDoacrossKind ODK;
11091 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11092 (DOC && (ODK.isSource(DOC)))) {
11093 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11094 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11095 << getOpenMPDirectiveName(OMPD_ordered)
11096 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11097 ErrorFound = true;
11098 } else {
11099 if (DC)
11100 DependSourceClause = C;
11101 else
11102 DoacrossSourceClause = C;
11103 }
11104 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11105 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11106 << (DC ? "depend" : "doacross") << 0;
11107 ErrorFound = true;
11108 }
11109 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11110 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11111 if (DependSourceClause || DoacrossSourceClause) {
11112 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11113 << (DC ? "depend" : "doacross") << 1;
11114 ErrorFound = true;
11115 }
11116 if (DC)
11117 DependSinkClause = C;
11118 else
11119 DoacrossSinkClause = C;
11120 }
11121 } else if (C->getClauseKind() == OMPC_threads) {
11122 TC = cast<OMPThreadsClause>(C);
11123 } else if (C->getClauseKind() == OMPC_simd) {
11124 SC = cast<OMPSIMDClause>(C);
11125 }
11126 }
11127 if (!ErrorFound && !SC &&
11128 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11129 // OpenMP [2.8.1,simd Construct, Restrictions]
11130 // An ordered construct with the simd clause is the only OpenMP construct
11131 // that can appear in the simd region.
11132 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11133 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11134 ErrorFound = true;
11135 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11137 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11138 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11139 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11140 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11141 ErrorFound = true;
11142 } else if ((DependFound || DoacrossFound) &&
11143 !DSAStack->getParentOrderedRegionParam().first) {
11145 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11146 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11147 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11148 ErrorFound = true;
11149 } else if (TC || Clauses.empty()) {
11150 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11151 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11152 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11153 << (TC != nullptr);
11154 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11155 ErrorFound = true;
11156 }
11157 }
11158 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11159 return StmtError();
11160
11161 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11162 // During execution of an iteration of a worksharing-loop or a loop nest
11163 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11164 // must not execute more than one ordered region corresponding to an ordered
11165 // construct without a depend clause.
11166 if (!DependFound && !DoacrossFound) {
11167 if (DSAStack->doesParentHasOrderedDirective()) {
11168 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11169 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11170 diag::note_omp_previous_directive)
11171 << "ordered";
11172 return StmtError();
11173 }
11174 DSAStack->setParentHasOrderedDirective(StartLoc);
11175 }
11176
11177 if (AStmt) {
11178 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11179
11181 }
11182
11183 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11184 AStmt);
11185}
11186
11187namespace {
11188/// Helper class for checking expression in 'omp atomic [update]'
11189/// construct.
11190class OpenMPAtomicUpdateChecker {
11191 /// Error results for atomic update expressions.
11192 enum ExprAnalysisErrorCode {
11193 /// A statement is not an expression statement.
11194 NotAnExpression,
11195 /// Expression is not builtin binary or unary operation.
11196 NotABinaryOrUnaryExpression,
11197 /// Unary operation is not post-/pre- increment/decrement operation.
11198 NotAnUnaryIncDecExpression,
11199 /// An expression is not of scalar type.
11200 NotAScalarType,
11201 /// A binary operation is not an assignment operation.
11202 NotAnAssignmentOp,
11203 /// RHS part of the binary operation is not a binary expression.
11204 NotABinaryExpression,
11205 /// RHS part is not additive/multiplicative/shift/bitwise binary
11206 /// expression.
11207 NotABinaryOperator,
11208 /// RHS binary operation does not have reference to the updated LHS
11209 /// part.
11210 NotAnUpdateExpression,
11211 /// An expression contains semantical error not related to
11212 /// 'omp atomic [update]'
11213 NotAValidExpression,
11214 /// No errors is found.
11215 NoError
11216 };
11217 /// Reference to Sema.
11218 Sema &SemaRef;
11219 /// A location for note diagnostics (when error is found).
11220 SourceLocation NoteLoc;
11221 /// 'x' lvalue part of the source atomic expression.
11222 Expr *X;
11223 /// 'expr' rvalue part of the source atomic expression.
11224 Expr *E;
11225 /// Helper expression of the form
11226 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11227 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11228 Expr *UpdateExpr;
11229 /// Is 'x' a LHS in a RHS part of full update expression. It is
11230 /// important for non-associative operations.
11231 bool IsXLHSInRHSPart;
11233 SourceLocation OpLoc;
11234 /// true if the source expression is a postfix unary operation, false
11235 /// if it is a prefix unary operation.
11236 bool IsPostfixUpdate;
11237
11238public:
11239 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11240 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11241 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11242 /// Check specified statement that it is suitable for 'atomic update'
11243 /// constructs and extract 'x', 'expr' and Operation from the original
11244 /// expression. If DiagId and NoteId == 0, then only check is performed
11245 /// without error notification.
11246 /// \param DiagId Diagnostic which should be emitted if error is found.
11247 /// \param NoteId Diagnostic note for the main error message.
11248 /// \return true if statement is not an update expression, false otherwise.
11249 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11250 /// Return the 'x' lvalue part of the source atomic expression.
11251 Expr *getX() const { return X; }
11252 /// Return the 'expr' rvalue part of the source atomic expression.
11253 Expr *getExpr() const { return E; }
11254 /// Return the update expression used in calculation of the updated
11255 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11256 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11257 Expr *getUpdateExpr() const { return UpdateExpr; }
11258 /// Return true if 'x' is LHS in RHS part of full update expression,
11259 /// false otherwise.
11260 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11261
11262 /// true if the source expression is a postfix unary operation, false
11263 /// if it is a prefix unary operation.
11264 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11265
11266private:
11267 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11268 unsigned NoteId = 0);
11269};
11270
11271bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11272 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11273 ExprAnalysisErrorCode ErrorFound = NoError;
11274 SourceLocation ErrorLoc, NoteLoc;
11275 SourceRange ErrorRange, NoteRange;
11276 // Allowed constructs are:
11277 // x = x binop expr;
11278 // x = expr binop x;
11279 if (AtomicBinOp->getOpcode() == BO_Assign) {
11280 X = AtomicBinOp->getLHS();
11281 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11282 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11283 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11284 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11285 AtomicInnerBinOp->isBitwiseOp()) {
11286 Op = AtomicInnerBinOp->getOpcode();
11287 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11288 Expr *LHS = AtomicInnerBinOp->getLHS();
11289 Expr *RHS = AtomicInnerBinOp->getRHS();
11290 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11291 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11292 /*Canonical=*/true);
11293 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11294 /*Canonical=*/true);
11295 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11296 /*Canonical=*/true);
11297 if (XId == LHSId) {
11298 E = RHS;
11299 IsXLHSInRHSPart = true;
11300 } else if (XId == RHSId) {
11301 E = LHS;
11302 IsXLHSInRHSPart = false;
11303 } else {
11304 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11305 ErrorRange = AtomicInnerBinOp->getSourceRange();
11306 NoteLoc = X->getExprLoc();
11307 NoteRange = X->getSourceRange();
11308 ErrorFound = NotAnUpdateExpression;
11309 }
11310 } else {
11311 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11312 ErrorRange = AtomicInnerBinOp->getSourceRange();
11313 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11314 NoteRange = SourceRange(NoteLoc, NoteLoc);
11315 ErrorFound = NotABinaryOperator;
11316 }
11317 } else {
11318 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11319 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11320 ErrorFound = NotABinaryExpression;
11321 }
11322 } else {
11323 ErrorLoc = AtomicBinOp->getExprLoc();
11324 ErrorRange = AtomicBinOp->getSourceRange();
11325 NoteLoc = AtomicBinOp->getOperatorLoc();
11326 NoteRange = SourceRange(NoteLoc, NoteLoc);
11327 ErrorFound = NotAnAssignmentOp;
11328 }
11329 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11330 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11331 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11332 return true;
11333 }
11334 if (SemaRef.CurContext->isDependentContext())
11335 E = X = UpdateExpr = nullptr;
11336 return ErrorFound != NoError;
11337}
11338
11339bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11340 unsigned NoteId) {
11341 ExprAnalysisErrorCode ErrorFound = NoError;
11342 SourceLocation ErrorLoc, NoteLoc;
11343 SourceRange ErrorRange, NoteRange;
11344 // Allowed constructs are:
11345 // x++;
11346 // x--;
11347 // ++x;
11348 // --x;
11349 // x binop= expr;
11350 // x = x binop expr;
11351 // x = expr binop x;
11352 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11353 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11354 if (AtomicBody->getType()->isScalarType() ||
11355 AtomicBody->isInstantiationDependent()) {
11356 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11357 AtomicBody->IgnoreParenImpCasts())) {
11358 // Check for Compound Assignment Operation
11360 AtomicCompAssignOp->getOpcode());
11361 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11362 E = AtomicCompAssignOp->getRHS();
11363 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11364 IsXLHSInRHSPart = true;
11365 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11366 AtomicBody->IgnoreParenImpCasts())) {
11367 // Check for Binary Operation
11368 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11369 return true;
11370 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11371 AtomicBody->IgnoreParenImpCasts())) {
11372 // Check for Unary Operation
11373 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11374 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11375 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11376 OpLoc = AtomicUnaryOp->getOperatorLoc();
11377 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11378 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11379 IsXLHSInRHSPart = true;
11380 } else {
11381 ErrorFound = NotAnUnaryIncDecExpression;
11382 ErrorLoc = AtomicUnaryOp->getExprLoc();
11383 ErrorRange = AtomicUnaryOp->getSourceRange();
11384 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11385 NoteRange = SourceRange(NoteLoc, NoteLoc);
11386 }
11387 } else if (!AtomicBody->isInstantiationDependent()) {
11388 ErrorFound = NotABinaryOrUnaryExpression;
11389 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11390 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11391 } else if (AtomicBody->containsErrors()) {
11392 ErrorFound = NotAValidExpression;
11393 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11394 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11395 }
11396 } else {
11397 ErrorFound = NotAScalarType;
11398 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11399 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11400 }
11401 } else {
11402 ErrorFound = NotAnExpression;
11403 NoteLoc = ErrorLoc = S->getBeginLoc();
11404 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11405 }
11406 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11407 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11408 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11409 return true;
11410 }
11411 if (SemaRef.CurContext->isDependentContext())
11412 E = X = UpdateExpr = nullptr;
11413 if (ErrorFound == NoError && E && X) {
11414 // Build an update expression of form 'OpaqueValueExpr(x) binop
11415 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11416 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11417 auto *OVEX = new (SemaRef.getASTContext())
11418 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11419 auto *OVEExpr = new (SemaRef.getASTContext())
11422 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11423 IsXLHSInRHSPart ? OVEExpr : OVEX);
11424 if (Update.isInvalid())
11425 return true;
11426 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11428 if (Update.isInvalid())
11429 return true;
11430 UpdateExpr = Update.get();
11431 }
11432 return ErrorFound != NoError;
11433}
11434
11435/// Get the node id of the fixed point of an expression \a S.
11436llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11437 llvm::FoldingSetNodeID Id;
11438 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11439 return Id;
11440}
11441
11442/// Check if two expressions are same.
11443bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11444 const Expr *RHS) {
11445 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11446}
11447
11448class OpenMPAtomicCompareChecker {
11449public:
11450 /// All kinds of errors that can occur in `atomic compare`
11451 enum ErrorTy {
11452 /// Empty compound statement.
11453 NoStmt = 0,
11454 /// More than one statement in a compound statement.
11455 MoreThanOneStmt,
11456 /// Not an assignment binary operator.
11457 NotAnAssignment,
11458 /// Not a conditional operator.
11459 NotCondOp,
11460 /// Wrong false expr. According to the spec, 'x' should be at the false
11461 /// expression of a conditional expression.
11462 WrongFalseExpr,
11463 /// The condition of a conditional expression is not a binary operator.
11464 NotABinaryOp,
11465 /// Invalid binary operator (not <, >, or ==).
11466 InvalidBinaryOp,
11467 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11468 InvalidComparison,
11469 /// X is not a lvalue.
11470 XNotLValue,
11471 /// Not a scalar.
11472 NotScalar,
11473 /// Not an integer.
11474 NotInteger,
11475 /// 'else' statement is not expected.
11476 UnexpectedElse,
11477 /// Not an equality operator.
11478 NotEQ,
11479 /// Invalid assignment (not v == x).
11480 InvalidAssignment,
11481 /// Not if statement
11482 NotIfStmt,
11483 /// More than two statements in a compound statement.
11484 MoreThanTwoStmts,
11485 /// Not a compound statement.
11486 NotCompoundStmt,
11487 /// No else statement.
11488 NoElse,
11489 /// Not 'if (r)'.
11490 InvalidCondition,
11491 /// No error.
11492 NoError,
11493 };
11494
11495 struct ErrorInfoTy {
11496 ErrorTy Error;
11497 SourceLocation ErrorLoc;
11498 SourceRange ErrorRange;
11499 SourceLocation NoteLoc;
11500 SourceRange NoteRange;
11501 };
11502
11503 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11504
11505 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11506 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11507
11508 Expr *getX() const { return X; }
11509 Expr *getE() const { return E; }
11510 Expr *getD() const { return D; }
11511 Expr *getCond() const { return C; }
11512 bool isXBinopExpr() const { return IsXBinopExpr; }
11513
11514protected:
11515 /// Reference to ASTContext
11516 ASTContext &ContextRef;
11517 /// 'x' lvalue part of the source atomic expression.
11518 Expr *X = nullptr;
11519 /// 'expr' or 'e' rvalue part of the source atomic expression.
11520 Expr *E = nullptr;
11521 /// 'd' rvalue part of the source atomic expression.
11522 Expr *D = nullptr;
11523 /// 'cond' part of the source atomic expression. It is in one of the following
11524 /// forms:
11525 /// expr ordop x
11526 /// x ordop expr
11527 /// x == e
11528 /// e == x
11529 Expr *C = nullptr;
11530 /// True if the cond expr is in the form of 'x ordop expr'.
11531 bool IsXBinopExpr = true;
11532
11533 /// Check if it is a valid conditional update statement (cond-update-stmt).
11534 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11535
11536 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11537 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11538
11539 /// Check if all captured values have right type.
11540 bool checkType(ErrorInfoTy &ErrorInfo) const;
11541
11542 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11543 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11545 return true;
11546
11547 if (ShouldBeLValue && !E->isLValue()) {
11548 ErrorInfo.Error = ErrorTy::XNotLValue;
11549 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11550 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11551 return false;
11552 }
11553
11554 QualType QTy = E->getType();
11555 if (!QTy->isScalarType()) {
11556 ErrorInfo.Error = ErrorTy::NotScalar;
11557 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11558 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11559 return false;
11560 }
11561 if (ShouldBeInteger && !QTy->isIntegerType()) {
11562 ErrorInfo.Error = ErrorTy::NotInteger;
11563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11565 return false;
11566 }
11567
11568 return true;
11569 }
11570};
11571
11572bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11573 ErrorInfoTy &ErrorInfo) {
11574 auto *Then = S->getThen();
11575 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11576 if (CS->body_empty()) {
11577 ErrorInfo.Error = ErrorTy::NoStmt;
11578 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11579 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11580 return false;
11581 }
11582 if (CS->size() > 1) {
11583 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11584 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11585 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11586 return false;
11587 }
11588 Then = CS->body_front();
11589 }
11590
11591 auto *BO = dyn_cast<BinaryOperator>(Then);
11592 if (!BO) {
11593 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11594 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11595 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11596 return false;
11597 }
11598 if (BO->getOpcode() != BO_Assign) {
11599 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11600 ErrorInfo.ErrorLoc = BO->getExprLoc();
11601 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11602 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11603 return false;
11604 }
11605
11606 X = BO->getLHS();
11607
11608 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11609 if (!Cond) {
11610 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11611 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11612 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11613 return false;
11614 }
11615
11616 switch (Cond->getOpcode()) {
11617 case BO_EQ: {
11618 C = Cond;
11619 D = BO->getRHS();
11620 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11621 E = Cond->getRHS();
11622 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11623 E = Cond->getLHS();
11624 } else {
11625 ErrorInfo.Error = ErrorTy::InvalidComparison;
11626 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11627 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11628 return false;
11629 }
11630 break;
11631 }
11632 case BO_LT:
11633 case BO_GT: {
11634 E = BO->getRHS();
11635 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11636 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11637 C = Cond;
11638 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11639 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11640 C = Cond;
11641 IsXBinopExpr = false;
11642 } else {
11643 ErrorInfo.Error = ErrorTy::InvalidComparison;
11644 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11645 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11646 return false;
11647 }
11648 break;
11649 }
11650 default:
11651 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11652 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11653 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11654 return false;
11655 }
11656
11657 if (S->getElse()) {
11658 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11659 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11660 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11661 return false;
11662 }
11663
11664 return true;
11665}
11666
11667bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11668 ErrorInfoTy &ErrorInfo) {
11669 auto *BO = dyn_cast<BinaryOperator>(S);
11670 if (!BO) {
11671 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11672 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11673 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11674 return false;
11675 }
11676 if (BO->getOpcode() != BO_Assign) {
11677 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11678 ErrorInfo.ErrorLoc = BO->getExprLoc();
11679 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11680 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11681 return false;
11682 }
11683
11684 X = BO->getLHS();
11685
11686 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11687 if (!CO) {
11688 ErrorInfo.Error = ErrorTy::NotCondOp;
11689 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11690 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11691 return false;
11692 }
11693
11694 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11695 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11696 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11697 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11698 CO->getFalseExpr()->getSourceRange();
11699 return false;
11700 }
11701
11702 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11703 if (!Cond) {
11704 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11705 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11706 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11707 CO->getCond()->getSourceRange();
11708 return false;
11709 }
11710
11711 switch (Cond->getOpcode()) {
11712 case BO_EQ: {
11713 C = Cond;
11714 D = CO->getTrueExpr();
11715 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11716 E = Cond->getRHS();
11717 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11718 E = Cond->getLHS();
11719 } else {
11720 ErrorInfo.Error = ErrorTy::InvalidComparison;
11721 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11722 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11723 return false;
11724 }
11725 break;
11726 }
11727 case BO_LT:
11728 case BO_GT: {
11729 E = CO->getTrueExpr();
11730 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11731 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11732 C = Cond;
11733 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11734 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11735 C = Cond;
11736 IsXBinopExpr = false;
11737 } else {
11738 ErrorInfo.Error = ErrorTy::InvalidComparison;
11739 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11740 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11741 return false;
11742 }
11743 break;
11744 }
11745 default:
11746 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11747 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11748 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11749 return false;
11750 }
11751
11752 return true;
11753}
11754
11755bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11756 // 'x' and 'e' cannot be nullptr
11757 assert(X && E && "X and E cannot be nullptr");
11758
11759 if (!CheckValue(X, ErrorInfo, true))
11760 return false;
11761
11762 if (!CheckValue(E, ErrorInfo, false))
11763 return false;
11764
11765 if (D && !CheckValue(D, ErrorInfo, false))
11766 return false;
11767
11768 return true;
11769}
11770
11771bool OpenMPAtomicCompareChecker::checkStmt(
11772 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11773 auto *CS = dyn_cast<CompoundStmt>(S);
11774 if (CS) {
11775 if (CS->body_empty()) {
11776 ErrorInfo.Error = ErrorTy::NoStmt;
11777 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11778 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11779 return false;
11780 }
11781
11782 if (CS->size() != 1) {
11783 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11784 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11785 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11786 return false;
11787 }
11788 S = CS->body_front();
11789 }
11790
11791 auto Res = false;
11792
11793 if (auto *IS = dyn_cast<IfStmt>(S)) {
11794 // Check if the statement is in one of the following forms
11795 // (cond-update-stmt):
11796 // if (expr ordop x) { x = expr; }
11797 // if (x ordop expr) { x = expr; }
11798 // if (x == e) { x = d; }
11799 Res = checkCondUpdateStmt(IS, ErrorInfo);
11800 } else {
11801 // Check if the statement is in one of the following forms (cond-expr-stmt):
11802 // x = expr ordop x ? expr : x;
11803 // x = x ordop expr ? expr : x;
11804 // x = x == e ? d : x;
11805 Res = checkCondExprStmt(S, ErrorInfo);
11806 }
11807
11808 if (!Res)
11809 return false;
11810
11811 return checkType(ErrorInfo);
11812}
11813
11814class OpenMPAtomicCompareCaptureChecker final
11815 : public OpenMPAtomicCompareChecker {
11816public:
11817 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11818
11819 Expr *getV() const { return V; }
11820 Expr *getR() const { return R; }
11821 bool isFailOnly() const { return IsFailOnly; }
11822 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11823
11824 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11825 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11826
11827private:
11828 bool checkType(ErrorInfoTy &ErrorInfo);
11829
11830 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11831 // form of 'conditional-update-capture-atomic' structured block on the v5.2
11832 // spec p.p. 82:
11833 // (1) { v = x; cond-update-stmt }
11834 // (2) { cond-update-stmt v = x; }
11835 // (3) if(x == e) { x = d; } else { v = x; }
11836 // (4) { r = x == e; if(r) { x = d; } }
11837 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11838
11839 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11840 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11841
11842 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11843 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11844 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
11845
11846 /// 'v' lvalue part of the source atomic expression.
11847 Expr *V = nullptr;
11848 /// 'r' lvalue part of the source atomic expression.
11849 Expr *R = nullptr;
11850 /// If 'v' is only updated when the comparison fails.
11851 bool IsFailOnly = false;
11852 /// If original value of 'x' must be stored in 'v', not an updated one.
11853 bool IsPostfixUpdate = false;
11854};
11855
11856bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11857 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11858 return false;
11859
11860 if (V && !CheckValue(V, ErrorInfo, true))
11861 return false;
11862
11863 if (R && !CheckValue(R, ErrorInfo, true, true))
11864 return false;
11865
11866 return true;
11867}
11868
11869bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
11870 ErrorInfoTy &ErrorInfo) {
11871 IsFailOnly = true;
11872
11873 auto *Then = S->getThen();
11874 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11875 if (CS->body_empty()) {
11876 ErrorInfo.Error = ErrorTy::NoStmt;
11877 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11878 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11879 return false;
11880 }
11881 if (CS->size() > 1) {
11882 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11883 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11884 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11885 return false;
11886 }
11887 Then = CS->body_front();
11888 }
11889
11890 auto *BO = dyn_cast<BinaryOperator>(Then);
11891 if (!BO) {
11892 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11893 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11894 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11895 return false;
11896 }
11897 if (BO->getOpcode() != BO_Assign) {
11898 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11899 ErrorInfo.ErrorLoc = BO->getExprLoc();
11900 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11901 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11902 return false;
11903 }
11904
11905 X = BO->getLHS();
11906 D = BO->getRHS();
11907
11908 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11909 if (!Cond) {
11910 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11911 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11912 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11913 return false;
11914 }
11915 if (Cond->getOpcode() != BO_EQ) {
11916 ErrorInfo.Error = ErrorTy::NotEQ;
11917 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11918 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11919 return false;
11920 }
11921
11922 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11923 E = Cond->getRHS();
11924 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11925 E = Cond->getLHS();
11926 } else {
11927 ErrorInfo.Error = ErrorTy::InvalidComparison;
11928 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11929 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11930 return false;
11931 }
11932
11933 C = Cond;
11934
11935 if (!S->getElse()) {
11936 ErrorInfo.Error = ErrorTy::NoElse;
11937 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11938 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11939 return false;
11940 }
11941
11942 auto *Else = S->getElse();
11943 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
11944 if (CS->body_empty()) {
11945 ErrorInfo.Error = ErrorTy::NoStmt;
11946 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11947 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11948 return false;
11949 }
11950 if (CS->size() > 1) {
11951 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11952 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11953 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11954 return false;
11955 }
11956 Else = CS->body_front();
11957 }
11958
11959 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
11960 if (!ElseBO) {
11961 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11962 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
11963 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
11964 return false;
11965 }
11966 if (ElseBO->getOpcode() != BO_Assign) {
11967 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11968 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
11969 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
11970 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
11971 return false;
11972 }
11973
11974 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
11975 ErrorInfo.Error = ErrorTy::InvalidAssignment;
11976 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
11977 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11978 ElseBO->getRHS()->getSourceRange();
11979 return false;
11980 }
11981
11982 V = ElseBO->getLHS();
11983
11984 return checkType(ErrorInfo);
11985}
11986
11987bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
11988 ErrorInfoTy &ErrorInfo) {
11989 // We don't check here as they should be already done before call this
11990 // function.
11991 auto *CS = cast<CompoundStmt>(S);
11992 assert(CS->size() == 2 && "CompoundStmt size is not expected");
11993 auto *S1 = cast<BinaryOperator>(CS->body_front());
11994 auto *S2 = cast<IfStmt>(CS->body_back());
11995 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
11996
11997 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
11998 ErrorInfo.Error = ErrorTy::InvalidCondition;
11999 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12000 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12001 return false;
12002 }
12003
12004 R = S1->getLHS();
12005
12006 auto *Then = S2->getThen();
12007 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12008 if (ThenCS->body_empty()) {
12009 ErrorInfo.Error = ErrorTy::NoStmt;
12010 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12011 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12012 return false;
12013 }
12014 if (ThenCS->size() > 1) {
12015 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12016 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12017 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12018 return false;
12019 }
12020 Then = ThenCS->body_front();
12021 }
12022
12023 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12024 if (!ThenBO) {
12025 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12026 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12027 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12028 return false;
12029 }
12030 if (ThenBO->getOpcode() != BO_Assign) {
12031 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12032 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12033 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12034 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12035 return false;
12036 }
12037
12038 X = ThenBO->getLHS();
12039 D = ThenBO->getRHS();
12040
12041 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12042 if (BO->getOpcode() != BO_EQ) {
12043 ErrorInfo.Error = ErrorTy::NotEQ;
12044 ErrorInfo.ErrorLoc = BO->getExprLoc();
12045 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12046 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12047 return false;
12048 }
12049
12050 C = BO;
12051
12052 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12053 E = BO->getRHS();
12054 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12055 E = BO->getLHS();
12056 } else {
12057 ErrorInfo.Error = ErrorTy::InvalidComparison;
12058 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12059 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12060 return false;
12061 }
12062
12063 if (S2->getElse()) {
12064 IsFailOnly = true;
12065
12066 auto *Else = S2->getElse();
12067 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12068 if (ElseCS->body_empty()) {
12069 ErrorInfo.Error = ErrorTy::NoStmt;
12070 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12071 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12072 return false;
12073 }
12074 if (ElseCS->size() > 1) {
12075 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12078 return false;
12079 }
12080 Else = ElseCS->body_front();
12081 }
12082
12083 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12084 if (!ElseBO) {
12085 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12086 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12087 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12088 return false;
12089 }
12090 if (ElseBO->getOpcode() != BO_Assign) {
12091 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12092 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12093 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12094 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12095 return false;
12096 }
12097 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12098 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12099 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12100 ErrorInfo.NoteLoc = X->getExprLoc();
12101 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12102 ErrorInfo.NoteRange = X->getSourceRange();
12103 return false;
12104 }
12105
12106 V = ElseBO->getLHS();
12107 }
12108
12109 return checkType(ErrorInfo);
12110}
12111
12112bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12113 ErrorInfoTy &ErrorInfo) {
12114 // if(x == e) { x = d; } else { v = x; }
12115 if (auto *IS = dyn_cast<IfStmt>(S))
12116 return checkForm3(IS, ErrorInfo);
12117
12118 auto *CS = dyn_cast<CompoundStmt>(S);
12119 if (!CS) {
12120 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12121 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12122 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12123 return false;
12124 }
12125 if (CS->body_empty()) {
12126 ErrorInfo.Error = ErrorTy::NoStmt;
12127 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12128 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12129 return false;
12130 }
12131
12132 // { if(x == e) { x = d; } else { v = x; } }
12133 if (CS->size() == 1) {
12134 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12135 if (!IS) {
12136 ErrorInfo.Error = ErrorTy::NotIfStmt;
12137 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12138 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12139 CS->body_front()->getSourceRange();
12140 return false;
12141 }
12142
12143 return checkForm3(IS, ErrorInfo);
12144 } else if (CS->size() == 2) {
12145 auto *S1 = CS->body_front();
12146 auto *S2 = CS->body_back();
12147
12148 Stmt *UpdateStmt = nullptr;
12149 Stmt *CondUpdateStmt = nullptr;
12150 Stmt *CondExprStmt = nullptr;
12151
12152 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12153 // It could be one of the following cases:
12154 // { v = x; cond-update-stmt }
12155 // { v = x; cond-expr-stmt }
12156 // { cond-expr-stmt; v = x; }
12157 // form 45
12158 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12159 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12160 // check if form 45
12161 if (isa<IfStmt>(S2))
12162 return checkForm45(CS, ErrorInfo);
12163 // { cond-expr-stmt; v = x; }
12164 CondExprStmt = S1;
12165 UpdateStmt = S2;
12166 } else {
12167 IsPostfixUpdate = true;
12168 UpdateStmt = S1;
12169 if (isa<IfStmt>(S2)) {
12170 // { v = x; cond-update-stmt }
12171 CondUpdateStmt = S2;
12172 } else {
12173 // { v = x; cond-expr-stmt }
12174 CondExprStmt = S2;
12175 }
12176 }
12177 } else {
12178 // { cond-update-stmt v = x; }
12179 UpdateStmt = S2;
12180 CondUpdateStmt = S1;
12181 }
12182
12183 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12184 auto *IS = dyn_cast<IfStmt>(CUS);
12185 if (!IS) {
12186 ErrorInfo.Error = ErrorTy::NotIfStmt;
12187 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12188 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12189 return false;
12190 }
12191
12192 return checkCondUpdateStmt(IS, ErrorInfo);
12193 };
12194
12195 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12196 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12197 auto *BO = dyn_cast<BinaryOperator>(US);
12198 if (!BO) {
12199 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12200 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12201 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12202 return false;
12203 }
12204 if (BO->getOpcode() != BO_Assign) {
12205 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12206 ErrorInfo.ErrorLoc = BO->getExprLoc();
12207 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12208 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12209 return false;
12210 }
12211 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12212 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12213 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12214 ErrorInfo.NoteLoc = this->X->getExprLoc();
12215 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12216 ErrorInfo.NoteRange = this->X->getSourceRange();
12217 return false;
12218 }
12219
12220 this->V = BO->getLHS();
12221
12222 return true;
12223 };
12224
12225 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12226 return false;
12227 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12228 return false;
12229 if (!CheckUpdateStmt(UpdateStmt))
12230 return false;
12231 } else {
12232 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12233 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12234 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12235 return false;
12236 }
12237
12238 return checkType(ErrorInfo);
12239}
12240} // namespace
12241
12243 Stmt *AStmt,
12244 SourceLocation StartLoc,
12245 SourceLocation EndLoc) {
12246 ASTContext &Context = getASTContext();
12247 // Register location of the first atomic directive.
12248 DSAStack->addAtomicDirectiveLoc(StartLoc);
12249 if (!AStmt)
12250 return StmtError();
12251
12252 // 1.2.2 OpenMP Language Terminology
12253 // Structured block - An executable statement with a single entry at the
12254 // top and a single exit at the bottom.
12255 // The point of exit cannot be a branch out of the structured block.
12256 // longjmp() and throw() must not violate the entry/exit criteria.
12257 OpenMPClauseKind AtomicKind = OMPC_unknown;
12258 SourceLocation AtomicKindLoc;
12259 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12260 SourceLocation MemOrderLoc;
12261 bool MutexClauseEncountered = false;
12262 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12263 for (const OMPClause *C : Clauses) {
12264 switch (C->getClauseKind()) {
12265 case OMPC_read:
12266 case OMPC_write:
12267 case OMPC_update:
12268 MutexClauseEncountered = true;
12269 [[fallthrough]];
12270 case OMPC_capture:
12271 case OMPC_compare: {
12272 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12273 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12274 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12275 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12276 << getOpenMPClauseName(AtomicKind);
12277 } else {
12278 AtomicKind = C->getClauseKind();
12279 AtomicKindLoc = C->getBeginLoc();
12280 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12281 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12282 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12283 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12284 << getOpenMPClauseName(AtomicKind);
12285 }
12286 }
12287 break;
12288 }
12289 case OMPC_weak:
12290 case OMPC_fail: {
12291 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12292 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12293 << getOpenMPClauseName(C->getClauseKind())
12294 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12295 return StmtError();
12296 }
12297 break;
12298 }
12299 case OMPC_seq_cst:
12300 case OMPC_acq_rel:
12301 case OMPC_acquire:
12302 case OMPC_release:
12303 case OMPC_relaxed: {
12304 if (MemOrderKind != OMPC_unknown) {
12305 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12306 << getOpenMPDirectiveName(OMPD_atomic) << 0
12307 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12308 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12309 << getOpenMPClauseName(MemOrderKind);
12310 } else {
12311 MemOrderKind = C->getClauseKind();
12312 MemOrderLoc = C->getBeginLoc();
12313 }
12314 break;
12315 }
12316 // The following clauses are allowed, but we don't need to do anything here.
12317 case OMPC_hint:
12318 break;
12319 default:
12320 llvm_unreachable("unknown clause is encountered");
12321 }
12322 }
12323 bool IsCompareCapture = false;
12324 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12325 EncounteredAtomicKinds.contains(OMPC_capture)) {
12326 IsCompareCapture = true;
12327 AtomicKind = OMPC_compare;
12328 }
12329 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12330 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12331 // release.
12332 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12333 // acquire.
12334 // If atomic-clause is update or not present then memory-order-clause must not
12335 // be acq_rel or acquire.
12336 if ((AtomicKind == OMPC_read &&
12337 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12338 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12339 AtomicKind == OMPC_unknown) &&
12340 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12341 SourceLocation Loc = AtomicKindLoc;
12342 if (AtomicKind == OMPC_unknown)
12343 Loc = StartLoc;
12344 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12345 << getOpenMPClauseName(AtomicKind)
12346 << (AtomicKind == OMPC_unknown ? 1 : 0)
12347 << getOpenMPClauseName(MemOrderKind);
12348 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12349 << getOpenMPClauseName(MemOrderKind);
12350 }
12351
12352 Stmt *Body = AStmt;
12353 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12354 Body = EWC->getSubExpr();
12355
12356 Expr *X = nullptr;
12357 Expr *V = nullptr;
12358 Expr *E = nullptr;
12359 Expr *UE = nullptr;
12360 Expr *D = nullptr;
12361 Expr *CE = nullptr;
12362 Expr *R = nullptr;
12363 bool IsXLHSInRHSPart = false;
12364 bool IsPostfixUpdate = false;
12365 bool IsFailOnly = false;
12366 // OpenMP [2.12.6, atomic Construct]
12367 // In the next expressions:
12368 // * x and v (as applicable) are both l-value expressions with scalar type.
12369 // * During the execution of an atomic region, multiple syntactic
12370 // occurrences of x must designate the same storage location.
12371 // * Neither of v and expr (as applicable) may access the storage location
12372 // designated by x.
12373 // * Neither of x and expr (as applicable) may access the storage location
12374 // designated by v.
12375 // * expr is an expression with scalar type.
12376 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12377 // * binop, binop=, ++, and -- are not overloaded operators.
12378 // * The expression x binop expr must be numerically equivalent to x binop
12379 // (expr). This requirement is satisfied if the operators in expr have
12380 // precedence greater than binop, or by using parentheses around expr or
12381 // subexpressions of expr.
12382 // * The expression expr binop x must be numerically equivalent to (expr)
12383 // binop x. This requirement is satisfied if the operators in expr have
12384 // precedence equal to or greater than binop, or by using parentheses around
12385 // expr or subexpressions of expr.
12386 // * For forms that allow multiple occurrences of x, the number of times
12387 // that x is evaluated is unspecified.
12388 if (AtomicKind == OMPC_read) {
12389 enum {
12390 NotAnExpression,
12391 NotAnAssignmentOp,
12392 NotAScalarType,
12393 NotAnLValue,
12394 NoError
12395 } ErrorFound = NoError;
12396 SourceLocation ErrorLoc, NoteLoc;
12397 SourceRange ErrorRange, NoteRange;
12398 // If clause is read:
12399 // v = x;
12400 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12401 const auto *AtomicBinOp =
12402 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12403 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12404 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12405 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12406 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12407 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12408 if (!X->isLValue() || !V->isLValue()) {
12409 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12410 ErrorFound = NotAnLValue;
12411 ErrorLoc = AtomicBinOp->getExprLoc();
12412 ErrorRange = AtomicBinOp->getSourceRange();
12413 NoteLoc = NotLValueExpr->getExprLoc();
12414 NoteRange = NotLValueExpr->getSourceRange();
12415 }
12416 } else if (!X->isInstantiationDependent() ||
12417 !V->isInstantiationDependent()) {
12418 const Expr *NotScalarExpr =
12419 (X->isInstantiationDependent() || X->getType()->isScalarType())
12420 ? V
12421 : X;
12422 ErrorFound = NotAScalarType;
12423 ErrorLoc = AtomicBinOp->getExprLoc();
12424 ErrorRange = AtomicBinOp->getSourceRange();
12425 NoteLoc = NotScalarExpr->getExprLoc();
12426 NoteRange = NotScalarExpr->getSourceRange();
12427 }
12428 } else if (!AtomicBody->isInstantiationDependent()) {
12429 ErrorFound = NotAnAssignmentOp;
12430 ErrorLoc = AtomicBody->getExprLoc();
12431 ErrorRange = AtomicBody->getSourceRange();
12432 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12433 : AtomicBody->getExprLoc();
12434 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12435 : AtomicBody->getSourceRange();
12436 }
12437 } else {
12438 ErrorFound = NotAnExpression;
12439 NoteLoc = ErrorLoc = Body->getBeginLoc();
12440 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12441 }
12442 if (ErrorFound != NoError) {
12443 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12444 << ErrorRange;
12445 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12446 << ErrorFound << NoteRange;
12447 return StmtError();
12448 }
12450 V = X = nullptr;
12451 } else if (AtomicKind == OMPC_write) {
12452 enum {
12453 NotAnExpression,
12454 NotAnAssignmentOp,
12455 NotAScalarType,
12456 NotAnLValue,
12457 NoError
12458 } ErrorFound = NoError;
12459 SourceLocation ErrorLoc, NoteLoc;
12460 SourceRange ErrorRange, NoteRange;
12461 // If clause is write:
12462 // x = expr;
12463 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12464 const auto *AtomicBinOp =
12465 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12466 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12467 X = AtomicBinOp->getLHS();
12468 E = AtomicBinOp->getRHS();
12469 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12471 if (!X->isLValue()) {
12472 ErrorFound = NotAnLValue;
12473 ErrorLoc = AtomicBinOp->getExprLoc();
12474 ErrorRange = AtomicBinOp->getSourceRange();
12475 NoteLoc = X->getExprLoc();
12476 NoteRange = X->getSourceRange();
12477 }
12478 } else if (!X->isInstantiationDependent() ||
12480 const Expr *NotScalarExpr =
12481 (X->isInstantiationDependent() || X->getType()->isScalarType())
12482 ? E
12483 : X;
12484 ErrorFound = NotAScalarType;
12485 ErrorLoc = AtomicBinOp->getExprLoc();
12486 ErrorRange = AtomicBinOp->getSourceRange();
12487 NoteLoc = NotScalarExpr->getExprLoc();
12488 NoteRange = NotScalarExpr->getSourceRange();
12489 }
12490 } else if (!AtomicBody->isInstantiationDependent()) {
12491 ErrorFound = NotAnAssignmentOp;
12492 ErrorLoc = AtomicBody->getExprLoc();
12493 ErrorRange = AtomicBody->getSourceRange();
12494 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12495 : AtomicBody->getExprLoc();
12496 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12497 : AtomicBody->getSourceRange();
12498 }
12499 } else {
12500 ErrorFound = NotAnExpression;
12501 NoteLoc = ErrorLoc = Body->getBeginLoc();
12502 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12503 }
12504 if (ErrorFound != NoError) {
12505 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12506 << ErrorRange;
12507 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12508 << ErrorFound << NoteRange;
12509 return StmtError();
12510 }
12512 E = X = nullptr;
12513 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12514 // If clause is update:
12515 // x++;
12516 // x--;
12517 // ++x;
12518 // --x;
12519 // x binop= expr;
12520 // x = x binop expr;
12521 // x = expr binop x;
12522 OpenMPAtomicUpdateChecker Checker(SemaRef);
12523 if (Checker.checkStatement(
12524 Body,
12525 (AtomicKind == OMPC_update)
12526 ? diag::err_omp_atomic_update_not_expression_statement
12527 : diag::err_omp_atomic_not_expression_statement,
12528 diag::note_omp_atomic_update))
12529 return StmtError();
12531 E = Checker.getExpr();
12532 X = Checker.getX();
12533 UE = Checker.getUpdateExpr();
12534 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12535 }
12536 } else if (AtomicKind == OMPC_capture) {
12537 enum {
12538 NotAnAssignmentOp,
12539 NotACompoundStatement,
12540 NotTwoSubstatements,
12541 NotASpecificExpression,
12542 NoError
12543 } ErrorFound = NoError;
12544 SourceLocation ErrorLoc, NoteLoc;
12545 SourceRange ErrorRange, NoteRange;
12546 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12547 // If clause is a capture:
12548 // v = x++;
12549 // v = x--;
12550 // v = ++x;
12551 // v = --x;
12552 // v = x binop= expr;
12553 // v = x = x binop expr;
12554 // v = x = expr binop x;
12555 const auto *AtomicBinOp =
12556 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12557 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12558 V = AtomicBinOp->getLHS();
12559 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12560 OpenMPAtomicUpdateChecker Checker(SemaRef);
12561 if (Checker.checkStatement(
12562 Body, diag::err_omp_atomic_capture_not_expression_statement,
12563 diag::note_omp_atomic_update))
12564 return StmtError();
12565 E = Checker.getExpr();
12566 X = Checker.getX();
12567 UE = Checker.getUpdateExpr();
12568 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12569 IsPostfixUpdate = Checker.isPostfixUpdate();
12570 } else if (!AtomicBody->isInstantiationDependent()) {
12571 ErrorLoc = AtomicBody->getExprLoc();
12572 ErrorRange = AtomicBody->getSourceRange();
12573 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12574 : AtomicBody->getExprLoc();
12575 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12576 : AtomicBody->getSourceRange();
12577 ErrorFound = NotAnAssignmentOp;
12578 }
12579 if (ErrorFound != NoError) {
12580 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12581 << ErrorRange;
12582 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12583 return StmtError();
12584 }
12586 UE = V = E = X = nullptr;
12587 } else {
12588 // If clause is a capture:
12589 // { v = x; x = expr; }
12590 // { v = x; x++; }
12591 // { v = x; x--; }
12592 // { v = x; ++x; }
12593 // { v = x; --x; }
12594 // { v = x; x binop= expr; }
12595 // { v = x; x = x binop expr; }
12596 // { v = x; x = expr binop x; }
12597 // { x++; v = x; }
12598 // { x--; v = x; }
12599 // { ++x; v = x; }
12600 // { --x; v = x; }
12601 // { x binop= expr; v = x; }
12602 // { x = x binop expr; v = x; }
12603 // { x = expr binop x; v = x; }
12604 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12605 // Check that this is { expr1; expr2; }
12606 if (CS->size() == 2) {
12607 Stmt *First = CS->body_front();
12608 Stmt *Second = CS->body_back();
12609 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12610 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12611 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12612 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12613 // Need to find what subexpression is 'v' and what is 'x'.
12614 OpenMPAtomicUpdateChecker Checker(SemaRef);
12615 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12616 BinaryOperator *BinOp = nullptr;
12617 if (IsUpdateExprFound) {
12618 BinOp = dyn_cast<BinaryOperator>(First);
12619 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12620 }
12621 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12622 // { v = x; x++; }
12623 // { v = x; x--; }
12624 // { v = x; ++x; }
12625 // { v = x; --x; }
12626 // { v = x; x binop= expr; }
12627 // { v = x; x = x binop expr; }
12628 // { v = x; x = expr binop x; }
12629 // Check that the first expression has form v = x.
12630 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12631 llvm::FoldingSetNodeID XId, PossibleXId;
12632 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12633 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12634 IsUpdateExprFound = XId == PossibleXId;
12635 if (IsUpdateExprFound) {
12636 V = BinOp->getLHS();
12637 X = Checker.getX();
12638 E = Checker.getExpr();
12639 UE = Checker.getUpdateExpr();
12640 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12641 IsPostfixUpdate = true;
12642 }
12643 }
12644 if (!IsUpdateExprFound) {
12645 IsUpdateExprFound = !Checker.checkStatement(First);
12646 BinOp = nullptr;
12647 if (IsUpdateExprFound) {
12648 BinOp = dyn_cast<BinaryOperator>(Second);
12649 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12650 }
12651 if (IsUpdateExprFound &&
12653 // { x++; v = x; }
12654 // { x--; v = x; }
12655 // { ++x; v = x; }
12656 // { --x; v = x; }
12657 // { x binop= expr; v = x; }
12658 // { x = x binop expr; v = x; }
12659 // { x = expr binop x; v = x; }
12660 // Check that the second expression has form v = x.
12661 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12662 llvm::FoldingSetNodeID XId, PossibleXId;
12663 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12664 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12665 IsUpdateExprFound = XId == PossibleXId;
12666 if (IsUpdateExprFound) {
12667 V = BinOp->getLHS();
12668 X = Checker.getX();
12669 E = Checker.getExpr();
12670 UE = Checker.getUpdateExpr();
12671 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12672 IsPostfixUpdate = false;
12673 }
12674 }
12675 }
12676 if (!IsUpdateExprFound) {
12677 // { v = x; x = expr; }
12678 auto *FirstExpr = dyn_cast<Expr>(First);
12679 auto *SecondExpr = dyn_cast<Expr>(Second);
12680 if (!FirstExpr || !SecondExpr ||
12681 !(FirstExpr->isInstantiationDependent() ||
12682 SecondExpr->isInstantiationDependent())) {
12683 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12684 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12685 ErrorFound = NotAnAssignmentOp;
12686 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12687 : First->getBeginLoc();
12688 NoteRange = ErrorRange = FirstBinOp
12689 ? FirstBinOp->getSourceRange()
12690 : SourceRange(ErrorLoc, ErrorLoc);
12691 } else {
12692 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12693 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12694 ErrorFound = NotAnAssignmentOp;
12695 NoteLoc = ErrorLoc = SecondBinOp
12696 ? SecondBinOp->getOperatorLoc()
12697 : Second->getBeginLoc();
12698 NoteRange = ErrorRange =
12699 SecondBinOp ? SecondBinOp->getSourceRange()
12700 : SourceRange(ErrorLoc, ErrorLoc);
12701 } else {
12702 Expr *PossibleXRHSInFirst =
12703 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12704 Expr *PossibleXLHSInSecond =
12705 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12706 llvm::FoldingSetNodeID X1Id, X2Id;
12707 PossibleXRHSInFirst->Profile(X1Id, Context,
12708 /*Canonical=*/true);
12709 PossibleXLHSInSecond->Profile(X2Id, Context,
12710 /*Canonical=*/true);
12711 IsUpdateExprFound = X1Id == X2Id;
12712 if (IsUpdateExprFound) {
12713 V = FirstBinOp->getLHS();
12714 X = SecondBinOp->getLHS();
12715 E = SecondBinOp->getRHS();
12716 UE = nullptr;
12717 IsXLHSInRHSPart = false;
12718 IsPostfixUpdate = true;
12719 } else {
12720 ErrorFound = NotASpecificExpression;
12721 ErrorLoc = FirstBinOp->getExprLoc();
12722 ErrorRange = FirstBinOp->getSourceRange();
12723 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12724 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12725 }
12726 }
12727 }
12728 }
12729 }
12730 } else {
12731 NoteLoc = ErrorLoc = Body->getBeginLoc();
12732 NoteRange = ErrorRange =
12733 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12734 ErrorFound = NotTwoSubstatements;
12735 }
12736 } else {
12737 NoteLoc = ErrorLoc = Body->getBeginLoc();
12738 NoteRange = ErrorRange =
12739 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12740 ErrorFound = NotACompoundStatement;
12741 }
12742 }
12743 if (ErrorFound != NoError) {
12744 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12745 << ErrorRange;
12746 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12747 return StmtError();
12748 }
12750 UE = V = E = X = nullptr;
12751 } else if (AtomicKind == OMPC_compare) {
12752 if (IsCompareCapture) {
12753 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12754 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12755 if (!Checker.checkStmt(Body, ErrorInfo)) {
12756 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12757 << ErrorInfo.ErrorRange;
12758 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12759 << ErrorInfo.Error << ErrorInfo.NoteRange;
12760 return StmtError();
12761 }
12762 X = Checker.getX();
12763 E = Checker.getE();
12764 D = Checker.getD();
12765 CE = Checker.getCond();
12766 V = Checker.getV();
12767 R = Checker.getR();
12768 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12769 IsXLHSInRHSPart = Checker.isXBinopExpr();
12770 IsFailOnly = Checker.isFailOnly();
12771 IsPostfixUpdate = Checker.isPostfixUpdate();
12772 } else {
12773 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12774 OpenMPAtomicCompareChecker Checker(SemaRef);
12775 if (!Checker.checkStmt(Body, ErrorInfo)) {
12776 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12777 << ErrorInfo.ErrorRange;
12778 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12779 << ErrorInfo.Error << ErrorInfo.NoteRange;
12780 return StmtError();
12781 }
12782 X = Checker.getX();
12783 E = Checker.getE();
12784 D = Checker.getD();
12785 CE = Checker.getCond();
12786 // The weak clause may only appear if the resulting atomic operation is
12787 // an atomic conditional update for which the comparison tests for
12788 // equality. It was not possible to do this check in
12789 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12790 // could not be performed (Clauses are not available).
12791 auto *It = find_if(Clauses, [](OMPClause *C) {
12792 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12793 });
12794 if (It != Clauses.end()) {
12795 auto *Cond = dyn_cast<BinaryOperator>(CE);
12796 if (Cond->getOpcode() != BO_EQ) {
12797 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12798 ErrorInfo.ErrorLoc = Cond->getExprLoc();
12799 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12800 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12801
12802 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12803 << ErrorInfo.ErrorRange;
12804 return StmtError();
12805 }
12806 }
12807 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12808 IsXLHSInRHSPart = Checker.isXBinopExpr();
12809 }
12810 }
12811
12813
12815 Context, StartLoc, EndLoc, Clauses, AStmt,
12816 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12817}
12818
12820 Stmt *AStmt,
12821 SourceLocation StartLoc,
12822 SourceLocation EndLoc) {
12823 if (!AStmt)
12824 return StmtError();
12825
12826 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
12827
12828 // OpenMP [2.16, Nesting of Regions]
12829 // If specified, a teams construct must be contained within a target
12830 // construct. That target construct must contain no statements or directives
12831 // outside of the teams construct.
12832 if (DSAStack->hasInnerTeamsRegion()) {
12833 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12834 bool OMPTeamsFound = true;
12835 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12836 auto I = CS->body_begin();
12837 while (I != CS->body_end()) {
12838 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12839 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12840 if (!IsTeams || I != CS->body_begin()) {
12841 OMPTeamsFound = false;
12842 if (IsTeams && I != CS->body_begin()) {
12843 // This is the two teams case. Since the InnerTeamsRegionLoc will
12844 // point to this second one reset the iterator to the other teams.
12845 --I;
12846 }
12847 break;
12848 }
12849 ++I;
12850 }
12851 assert(I != CS->body_end() && "Not found statement");
12852 S = *I;
12853 } else {
12854 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12855 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12856 }
12857 if (!OMPTeamsFound) {
12858 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12859 Diag(DSAStack->getInnerTeamsRegionLoc(),
12860 diag::note_omp_nested_teams_construct_here);
12861 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12862 << isa<OMPExecutableDirective>(S);
12863 return StmtError();
12864 }
12865 }
12866
12867 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12868 AStmt);
12869}
12870
12872 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12873 SourceLocation EndLoc) {
12874 if (!AStmt)
12875 return StmtError();
12876
12877 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
12878
12880 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12881 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12882}
12883
12885 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12886 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12887 if (!AStmt)
12888 return StmtError();
12889
12890 CapturedStmt *CS =
12891 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
12892
12894 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12895 // define the nested loops number.
12896 unsigned NestedLoopCount =
12897 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
12898 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
12899 VarsWithImplicitDSA, B);
12900 if (NestedLoopCount == 0)
12901 return StmtError();
12902
12903 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
12904 return StmtError();
12905
12907 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12908 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12909}
12910
12911/// Check for existence of a map clause in the list of clauses.
12913 const OpenMPClauseKind K) {
12914 return llvm::any_of(
12915 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
12916}
12917
12918template <typename... Params>
12920 const Params... ClauseTypes) {
12921 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
12922}
12923
12924/// Check if the variables in the mapping clause are externally visible.
12926 for (const OMPClause *C : Clauses) {
12927 if (auto *TC = dyn_cast<OMPToClause>(C))
12928 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
12929 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12930 (VD->isExternallyVisible() &&
12931 VD->getVisibility() != HiddenVisibility);
12932 });
12933 else if (auto *FC = dyn_cast<OMPFromClause>(C))
12934 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
12935 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12936 (VD->isExternallyVisible() &&
12937 VD->getVisibility() != HiddenVisibility);
12938 });
12939 }
12940
12941 return true;
12942}
12943
12946 Stmt *AStmt, SourceLocation StartLoc,
12947 SourceLocation EndLoc) {
12948 if (!AStmt)
12949 return StmtError();
12950
12951 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12952
12953 // OpenMP [2.12.2, target data Construct, Restrictions]
12954 // At least one map, use_device_addr or use_device_ptr clause must appear on
12955 // the directive.
12956 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
12957 (getLangOpts().OpenMP < 50 ||
12958 !hasClauses(Clauses, OMPC_use_device_addr))) {
12959 StringRef Expected;
12960 if (getLangOpts().OpenMP < 50)
12961 Expected = "'map' or 'use_device_ptr'";
12962 else
12963 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
12964 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12965 << Expected << getOpenMPDirectiveName(OMPD_target_data);
12966 return StmtError();
12967 }
12968
12970
12971 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
12972 Clauses, AStmt);
12973}
12974
12976 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
12977 SourceLocation EndLoc, Stmt *AStmt) {
12978 if (!AStmt)
12979 return StmtError();
12980
12981 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
12982
12983 // OpenMP [2.10.2, Restrictions, p. 99]
12984 // At least one map clause must appear on the directive.
12985 if (!hasClauses(Clauses, OMPC_map)) {
12986 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12987 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
12988 return StmtError();
12989 }
12990
12991 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
12992 Clauses, AStmt);
12993}
12994
12996 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
12997 SourceLocation EndLoc, Stmt *AStmt) {
12998 if (!AStmt)
12999 return StmtError();
13000
13001 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13002
13003 // OpenMP [2.10.3, Restrictions, p. 102]
13004 // At least one map clause must appear on the directive.
13005 if (!hasClauses(Clauses, OMPC_map)) {
13006 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13007 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13008 return StmtError();
13009 }
13010
13011 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13012 Clauses, AStmt);
13013}
13014
13016 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13017 SourceLocation EndLoc, Stmt *AStmt) {
13018 if (!AStmt)
13019 return StmtError();
13020
13021 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13022
13023 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13024 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13025 return StmtError();
13026 }
13027
13028 if (!isClauseMappable(Clauses)) {
13029 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13030 return StmtError();
13031 }
13032
13033 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13034 Clauses, AStmt);
13035}
13036
13037/// This checks whether a \p ClauseType clause \p C has at most \p Max
13038/// expression. If not, a diag of number \p Diag will be emitted.
13039template <typename ClauseType>
13040static bool checkNumExprsInClause(SemaBase &SemaRef,
13041 ArrayRef<OMPClause *> Clauses,
13042 unsigned MaxNum, unsigned Diag) {
13043 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13044 if (ClauseItr == Clauses.end())
13045 return true;
13046 const auto *C = cast<ClauseType>(*ClauseItr);
13047 auto VarList = C->getVarRefs();
13048 if (VarList.size() > MaxNum) {
13049 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13050 << getOpenMPClauseName(C->getClauseKind());
13051 return false;
13052 }
13053 return true;
13054}
13055
13057 Stmt *AStmt,
13058 SourceLocation StartLoc,
13059 SourceLocation EndLoc) {
13060 if (!AStmt)
13061 return StmtError();
13062
13063 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13064 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13065 !checkNumExprsInClause<OMPThreadLimitClause>(
13066 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13067 return StmtError();
13068
13069 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13070 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13071 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13072
13073 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13074
13075 DSAStack->setParentTeamsRegionLoc(StartLoc);
13076
13077 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13078 AStmt);
13079}
13080
13082 SourceLocation StartLoc, SourceLocation EndLoc,
13083 OpenMPDirectiveKind CancelRegion) {
13084 if (DSAStack->isParentNowaitRegion()) {
13085 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13086 return StmtError();
13087 }
13088 if (DSAStack->isParentOrderedRegion()) {
13089 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13090 return StmtError();
13091 }
13093 EndLoc, CancelRegion);
13094}
13095
13097 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13098 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13099 if (DSAStack->isParentNowaitRegion()) {
13100 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13101 return StmtError();
13102 }
13103 if (DSAStack->isParentOrderedRegion()) {
13104 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13105 return StmtError();
13106 }
13107 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13108 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13109 CancelRegion);
13110}
13111
13113 ArrayRef<OMPClause *> Clauses) {
13114 const OMPClause *ReductionClause = nullptr;
13115 const OMPClause *NogroupClause = nullptr;
13116 for (const OMPClause *C : Clauses) {
13117 if (C->getClauseKind() == OMPC_reduction) {
13118 ReductionClause = C;
13119 if (NogroupClause)
13120 break;
13121 continue;
13122 }
13123 if (C->getClauseKind() == OMPC_nogroup) {
13124 NogroupClause = C;
13125 if (ReductionClause)
13126 break;
13127 continue;
13128 }
13129 }
13130 if (ReductionClause && NogroupClause) {
13131 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13132 << SourceRange(NogroupClause->getBeginLoc(),
13133 NogroupClause->getEndLoc());
13134 return true;
13135 }
13136 return false;
13137}
13138
13140 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13141 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13142 if (!AStmt)
13143 return StmtError();
13144
13145 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13147 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13148 // define the nested loops number.
13149 unsigned NestedLoopCount =
13150 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13151 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13152 *DSAStack, VarsWithImplicitDSA, B);
13153 if (NestedLoopCount == 0)
13154 return StmtError();
13155
13156 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13157 "omp for loop exprs were not built");
13158
13159 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13160 // The grainsize clause and num_tasks clause are mutually exclusive and may
13161 // not appear on the same taskloop directive.
13163 {OMPC_grainsize, OMPC_num_tasks}))
13164 return StmtError();
13165 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13166 // If a reduction clause is present on the taskloop directive, the nogroup
13167 // clause must not be specified.
13169 return StmtError();
13170
13172 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13173 NestedLoopCount, Clauses, AStmt, B,
13174 DSAStack->isCancelRegion());
13175}
13176
13178 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13179 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13180 if (!AStmt)
13181 return StmtError();
13182
13183 CapturedStmt *CS =
13184 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13185
13186 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13188 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13189 // define the nested loops number.
13190 unsigned NestedLoopCount =
13191 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13192 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13193 VarsWithImplicitDSA, B);
13194 if (NestedLoopCount == 0)
13195 return StmtError();
13196
13197 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13198 return StmtError();
13199
13200 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13201 // The grainsize clause and num_tasks clause are mutually exclusive and may
13202 // not appear on the same taskloop directive.
13204 {OMPC_grainsize, OMPC_num_tasks}))
13205 return StmtError();
13206 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13207 // If a reduction clause is present on the taskloop directive, the nogroup
13208 // clause must not be specified.
13210 return StmtError();
13212 return StmtError();
13213
13214 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13215 NestedLoopCount, Clauses, AStmt, B);
13216}
13217
13219 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13220 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13221 if (!AStmt)
13222 return StmtError();
13223
13224 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13226 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13227 // define the nested loops number.
13228 unsigned NestedLoopCount =
13229 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13230 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13231 *DSAStack, VarsWithImplicitDSA, B);
13232 if (NestedLoopCount == 0)
13233 return StmtError();
13234
13235 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13236 "omp for loop exprs were not built");
13237
13238 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13239 // The grainsize clause and num_tasks clause are mutually exclusive and may
13240 // not appear on the same taskloop directive.
13242 {OMPC_grainsize, OMPC_num_tasks}))
13243 return StmtError();
13244 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13245 // If a reduction clause is present on the taskloop directive, the nogroup
13246 // clause must not be specified.
13248 return StmtError();
13249
13251 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13252 NestedLoopCount, Clauses, AStmt, B,
13253 DSAStack->isCancelRegion());
13254}
13255
13257 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13258 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13259 if (!AStmt)
13260 return StmtError();
13261
13262 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13264 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13265 // define the nested loops number.
13266 unsigned NestedLoopCount =
13267 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13268 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13269 *DSAStack, VarsWithImplicitDSA, B);
13270 if (NestedLoopCount == 0)
13271 return StmtError();
13272
13273 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13274 "omp for loop exprs were not built");
13275
13276 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13277 // The grainsize clause and num_tasks clause are mutually exclusive and may
13278 // not appear on the same taskloop directive.
13280 {OMPC_grainsize, OMPC_num_tasks}))
13281 return StmtError();
13282 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13283 // If a reduction clause is present on the taskloop directive, the nogroup
13284 // clause must not be specified.
13286 return StmtError();
13287
13289 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13290 NestedLoopCount, Clauses, AStmt, B,
13291 DSAStack->isCancelRegion());
13292}
13293
13295 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13296 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13297 if (!AStmt)
13298 return StmtError();
13299
13300 CapturedStmt *CS =
13301 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13302
13303 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13305 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13306 // define the nested loops number.
13307 unsigned NestedLoopCount =
13308 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13309 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13310 VarsWithImplicitDSA, B);
13311 if (NestedLoopCount == 0)
13312 return StmtError();
13313
13314 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13315 return StmtError();
13316
13317 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13318 // The grainsize clause and num_tasks clause are mutually exclusive and may
13319 // not appear on the same taskloop directive.
13321 {OMPC_grainsize, OMPC_num_tasks}))
13322 return StmtError();
13323 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13324 // If a reduction clause is present on the taskloop directive, the nogroup
13325 // clause must not be specified.
13327 return StmtError();
13329 return StmtError();
13330
13332 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13333}
13334
13336 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13337 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13338 if (!AStmt)
13339 return StmtError();
13340
13341 CapturedStmt *CS =
13342 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13343
13344 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13346 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13347 // define the nested loops number.
13348 unsigned NestedLoopCount =
13349 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13350 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13351 VarsWithImplicitDSA, B);
13352 if (NestedLoopCount == 0)
13353 return StmtError();
13354
13355 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13356 return StmtError();
13357
13358 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13359 // The grainsize clause and num_tasks clause are mutually exclusive and may
13360 // not appear on the same taskloop directive.
13362 {OMPC_grainsize, OMPC_num_tasks}))
13363 return StmtError();
13364 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13365 // If a reduction clause is present on the taskloop directive, the nogroup
13366 // clause must not be specified.
13368 return StmtError();
13370 return StmtError();
13371
13373 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13374}
13375
13377 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13378 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13379 if (!AStmt)
13380 return StmtError();
13381
13382 CapturedStmt *CS =
13383 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13384
13386 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13387 // define the nested loops number.
13388 unsigned NestedLoopCount = checkOpenMPLoop(
13389 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13390 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13391 VarsWithImplicitDSA, B);
13392 if (NestedLoopCount == 0)
13393 return StmtError();
13394
13395 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13396 "omp for loop exprs were not built");
13397
13398 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13399 // The grainsize clause and num_tasks clause are mutually exclusive and may
13400 // not appear on the same taskloop directive.
13402 {OMPC_grainsize, OMPC_num_tasks}))
13403 return StmtError();
13404 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13405 // If a reduction clause is present on the taskloop directive, the nogroup
13406 // clause must not be specified.
13408 return StmtError();
13409
13411 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13412 DSAStack->isCancelRegion());
13413}
13414
13416 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13417 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13418 if (!AStmt)
13419 return StmtError();
13420
13421 CapturedStmt *CS =
13422 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13423
13425 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13426 // define the nested loops number.
13427 unsigned NestedLoopCount = checkOpenMPLoop(
13428 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13429 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13430 VarsWithImplicitDSA, B);
13431 if (NestedLoopCount == 0)
13432 return StmtError();
13433
13434 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13435 "omp for loop exprs were not built");
13436
13437 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13438 // The grainsize clause and num_tasks clause are mutually exclusive and may
13439 // not appear on the same taskloop directive.
13441 {OMPC_grainsize, OMPC_num_tasks}))
13442 return StmtError();
13443 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13444 // If a reduction clause is present on the taskloop directive, the nogroup
13445 // clause must not be specified.
13447 return StmtError();
13448
13450 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13451 DSAStack->isCancelRegion());
13452}
13453
13455 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13456 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13457 if (!AStmt)
13458 return StmtError();
13459
13461 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13462
13464 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13465 // define the nested loops number.
13466 unsigned NestedLoopCount = checkOpenMPLoop(
13467 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13468 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13469 VarsWithImplicitDSA, B);
13470 if (NestedLoopCount == 0)
13471 return StmtError();
13472
13473 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13474 return StmtError();
13475
13476 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13477 // The grainsize clause and num_tasks clause are mutually exclusive and may
13478 // not appear on the same taskloop directive.
13480 {OMPC_grainsize, OMPC_num_tasks}))
13481 return StmtError();
13482 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13483 // If a reduction clause is present on the taskloop directive, the nogroup
13484 // clause must not be specified.
13486 return StmtError();
13488 return StmtError();
13489
13491 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13492}
13493
13495 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13496 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13497 if (!AStmt)
13498 return StmtError();
13499
13501 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13502
13504 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13505 // define the nested loops number.
13506 unsigned NestedLoopCount = checkOpenMPLoop(
13507 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13508 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13509 VarsWithImplicitDSA, B);
13510 if (NestedLoopCount == 0)
13511 return StmtError();
13512
13513 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13514 return StmtError();
13515
13516 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13517 // The grainsize clause and num_tasks clause are mutually exclusive and may
13518 // not appear on the same taskloop directive.
13520 {OMPC_grainsize, OMPC_num_tasks}))
13521 return StmtError();
13522 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13523 // If a reduction clause is present on the taskloop directive, the nogroup
13524 // clause must not be specified.
13526 return StmtError();
13528 return StmtError();
13529
13531 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13532}
13533
13535 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13536 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13537 if (!AStmt)
13538 return StmtError();
13539
13540 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13542 // In presence of clause 'collapse' with number of loops, it will
13543 // define the nested loops number.
13544 unsigned NestedLoopCount =
13545 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13546 nullptr /*ordered not a clause on distribute*/, AStmt,
13547 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13548 if (NestedLoopCount == 0)
13549 return StmtError();
13550
13551 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13552 "omp for loop exprs were not built");
13553
13555 auto *DistributeDirective = OMPDistributeDirective::Create(
13556 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13557 return DistributeDirective;
13558}
13559
13561 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13562 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13563 if (!AStmt)
13564 return StmtError();
13565
13566 CapturedStmt *CS =
13567 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13568
13570 // In presence of clause 'collapse' with number of loops, it will
13571 // define the nested loops number.
13572 unsigned NestedLoopCount = checkOpenMPLoop(
13573 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13574 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13575 VarsWithImplicitDSA, B);
13576 if (NestedLoopCount == 0)
13577 return StmtError();
13578
13579 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13580 "omp for loop exprs were not built");
13581
13583 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13584 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13585}
13586
13588 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13589 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13590 if (!AStmt)
13591 return StmtError();
13592
13594 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13595
13597 // In presence of clause 'collapse' with number of loops, it will
13598 // define the nested loops number.
13599 unsigned NestedLoopCount = checkOpenMPLoop(
13600 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13601 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13602 VarsWithImplicitDSA, B);
13603 if (NestedLoopCount == 0)
13604 return StmtError();
13605
13606 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13607 return StmtError();
13608
13610 return StmtError();
13611
13613 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13614}
13615
13617 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13618 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13619 if (!AStmt)
13620 return StmtError();
13621
13622 CapturedStmt *CS =
13623 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
13624
13626 // In presence of clause 'collapse' with number of loops, it will
13627 // define the nested loops number.
13628 unsigned NestedLoopCount =
13629 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13630 nullptr /*ordered not a clause on distribute*/, CS,
13631 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13632 if (NestedLoopCount == 0)
13633 return StmtError();
13634
13635 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13636 return StmtError();
13637
13639 return StmtError();
13640
13641 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13642 NestedLoopCount, Clauses, AStmt, B);
13643}
13644
13646 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13647 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13648 if (!AStmt)
13649 return StmtError();
13650
13651 CapturedStmt *CS =
13652 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13653
13655 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13656 // define the nested loops number.
13657 unsigned NestedLoopCount = checkOpenMPLoop(
13658 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13659 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13660 VarsWithImplicitDSA, B);
13661 if (NestedLoopCount == 0)
13662 return StmtError();
13663
13664 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13665 return StmtError();
13666
13668 return StmtError();
13669
13671 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13672}
13673
13675 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13676 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13677 if (!AStmt)
13678 return StmtError();
13679
13680 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13681
13683 // In presence of clause 'collapse' with number of loops, it will define the
13684 // nested loops number.
13685 unsigned NestedLoopCount =
13686 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13687 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13688 VarsWithImplicitDSA, B);
13689 if (NestedLoopCount == 0)
13690 return StmtError();
13691
13692 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13693 return StmtError();
13694
13696 return StmtError();
13697
13698 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13699 NestedLoopCount, Clauses, AStmt, B);
13700}
13701
13703 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13704 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13705 if (!AStmt)
13706 return StmtError();
13707
13708 CapturedStmt *CS =
13709 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13710
13712 // In presence of clause 'collapse' with number of loops, it will
13713 // define the nested loops number.
13714 unsigned NestedLoopCount =
13715 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13716 nullptr /*ordered not a clause on distribute*/, CS,
13717 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13718 if (NestedLoopCount == 0)
13719 return StmtError();
13720
13721 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13722 "omp teams distribute loop exprs were not built");
13723
13724 DSAStack->setParentTeamsRegionLoc(StartLoc);
13725
13727 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13728}
13729
13731 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13732 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13733 if (!AStmt)
13734 return StmtError();
13735
13736 CapturedStmt *CS =
13737 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13738
13740 // In presence of clause 'collapse' with number of loops, it will
13741 // define the nested loops number.
13742 unsigned NestedLoopCount = checkOpenMPLoop(
13743 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13744 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13745 VarsWithImplicitDSA, B);
13746 if (NestedLoopCount == 0)
13747 return StmtError();
13748
13749 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13750 return StmtError();
13751
13753 return StmtError();
13754
13755 DSAStack->setParentTeamsRegionLoc(StartLoc);
13756
13758 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13759}
13760
13762 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13763 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13764 if (!AStmt)
13765 return StmtError();
13766
13768 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13769
13771 // In presence of clause 'collapse' with number of loops, it will
13772 // define the nested loops number.
13773 unsigned NestedLoopCount = checkOpenMPLoop(
13774 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13775 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13776 VarsWithImplicitDSA, B);
13777 if (NestedLoopCount == 0)
13778 return StmtError();
13779
13780 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13781 return StmtError();
13782
13784 return StmtError();
13785
13786 DSAStack->setParentTeamsRegionLoc(StartLoc);
13787
13789 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13790}
13791
13793 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13794 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13795 if (!AStmt)
13796 return StmtError();
13797
13799 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13800
13802 // In presence of clause 'collapse' with number of loops, it will
13803 // define the nested loops number.
13804 unsigned NestedLoopCount = checkOpenMPLoop(
13805 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13806 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13807 VarsWithImplicitDSA, B);
13808
13809 if (NestedLoopCount == 0)
13810 return StmtError();
13811
13812 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13813 "omp for loop exprs were not built");
13814
13815 DSAStack->setParentTeamsRegionLoc(StartLoc);
13816
13818 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13819 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13820}
13821
13823 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13824 SourceLocation EndLoc) {
13825 if (!AStmt)
13826 return StmtError();
13827
13828 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
13829
13830 const OMPClause *BareClause = nullptr;
13831 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
13832 hasClauses(Clauses, OMPC_thread_limit);
13833 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
13834 BareClause = C;
13835 return C->getClauseKind() == OMPC_ompx_bare;
13836 });
13837
13838 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13839 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
13840 return StmtError();
13841 }
13842
13843 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
13844 unsigned DiagNo = HasBareClause
13845 ? diag::err_ompx_more_than_three_expr_not_allowed
13846 : diag::err_omp_multi_expr_not_allowed;
13847 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
13848 ClauseMaxNumExprs, DiagNo) ||
13849 !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses,
13850 ClauseMaxNumExprs, DiagNo))
13851 return StmtError();
13852
13853 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
13854 Clauses, AStmt);
13855}
13856
13858 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13859 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13860 if (!AStmt)
13861 return StmtError();
13862
13863 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13864 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13865 !checkNumExprsInClause<OMPThreadLimitClause>(
13866 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13867 return StmtError();
13868
13869 CapturedStmt *CS =
13870 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
13871
13873 // In presence of clause 'collapse' with number of loops, it will
13874 // define the nested loops number.
13875 unsigned NestedLoopCount = checkOpenMPLoop(
13876 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
13877 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13878 VarsWithImplicitDSA, B);
13879 if (NestedLoopCount == 0)
13880 return StmtError();
13881
13882 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13883 "omp target teams distribute loop exprs were not built");
13884
13886 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13887}
13888
13890 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13891 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13892 if (!AStmt)
13893 return StmtError();
13894
13895 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13896 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13897 !checkNumExprsInClause<OMPThreadLimitClause>(
13898 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13899 return StmtError();
13900
13902 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
13903
13905 // In presence of clause 'collapse' with number of loops, it will
13906 // define the nested loops number.
13907 unsigned NestedLoopCount = checkOpenMPLoop(
13908 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13909 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13910 VarsWithImplicitDSA, B);
13911 if (NestedLoopCount == 0)
13912 return StmtError();
13913
13914 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13915 return StmtError();
13916
13918 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13919 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13920}
13921
13923 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13924 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13925 if (!AStmt)
13926 return StmtError();
13927
13928 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13929 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13930 !checkNumExprsInClause<OMPThreadLimitClause>(
13931 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13932 return StmtError();
13933
13935 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
13936
13938 // In presence of clause 'collapse' with number of loops, it will
13939 // define the nested loops number.
13940 unsigned NestedLoopCount =
13941 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
13942 getCollapseNumberExpr(Clauses),
13943 nullptr /*ordered not a clause on distribute*/, CS,
13944 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13945 if (NestedLoopCount == 0)
13946 return StmtError();
13947
13948 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13949 return StmtError();
13950
13952 return StmtError();
13953
13955 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13956}
13957
13959 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13960 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13961 if (!AStmt)
13962 return StmtError();
13963
13964 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13965 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13966 !checkNumExprsInClause<OMPThreadLimitClause>(
13967 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13968 return StmtError();
13969
13971 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
13972
13974 // In presence of clause 'collapse' with number of loops, it will
13975 // define the nested loops number.
13976 unsigned NestedLoopCount = checkOpenMPLoop(
13977 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13978 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13979 VarsWithImplicitDSA, B);
13980 if (NestedLoopCount == 0)
13981 return StmtError();
13982
13983 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13984 return StmtError();
13985
13987 return StmtError();
13988
13990 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13991}
13992
13993bool SemaOpenMP::checkTransformableLoopNest(
13994 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
13996 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
13997 OriginalInits.emplace_back();
13999 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14000 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14001 Stmt *CurStmt) {
14002 VarsWithInheritedDSAType TmpDSA;
14003 unsigned SingleNumLoops =
14004 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14005 TmpDSA, LoopHelpers[Cnt]);
14006 if (SingleNumLoops == 0)
14007 return true;
14008 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14009 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14010 OriginalInits.back().push_back(For->getInit());
14011 Body = For->getBody();
14012 } else {
14013 assert(isa<CXXForRangeStmt>(CurStmt) &&
14014 "Expected canonical for or range-based for loops.");
14015 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14016 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14017 Body = CXXFor->getBody();
14018 }
14019 OriginalInits.emplace_back();
14020 return false;
14021 },
14022 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14023 Stmt *DependentPreInits;
14024 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14025 DependentPreInits = Dir->getPreInits();
14026 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14027 DependentPreInits = Dir->getPreInits();
14028 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14029 DependentPreInits = Dir->getPreInits();
14030 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14031 DependentPreInits = Dir->getPreInits();
14032 else
14033 llvm_unreachable("Unhandled loop transformation");
14034
14035 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
14036 });
14037 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14038 OriginalInits.pop_back();
14039 return Result;
14040}
14041
14042/// Add preinit statements that need to be propageted from the selected loop.
14043static void addLoopPreInits(ASTContext &Context,
14045 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14046 SmallVectorImpl<Stmt *> &PreInits) {
14047
14048 // For range-based for-statements, ensure that their syntactic sugar is
14049 // executed by adding them as pre-init statements.
14050 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14051 Stmt *RangeInit = CXXRangeFor->getInit();
14052 if (RangeInit)
14053 PreInits.push_back(RangeInit);
14054
14055 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14056 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14057 RangeStmt->getBeginLoc(),
14058 RangeStmt->getEndLoc()));
14059
14060 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14061 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14062 RangeEnd->getBeginLoc(),
14063 RangeEnd->getEndLoc()));
14064 }
14065
14066 llvm::append_range(PreInits, OriginalInit);
14067
14068 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14069 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14070 PreInits.push_back(new (Context) DeclStmt(
14071 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14072 }
14073
14074 // Gather declarations for the data members used as counters.
14075 for (Expr *CounterRef : LoopHelper.Counters) {
14076 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14077 if (isa<OMPCapturedExprDecl>(CounterDecl))
14078 PreInits.push_back(new (Context) DeclStmt(
14079 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14080 }
14081}
14082
14083/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14084/// loop of a construct.
14085static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14086 size_t NumLoops = LoopStmts.size();
14088 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14089 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14090 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14091 LoopStmts[Cnt] = CurStmt;
14092 return false;
14093 });
14094 assert(!is_contained(LoopStmts, nullptr) &&
14095 "Expecting a loop statement for each affected loop");
14096}
14097
14099 Stmt *AStmt,
14100 SourceLocation StartLoc,
14101 SourceLocation EndLoc) {
14102 ASTContext &Context = getASTContext();
14103 Scope *CurScope = SemaRef.getCurScope();
14104
14105 const auto *SizesClause =
14106 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14107 if (!SizesClause ||
14108 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14109 return StmtError();
14110 unsigned NumLoops = SizesClause->getNumSizes();
14111
14112 // Empty statement should only be possible if there already was an error.
14113 if (!AStmt)
14114 return StmtError();
14115
14116 // Verify and diagnose loop nest.
14118 Stmt *Body = nullptr;
14119 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14120 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14121 OriginalInits))
14122 return StmtError();
14123
14124 // Delay tiling to when template is completely instantiated.
14126 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14127 NumLoops, AStmt, nullptr, nullptr);
14128
14129 assert(LoopHelpers.size() == NumLoops &&
14130 "Expecting loop iteration space dimensionality to match number of "
14131 "affected loops");
14132 assert(OriginalInits.size() == NumLoops &&
14133 "Expecting loop iteration space dimensionality to match number of "
14134 "affected loops");
14135
14136 // Collect all affected loop statements.
14137 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14138 collectLoopStmts(AStmt, LoopStmts);
14139
14140 SmallVector<Stmt *, 4> PreInits;
14141 CaptureVars CopyTransformer(SemaRef);
14142
14143 // Create iteration variables for the generated loops.
14144 SmallVector<VarDecl *, 4> FloorIndVars;
14145 SmallVector<VarDecl *, 4> TileIndVars;
14146 FloorIndVars.resize(NumLoops);
14147 TileIndVars.resize(NumLoops);
14148 for (unsigned I = 0; I < NumLoops; ++I) {
14149 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14150
14151 assert(LoopHelper.Counters.size() == 1 &&
14152 "Expect single-dimensional loop iteration space");
14153 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14154 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14155 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14156 QualType CntTy = IterVarRef->getType();
14157
14158 // Iteration variable for the floor (i.e. outer) loop.
14159 {
14160 std::string FloorCntName =
14161 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14162 VarDecl *FloorCntDecl =
14163 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14164 FloorIndVars[I] = FloorCntDecl;
14165 }
14166
14167 // Iteration variable for the tile (i.e. inner) loop.
14168 {
14169 std::string TileCntName =
14170 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14171
14172 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14173 // used by the expressions to derive the original iteration variable's
14174 // value from the logical iteration number.
14175 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14176 TileCntDecl->setDeclName(
14177 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14178 TileIndVars[I] = TileCntDecl;
14179 }
14180
14181 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14182 PreInits);
14183 }
14184
14185 // Once the original iteration values are set, append the innermost body.
14186 Stmt *Inner = Body;
14187
14188 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14189 SizesClause, CurScope](int I) -> Expr * {
14190 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14191 if (isa<ConstantExpr>(DimTileSizeExpr))
14192 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14193
14194 // When the tile size is not a constant but a variable, it is possible to
14195 // pass non-positive numbers. For instance:
14196 // \code{c}
14197 // int a = 0;
14198 // #pragma omp tile sizes(a)
14199 // for (int i = 0; i < 42; ++i)
14200 // body(i);
14201 // \endcode
14202 // Although there is no meaningful interpretation of the tile size, the body
14203 // should still be executed 42 times to avoid surprises. To preserve the
14204 // invariant that every loop iteration is executed exactly once and not
14205 // cause an infinite loop, apply a minimum tile size of one.
14206 // Build expr:
14207 // \code{c}
14208 // (TS <= 0) ? 1 : TS
14209 // \endcode
14210 QualType DimTy = DimTileSizeExpr->getType();
14211 uint64_t DimWidth = Context.getTypeSize(DimTy);
14213 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14214 IntegerLiteral *One =
14215 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14217 CurScope, {}, BO_LE,
14218 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14219 Expr *MinOne = new (Context) ConditionalOperator(
14220 Cond, {}, One, {},
14221 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14223 return MinOne;
14224 };
14225
14226 // Create tile loops from the inside to the outside.
14227 for (int I = NumLoops - 1; I >= 0; --I) {
14228 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14229 Expr *NumIterations = LoopHelper.NumIterations;
14230 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14231 QualType IVTy = NumIterations->getType();
14232 Stmt *LoopStmt = LoopStmts[I];
14233
14234 // Commonly used variables. One of the constraints of an AST is that every
14235 // node object must appear at most once, hence we define lamdas that create
14236 // a new AST node at every use.
14237 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14238 OrigCntVar]() {
14239 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14240 OrigCntVar->getExprLoc());
14241 };
14242 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14243 OrigCntVar]() {
14244 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14245 OrigCntVar->getExprLoc());
14246 };
14247
14248 // For init-statement: auto .tile.iv = .floor.iv
14250 TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(),
14251 /*DirectInit=*/false);
14252 Decl *CounterDecl = TileIndVars[I];
14253 StmtResult InitStmt = new (Context)
14254 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14255 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14256 if (!InitStmt.isUsable())
14257 return StmtError();
14258
14259 // For cond-expression:
14260 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14261 ExprResult EndOfTile =
14262 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14263 MakeFloorIVRef(), MakeDimTileSize(I));
14264 if (!EndOfTile.isUsable())
14265 return StmtError();
14266 ExprResult IsPartialTile =
14267 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14268 NumIterations, EndOfTile.get());
14269 if (!IsPartialTile.isUsable())
14270 return StmtError();
14271 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14272 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14273 IsPartialTile.get(), NumIterations, EndOfTile.get());
14274 if (!MinTileAndIterSpace.isUsable())
14275 return StmtError();
14276 ExprResult CondExpr =
14277 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14278 MakeTileIVRef(), MinTileAndIterSpace.get());
14279 if (!CondExpr.isUsable())
14280 return StmtError();
14281
14282 // For incr-statement: ++.tile.iv
14283 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14284 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14285 if (!IncrStmt.isUsable())
14286 return StmtError();
14287
14288 // Statements to set the original iteration variable's value from the
14289 // logical iteration number.
14290 // Generated for loop is:
14291 // \code
14292 // Original_for_init;
14293 // for (auto .tile.iv = .floor.iv;
14294 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14295 // ++.tile.iv) {
14296 // Original_Body;
14297 // Original_counter_update;
14298 // }
14299 // \endcode
14300 // FIXME: If the innermost body is an loop itself, inserting these
14301 // statements stops it being recognized as a perfectly nested loop (e.g.
14302 // for applying tiling again). If this is the case, sink the expressions
14303 // further into the inner loop.
14304 SmallVector<Stmt *, 4> BodyParts;
14305 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14306 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14307 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14308 BodyParts.push_back(Inner);
14309 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14310 Inner->getBeginLoc(), Inner->getEndLoc());
14311 Inner = new (Context)
14312 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14313 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14314 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14315 }
14316
14317 // Create floor loops from the inside to the outside.
14318 for (int I = NumLoops - 1; I >= 0; --I) {
14319 auto &LoopHelper = LoopHelpers[I];
14320 Expr *NumIterations = LoopHelper.NumIterations;
14321 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14322 QualType IVTy = NumIterations->getType();
14323
14324 // Commonly used variables. One of the constraints of an AST is that every
14325 // node object must appear at most once, hence we define lamdas that create
14326 // a new AST node at every use.
14327 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14328 OrigCntVar]() {
14329 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14330 OrigCntVar->getExprLoc());
14331 };
14332
14333 // For init-statement: auto .floor.iv = 0
14335 FloorIndVars[I],
14336 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14337 /*DirectInit=*/false);
14338 Decl *CounterDecl = FloorIndVars[I];
14339 StmtResult InitStmt = new (Context)
14340 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14341 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14342 if (!InitStmt.isUsable())
14343 return StmtError();
14344
14345 // For cond-expression: .floor.iv < NumIterations
14346 ExprResult CondExpr =
14347 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14348 MakeFloorIVRef(), NumIterations);
14349 if (!CondExpr.isUsable())
14350 return StmtError();
14351
14352 // For incr-statement: .floor.iv += DimTileSize
14353 ExprResult IncrStmt =
14354 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14355 MakeFloorIVRef(), MakeDimTileSize(I));
14356 if (!IncrStmt.isUsable())
14357 return StmtError();
14358
14359 Inner = new (Context)
14360 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14361 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14362 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14363 }
14364
14365 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14366 AStmt, Inner,
14367 buildPreInits(Context, PreInits));
14368}
14369
14371 Stmt *AStmt,
14372 SourceLocation StartLoc,
14373 SourceLocation EndLoc) {
14374 ASTContext &Context = getASTContext();
14375 Scope *CurScope = SemaRef.getCurScope();
14376 // Empty statement should only be possible if there already was an error.
14377 if (!AStmt)
14378 return StmtError();
14379
14381 {OMPC_partial, OMPC_full}))
14382 return StmtError();
14383
14384 const OMPFullClause *FullClause =
14385 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14386 const OMPPartialClause *PartialClause =
14387 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14388 assert(!(FullClause && PartialClause) &&
14389 "mutual exclusivity must have been checked before");
14390
14391 constexpr unsigned NumLoops = 1;
14392 Stmt *Body = nullptr;
14394 NumLoops);
14395 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14396 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14397 Body, OriginalInits))
14398 return StmtError();
14399
14400 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14401
14402 // Delay unrolling to when template is completely instantiated.
14404 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14405 NumGeneratedLoops, nullptr, nullptr);
14406
14407 assert(LoopHelpers.size() == NumLoops &&
14408 "Expecting a single-dimensional loop iteration space");
14409 assert(OriginalInits.size() == NumLoops &&
14410 "Expecting a single-dimensional loop iteration space");
14411 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14412
14413 if (FullClause) {
14415 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14416 /*SuppressExprDiags=*/true)
14417 .isUsable()) {
14418 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14419 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14420 << "#pragma omp unroll full";
14421 return StmtError();
14422 }
14423 }
14424
14425 // The generated loop may only be passed to other loop-associated directive
14426 // when a partial clause is specified. Without the requirement it is
14427 // sufficient to generate loop unroll metadata at code-generation.
14428 if (NumGeneratedLoops == 0)
14429 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14430 NumGeneratedLoops, nullptr, nullptr);
14431
14432 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14433 // associated with another loop directive.
14434 //
14435 // The canonical loop analysis return by checkTransformableLoopNest assumes
14436 // the following structure to be the same loop without transformations or
14437 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14438 // LoopHelper.Counters;
14439 // for (; IV < LoopHelper.NumIterations; ++IV) {
14440 // LoopHelper.Updates;
14441 // Body;
14442 // }
14443 // \endcode
14444 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14445 // and referenced by LoopHelper.IterationVarRef.
14446 //
14447 // The unrolling directive transforms this into the following loop:
14448 // \code
14449 // OriginalInits; \
14450 // LoopHelper.PreInits; > NewPreInits
14451 // LoopHelper.Counters; /
14452 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14453 // #pragma clang loop unroll_count(Factor)
14454 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14455 // {
14456 // LoopHelper.Updates;
14457 // Body;
14458 // }
14459 // }
14460 // \endcode
14461 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14462 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14463 // references it. If the partially unrolled loop is associated with another
14464 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14465 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14466 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14467 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14468 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14469 // property of the OMPLoopBasedDirective instead of statements in
14470 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14471 // of a canonical loop nest where these PreInits are emitted before the
14472 // outermost directive.
14473
14474 // Find the loop statement.
14475 Stmt *LoopStmt = nullptr;
14476 collectLoopStmts(AStmt, {LoopStmt});
14477
14478 // Determine the PreInit declarations.
14479 SmallVector<Stmt *, 4> PreInits;
14480 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14481
14482 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14483 QualType IVTy = IterationVarRef->getType();
14484 assert(LoopHelper.Counters.size() == 1 &&
14485 "Expecting a single-dimensional loop iteration space");
14486 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14487
14488 // Determine the unroll factor.
14489 uint64_t Factor;
14490 SourceLocation FactorLoc;
14491 if (Expr *FactorVal = PartialClause->getFactor()) {
14492 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14493 FactorLoc = FactorVal->getExprLoc();
14494 } else {
14495 // TODO: Use a better profitability model.
14496 Factor = 2;
14497 }
14498 assert(Factor > 0 && "Expected positive unroll factor");
14499 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14501 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14502 IVTy, FactorLoc);
14503 };
14504
14505 // Iteration variable SourceLocations.
14506 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14507 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14508 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14509
14510 // Internal variable names.
14511 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14512 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14513 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14514 std::string InnerTripCountName =
14515 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
14516
14517 // Create the iteration variable for the unrolled loop.
14518 VarDecl *OuterIVDecl =
14519 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
14520 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14521 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
14522 };
14523
14524 // Iteration variable for the inner loop: Reuse the iteration variable created
14525 // by checkOpenMPLoop.
14526 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14527 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
14528 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14529 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
14530 };
14531
14532 // Make a copy of the NumIterations expression for each use: By the AST
14533 // constraints, every expression object in a DeclContext must be unique.
14534 CaptureVars CopyTransformer(SemaRef);
14535 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14536 return AssertSuccess(
14537 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14538 };
14539
14540 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
14541 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
14542 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
14543 /*DirectInit=*/false);
14544 StmtResult InnerInit = new (Context)
14545 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14546 if (!InnerInit.isUsable())
14547 return StmtError();
14548
14549 // Inner For cond-expression:
14550 // \code
14551 // .unroll_inner.iv < .unrolled.iv + Factor &&
14552 // .unroll_inner.iv < NumIterations
14553 // \endcode
14554 // This conjunction of two conditions allows ScalarEvolution to derive the
14555 // maximum trip count of the inner loop.
14556 ExprResult EndOfTile =
14557 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14558 MakeOuterRef(), MakeFactorExpr());
14559 if (!EndOfTile.isUsable())
14560 return StmtError();
14561 ExprResult InnerCond1 =
14562 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14563 MakeInnerRef(), EndOfTile.get());
14564 if (!InnerCond1.isUsable())
14565 return StmtError();
14566 ExprResult InnerCond2 =
14567 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14568 MakeInnerRef(), MakeNumIterations());
14569 if (!InnerCond2.isUsable())
14570 return StmtError();
14571 ExprResult InnerCond =
14572 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
14573 InnerCond1.get(), InnerCond2.get());
14574 if (!InnerCond.isUsable())
14575 return StmtError();
14576
14577 // Inner For incr-statement: ++.unroll_inner.iv
14578 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
14579 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
14580 if (!InnerIncr.isUsable())
14581 return StmtError();
14582
14583 // Inner For statement.
14584 SmallVector<Stmt *> InnerBodyStmts;
14585 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14586 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14587 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14588 InnerBodyStmts.push_back(Body);
14589 CompoundStmt *InnerBody =
14591 Body->getBeginLoc(), Body->getEndLoc());
14592 ForStmt *InnerFor = new (Context)
14593 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
14594 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
14595 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14596
14597 // Unroll metadata for the inner loop.
14598 // This needs to take into account the remainder portion of the unrolled loop,
14599 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
14600 // supports multiple loop exits. Instead, unroll using a factor equivalent to
14601 // the maximum trip count, which will also generate a remainder loop. Just
14602 // `unroll(enable)` (which could have been useful if the user has not
14603 // specified a concrete factor; even though the outer loop cannot be
14604 // influenced anymore, would avoid more code bloat than necessary) will refuse
14605 // the loop because "Won't unroll; remainder loop could not be generated when
14606 // assuming runtime trip count". Even if it did work, it must not choose a
14607 // larger unroll factor than the maximum loop length, or it would always just
14608 // execute the remainder loop.
14609 LoopHintAttr *UnrollHintAttr =
14610 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14611 LoopHintAttr::Numeric, MakeFactorExpr());
14612 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
14613 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
14614
14615 // Outer For init-statement: auto .unrolled.iv = 0
14617 OuterIVDecl,
14618 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14619 /*DirectInit=*/false);
14620 StmtResult OuterInit = new (Context)
14621 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14622 if (!OuterInit.isUsable())
14623 return StmtError();
14624
14625 // Outer For cond-expression: .unrolled.iv < NumIterations
14626 ExprResult OuterConde =
14627 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14628 MakeOuterRef(), MakeNumIterations());
14629 if (!OuterConde.isUsable())
14630 return StmtError();
14631
14632 // Outer For incr-statement: .unrolled.iv += Factor
14633 ExprResult OuterIncr =
14634 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14635 MakeOuterRef(), MakeFactorExpr());
14636 if (!OuterIncr.isUsable())
14637 return StmtError();
14638
14639 // Outer For statement.
14640 ForStmt *OuterFor = new (Context)
14641 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
14642 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
14643 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14644
14645 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14646 NumGeneratedLoops, OuterFor,
14647 buildPreInits(Context, PreInits));
14648}
14649
14651 SourceLocation StartLoc,
14652 SourceLocation EndLoc) {
14653 ASTContext &Context = getASTContext();
14654 Scope *CurScope = SemaRef.getCurScope();
14655
14656 // Empty statement should only be possible if there already was an error.
14657 if (!AStmt)
14658 return StmtError();
14659
14660 constexpr unsigned NumLoops = 1;
14661 Stmt *Body = nullptr;
14663 NumLoops);
14664 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14665 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14666 Body, OriginalInits))
14667 return StmtError();
14668
14669 // Delay applying the transformation to when template is completely
14670 // instantiated.
14672 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14673 nullptr, nullptr);
14674
14675 assert(LoopHelpers.size() == NumLoops &&
14676 "Expecting a single-dimensional loop iteration space");
14677 assert(OriginalInits.size() == NumLoops &&
14678 "Expecting a single-dimensional loop iteration space");
14679 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14680
14681 // Find the loop statement.
14682 Stmt *LoopStmt = nullptr;
14683 collectLoopStmts(AStmt, {LoopStmt});
14684
14685 // Determine the PreInit declarations.
14686 SmallVector<Stmt *> PreInits;
14687 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14688
14689 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14690 QualType IVTy = IterationVarRef->getType();
14691 uint64_t IVWidth = Context.getTypeSize(IVTy);
14692 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14693
14694 // Iteration variable SourceLocations.
14695 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14696 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14697 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14698
14699 // Locations pointing to the transformation.
14700 SourceLocation TransformLoc = StartLoc;
14701 SourceLocation TransformLocBegin = StartLoc;
14702 SourceLocation TransformLocEnd = EndLoc;
14703
14704 // Internal variable names.
14705 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14706 SmallString<64> ForwardIVName(".forward.iv.");
14707 ForwardIVName += OrigVarName;
14708 SmallString<64> ReversedIVName(".reversed.iv.");
14709 ReversedIVName += OrigVarName;
14710
14711 // LoopHelper.Updates will read the logical iteration number from
14712 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
14713 // that logical iteration from it, then assign it to the user loop counter
14714 // variable. We cannot directly use LoopHelper.IterationVarRef as the
14715 // induction variable of the generated loop because it may cause an underflow:
14716 // \code{.c}
14717 // for (unsigned i = 0; i < n; ++i)
14718 // body(i);
14719 // \endcode
14720 //
14721 // Naive reversal:
14722 // \code{.c}
14723 // for (unsigned i = n-1; i >= 0; --i)
14724 // body(i);
14725 // \endcode
14726 //
14727 // Instead, we introduce a new iteration variable representing the logical
14728 // iteration counter of the original loop, convert it to the logical iteration
14729 // number of the reversed loop, then let LoopHelper.Updates compute the user's
14730 // loop iteration variable from it.
14731 // \code{.cpp}
14732 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
14733 // auto .reversed.iv = n - .forward.iv - 1;
14734 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
14735 // body(i); // Body
14736 // }
14737 // \endcode
14738
14739 // Subexpressions with more than one use. One of the constraints of an AST is
14740 // that every node object must appear at most once, hence we define a lambda
14741 // that creates a new AST node at every use.
14742 CaptureVars CopyTransformer(SemaRef);
14743 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14744 return AssertSuccess(
14745 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14746 };
14747
14748 // Create the iteration variable for the forward loop (from 0 to n-1).
14749 VarDecl *ForwardIVDecl =
14750 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
14751 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
14752 OrigVarLoc]() {
14753 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
14754 };
14755
14756 // Iteration variable for the reversed induction variable (from n-1 downto 0):
14757 // Reuse the iteration variable created by checkOpenMPLoop.
14758 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14759 ReversedIVDecl->setDeclName(
14760 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
14761
14762 // For init-statement:
14763 // \code{.cpp}
14764 // auto .forward.iv = 0;
14765 // \endcode
14766 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
14767 ForwardIVDecl->getType(), OrigVarLoc);
14768 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
14769 StmtResult Init = new (Context)
14770 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14771 if (!Init.isUsable())
14772 return StmtError();
14773
14774 // Forward iv cond-expression:
14775 // \code{.cpp}
14776 // .forward.iv < MakeNumIterations()
14777 // \endcode
14778 ExprResult Cond =
14779 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14780 MakeForwardRef(), MakeNumIterations());
14781 if (!Cond.isUsable())
14782 return StmtError();
14783
14784 // Forward incr-statement:
14785 // \code{.c}
14786 // ++.forward.iv
14787 // \endcode
14788 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
14789 UO_PreInc, MakeForwardRef());
14790 if (!Incr.isUsable())
14791 return StmtError();
14792
14793 // Reverse the forward-iv:
14794 // \code{.cpp}
14795 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
14796 // \endcode
14797 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
14798 TransformLoc);
14799 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
14800 MakeNumIterations(), One);
14801 if (!Minus.isUsable())
14802 return StmtError();
14803 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
14804 MakeForwardRef());
14805 if (!Minus.isUsable())
14806 return StmtError();
14807 StmtResult InitReversed = new (Context) DeclStmt(
14808 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14809 if (!InitReversed.isUsable())
14810 return StmtError();
14811 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
14812 /*DirectInit=*/false);
14813
14814 // The new loop body.
14815 SmallVector<Stmt *, 4> BodyStmts;
14816 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
14817 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14818 BodyStmts.push_back(InitReversed.get());
14819 llvm::append_range(BodyStmts, LoopHelper.Updates);
14820 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14821 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14822 BodyStmts.push_back(Body);
14823 auto *ReversedBody =
14824 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
14825 Body->getBeginLoc(), Body->getEndLoc());
14826
14827 // Finally create the reversed For-statement.
14828 auto *ReversedFor = new (Context)
14829 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
14830 ReversedBody, LoopHelper.Init->getBeginLoc(),
14831 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14832 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14833 ReversedFor,
14834 buildPreInits(Context, PreInits));
14835}
14836
14838 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14839 SourceLocation EndLoc) {
14840 ASTContext &Context = getASTContext();
14841 DeclContext *CurContext = SemaRef.CurContext;
14842 Scope *CurScope = SemaRef.getCurScope();
14843
14844 // Empty statement should only be possible if there already was an error.
14845 if (!AStmt)
14846 return StmtError();
14847
14848 // interchange without permutation clause swaps two loops.
14849 constexpr size_t NumLoops = 2;
14850
14851 // Verify and diagnose loop nest.
14853 Stmt *Body = nullptr;
14854 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
14855 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14856 LoopHelpers, Body, OriginalInits))
14857 return StmtError();
14858
14859 // Delay interchange to when template is completely instantiated.
14860 if (CurContext->isDependentContext())
14861 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14862 NumLoops, AStmt, nullptr, nullptr);
14863
14864 assert(LoopHelpers.size() == NumLoops &&
14865 "Expecting loop iteration space dimensionaly to match number of "
14866 "affected loops");
14867 assert(OriginalInits.size() == NumLoops &&
14868 "Expecting loop iteration space dimensionaly to match number of "
14869 "affected loops");
14870
14871 // Decode the permutation clause.
14872 constexpr uint64_t Permutation[] = {1, 0};
14873
14874 // Find the affected loops.
14875 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14876 collectLoopStmts(AStmt, LoopStmts);
14877
14878 // Collect pre-init statements on the order before the permuation.
14879 SmallVector<Stmt *> PreInits;
14880 for (auto I : llvm::seq<int>(NumLoops)) {
14881 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14882
14883 assert(LoopHelper.Counters.size() == 1 &&
14884 "Single-dimensional loop iteration space expected");
14885 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14886
14887 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14888 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14889 PreInits);
14890 }
14891
14892 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
14893 CaptureVars CopyTransformer(SemaRef);
14894
14895 // Create the permuted loops from the inside to the outside of the
14896 // interchanged loop nest. Body of the innermost new loop is the original
14897 // innermost body.
14898 Stmt *Inner = Body;
14899 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
14900 // Get the original loop that belongs to this new position.
14901 uint64_t SourceIdx = Permutation[TargetIdx];
14902 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
14903 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
14904 assert(SourceHelper.Counters.size() == 1 &&
14905 "Single-dimensional loop iteration space expected");
14906 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
14907
14908 // Normalized loop counter variable: From 0 to n-1, always an integer type.
14909 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
14910 QualType IVTy = IterVarRef->getType();
14911 assert(IVTy->isIntegerType() &&
14912 "Expected the logical iteration counter to be an integer");
14913
14914 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14915 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
14916
14917 // Make a copy of the NumIterations expression for each use: By the AST
14918 // constraints, every expression object in a DeclContext must be unique.
14919 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
14920 return AssertSuccess(
14921 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
14922 };
14923
14924 // Iteration variable for the permuted loop. Reuse the one from
14925 // checkOpenMPLoop which will also be used to update the original loop
14926 // variable.
14927 SmallString<64> PermutedCntName(".permuted_");
14928 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
14929 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14930 PermutedCntDecl->setDeclName(
14931 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
14932 PermutedIndVars[TargetIdx] = PermutedCntDecl;
14933 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
14934 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
14935 };
14936
14937 // For init-statement:
14938 // \code
14939 // auto .permuted_{target}.iv = 0
14940 // \endcode
14941 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
14942 if (!Zero.isUsable())
14943 return StmtError();
14944 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
14945 /*DirectInit=*/false);
14946 StmtResult InitStmt = new (Context)
14947 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
14948 OrigCntVar->getEndLoc());
14949 if (!InitStmt.isUsable())
14950 return StmtError();
14951
14952 // For cond-expression:
14953 // \code
14954 // .permuted_{target}.iv < MakeNumIterations()
14955 // \endcode
14956 ExprResult CondExpr =
14957 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
14958 MakePermutedRef(), MakeNumIterations());
14959 if (!CondExpr.isUsable())
14960 return StmtError();
14961
14962 // For incr-statement:
14963 // \code
14964 // ++.tile.iv
14965 // \endcode
14966 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14967 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
14968 if (!IncrStmt.isUsable())
14969 return StmtError();
14970
14971 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
14972 SourceHelper.Updates.end());
14973 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
14974 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14975 BodyParts.push_back(Inner);
14976 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14977 Inner->getBeginLoc(), Inner->getEndLoc());
14978 Inner = new (Context) ForStmt(
14979 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
14980 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
14981 SourceHelper.Inc->getEndLoc());
14982 }
14983
14984 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14985 NumLoops, AStmt, Inner,
14986 buildPreInits(Context, PreInits));
14987}
14988
14990 Expr *Expr,
14991 SourceLocation StartLoc,
14992 SourceLocation LParenLoc,
14993 SourceLocation EndLoc) {
14994 OMPClause *Res = nullptr;
14995 switch (Kind) {
14996 case OMPC_final:
14997 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
14998 break;
14999 case OMPC_num_threads:
15000 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15001 break;
15002 case OMPC_safelen:
15003 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15004 break;
15005 case OMPC_simdlen:
15006 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15007 break;
15008 case OMPC_allocator:
15009 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15010 break;
15011 case OMPC_collapse:
15012 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15013 break;
15014 case OMPC_ordered:
15015 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15016 break;
15017 case OMPC_priority:
15018 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15019 break;
15020 case OMPC_hint:
15021 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15022 break;
15023 case OMPC_depobj:
15024 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15025 break;
15026 case OMPC_detach:
15027 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15028 break;
15029 case OMPC_novariants:
15030 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15031 break;
15032 case OMPC_nocontext:
15033 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15034 break;
15035 case OMPC_filter:
15036 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15037 break;
15038 case OMPC_partial:
15039 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15040 break;
15041 case OMPC_message:
15042 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15043 break;
15044 case OMPC_align:
15045 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15046 break;
15047 case OMPC_ompx_dyn_cgroup_mem:
15048 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15049 break;
15050 case OMPC_holds:
15051 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
15052 break;
15053 case OMPC_grainsize:
15054 case OMPC_num_tasks:
15055 case OMPC_device:
15056 case OMPC_if:
15057 case OMPC_default:
15058 case OMPC_proc_bind:
15059 case OMPC_schedule:
15060 case OMPC_private:
15061 case OMPC_firstprivate:
15062 case OMPC_lastprivate:
15063 case OMPC_shared:
15064 case OMPC_reduction:
15065 case OMPC_task_reduction:
15066 case OMPC_in_reduction:
15067 case OMPC_linear:
15068 case OMPC_aligned:
15069 case OMPC_copyin:
15070 case OMPC_copyprivate:
15071 case OMPC_nowait:
15072 case OMPC_untied:
15073 case OMPC_mergeable:
15074 case OMPC_threadprivate:
15075 case OMPC_sizes:
15076 case OMPC_allocate:
15077 case OMPC_flush:
15078 case OMPC_read:
15079 case OMPC_write:
15080 case OMPC_update:
15081 case OMPC_capture:
15082 case OMPC_compare:
15083 case OMPC_seq_cst:
15084 case OMPC_acq_rel:
15085 case OMPC_acquire:
15086 case OMPC_release:
15087 case OMPC_relaxed:
15088 case OMPC_depend:
15089 case OMPC_threads:
15090 case OMPC_simd:
15091 case OMPC_map:
15092 case OMPC_nogroup:
15093 case OMPC_dist_schedule:
15094 case OMPC_defaultmap:
15095 case OMPC_unknown:
15096 case OMPC_uniform:
15097 case OMPC_to:
15098 case OMPC_from:
15099 case OMPC_use_device_ptr:
15100 case OMPC_use_device_addr:
15101 case OMPC_is_device_ptr:
15102 case OMPC_unified_address:
15103 case OMPC_unified_shared_memory:
15104 case OMPC_reverse_offload:
15105 case OMPC_dynamic_allocators:
15106 case OMPC_atomic_default_mem_order:
15107 case OMPC_device_type:
15108 case OMPC_match:
15109 case OMPC_nontemporal:
15110 case OMPC_order:
15111 case OMPC_at:
15112 case OMPC_severity:
15113 case OMPC_destroy:
15114 case OMPC_inclusive:
15115 case OMPC_exclusive:
15116 case OMPC_uses_allocators:
15117 case OMPC_affinity:
15118 case OMPC_when:
15119 case OMPC_bind:
15120 case OMPC_num_teams:
15121 case OMPC_thread_limit:
15122 default:
15123 llvm_unreachable("Clause is not allowed.");
15124 }
15125 return Res;
15126}
15127
15128// An OpenMP directive such as 'target parallel' has two captured regions:
15129// for the 'target' and 'parallel' respectively. This function returns
15130// the region in which to capture expressions associated with a clause.
15131// A return value of OMPD_unknown signifies that the expression should not
15132// be captured.
15134 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15135 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15136 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15137 "Invalid directive with CKind-clause");
15138
15139 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15140 if (NameModifier != OMPD_unknown &&
15141 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15142 return OMPD_unknown;
15143
15144 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15145
15146 // [5.2:341:24-30]
15147 // If the clauses have expressions on them, such as for various clauses where
15148 // the argument of the clause is an expression, or lower-bound, length, or
15149 // stride expressions inside array sections (or subscript and stride
15150 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15151 // expressions, the expressions are evaluated immediately before the construct
15152 // to which the clause has been split or duplicated per the above rules
15153 // (therefore inside of the outer leaf constructs). However, the expressions
15154 // inside the num_teams and thread_limit clauses are always evaluated before
15155 // the outermost leaf construct.
15156
15157 // Process special cases first.
15158 switch (CKind) {
15159 case OMPC_if:
15160 switch (DKind) {
15161 case OMPD_teams_loop:
15162 case OMPD_target_teams_loop:
15163 // For [target] teams loop, assume capture region is 'teams' so it's
15164 // available for codegen later to use if/when necessary.
15165 return OMPD_teams;
15166 case OMPD_target_update:
15167 case OMPD_target_enter_data:
15168 case OMPD_target_exit_data:
15169 return OMPD_task;
15170 default:
15171 break;
15172 }
15173 break;
15174 case OMPC_num_teams:
15175 case OMPC_thread_limit:
15176 case OMPC_ompx_dyn_cgroup_mem:
15177 if (Leafs[0] == OMPD_target)
15178 return OMPD_target;
15179 break;
15180 case OMPC_device:
15181 if (Leafs[0] == OMPD_target ||
15182 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15183 OMPD_target_enter_data, OMPD_target_exit_data},
15184 DKind))
15185 return OMPD_task;
15186 break;
15187 case OMPC_novariants:
15188 case OMPC_nocontext:
15189 if (DKind == OMPD_dispatch)
15190 return OMPD_task;
15191 break;
15192 case OMPC_when:
15193 if (DKind == OMPD_metadirective)
15194 return OMPD_metadirective;
15195 break;
15196 case OMPC_filter:
15197 return OMPD_unknown;
15198 default:
15199 break;
15200 }
15201
15202 // If none of the special cases above applied, and DKind is a capturing
15203 // directive, find the innermost enclosing leaf construct that allows the
15204 // clause, and returns the corresponding capture region.
15205
15206 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15207 // Find the index in "Leafs" of the last leaf that allows the given
15208 // clause. The search will only include indexes [0, EndIdx).
15209 // EndIdx may be set to the index of the NameModifier, if present.
15210 int InnermostIdx = [&]() {
15211 for (int I = EndIdx - 1; I >= 0; --I) {
15212 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15213 return I;
15214 }
15215 return -1;
15216 }();
15217
15218 // Find the nearest enclosing capture region.
15220 for (int I = InnermostIdx - 1; I >= 0; --I) {
15221 if (!isOpenMPCapturingDirective(Leafs[I]))
15222 continue;
15223 Regions.clear();
15224 getOpenMPCaptureRegions(Regions, Leafs[I]);
15225 if (Regions[0] != OMPD_unknown)
15226 return Regions.back();
15227 }
15228 return OMPD_unknown;
15229 };
15230
15231 if (isOpenMPCapturingDirective(DKind)) {
15232 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15233 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15234 if (Leafs[I] == Dir)
15235 return I + 1;
15236 }
15237 return 0;
15238 };
15239
15240 int End = NameModifier == OMPD_unknown ? Leafs.size()
15241 : GetLeafIndex(NameModifier);
15242 return GetEnclosingRegion(End, CKind);
15243 }
15244
15245 return OMPD_unknown;
15246}
15247
15249 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15250 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15251 SourceLocation ColonLoc, SourceLocation EndLoc) {
15252 Expr *ValExpr = Condition;
15253 Stmt *HelperValStmt = nullptr;
15254 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15255 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15256 !Condition->isInstantiationDependent() &&
15257 !Condition->containsUnexpandedParameterPack()) {
15259 if (Val.isInvalid())
15260 return nullptr;
15261
15262 ValExpr = Val.get();
15263
15264 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15265 CaptureRegion = getOpenMPCaptureRegionForClause(
15266 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15267 if (CaptureRegion != OMPD_unknown &&
15269 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15270 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15271 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15272 HelperValStmt = buildPreInits(getASTContext(), Captures);
15273 }
15274 }
15275
15276 return new (getASTContext())
15277 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15278 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15279}
15280
15282 SourceLocation StartLoc,
15283 SourceLocation LParenLoc,
15284 SourceLocation EndLoc) {
15285 Expr *ValExpr = Condition;
15286 Stmt *HelperValStmt = nullptr;
15287 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15288 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15289 !Condition->isInstantiationDependent() &&
15290 !Condition->containsUnexpandedParameterPack()) {
15292 if (Val.isInvalid())
15293 return nullptr;
15294
15295 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
15296
15297 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15298 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15299 getLangOpts().OpenMP);
15300 if (CaptureRegion != OMPD_unknown &&
15302 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15303 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15304 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15305 HelperValStmt = buildPreInits(getASTContext(), Captures);
15306 }
15307 }
15308
15309 return new (getASTContext()) OMPFinalClause(
15310 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15311}
15312
15315 Expr *Op) {
15316 if (!Op)
15317 return ExprError();
15318
15319 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15320 public:
15321 IntConvertDiagnoser()
15322 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
15323 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15324 QualType T) override {
15325 return S.Diag(Loc, diag::err_omp_not_integral) << T;
15326 }
15327 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15328 QualType T) override {
15329 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15330 }
15331 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15332 QualType T,
15333 QualType ConvTy) override {
15334 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15335 }
15336 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15337 QualType ConvTy) override {
15338 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15339 << ConvTy->isEnumeralType() << ConvTy;
15340 }
15341 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15342 QualType T) override {
15343 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15344 }
15345 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15346 QualType ConvTy) override {
15347 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15348 << ConvTy->isEnumeralType() << ConvTy;
15349 }
15350 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15351 QualType) override {
15352 llvm_unreachable("conversion functions are permitted");
15353 }
15354 } ConvertDiagnoser;
15355 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
15356}
15357
15358static bool
15360 bool StrictlyPositive, bool BuildCapture = false,
15361 OpenMPDirectiveKind DKind = OMPD_unknown,
15362 OpenMPDirectiveKind *CaptureRegion = nullptr,
15363 Stmt **HelperValStmt = nullptr) {
15364 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15365 !ValExpr->isInstantiationDependent()) {
15366 SourceLocation Loc = ValExpr->getExprLoc();
15369 if (Value.isInvalid())
15370 return false;
15371
15372 ValExpr = Value.get();
15373 // The expression must evaluate to a non-negative integer value.
15374 if (std::optional<llvm::APSInt> Result =
15375 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
15376 if (Result->isSigned() &&
15377 !((!StrictlyPositive && Result->isNonNegative()) ||
15378 (StrictlyPositive && Result->isStrictlyPositive()))) {
15379 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15380 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15381 << ValExpr->getSourceRange();
15382 return false;
15383 }
15384 }
15385 if (!BuildCapture)
15386 return true;
15387 *CaptureRegion =
15388 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15389 if (*CaptureRegion != OMPD_unknown &&
15390 !SemaRef.CurContext->isDependentContext()) {
15391 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15392 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15393 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15394 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
15395 }
15396 }
15397 return true;
15398}
15399
15401 SourceLocation StartLoc,
15402 SourceLocation LParenLoc,
15403 SourceLocation EndLoc) {
15404 Expr *ValExpr = NumThreads;
15405 Stmt *HelperValStmt = nullptr;
15406
15407 // OpenMP [2.5, Restrictions]
15408 // The num_threads expression must evaluate to a positive integer value.
15409 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15410 /*StrictlyPositive=*/true))
15411 return nullptr;
15412
15413 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15415 DKind, OMPC_num_threads, getLangOpts().OpenMP);
15416 if (CaptureRegion != OMPD_unknown &&
15418 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15419 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15420 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15421 HelperValStmt = buildPreInits(getASTContext(), Captures);
15422 }
15423
15424 return new (getASTContext()) OMPNumThreadsClause(
15425 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15426}
15427
15429 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15430 bool SuppressExprDiags) {
15431 if (!E)
15432 return ExprError();
15433 if (E->isValueDependent() || E->isTypeDependent() ||
15435 return E;
15436
15437 llvm::APSInt Result;
15438 ExprResult ICE;
15439 if (SuppressExprDiags) {
15440 // Use a custom diagnoser that suppresses 'note' diagnostics about the
15441 // expression.
15442 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15443 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15445 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15446 llvm_unreachable("Diagnostic suppressed");
15447 }
15448 } Diagnoser;
15451 } else {
15453 /*FIXME*/ Sema::AllowFold);
15454 }
15455 if (ICE.isInvalid())
15456 return ExprError();
15457
15458 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
15459 (!StrictlyPositive && !Result.isNonNegative())) {
15460 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
15461 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15462 << E->getSourceRange();
15463 return ExprError();
15464 }
15465 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
15466 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
15467 << E->getSourceRange();
15468 return ExprError();
15469 }
15470 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
15471 DSAStack->setAssociatedLoops(Result.getExtValue());
15472 else if (CKind == OMPC_ordered)
15473 DSAStack->setAssociatedLoops(Result.getExtValue());
15474 return ICE;
15475}
15476
15478 SourceLocation StartLoc,
15479 SourceLocation LParenLoc,
15480 SourceLocation EndLoc) {
15481 // OpenMP [2.8.1, simd construct, Description]
15482 // The parameter of the safelen clause must be a constant
15483 // positive integer expression.
15484 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
15485 if (Safelen.isInvalid())
15486 return nullptr;
15487 return new (getASTContext())
15488 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
15489}
15490
15492 SourceLocation StartLoc,
15493 SourceLocation LParenLoc,
15494 SourceLocation EndLoc) {
15495 // OpenMP [2.8.1, simd construct, Description]
15496 // The parameter of the simdlen clause must be a constant
15497 // positive integer expression.
15498 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
15499 if (Simdlen.isInvalid())
15500 return nullptr;
15501 return new (getASTContext())
15502 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
15503}
15504
15505/// Tries to find omp_allocator_handle_t type.
15507 DSAStackTy *Stack) {
15508 if (!Stack->getOMPAllocatorHandleT().isNull())
15509 return true;
15510
15511 // Set the allocator handle type.
15512 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
15513 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
15514 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
15515 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15516 << "omp_allocator_handle_t";
15517 return false;
15518 }
15519 QualType AllocatorHandleEnumTy = PT.get();
15520 AllocatorHandleEnumTy.addConst();
15521 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15522
15523 // Fill the predefined allocator map.
15524 bool ErrorFound = false;
15525 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15526 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
15527 StringRef Allocator =
15528 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15529 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
15530 auto *VD = dyn_cast_or_null<ValueDecl>(
15531 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
15532 if (!VD) {
15533 ErrorFound = true;
15534 break;
15535 }
15536 QualType AllocatorType =
15538 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
15539 if (!Res.isUsable()) {
15540 ErrorFound = true;
15541 break;
15542 }
15543 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
15545 /* AllowExplicit */ true);
15546 if (!Res.isUsable()) {
15547 ErrorFound = true;
15548 break;
15549 }
15550 Stack->setAllocator(AllocatorKind, Res.get());
15551 }
15552 if (ErrorFound) {
15553 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15554 << "omp_allocator_handle_t";
15555 return false;
15556 }
15557
15558 return true;
15559}
15560
15562 SourceLocation StartLoc,
15563 SourceLocation LParenLoc,
15564 SourceLocation EndLoc) {
15565 // OpenMP [2.11.3, allocate Directive, Description]
15566 // allocator is an expression of omp_allocator_handle_t type.
15568 return nullptr;
15569
15571 if (Allocator.isInvalid())
15572 return nullptr;
15574 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
15576 /*AllowExplicit=*/true);
15577 if (Allocator.isInvalid())
15578 return nullptr;
15579 return new (getASTContext())
15580 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
15581}
15582
15584 SourceLocation StartLoc,
15585 SourceLocation LParenLoc,
15586 SourceLocation EndLoc) {
15587 // OpenMP [2.7.1, loop construct, Description]
15588 // OpenMP [2.8.1, simd construct, Description]
15589 // OpenMP [2.9.6, distribute construct, Description]
15590 // The parameter of the collapse clause must be a constant
15591 // positive integer expression.
15592 ExprResult NumForLoopsResult =
15593 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
15594 if (NumForLoopsResult.isInvalid())
15595 return nullptr;
15596 return new (getASTContext())
15597 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
15598}
15599
15601 SourceLocation EndLoc,
15602 SourceLocation LParenLoc,
15603 Expr *NumForLoops) {
15604 // OpenMP [2.7.1, loop construct, Description]
15605 // OpenMP [2.8.1, simd construct, Description]
15606 // OpenMP [2.9.6, distribute construct, Description]
15607 // The parameter of the ordered clause must be a constant
15608 // positive integer expression if any.
15609 if (NumForLoops && LParenLoc.isValid()) {
15610 ExprResult NumForLoopsResult =
15611 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
15612 if (NumForLoopsResult.isInvalid())
15613 return nullptr;
15614 NumForLoops = NumForLoopsResult.get();
15615 } else {
15616 NumForLoops = nullptr;
15617 }
15618 auto *Clause =
15620 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
15621 StartLoc, LParenLoc, EndLoc);
15622 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
15623 return Clause;
15624}
15625
15627 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
15628 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15629 OMPClause *Res = nullptr;
15630 switch (Kind) {
15631 case OMPC_default:
15632 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
15633 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15634 break;
15635 case OMPC_proc_bind:
15636 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
15637 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15638 break;
15639 case OMPC_atomic_default_mem_order:
15641 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
15642 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15643 break;
15644 case OMPC_fail:
15645 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
15646 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15647 break;
15648 case OMPC_update:
15649 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
15650 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15651 break;
15652 case OMPC_bind:
15653 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
15654 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15655 break;
15656 case OMPC_at:
15657 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
15658 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15659 break;
15660 case OMPC_severity:
15662 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
15663 LParenLoc, EndLoc);
15664 break;
15665 case OMPC_if:
15666 case OMPC_final:
15667 case OMPC_num_threads:
15668 case OMPC_safelen:
15669 case OMPC_simdlen:
15670 case OMPC_sizes:
15671 case OMPC_allocator:
15672 case OMPC_collapse:
15673 case OMPC_schedule:
15674 case OMPC_private:
15675 case OMPC_firstprivate:
15676 case OMPC_lastprivate:
15677 case OMPC_shared:
15678 case OMPC_reduction:
15679 case OMPC_task_reduction:
15680 case OMPC_in_reduction:
15681 case OMPC_linear:
15682 case OMPC_aligned:
15683 case OMPC_copyin:
15684 case OMPC_copyprivate:
15685 case OMPC_ordered:
15686 case OMPC_nowait:
15687 case OMPC_untied:
15688 case OMPC_mergeable:
15689 case OMPC_threadprivate:
15690 case OMPC_allocate:
15691 case OMPC_flush:
15692 case OMPC_depobj:
15693 case OMPC_read:
15694 case OMPC_write:
15695 case OMPC_capture:
15696 case OMPC_compare:
15697 case OMPC_seq_cst:
15698 case OMPC_acq_rel:
15699 case OMPC_acquire:
15700 case OMPC_release:
15701 case OMPC_relaxed:
15702 case OMPC_depend:
15703 case OMPC_device:
15704 case OMPC_threads:
15705 case OMPC_simd:
15706 case OMPC_map:
15707 case OMPC_num_teams:
15708 case OMPC_thread_limit:
15709 case OMPC_priority:
15710 case OMPC_grainsize:
15711 case OMPC_nogroup:
15712 case OMPC_num_tasks:
15713 case OMPC_hint:
15714 case OMPC_dist_schedule:
15715 case OMPC_defaultmap:
15716 case OMPC_unknown:
15717 case OMPC_uniform:
15718 case OMPC_to:
15719 case OMPC_from:
15720 case OMPC_use_device_ptr:
15721 case OMPC_use_device_addr:
15722 case OMPC_is_device_ptr:
15723 case OMPC_has_device_addr:
15724 case OMPC_unified_address:
15725 case OMPC_unified_shared_memory:
15726 case OMPC_reverse_offload:
15727 case OMPC_dynamic_allocators:
15728 case OMPC_device_type:
15729 case OMPC_match:
15730 case OMPC_nontemporal:
15731 case OMPC_destroy:
15732 case OMPC_novariants:
15733 case OMPC_nocontext:
15734 case OMPC_detach:
15735 case OMPC_inclusive:
15736 case OMPC_exclusive:
15737 case OMPC_uses_allocators:
15738 case OMPC_affinity:
15739 case OMPC_when:
15740 case OMPC_message:
15741 default:
15742 llvm_unreachable("Clause is not allowed.");
15743 }
15744 return Res;
15745}
15746
15747static std::string
15749 ArrayRef<unsigned> Exclude = std::nullopt) {
15750 SmallString<256> Buffer;
15751 llvm::raw_svector_ostream Out(Buffer);
15752 unsigned Skipped = Exclude.size();
15753 for (unsigned I = First; I < Last; ++I) {
15754 if (llvm::is_contained(Exclude, I)) {
15755 --Skipped;
15756 continue;
15757 }
15758 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15759 if (I + Skipped + 2 == Last)
15760 Out << " or ";
15761 else if (I + Skipped + 1 != Last)
15762 Out << ", ";
15763 }
15764 return std::string(Out.str());
15765}
15766
15768 SourceLocation KindKwLoc,
15769 SourceLocation StartLoc,
15770 SourceLocation LParenLoc,
15771 SourceLocation EndLoc) {
15772 if (Kind == OMP_DEFAULT_unknown) {
15773 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15774 << getListOfPossibleValues(OMPC_default, /*First=*/0,
15775 /*Last=*/unsigned(OMP_DEFAULT_unknown))
15776 << getOpenMPClauseName(OMPC_default);
15777 return nullptr;
15778 }
15779
15780 switch (Kind) {
15781 case OMP_DEFAULT_none:
15782 DSAStack->setDefaultDSANone(KindKwLoc);
15783 break;
15784 case OMP_DEFAULT_shared:
15785 DSAStack->setDefaultDSAShared(KindKwLoc);
15786 break;
15787 case OMP_DEFAULT_firstprivate:
15788 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15789 break;
15790 case OMP_DEFAULT_private:
15791 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15792 break;
15793 default:
15794 llvm_unreachable("DSA unexpected in OpenMP default clause");
15795 }
15796
15797 return new (getASTContext())
15798 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15799}
15800
15802 SourceLocation KindKwLoc,
15803 SourceLocation StartLoc,
15804 SourceLocation LParenLoc,
15805 SourceLocation EndLoc) {
15806 if (Kind == OMP_PROC_BIND_unknown) {
15807 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15808 << getListOfPossibleValues(OMPC_proc_bind,
15809 /*First=*/unsigned(OMP_PROC_BIND_master),
15810 /*Last=*/
15811 unsigned(getLangOpts().OpenMP > 50
15812 ? OMP_PROC_BIND_primary
15813 : OMP_PROC_BIND_spread) +
15814 1)
15815 << getOpenMPClauseName(OMPC_proc_bind);
15816 return nullptr;
15817 }
15818 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
15819 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15820 << getListOfPossibleValues(OMPC_proc_bind,
15821 /*First=*/unsigned(OMP_PROC_BIND_master),
15822 /*Last=*/
15823 unsigned(OMP_PROC_BIND_spread) + 1)
15824 << getOpenMPClauseName(OMPC_proc_bind);
15825 return new (getASTContext())
15826 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15827}
15828
15831 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15833 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15835 OMPC_atomic_default_mem_order, /*First=*/0,
15837 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15838 return nullptr;
15839 }
15841 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15842}
15843
15845 SourceLocation KindKwLoc,
15846 SourceLocation StartLoc,
15847 SourceLocation LParenLoc,
15848 SourceLocation EndLoc) {
15849 if (Kind == OMPC_AT_unknown) {
15850 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15851 << getListOfPossibleValues(OMPC_at, /*First=*/0,
15852 /*Last=*/OMPC_AT_unknown)
15853 << getOpenMPClauseName(OMPC_at);
15854 return nullptr;
15855 }
15856 return new (getASTContext())
15857 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15858}
15859
15861 SourceLocation KindKwLoc,
15862 SourceLocation StartLoc,
15863 SourceLocation LParenLoc,
15864 SourceLocation EndLoc) {
15865 if (Kind == OMPC_SEVERITY_unknown) {
15866 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15867 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
15868 /*Last=*/OMPC_SEVERITY_unknown)
15869 << getOpenMPClauseName(OMPC_severity);
15870 return nullptr;
15871 }
15872 return new (getASTContext())
15873 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15874}
15875
15877 SourceLocation StartLoc,
15878 SourceLocation LParenLoc,
15879 SourceLocation EndLoc) {
15880 assert(ME && "NULL expr in Message clause");
15881 if (!isa<StringLiteral>(ME)) {
15882 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
15883 << getOpenMPClauseName(OMPC_message);
15884 return nullptr;
15885 }
15886 return new (getASTContext())
15887 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
15888}
15889
15892 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
15893 SourceLocation KindLoc, SourceLocation EndLoc) {
15894 if (Kind != OMPC_ORDER_concurrent ||
15895 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
15896 // Kind should be concurrent,
15897 // Modifiers introduced in OpenMP 5.1
15898 static_assert(OMPC_ORDER_unknown > 0,
15899 "OMPC_ORDER_unknown not greater than 0");
15900
15901 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
15902 << getListOfPossibleValues(OMPC_order,
15903 /*First=*/0,
15904 /*Last=*/OMPC_ORDER_unknown)
15905 << getOpenMPClauseName(OMPC_order);
15906 return nullptr;
15907 }
15908 if (getLangOpts().OpenMP >= 51) {
15909 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
15910 Diag(MLoc, diag::err_omp_unexpected_clause_value)
15911 << getListOfPossibleValues(OMPC_order,
15912 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
15913 /*Last=*/OMPC_ORDER_MODIFIER_last)
15914 << getOpenMPClauseName(OMPC_order);
15915 } else {
15916 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
15917 if (DSAStack->getCurScope()) {
15918 // mark the current scope with 'order' flag
15919 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
15920 DSAStack->getCurScope()->setFlags(existingFlags |
15922 }
15923 }
15924 }
15925 return new (getASTContext()) OMPOrderClause(
15926 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
15927}
15928
15930 SourceLocation KindKwLoc,
15931 SourceLocation StartLoc,
15932 SourceLocation LParenLoc,
15933 SourceLocation EndLoc) {
15934 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
15935 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
15936 SmallVector<unsigned> Except = {
15937 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
15938 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
15939 if (getLangOpts().OpenMP < 51)
15940 Except.push_back(OMPC_DEPEND_inoutset);
15941 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15942 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
15943 /*Last=*/OMPC_DEPEND_unknown, Except)
15944 << getOpenMPClauseName(OMPC_update);
15945 return nullptr;
15946 }
15947 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
15948 KindKwLoc, Kind, EndLoc);
15949}
15950
15952 SourceLocation StartLoc,
15953 SourceLocation LParenLoc,
15954 SourceLocation EndLoc) {
15955 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
15956
15957 for (Expr *&SizeExpr : SanitizedSizeExprs) {
15958 // Skip if already sanitized, e.g. during a partial template instantiation.
15959 if (!SizeExpr)
15960 continue;
15961
15962 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
15963 /*StrictlyPositive=*/true);
15964
15965 // isNonNegativeIntegerValue returns true for non-integral types (but still
15966 // emits error diagnostic), so check for the expected type explicitly.
15967 QualType SizeTy = SizeExpr->getType();
15968 if (!SizeTy->isIntegerType())
15969 IsValid = false;
15970
15971 // Handling in templates is tricky. There are four possibilities to
15972 // consider:
15973 //
15974 // 1a. The expression is valid and we are in a instantiated template or not
15975 // in a template:
15976 // Pass valid expression to be further analysed later in Sema.
15977 // 1b. The expression is valid and we are in a template (including partial
15978 // instantiation):
15979 // isNonNegativeIntegerValue skipped any checks so there is no
15980 // guarantee it will be correct after instantiation.
15981 // ActOnOpenMPSizesClause will be called again at instantiation when
15982 // it is not in a dependent context anymore. This may cause warnings
15983 // to be emitted multiple times.
15984 // 2a. The expression is invalid and we are in an instantiated template or
15985 // not in a template:
15986 // Invalidate the expression with a clearly wrong value (nullptr) so
15987 // later in Sema we do not have to do the same validity analysis again
15988 // or crash from unexpected data. Error diagnostics have already been
15989 // emitted.
15990 // 2b. The expression is invalid and we are in a template (including partial
15991 // instantiation):
15992 // Pass the invalid expression as-is, template instantiation may
15993 // replace unexpected types/values with valid ones. The directives
15994 // with this clause must not try to use these expressions in dependent
15995 // contexts, but delay analysis until full instantiation.
15996 if (!SizeExpr->isInstantiationDependent() && !IsValid)
15997 SizeExpr = nullptr;
15998 }
15999
16000 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16001 SanitizedSizeExprs);
16002}
16003
16005 SourceLocation EndLoc) {
16006 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16007}
16008
16010 SourceLocation StartLoc,
16011 SourceLocation LParenLoc,
16012 SourceLocation EndLoc) {
16013 if (FactorExpr) {
16014 // If an argument is specified, it must be a constant (or an unevaluated
16015 // template expression).
16017 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16018 if (FactorResult.isInvalid())
16019 return nullptr;
16020 FactorExpr = FactorResult.get();
16021 }
16022
16023 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16024 FactorExpr);
16025}
16026
16028 SourceLocation LParenLoc,
16029 SourceLocation EndLoc) {
16030 ExprResult AlignVal;
16031 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16032 if (AlignVal.isInvalid())
16033 return nullptr;
16034 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16035 LParenLoc, EndLoc);
16036}
16037
16040 SourceLocation StartLoc, SourceLocation LParenLoc,
16041 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16042 SourceLocation EndLoc) {
16043 OMPClause *Res = nullptr;
16044 switch (Kind) {
16045 case OMPC_schedule:
16046 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16047 assert(Argument.size() == NumberOfElements &&
16048 ArgumentLoc.size() == NumberOfElements);
16050 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16051 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16052 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16053 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16054 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16055 break;
16056 case OMPC_if:
16057 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16058 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16059 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16060 DelimLoc, EndLoc);
16061 break;
16062 case OMPC_dist_schedule:
16064 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16065 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16066 break;
16067 case OMPC_defaultmap:
16068 enum { Modifier, DefaultmapKind };
16070 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16071 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16072 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16073 EndLoc);
16074 break;
16075 case OMPC_order:
16076 enum { OrderModifier, OrderKind };
16078 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16079 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16080 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16081 break;
16082 case OMPC_device:
16083 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16085 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16086 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16087 break;
16088 case OMPC_grainsize:
16089 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16090 "Modifier for grainsize clause and its location are expected.");
16092 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16093 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16094 break;
16095 case OMPC_num_tasks:
16096 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16097 "Modifier for num_tasks clause and its location are expected.");
16099 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16100 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16101 break;
16102 case OMPC_final:
16103 case OMPC_num_threads:
16104 case OMPC_safelen:
16105 case OMPC_simdlen:
16106 case OMPC_sizes:
16107 case OMPC_allocator:
16108 case OMPC_collapse:
16109 case OMPC_default:
16110 case OMPC_proc_bind:
16111 case OMPC_private:
16112 case OMPC_firstprivate:
16113 case OMPC_lastprivate:
16114 case OMPC_shared:
16115 case OMPC_reduction:
16116 case OMPC_task_reduction:
16117 case OMPC_in_reduction:
16118 case OMPC_linear:
16119 case OMPC_aligned:
16120 case OMPC_copyin:
16121 case OMPC_copyprivate:
16122 case OMPC_ordered:
16123 case OMPC_nowait:
16124 case OMPC_untied:
16125 case OMPC_mergeable:
16126 case OMPC_threadprivate:
16127 case OMPC_allocate:
16128 case OMPC_flush:
16129 case OMPC_depobj:
16130 case OMPC_read:
16131 case OMPC_write:
16132 case OMPC_update:
16133 case OMPC_capture:
16134 case OMPC_compare:
16135 case OMPC_seq_cst:
16136 case OMPC_acq_rel:
16137 case OMPC_acquire:
16138 case OMPC_release:
16139 case OMPC_relaxed:
16140 case OMPC_depend:
16141 case OMPC_threads:
16142 case OMPC_simd:
16143 case OMPC_map:
16144 case OMPC_num_teams:
16145 case OMPC_thread_limit:
16146 case OMPC_priority:
16147 case OMPC_nogroup:
16148 case OMPC_hint:
16149 case OMPC_unknown:
16150 case OMPC_uniform:
16151 case OMPC_to:
16152 case OMPC_from:
16153 case OMPC_use_device_ptr:
16154 case OMPC_use_device_addr:
16155 case OMPC_is_device_ptr:
16156 case OMPC_has_device_addr:
16157 case OMPC_unified_address:
16158 case OMPC_unified_shared_memory:
16159 case OMPC_reverse_offload:
16160 case OMPC_dynamic_allocators:
16161 case OMPC_atomic_default_mem_order:
16162 case OMPC_device_type:
16163 case OMPC_match:
16164 case OMPC_nontemporal:
16165 case OMPC_at:
16166 case OMPC_severity:
16167 case OMPC_message:
16168 case OMPC_destroy:
16169 case OMPC_novariants:
16170 case OMPC_nocontext:
16171 case OMPC_detach:
16172 case OMPC_inclusive:
16173 case OMPC_exclusive:
16174 case OMPC_uses_allocators:
16175 case OMPC_affinity:
16176 case OMPC_when:
16177 case OMPC_bind:
16178 default:
16179 llvm_unreachable("Clause is not allowed.");
16180 }
16181 return Res;
16182}
16183
16186 SourceLocation M1Loc, SourceLocation M2Loc) {
16187 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16188 SmallVector<unsigned, 2> Excluded;
16190 Excluded.push_back(M2);
16191 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16192 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16193 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16194 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16195 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16196 << getListOfPossibleValues(OMPC_schedule,
16197 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16199 Excluded)
16200 << getOpenMPClauseName(OMPC_schedule);
16201 return true;
16202 }
16203 return false;
16204}
16205
16208 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16209 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16210 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16211 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16212 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16213 return nullptr;
16214 // OpenMP, 2.7.1, Loop Construct, Restrictions
16215 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16216 // but not both.
16217 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16218 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16219 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16220 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16221 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16222 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16223 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16224 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16225 return nullptr;
16226 }
16227 if (Kind == OMPC_SCHEDULE_unknown) {
16228 std::string Values;
16229 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16230 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16231 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16233 Exclude);
16234 } else {
16235 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16236 /*Last=*/OMPC_SCHEDULE_unknown);
16237 }
16238 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16239 << Values << getOpenMPClauseName(OMPC_schedule);
16240 return nullptr;
16241 }
16242 // OpenMP, 2.7.1, Loop Construct, Restrictions
16243 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16244 // schedule(guided).
16245 // OpenMP 5.0 does not have this restriction.
16246 if (getLangOpts().OpenMP < 50 &&
16247 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16248 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16249 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16250 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16251 diag::err_omp_schedule_nonmonotonic_static);
16252 return nullptr;
16253 }
16254 Expr *ValExpr = ChunkSize;
16255 Stmt *HelperValStmt = nullptr;
16256 if (ChunkSize) {
16257 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16258 !ChunkSize->isInstantiationDependent() &&
16259 !ChunkSize->containsUnexpandedParameterPack()) {
16260 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16261 ExprResult Val =
16262 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16263 if (Val.isInvalid())
16264 return nullptr;
16265
16266 ValExpr = Val.get();
16267
16268 // OpenMP [2.7.1, Restrictions]
16269 // chunk_size must be a loop invariant integer expression with a positive
16270 // value.
16271 if (std::optional<llvm::APSInt> Result =
16273 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16274 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16275 << "schedule" << 1 << ChunkSize->getSourceRange();
16276 return nullptr;
16277 }
16279 DSAStack->getCurrentDirective(), OMPC_schedule,
16280 getLangOpts().OpenMP) != OMPD_unknown &&
16282 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16283 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16284 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16285 HelperValStmt = buildPreInits(getASTContext(), Captures);
16286 }
16287 }
16288 }
16289
16290 return new (getASTContext())
16291 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16292 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16293}
16294
16296 SourceLocation StartLoc,
16297 SourceLocation EndLoc) {
16298 OMPClause *Res = nullptr;
16299 switch (Kind) {
16300 case OMPC_ordered:
16301 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16302 break;
16303 case OMPC_nowait:
16304 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16305 break;
16306 case OMPC_untied:
16307 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16308 break;
16309 case OMPC_mergeable:
16310 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16311 break;
16312 case OMPC_read:
16313 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16314 break;
16315 case OMPC_write:
16316 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16317 break;
16318 case OMPC_update:
16319 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16320 break;
16321 case OMPC_capture:
16322 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16323 break;
16324 case OMPC_compare:
16325 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16326 break;
16327 case OMPC_fail:
16328 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16329 break;
16330 case OMPC_seq_cst:
16331 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16332 break;
16333 case OMPC_acq_rel:
16334 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16335 break;
16336 case OMPC_acquire:
16337 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16338 break;
16339 case OMPC_release:
16340 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16341 break;
16342 case OMPC_relaxed:
16343 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16344 break;
16345 case OMPC_weak:
16346 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16347 break;
16348 case OMPC_threads:
16349 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16350 break;
16351 case OMPC_simd:
16352 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16353 break;
16354 case OMPC_nogroup:
16355 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16356 break;
16357 case OMPC_unified_address:
16358 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16359 break;
16360 case OMPC_unified_shared_memory:
16361 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16362 break;
16363 case OMPC_reverse_offload:
16364 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16365 break;
16366 case OMPC_dynamic_allocators:
16367 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16368 break;
16369 case OMPC_destroy:
16370 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16371 /*LParenLoc=*/SourceLocation(),
16372 /*VarLoc=*/SourceLocation(), EndLoc);
16373 break;
16374 case OMPC_full:
16375 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16376 break;
16377 case OMPC_partial:
16378 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16379 break;
16380 case OMPC_ompx_bare:
16381 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16382 break;
16383 case OMPC_if:
16384 case OMPC_final:
16385 case OMPC_num_threads:
16386 case OMPC_safelen:
16387 case OMPC_simdlen:
16388 case OMPC_sizes:
16389 case OMPC_allocator:
16390 case OMPC_collapse:
16391 case OMPC_schedule:
16392 case OMPC_private:
16393 case OMPC_firstprivate:
16394 case OMPC_lastprivate:
16395 case OMPC_shared:
16396 case OMPC_reduction:
16397 case OMPC_task_reduction:
16398 case OMPC_in_reduction:
16399 case OMPC_linear:
16400 case OMPC_aligned:
16401 case OMPC_copyin:
16402 case OMPC_copyprivate:
16403 case OMPC_default:
16404 case OMPC_proc_bind:
16405 case OMPC_threadprivate:
16406 case OMPC_allocate:
16407 case OMPC_flush:
16408 case OMPC_depobj:
16409 case OMPC_depend:
16410 case OMPC_device:
16411 case OMPC_map:
16412 case OMPC_num_teams:
16413 case OMPC_thread_limit:
16414 case OMPC_priority:
16415 case OMPC_grainsize:
16416 case OMPC_num_tasks:
16417 case OMPC_hint:
16418 case OMPC_dist_schedule:
16419 case OMPC_defaultmap:
16420 case OMPC_unknown:
16421 case OMPC_uniform:
16422 case OMPC_to:
16423 case OMPC_from:
16424 case OMPC_use_device_ptr:
16425 case OMPC_use_device_addr:
16426 case OMPC_is_device_ptr:
16427 case OMPC_has_device_addr:
16428 case OMPC_atomic_default_mem_order:
16429 case OMPC_device_type:
16430 case OMPC_match:
16431 case OMPC_nontemporal:
16432 case OMPC_order:
16433 case OMPC_at:
16434 case OMPC_severity:
16435 case OMPC_message:
16436 case OMPC_novariants:
16437 case OMPC_nocontext:
16438 case OMPC_detach:
16439 case OMPC_inclusive:
16440 case OMPC_exclusive:
16441 case OMPC_uses_allocators:
16442 case OMPC_affinity:
16443 case OMPC_when:
16444 case OMPC_ompx_dyn_cgroup_mem:
16445 default:
16446 llvm_unreachable("Clause is not allowed.");
16447 }
16448 return Res;
16449}
16450
16452 SourceLocation EndLoc) {
16453 DSAStack->setNowaitRegion();
16454 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
16455}
16456
16458 SourceLocation EndLoc) {
16459 DSAStack->setUntiedRegion();
16460 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
16461}
16462
16464 SourceLocation EndLoc) {
16465 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
16466}
16467
16469 SourceLocation EndLoc) {
16470 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
16471}
16472
16474 SourceLocation EndLoc) {
16475 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
16476}
16477
16479 SourceLocation EndLoc) {
16480 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
16481}
16482
16484 SourceLocation EndLoc) {
16485 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
16486}
16487
16489 SourceLocation EndLoc) {
16490 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
16491}
16492
16494 SourceLocation EndLoc) {
16495 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
16496}
16497
16499 SourceLocation KindLoc,
16500 SourceLocation StartLoc,
16501 SourceLocation LParenLoc,
16502 SourceLocation EndLoc) {
16503
16505 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16506 return nullptr;
16507 }
16508 return new (getASTContext())
16509 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
16510}
16511
16513 SourceLocation EndLoc) {
16514 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
16515}
16516
16518 SourceLocation EndLoc) {
16519 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
16520}
16521
16523 SourceLocation EndLoc) {
16524 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
16525}
16526
16528 SourceLocation EndLoc) {
16529 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
16530}
16531
16533 SourceLocation EndLoc) {
16534 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
16535}
16536
16538 SourceLocation EndLoc) {
16539 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
16540}
16541
16543 SourceLocation EndLoc) {
16544 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
16545}
16546
16548 SourceLocation EndLoc) {
16549 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
16550}
16551
16553 SourceLocation EndLoc) {
16554 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
16555}
16556
16558 SourceLocation EndLoc) {
16559 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
16560}
16561
16562OMPClause *
16564 SourceLocation EndLoc) {
16565 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16566}
16567
16569 SourceLocation EndLoc) {
16570 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
16571}
16572
16573OMPClause *
16575 SourceLocation EndLoc) {
16576 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
16577}
16578
16581 SourceLocation StartLoc,
16582 SourceLocation EndLoc) {
16583
16584 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16585 // At least one action-clause must appear on a directive.
16586 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16587 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
16588 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16589 << Expected << getOpenMPDirectiveName(OMPD_interop);
16590 return StmtError();
16591 }
16592
16593 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16594 // A depend clause can only appear on the directive if a targetsync
16595 // interop-type is present or the interop-var was initialized with
16596 // the targetsync interop-type.
16597
16598 // If there is any 'init' clause diagnose if there is no 'init' clause with
16599 // interop-type of 'targetsync'. Cases involving other directives cannot be
16600 // diagnosed.
16601 const OMPDependClause *DependClause = nullptr;
16602 bool HasInitClause = false;
16603 bool IsTargetSync = false;
16604 for (const OMPClause *C : Clauses) {
16605 if (IsTargetSync)
16606 break;
16607 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
16608 HasInitClause = true;
16609 if (InitClause->getIsTargetSync())
16610 IsTargetSync = true;
16611 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
16612 DependClause = DC;
16613 }
16614 }
16615 if (DependClause && HasInitClause && !IsTargetSync) {
16616 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16617 return StmtError();
16618 }
16619
16620 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16621 // Each interop-var may be specified for at most one action-clause of each
16622 // interop construct.
16624 for (OMPClause *C : Clauses) {
16625 OpenMPClauseKind ClauseKind = C->getClauseKind();
16626 std::pair<ValueDecl *, bool> DeclResult;
16627 SourceLocation ELoc;
16628 SourceRange ERange;
16629
16630 if (ClauseKind == OMPC_init) {
16631 auto *E = cast<OMPInitClause>(C)->getInteropVar();
16632 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16633 } else if (ClauseKind == OMPC_use) {
16634 auto *E = cast<OMPUseClause>(C)->getInteropVar();
16635 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16636 } else if (ClauseKind == OMPC_destroy) {
16637 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
16638 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16639 }
16640
16641 if (DeclResult.first) {
16642 if (!InteropVars.insert(DeclResult.first).second) {
16643 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16644 << DeclResult.first;
16645 return StmtError();
16646 }
16647 }
16648 }
16649
16650 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
16651 Clauses);
16652}
16653
16654static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
16655 SourceLocation VarLoc,
16656 OpenMPClauseKind Kind) {
16657 SourceLocation ELoc;
16658 SourceRange ERange;
16659 Expr *RefExpr = InteropVarExpr;
16660 auto Res =
16661 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
16662 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
16663
16664 if (Res.second) {
16665 // It will be analyzed later.
16666 return true;
16667 }
16668
16669 if (!Res.first)
16670 return false;
16671
16672 // Interop variable should be of type omp_interop_t.
16673 bool HasError = false;
16674 QualType InteropType;
16675 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
16676 VarLoc, Sema::LookupOrdinaryName);
16677 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
16678 NamedDecl *ND = Result.getFoundDecl();
16679 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
16680 InteropType = QualType(TD->getTypeForDecl(), 0);
16681 } else {
16682 HasError = true;
16683 }
16684 } else {
16685 HasError = true;
16686 }
16687
16688 if (HasError) {
16689 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
16690 << "omp_interop_t";
16691 return false;
16692 }
16693
16694 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
16695 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
16696 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16697 return false;
16698 }
16699
16700 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16701 // The interop-var passed to init or destroy must be non-const.
16702 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16703 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
16704 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
16705 << /*non-const*/ 1;
16706 return false;
16707 }
16708 return true;
16709}
16710
16712 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
16713 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
16714
16715 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
16716 return nullptr;
16717
16718 // Check prefer_type values. These foreign-runtime-id values are either
16719 // string literals or constant integral expressions.
16720 for (const Expr *E : InteropInfo.PreferTypes) {
16721 if (E->isValueDependent() || E->isTypeDependent() ||
16723 continue;
16725 continue;
16726 if (isa<StringLiteral>(E))
16727 continue;
16728 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
16729 return nullptr;
16730 }
16731
16732 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
16733 StartLoc, LParenLoc, VarLoc, EndLoc);
16734}
16735
16737 SourceLocation StartLoc,
16738 SourceLocation LParenLoc,
16739 SourceLocation VarLoc,
16740 SourceLocation EndLoc) {
16741
16742 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
16743 return nullptr;
16744
16745 return new (getASTContext())
16746 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16747}
16748
16750 SourceLocation StartLoc,
16751 SourceLocation LParenLoc,
16752 SourceLocation VarLoc,
16753 SourceLocation EndLoc) {
16754 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
16755 DSAStack->getCurrentDirective() == OMPD_depobj) {
16756 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16757 << getOpenMPClauseName(OMPC_destroy)
16758 << getOpenMPDirectiveName(OMPD_depobj);
16759 return nullptr;
16760 }
16761 if (InteropVar &&
16762 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
16763 return nullptr;
16764
16765 return new (getASTContext())
16766 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16767}
16768
16770 SourceLocation StartLoc,
16771 SourceLocation LParenLoc,
16772 SourceLocation EndLoc) {
16773 Expr *ValExpr = Condition;
16774 Stmt *HelperValStmt = nullptr;
16775 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16776 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16777 !Condition->isInstantiationDependent() &&
16778 !Condition->containsUnexpandedParameterPack()) {
16780 if (Val.isInvalid())
16781 return nullptr;
16782
16783 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16784
16785 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16786 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
16787 getLangOpts().OpenMP);
16788 if (CaptureRegion != OMPD_unknown &&
16790 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16791 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16792 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16793 HelperValStmt = buildPreInits(getASTContext(), Captures);
16794 }
16795 }
16796
16797 return new (getASTContext()) OMPNovariantsClause(
16798 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16799}
16800
16802 SourceLocation StartLoc,
16803 SourceLocation LParenLoc,
16804 SourceLocation EndLoc) {
16805 Expr *ValExpr = Condition;
16806 Stmt *HelperValStmt = nullptr;
16807 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16808 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16809 !Condition->isInstantiationDependent() &&
16810 !Condition->containsUnexpandedParameterPack()) {
16812 if (Val.isInvalid())
16813 return nullptr;
16814
16815 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16816
16817 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16818 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
16819 getLangOpts().OpenMP);
16820 if (CaptureRegion != OMPD_unknown &&
16822 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16823 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16824 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16825 HelperValStmt = buildPreInits(getASTContext(), Captures);
16826 }
16827 }
16828
16829 return new (getASTContext()) OMPNocontextClause(
16830 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16831}
16832
16834 SourceLocation StartLoc,
16835 SourceLocation LParenLoc,
16836 SourceLocation EndLoc) {
16837 Expr *ValExpr = ThreadID;
16838 Stmt *HelperValStmt = nullptr;
16839
16840 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16841 OpenMPDirectiveKind CaptureRegion =
16842 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
16843 if (CaptureRegion != OMPD_unknown &&
16845 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16846 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16847 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16848 HelperValStmt = buildPreInits(getASTContext(), Captures);
16849 }
16850
16851 return new (getASTContext()) OMPFilterClause(
16852 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16853}
16854
16856 ArrayRef<Expr *> VarList,
16857 const OMPVarListLocTy &Locs,
16859 SourceLocation StartLoc = Locs.StartLoc;
16860 SourceLocation LParenLoc = Locs.LParenLoc;
16861 SourceLocation EndLoc = Locs.EndLoc;
16862 OMPClause *Res = nullptr;
16863 int ExtraModifier = Data.ExtraModifier;
16864 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
16865 SourceLocation ColonLoc = Data.ColonLoc;
16866 switch (Kind) {
16867 case OMPC_private:
16868 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16869 break;
16870 case OMPC_firstprivate:
16871 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16872 break;
16873 case OMPC_lastprivate:
16874 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
16875 "Unexpected lastprivate modifier.");
16877 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
16878 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
16879 break;
16880 case OMPC_shared:
16881 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
16882 break;
16883 case OMPC_reduction:
16884 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
16885 "Unexpected lastprivate modifier.");
16887 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
16888 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
16889 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16890 break;
16891 case OMPC_task_reduction:
16893 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16894 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16895 break;
16896 case OMPC_in_reduction:
16898 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16899 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16900 break;
16901 case OMPC_linear:
16902 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
16903 "Unexpected linear modifier.");
16905 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
16906 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
16907 ColonLoc, Data.StepModifierLoc, EndLoc);
16908 break;
16909 case OMPC_aligned:
16910 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
16911 LParenLoc, ColonLoc, EndLoc);
16912 break;
16913 case OMPC_copyin:
16914 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
16915 break;
16916 case OMPC_copyprivate:
16917 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16918 break;
16919 case OMPC_flush:
16920 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
16921 break;
16922 case OMPC_depend:
16923 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
16924 "Unexpected depend modifier.");
16926 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
16927 ColonLoc, Data.OmpAllMemoryLoc},
16928 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
16929 break;
16930 case OMPC_map:
16931 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
16932 "Unexpected map modifier.");
16934 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
16935 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
16936 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
16937 ExtraModifierLoc, ColonLoc, VarList, Locs);
16938 break;
16939 case OMPC_to:
16940 Res =
16941 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
16942 Data.ReductionOrMapperIdScopeSpec,
16943 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
16944 break;
16945 case OMPC_from:
16946 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
16947 Data.ReductionOrMapperIdScopeSpec,
16948 Data.ReductionOrMapperId, ColonLoc, VarList,
16949 Locs);
16950 break;
16951 case OMPC_use_device_ptr:
16952 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
16953 break;
16954 case OMPC_use_device_addr:
16955 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
16956 break;
16957 case OMPC_is_device_ptr:
16958 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
16959 break;
16960 case OMPC_has_device_addr:
16961 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
16962 break;
16963 case OMPC_allocate:
16964 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
16965 LParenLoc, ColonLoc, EndLoc);
16966 break;
16967 case OMPC_nontemporal:
16968 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
16969 break;
16970 case OMPC_inclusive:
16971 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
16972 break;
16973 case OMPC_exclusive:
16974 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
16975 break;
16976 case OMPC_affinity:
16977 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
16978 Data.DepModOrTailExpr, VarList);
16979 break;
16980 case OMPC_doacross:
16982 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
16983 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
16984 break;
16985 case OMPC_num_teams:
16986 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
16987 break;
16988 case OMPC_thread_limit:
16989 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
16990 break;
16991 case OMPC_if:
16992 case OMPC_depobj:
16993 case OMPC_final:
16994 case OMPC_num_threads:
16995 case OMPC_safelen:
16996 case OMPC_simdlen:
16997 case OMPC_sizes:
16998 case OMPC_allocator:
16999 case OMPC_collapse:
17000 case OMPC_default:
17001 case OMPC_proc_bind:
17002 case OMPC_schedule:
17003 case OMPC_ordered:
17004 case OMPC_nowait:
17005 case OMPC_untied:
17006 case OMPC_mergeable:
17007 case OMPC_threadprivate:
17008 case OMPC_read:
17009 case OMPC_write:
17010 case OMPC_update:
17011 case OMPC_capture:
17012 case OMPC_compare:
17013 case OMPC_seq_cst:
17014 case OMPC_acq_rel:
17015 case OMPC_acquire:
17016 case OMPC_release:
17017 case OMPC_relaxed:
17018 case OMPC_device:
17019 case OMPC_threads:
17020 case OMPC_simd:
17021 case OMPC_priority:
17022 case OMPC_grainsize:
17023 case OMPC_nogroup:
17024 case OMPC_num_tasks:
17025 case OMPC_hint:
17026 case OMPC_dist_schedule:
17027 case OMPC_defaultmap:
17028 case OMPC_unknown:
17029 case OMPC_uniform:
17030 case OMPC_unified_address:
17031 case OMPC_unified_shared_memory:
17032 case OMPC_reverse_offload:
17033 case OMPC_dynamic_allocators:
17034 case OMPC_atomic_default_mem_order:
17035 case OMPC_device_type:
17036 case OMPC_match:
17037 case OMPC_order:
17038 case OMPC_at:
17039 case OMPC_severity:
17040 case OMPC_message:
17041 case OMPC_destroy:
17042 case OMPC_novariants:
17043 case OMPC_nocontext:
17044 case OMPC_detach:
17045 case OMPC_uses_allocators:
17046 case OMPC_when:
17047 case OMPC_bind:
17048 default:
17049 llvm_unreachable("Clause is not allowed.");
17050 }
17051 return Res;
17052}
17053
17055 ExprObjectKind OK,
17058 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17059 if (!Res.isUsable())
17060 return ExprError();
17061 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17062 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17063 if (!Res.isUsable())
17064 return ExprError();
17065 }
17066 if (VK != VK_LValue && Res.get()->isGLValue()) {
17067 Res = SemaRef.DefaultLvalueConversion(Res.get());
17068 if (!Res.isUsable())
17069 return ExprError();
17070 }
17071 return Res;
17072}
17073
17075 SourceLocation StartLoc,
17076 SourceLocation LParenLoc,
17077 SourceLocation EndLoc) {
17079 SmallVector<Expr *, 8> PrivateCopies;
17080 bool IsImplicitClause =
17081 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17082 for (Expr *RefExpr : VarList) {
17083 assert(RefExpr && "NULL expr in OpenMP private clause.");
17084 SourceLocation ELoc;
17085 SourceRange ERange;
17086 Expr *SimpleRefExpr = RefExpr;
17087 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17088 if (Res.second) {
17089 // It will be analyzed later.
17090 Vars.push_back(RefExpr);
17091 PrivateCopies.push_back(nullptr);
17092 }
17093 ValueDecl *D = Res.first;
17094 if (!D)
17095 continue;
17096
17097 QualType Type = D->getType();
17098 auto *VD = dyn_cast<VarDecl>(D);
17099
17100 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17101 // A variable that appears in a private clause must not have an incomplete
17102 // type or a reference type.
17104 diag::err_omp_private_incomplete_type))
17105 continue;
17106 Type = Type.getNonReferenceType();
17107
17108 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17109 // A variable that is privatized must not have a const-qualified type
17110 // unless it is of class type with a mutable member. This restriction does
17111 // not apply to the firstprivate clause.
17112 //
17113 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17114 // A variable that appears in a private clause must not have a
17115 // const-qualified type unless it is of class type with a mutable member.
17116 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17117 continue;
17118
17119 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17120 // in a Construct]
17121 // Variables with the predetermined data-sharing attributes may not be
17122 // listed in data-sharing attributes clauses, except for the cases
17123 // listed below. For these exceptions only, listing a predetermined
17124 // variable in a data-sharing attribute clause is allowed and overrides
17125 // the variable's predetermined data-sharing attributes.
17126 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17127 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17128 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17129 << getOpenMPClauseName(OMPC_private);
17131 continue;
17132 }
17133
17134 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17135 // Variably modified types are not supported for tasks.
17137 isOpenMPTaskingDirective(CurrDir)) {
17138 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17139 << getOpenMPClauseName(OMPC_private) << Type
17140 << getOpenMPDirectiveName(CurrDir);
17141 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17143 Diag(D->getLocation(),
17144 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17145 << D;
17146 continue;
17147 }
17148
17149 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17150 // A list item cannot appear in both a map clause and a data-sharing
17151 // attribute clause on the same construct
17152 //
17153 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17154 // A list item cannot appear in both a map clause and a data-sharing
17155 // attribute clause on the same construct unless the construct is a
17156 // combined construct.
17157 if ((getLangOpts().OpenMP <= 45 &&
17159 CurrDir == OMPD_target) {
17160 OpenMPClauseKind ConflictKind;
17161 if (DSAStack->checkMappableExprComponentListsForDecl(
17162 VD, /*CurrentRegionOnly=*/true,
17164 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17165 ConflictKind = WhereFoundClauseKind;
17166 return true;
17167 })) {
17168 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17169 << getOpenMPClauseName(OMPC_private)
17170 << getOpenMPClauseName(ConflictKind)
17171 << getOpenMPDirectiveName(CurrDir);
17173 continue;
17174 }
17175 }
17176
17177 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17178 // A variable of class type (or array thereof) that appears in a private
17179 // clause requires an accessible, unambiguous default constructor for the
17180 // class type.
17181 // Generate helper private variable and initialize it with the default
17182 // value. The address of the original variable is replaced by the address of
17183 // the new private variable in CodeGen. This new variable is not added to
17184 // IdResolver, so the code in the OpenMP region uses original variable for
17185 // proper diagnostics.
17186 Type = Type.getUnqualifiedType();
17187 VarDecl *VDPrivate =
17188 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17189 D->hasAttrs() ? &D->getAttrs() : nullptr,
17190 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17192 if (VDPrivate->isInvalidDecl())
17193 continue;
17194 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17195 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17196
17197 DeclRefExpr *Ref = nullptr;
17198 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17199 auto *FD = dyn_cast<FieldDecl>(D);
17200 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17201 if (VD)
17203 RefExpr->getExprLoc());
17204 else
17205 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17206 }
17207 if (!IsImplicitClause)
17208 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17209 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17210 ? RefExpr->IgnoreParens()
17211 : Ref);
17212 PrivateCopies.push_back(VDPrivateRefExpr);
17213 }
17214
17215 if (Vars.empty())
17216 return nullptr;
17217
17218 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17219 Vars, PrivateCopies);
17220}
17221
17223 SourceLocation StartLoc,
17224 SourceLocation LParenLoc,
17225 SourceLocation EndLoc) {
17227 SmallVector<Expr *, 8> PrivateCopies;
17229 SmallVector<Decl *, 4> ExprCaptures;
17230 bool IsImplicitClause =
17231 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17232 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17233
17234 for (Expr *RefExpr : VarList) {
17235 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17236 SourceLocation ELoc;
17237 SourceRange ERange;
17238 Expr *SimpleRefExpr = RefExpr;
17239 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17240 if (Res.second) {
17241 // It will be analyzed later.
17242 Vars.push_back(RefExpr);
17243 PrivateCopies.push_back(nullptr);
17244 Inits.push_back(nullptr);
17245 }
17246 ValueDecl *D = Res.first;
17247 if (!D)
17248 continue;
17249
17250 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17251 QualType Type = D->getType();
17252 auto *VD = dyn_cast<VarDecl>(D);
17253
17254 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17255 // A variable that appears in a private clause must not have an incomplete
17256 // type or a reference type.
17258 diag::err_omp_firstprivate_incomplete_type))
17259 continue;
17260 Type = Type.getNonReferenceType();
17261
17262 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17263 // A variable of class type (or array thereof) that appears in a private
17264 // clause requires an accessible, unambiguous copy constructor for the
17265 // class type.
17266 QualType ElemType =
17268
17269 // If an implicit firstprivate variable found it was checked already.
17270 DSAStackTy::DSAVarData TopDVar;
17271 if (!IsImplicitClause) {
17272 DSAStackTy::DSAVarData DVar =
17273 DSAStack->getTopDSA(D, /*FromParent=*/false);
17274 TopDVar = DVar;
17275 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17276 bool IsConstant = ElemType.isConstant(getASTContext());
17277 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17278 // A list item that specifies a given variable may not appear in more
17279 // than one clause on the same directive, except that a variable may be
17280 // specified in both firstprivate and lastprivate clauses.
17281 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17282 // A list item may appear in a firstprivate or lastprivate clause but not
17283 // both.
17284 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17285 (isOpenMPDistributeDirective(CurrDir) ||
17286 DVar.CKind != OMPC_lastprivate) &&
17287 DVar.RefExpr) {
17288 Diag(ELoc, diag::err_omp_wrong_dsa)
17289 << getOpenMPClauseName(DVar.CKind)
17290 << getOpenMPClauseName(OMPC_firstprivate);
17292 continue;
17293 }
17294
17295 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17296 // in a Construct]
17297 // Variables with the predetermined data-sharing attributes may not be
17298 // listed in data-sharing attributes clauses, except for the cases
17299 // listed below. For these exceptions only, listing a predetermined
17300 // variable in a data-sharing attribute clause is allowed and overrides
17301 // the variable's predetermined data-sharing attributes.
17302 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17303 // in a Construct, C/C++, p.2]
17304 // Variables with const-qualified type having no mutable member may be
17305 // listed in a firstprivate clause, even if they are static data members.
17306 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17307 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17308 Diag(ELoc, diag::err_omp_wrong_dsa)
17309 << getOpenMPClauseName(DVar.CKind)
17310 << getOpenMPClauseName(OMPC_firstprivate);
17312 continue;
17313 }
17314
17315 // OpenMP [2.9.3.4, Restrictions, p.2]
17316 // A list item that is private within a parallel region must not appear
17317 // in a firstprivate clause on a worksharing construct if any of the
17318 // worksharing regions arising from the worksharing construct ever bind
17319 // to any of the parallel regions arising from the parallel construct.
17320 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17321 // A list item that is private within a teams region must not appear in a
17322 // firstprivate clause on a distribute construct if any of the distribute
17323 // regions arising from the distribute construct ever bind to any of the
17324 // teams regions arising from the teams construct.
17325 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17326 // A list item that appears in a reduction clause of a teams construct
17327 // must not appear in a firstprivate clause on a distribute construct if
17328 // any of the distribute regions arising from the distribute construct
17329 // ever bind to any of the teams regions arising from the teams construct.
17330 if ((isOpenMPWorksharingDirective(CurrDir) ||
17331 isOpenMPDistributeDirective(CurrDir)) &&
17332 !isOpenMPParallelDirective(CurrDir) &&
17333 !isOpenMPTeamsDirective(CurrDir)) {
17334 DVar = DSAStack->getImplicitDSA(D, true);
17335 if (DVar.CKind != OMPC_shared &&
17336 (isOpenMPParallelDirective(DVar.DKind) ||
17337 isOpenMPTeamsDirective(DVar.DKind) ||
17338 DVar.DKind == OMPD_unknown)) {
17339 Diag(ELoc, diag::err_omp_required_access)
17340 << getOpenMPClauseName(OMPC_firstprivate)
17341 << getOpenMPClauseName(OMPC_shared);
17343 continue;
17344 }
17345 }
17346 // OpenMP [2.9.3.4, Restrictions, p.3]
17347 // A list item that appears in a reduction clause of a parallel construct
17348 // must not appear in a firstprivate clause on a worksharing or task
17349 // construct if any of the worksharing or task regions arising from the
17350 // worksharing or task construct ever bind to any of the parallel regions
17351 // arising from the parallel construct.
17352 // OpenMP [2.9.3.4, Restrictions, p.4]
17353 // A list item that appears in a reduction clause in worksharing
17354 // construct must not appear in a firstprivate clause in a task construct
17355 // encountered during execution of any of the worksharing regions arising
17356 // from the worksharing construct.
17357 if (isOpenMPTaskingDirective(CurrDir)) {
17358 DVar = DSAStack->hasInnermostDSA(
17359 D,
17360 [](OpenMPClauseKind C, bool AppliedToPointee) {
17361 return C == OMPC_reduction && !AppliedToPointee;
17362 },
17363 [](OpenMPDirectiveKind K) {
17364 return isOpenMPParallelDirective(K) ||
17367 },
17368 /*FromParent=*/true);
17369 if (DVar.CKind == OMPC_reduction &&
17370 (isOpenMPParallelDirective(DVar.DKind) ||
17371 isOpenMPWorksharingDirective(DVar.DKind) ||
17372 isOpenMPTeamsDirective(DVar.DKind))) {
17373 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17374 << getOpenMPDirectiveName(DVar.DKind);
17376 continue;
17377 }
17378 }
17379
17380 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17381 // A list item cannot appear in both a map clause and a data-sharing
17382 // attribute clause on the same construct
17383 //
17384 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17385 // A list item cannot appear in both a map clause and a data-sharing
17386 // attribute clause on the same construct unless the construct is a
17387 // combined construct.
17388 if ((getLangOpts().OpenMP <= 45 &&
17390 CurrDir == OMPD_target) {
17391 OpenMPClauseKind ConflictKind;
17392 if (DSAStack->checkMappableExprComponentListsForDecl(
17393 VD, /*CurrentRegionOnly=*/true,
17394 [&ConflictKind](
17396 OpenMPClauseKind WhereFoundClauseKind) {
17397 ConflictKind = WhereFoundClauseKind;
17398 return true;
17399 })) {
17400 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17401 << getOpenMPClauseName(OMPC_firstprivate)
17402 << getOpenMPClauseName(ConflictKind)
17403 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17405 continue;
17406 }
17407 }
17408 }
17409
17410 // Variably modified types are not supported for tasks.
17412 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
17413 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17414 << getOpenMPClauseName(OMPC_firstprivate) << Type
17415 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17416 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17418 Diag(D->getLocation(),
17419 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17420 << D;
17421 continue;
17422 }
17423
17424 Type = Type.getUnqualifiedType();
17425 VarDecl *VDPrivate =
17426 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17427 D->hasAttrs() ? &D->getAttrs() : nullptr,
17428 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17429 // Generate helper private variable and initialize it with the value of the
17430 // original variable. The address of the original variable is replaced by
17431 // the address of the new private variable in the CodeGen. This new variable
17432 // is not added to IdResolver, so the code in the OpenMP region uses
17433 // original variable for proper diagnostics and variable capturing.
17434 Expr *VDInitRefExpr = nullptr;
17435 // For arrays generate initializer for single element and replace it by the
17436 // original array element in CodeGen.
17437 if (Type->isArrayType()) {
17438 VarDecl *VDInit =
17439 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
17440 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
17441 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
17442 ElemType = ElemType.getUnqualifiedType();
17443 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
17444 ElemType, ".firstprivate.temp");
17445 InitializedEntity Entity =
17448
17449 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
17450 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
17451 if (Result.isInvalid())
17452 VDPrivate->setInvalidDecl();
17453 else
17454 VDPrivate->setInit(Result.getAs<Expr>());
17455 // Remove temp variable declaration.
17456 getASTContext().Deallocate(VDInitTemp);
17457 } else {
17458 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
17459 ".firstprivate.temp");
17460 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
17461 RefExpr->getExprLoc());
17463 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
17464 /*DirectInit=*/false);
17465 }
17466 if (VDPrivate->isInvalidDecl()) {
17467 if (IsImplicitClause) {
17468 Diag(RefExpr->getExprLoc(),
17469 diag::note_omp_task_predetermined_firstprivate_here);
17470 }
17471 continue;
17472 }
17473 SemaRef.CurContext->addDecl(VDPrivate);
17474 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17475 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
17476 RefExpr->getExprLoc());
17477 DeclRefExpr *Ref = nullptr;
17478 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17479 if (TopDVar.CKind == OMPC_lastprivate) {
17480 Ref = TopDVar.PrivateCopy;
17481 } else {
17482 auto *FD = dyn_cast<FieldDecl>(D);
17483 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17484 if (VD)
17485 Ref =
17487 RefExpr->getExprLoc());
17488 else
17489 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17490 if (VD || !isOpenMPCapturedDecl(D))
17491 ExprCaptures.push_back(Ref->getDecl());
17492 }
17493 }
17494 if (!IsImplicitClause)
17495 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17496 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17497 ? RefExpr->IgnoreParens()
17498 : Ref);
17499 PrivateCopies.push_back(VDPrivateRefExpr);
17500 Inits.push_back(VDInitRefExpr);
17501 }
17502
17503 if (Vars.empty())
17504 return nullptr;
17505
17507 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17508 buildPreInits(getASTContext(), ExprCaptures));
17509}
17510
17513 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
17514 SourceLocation LParenLoc, SourceLocation EndLoc) {
17515 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
17516 assert(ColonLoc.isValid() && "Colon location must be valid.");
17517 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17518 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
17519 /*Last=*/OMPC_LASTPRIVATE_unknown)
17520 << getOpenMPClauseName(OMPC_lastprivate);
17521 return nullptr;
17522 }
17523
17525 SmallVector<Expr *, 8> SrcExprs;
17526 SmallVector<Expr *, 8> DstExprs;
17527 SmallVector<Expr *, 8> AssignmentOps;
17528 SmallVector<Decl *, 4> ExprCaptures;
17529 SmallVector<Expr *, 4> ExprPostUpdates;
17530 for (Expr *RefExpr : VarList) {
17531 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17532 SourceLocation ELoc;
17533 SourceRange ERange;
17534 Expr *SimpleRefExpr = RefExpr;
17535 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17536 if (Res.second) {
17537 // It will be analyzed later.
17538 Vars.push_back(RefExpr);
17539 SrcExprs.push_back(nullptr);
17540 DstExprs.push_back(nullptr);
17541 AssignmentOps.push_back(nullptr);
17542 }
17543 ValueDecl *D = Res.first;
17544 if (!D)
17545 continue;
17546
17547 QualType Type = D->getType();
17548 auto *VD = dyn_cast<VarDecl>(D);
17549
17550 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
17551 // A variable that appears in a lastprivate clause must not have an
17552 // incomplete type or a reference type.
17554 diag::err_omp_lastprivate_incomplete_type))
17555 continue;
17556 Type = Type.getNonReferenceType();
17557
17558 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17559 // A variable that is privatized must not have a const-qualified type
17560 // unless it is of class type with a mutable member. This restriction does
17561 // not apply to the firstprivate clause.
17562 //
17563 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
17564 // A variable that appears in a lastprivate clause must not have a
17565 // const-qualified type unless it is of class type with a mutable member.
17566 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
17567 continue;
17568
17569 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
17570 // A list item that appears in a lastprivate clause with the conditional
17571 // modifier must be a scalar variable.
17572 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
17573 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17574 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17576 Diag(D->getLocation(),
17577 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17578 << D;
17579 continue;
17580 }
17581
17582 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17583 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
17584 // in a Construct]
17585 // Variables with the predetermined data-sharing attributes may not be
17586 // listed in data-sharing attributes clauses, except for the cases
17587 // listed below.
17588 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17589 // A list item may appear in a firstprivate or lastprivate clause but not
17590 // both.
17591 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17592 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17593 (isOpenMPDistributeDirective(CurrDir) ||
17594 DVar.CKind != OMPC_firstprivate) &&
17595 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
17596 Diag(ELoc, diag::err_omp_wrong_dsa)
17597 << getOpenMPClauseName(DVar.CKind)
17598 << getOpenMPClauseName(OMPC_lastprivate);
17600 continue;
17601 }
17602
17603 // OpenMP [2.14.3.5, Restrictions, p.2]
17604 // A list item that is private within a parallel region, or that appears in
17605 // the reduction clause of a parallel construct, must not appear in a
17606 // lastprivate clause on a worksharing construct if any of the corresponding
17607 // worksharing regions ever binds to any of the corresponding parallel
17608 // regions.
17609 DSAStackTy::DSAVarData TopDVar = DVar;
17610 if (isOpenMPWorksharingDirective(CurrDir) &&
17611 !isOpenMPParallelDirective(CurrDir) &&
17612 !isOpenMPTeamsDirective(CurrDir)) {
17613 DVar = DSAStack->getImplicitDSA(D, true);
17614 if (DVar.CKind != OMPC_shared) {
17615 Diag(ELoc, diag::err_omp_required_access)
17616 << getOpenMPClauseName(OMPC_lastprivate)
17617 << getOpenMPClauseName(OMPC_shared);
17619 continue;
17620 }
17621 }
17622
17623 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
17624 // A variable of class type (or array thereof) that appears in a
17625 // lastprivate clause requires an accessible, unambiguous default
17626 // constructor for the class type, unless the list item is also specified
17627 // in a firstprivate clause.
17628 // A variable of class type (or array thereof) that appears in a
17629 // lastprivate clause requires an accessible, unambiguous copy assignment
17630 // operator for the class type.
17632 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
17633 Type.getUnqualifiedType(), ".lastprivate.src",
17634 D->hasAttrs() ? &D->getAttrs() : nullptr);
17635 DeclRefExpr *PseudoSrcExpr =
17636 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
17637 VarDecl *DstVD =
17638 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
17639 D->hasAttrs() ? &D->getAttrs() : nullptr);
17640 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
17641 // For arrays generate assignment operation for single element and replace
17642 // it by the original array element in CodeGen.
17643 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
17644 PseudoDstExpr, PseudoSrcExpr);
17645 if (AssignmentOp.isInvalid())
17646 continue;
17647 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
17648 /*DiscardedValue*/ false);
17649 if (AssignmentOp.isInvalid())
17650 continue;
17651
17652 DeclRefExpr *Ref = nullptr;
17653 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17654 if (TopDVar.CKind == OMPC_firstprivate) {
17655 Ref = TopDVar.PrivateCopy;
17656 } else {
17657 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17658 if (!isOpenMPCapturedDecl(D))
17659 ExprCaptures.push_back(Ref->getDecl());
17660 }
17661 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17663 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
17665 if (!RefRes.isUsable())
17666 continue;
17667 ExprResult PostUpdateRes =
17668 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
17669 SimpleRefExpr, RefRes.get());
17670 if (!PostUpdateRes.isUsable())
17671 continue;
17672 ExprPostUpdates.push_back(
17673 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
17674 }
17675 }
17676 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17677 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17678 ? RefExpr->IgnoreParens()
17679 : Ref);
17680 SrcExprs.push_back(PseudoSrcExpr);
17681 DstExprs.push_back(PseudoDstExpr);
17682 AssignmentOps.push_back(AssignmentOp.get());
17683 }
17684
17685 if (Vars.empty())
17686 return nullptr;
17687
17689 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17690 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17691 buildPreInits(getASTContext(), ExprCaptures),
17692 buildPostUpdate(SemaRef, ExprPostUpdates));
17693}
17694
17696 SourceLocation StartLoc,
17697 SourceLocation LParenLoc,
17698 SourceLocation EndLoc) {
17700 for (Expr *RefExpr : VarList) {
17701 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17702 SourceLocation ELoc;
17703 SourceRange ERange;
17704 Expr *SimpleRefExpr = RefExpr;
17705 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17706 if (Res.second) {
17707 // It will be analyzed later.
17708 Vars.push_back(RefExpr);
17709 }
17710 ValueDecl *D = Res.first;
17711 if (!D)
17712 continue;
17713
17714 auto *VD = dyn_cast<VarDecl>(D);
17715 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17716 // in a Construct]
17717 // Variables with the predetermined data-sharing attributes may not be
17718 // listed in data-sharing attributes clauses, except for the cases
17719 // listed below. For these exceptions only, listing a predetermined
17720 // variable in a data-sharing attribute clause is allowed and overrides
17721 // the variable's predetermined data-sharing attributes.
17722 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17723 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17724 DVar.RefExpr) {
17725 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17726 << getOpenMPClauseName(OMPC_shared);
17728 continue;
17729 }
17730
17731 DeclRefExpr *Ref = nullptr;
17732 if (!VD && isOpenMPCapturedDecl(D) &&
17734 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17735 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17736 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
17737 ? RefExpr->IgnoreParens()
17738 : Ref);
17739 }
17740
17741 if (Vars.empty())
17742 return nullptr;
17743
17744 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17745 Vars);
17746}
17747
17748namespace {
17749class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
17750 DSAStackTy *Stack;
17751
17752public:
17753 bool VisitDeclRefExpr(DeclRefExpr *E) {
17754 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
17755 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
17756 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17757 return false;
17758 if (DVar.CKind != OMPC_unknown)
17759 return true;
17760 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17761 VD,
17762 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
17763 return isOpenMPPrivate(C) && !AppliedToPointee;
17764 },
17765 [](OpenMPDirectiveKind) { return true; },
17766 /*FromParent=*/true);
17767 return DVarPrivate.CKind != OMPC_unknown;
17768 }
17769 return false;
17770 }
17771 bool VisitStmt(Stmt *S) {
17772 for (Stmt *Child : S->children()) {
17773 if (Child && Visit(Child))
17774 return true;
17775 }
17776 return false;
17777 }
17778 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17779};
17780} // namespace
17781
17782namespace {
17783// Transform MemberExpression for specified FieldDecl of current class to
17784// DeclRefExpr to specified OMPCapturedExprDecl.
17785class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
17786 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
17787 ValueDecl *Field = nullptr;
17788 DeclRefExpr *CapturedExpr = nullptr;
17789
17790public:
17791 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
17792 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
17793
17794 ExprResult TransformMemberExpr(MemberExpr *E) {
17795 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
17796 E->getMemberDecl() == Field) {
17797 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
17798 return CapturedExpr;
17799 }
17800 return BaseTransform::TransformMemberExpr(E);
17801 }
17802 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
17803};
17804} // namespace
17805
17806template <typename T, typename U>
17808 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
17809 for (U &Set : Lookups) {
17810 for (auto *D : Set) {
17811 if (T Res = Gen(cast<ValueDecl>(D)))
17812 return Res;
17813 }
17814 }
17815 return T();
17816}
17817
17819 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
17820
17821 for (auto *RD : D->redecls()) {
17822 // Don't bother with extra checks if we already know this one isn't visible.
17823 if (RD == D)
17824 continue;
17825
17826 auto ND = cast<NamedDecl>(RD);
17827 if (LookupResult::isVisible(SemaRef, ND))
17828 return ND;
17829 }
17830
17831 return nullptr;
17832}
17833
17834static void
17838 // Find all of the associated namespaces and classes based on the
17839 // arguments we have.
17840 Sema::AssociatedNamespaceSet AssociatedNamespaces;
17841 Sema::AssociatedClassSet AssociatedClasses;
17842 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
17843 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
17844 AssociatedClasses);
17845
17846 // C++ [basic.lookup.argdep]p3:
17847 // Let X be the lookup set produced by unqualified lookup (3.4.1)
17848 // and let Y be the lookup set produced by argument dependent
17849 // lookup (defined as follows). If X contains [...] then Y is
17850 // empty. Otherwise Y is the set of declarations found in the
17851 // namespaces associated with the argument types as described
17852 // below. The set of declarations found by the lookup of the name
17853 // is the union of X and Y.
17854 //
17855 // Here, we compute Y and add its members to the overloaded
17856 // candidate set.
17857 for (auto *NS : AssociatedNamespaces) {
17858 // When considering an associated namespace, the lookup is the
17859 // same as the lookup performed when the associated namespace is
17860 // used as a qualifier (3.4.3.2) except that:
17861 //
17862 // -- Any using-directives in the associated namespace are
17863 // ignored.
17864 //
17865 // -- Any namespace-scope friend functions declared in
17866 // associated classes are visible within their respective
17867 // namespaces even if they are not visible during an ordinary
17868 // lookup (11.4).
17869 DeclContext::lookup_result R = NS->lookup(Id.getName());
17870 for (auto *D : R) {
17871 auto *Underlying = D;
17872 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
17873 Underlying = USD->getTargetDecl();
17874
17875 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
17876 !isa<OMPDeclareMapperDecl>(Underlying))
17877 continue;
17878
17879 if (!SemaRef.isVisible(D)) {
17880 D = findAcceptableDecl(SemaRef, D);
17881 if (!D)
17882 continue;
17883 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
17884 Underlying = USD->getTargetDecl();
17885 }
17886 Lookups.emplace_back();
17887 Lookups.back().addDecl(Underlying);
17888 }
17889 }
17890}
17891
17892static ExprResult
17894 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
17895 const DeclarationNameInfo &ReductionId, QualType Ty,
17896 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
17897 if (ReductionIdScopeSpec.isInvalid())
17898 return ExprError();
17899 SmallVector<UnresolvedSet<8>, 4> Lookups;
17900 if (S) {
17901 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
17902 Lookup.suppressDiagnostics();
17903 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
17904 /*ObjectType=*/QualType())) {
17905 NamedDecl *D = Lookup.getRepresentativeDecl();
17906 do {
17907 S = S->getParent();
17908 } while (S && !S->isDeclScope(D));
17909 if (S)
17910 S = S->getParent();
17911 Lookups.emplace_back();
17912 Lookups.back().append(Lookup.begin(), Lookup.end());
17913 Lookup.clear();
17914 }
17915 } else if (auto *ULE =
17916 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
17917 Lookups.push_back(UnresolvedSet<8>());
17918 Decl *PrevD = nullptr;
17919 for (NamedDecl *D : ULE->decls()) {
17920 if (D == PrevD)
17921 Lookups.push_back(UnresolvedSet<8>());
17922 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
17923 Lookups.back().addDecl(DRD);
17924 PrevD = D;
17925 }
17926 }
17927 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
17930 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
17931 return !D->isInvalidDecl() &&
17932 (D->getType()->isDependentType() ||
17933 D->getType()->isInstantiationDependentType() ||
17934 D->getType()->containsUnexpandedParameterPack());
17935 })) {
17936 UnresolvedSet<8> ResSet;
17937 for (const UnresolvedSet<8> &Set : Lookups) {
17938 if (Set.empty())
17939 continue;
17940 ResSet.append(Set.begin(), Set.end());
17941 // The last item marks the end of all declarations at the specified scope.
17942 ResSet.addDecl(Set[Set.size() - 1]);
17943 }
17945 SemaRef.Context, /*NamingClass=*/nullptr,
17946 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
17947 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
17948 /*KnownInstantiationDependent=*/false);
17949 }
17950 // Lookup inside the classes.
17951 // C++ [over.match.oper]p3:
17952 // For a unary operator @ with an operand of a type whose
17953 // cv-unqualified version is T1, and for a binary operator @ with
17954 // a left operand of a type whose cv-unqualified version is T1 and
17955 // a right operand of a type whose cv-unqualified version is T2,
17956 // three sets of candidate functions, designated member
17957 // candidates, non-member candidates and built-in candidates, are
17958 // constructed as follows:
17959 // -- If T1 is a complete class type or a class currently being
17960 // defined, the set of member candidates is the result of the
17961 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
17962 // the set of member candidates is empty.
17963 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
17964 Lookup.suppressDiagnostics();
17965 if (const auto *TyRec = Ty->getAs<RecordType>()) {
17966 // Complete the type if it can be completed.
17967 // If the type is neither complete nor being defined, bail out now.
17968 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
17969 TyRec->getDecl()->getDefinition()) {
17970 Lookup.clear();
17971 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
17972 if (Lookup.empty()) {
17973 Lookups.emplace_back();
17974 Lookups.back().append(Lookup.begin(), Lookup.end());
17975 }
17976 }
17977 }
17978 // Perform ADL.
17979 if (SemaRef.getLangOpts().CPlusPlus)
17980 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
17981 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
17982 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
17983 if (!D->isInvalidDecl() &&
17984 SemaRef.Context.hasSameType(D->getType(), Ty))
17985 return D;
17986 return nullptr;
17987 }))
17988 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
17989 VK_LValue, Loc);
17990 if (SemaRef.getLangOpts().CPlusPlus) {
17991 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
17992 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
17993 if (!D->isInvalidDecl() &&
17994 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
17995 !Ty.isMoreQualifiedThan(D->getType()))
17996 return D;
17997 return nullptr;
17998 })) {
17999 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18000 /*DetectVirtual=*/false);
18001 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18002 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18003 VD->getType().getUnqualifiedType()))) {
18004 if (SemaRef.CheckBaseClassAccess(
18005 Loc, VD->getType(), Ty, Paths.front(),
18006 /*DiagID=*/0) != Sema::AR_inaccessible) {
18007 SemaRef.BuildBasePathArray(Paths, BasePath);
18008 return SemaRef.BuildDeclRefExpr(
18010 }
18011 }
18012 }
18013 }
18014 }
18015 if (ReductionIdScopeSpec.isSet()) {
18016 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18017 << Ty << Range;
18018 return ExprError();
18019 }
18020 return ExprEmpty();
18021}
18022
18023namespace {
18024/// Data for the reduction-based clauses.
18025struct ReductionData {
18026 /// List of original reduction items.
18028 /// List of private copies of the reduction items.
18029 SmallVector<Expr *, 8> Privates;
18030 /// LHS expressions for the reduction_op expressions.
18032 /// RHS expressions for the reduction_op expressions.
18034 /// Reduction operation expression.
18035 SmallVector<Expr *, 8> ReductionOps;
18036 /// inscan copy operation expressions.
18037 SmallVector<Expr *, 8> InscanCopyOps;
18038 /// inscan copy temp array expressions for prefix sums.
18039 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18040 /// inscan copy temp array element expressions for prefix sums.
18041 SmallVector<Expr *, 8> InscanCopyArrayElems;
18042 /// Taskgroup descriptors for the corresponding reduction items in
18043 /// in_reduction clauses.
18044 SmallVector<Expr *, 8> TaskgroupDescriptors;
18045 /// List of captures for clause.
18046 SmallVector<Decl *, 4> ExprCaptures;
18047 /// List of postupdate expressions.
18048 SmallVector<Expr *, 4> ExprPostUpdates;
18049 /// Reduction modifier.
18050 unsigned RedModifier = 0;
18051 ReductionData() = delete;
18052 /// Reserves required memory for the reduction data.
18053 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18054 Vars.reserve(Size);
18055 Privates.reserve(Size);
18056 LHSs.reserve(Size);
18057 RHSs.reserve(Size);
18058 ReductionOps.reserve(Size);
18059 if (RedModifier == OMPC_REDUCTION_inscan) {
18060 InscanCopyOps.reserve(Size);
18061 InscanCopyArrayTemps.reserve(Size);
18062 InscanCopyArrayElems.reserve(Size);
18063 }
18064 TaskgroupDescriptors.reserve(Size);
18065 ExprCaptures.reserve(Size);
18066 ExprPostUpdates.reserve(Size);
18067 }
18068 /// Stores reduction item and reduction operation only (required for dependent
18069 /// reduction item).
18070 void push(Expr *Item, Expr *ReductionOp) {
18071 Vars.emplace_back(Item);
18072 Privates.emplace_back(nullptr);
18073 LHSs.emplace_back(nullptr);
18074 RHSs.emplace_back(nullptr);
18075 ReductionOps.emplace_back(ReductionOp);
18076 TaskgroupDescriptors.emplace_back(nullptr);
18077 if (RedModifier == OMPC_REDUCTION_inscan) {
18078 InscanCopyOps.push_back(nullptr);
18079 InscanCopyArrayTemps.push_back(nullptr);
18080 InscanCopyArrayElems.push_back(nullptr);
18081 }
18082 }
18083 /// Stores reduction data.
18084 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18085 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18086 Expr *CopyArrayElem) {
18087 Vars.emplace_back(Item);
18088 Privates.emplace_back(Private);
18089 LHSs.emplace_back(LHS);
18090 RHSs.emplace_back(RHS);
18091 ReductionOps.emplace_back(ReductionOp);
18092 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18093 if (RedModifier == OMPC_REDUCTION_inscan) {
18094 InscanCopyOps.push_back(CopyOp);
18095 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18096 InscanCopyArrayElems.push_back(CopyArrayElem);
18097 } else {
18098 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18099 CopyArrayElem == nullptr &&
18100 "Copy operation must be used for inscan reductions only.");
18101 }
18102 }
18103};
18104} // namespace
18105
18107 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18108 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18109 const Expr *Length = OASE->getLength();
18110 if (Length == nullptr) {
18111 // For array sections of the form [1:] or [:], we would need to analyze
18112 // the lower bound...
18113 if (OASE->getColonLocFirst().isValid())
18114 return false;
18115
18116 // This is an array subscript which has implicit length 1!
18117 SingleElement = true;
18118 ArraySizes.push_back(llvm::APSInt::get(1));
18119 } else {
18121 if (!Length->EvaluateAsInt(Result, Context))
18122 return false;
18123
18124 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18125 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18126 ArraySizes.push_back(ConstantLengthValue);
18127 }
18128
18129 // Get the base of this array section and walk up from there.
18130 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18131
18132 // We require length = 1 for all array sections except the right-most to
18133 // guarantee that the memory region is contiguous and has no holes in it.
18134 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18135 Length = TempOASE->getLength();
18136 if (Length == nullptr) {
18137 // For array sections of the form [1:] or [:], we would need to analyze
18138 // the lower bound...
18139 if (OASE->getColonLocFirst().isValid())
18140 return false;
18141
18142 // This is an array subscript which has implicit length 1!
18143 ArraySizes.push_back(llvm::APSInt::get(1));
18144 } else {
18146 if (!Length->EvaluateAsInt(Result, Context))
18147 return false;
18148
18149 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18150 if (ConstantLengthValue.getSExtValue() != 1)
18151 return false;
18152
18153 ArraySizes.push_back(ConstantLengthValue);
18154 }
18155 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18156 }
18157
18158 // If we have a single element, we don't need to add the implicit lengths.
18159 if (!SingleElement) {
18160 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18161 // Has implicit length 1!
18162 ArraySizes.push_back(llvm::APSInt::get(1));
18163 Base = TempASE->getBase()->IgnoreParenImpCasts();
18164 }
18165 }
18166
18167 // This array section can be privatized as a single value or as a constant
18168 // sized array.
18169 return true;
18170}
18171
18172static BinaryOperatorKind
18174 if (BOK == BO_Add)
18175 return BO_AddAssign;
18176 if (BOK == BO_Mul)
18177 return BO_MulAssign;
18178 if (BOK == BO_And)
18179 return BO_AndAssign;
18180 if (BOK == BO_Or)
18181 return BO_OrAssign;
18182 if (BOK == BO_Xor)
18183 return BO_XorAssign;
18184 return BOK;
18185}
18186
18188 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18189 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18190 SourceLocation ColonLoc, SourceLocation EndLoc,
18191 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18192 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18193 DeclarationName DN = ReductionId.getName();
18195 BinaryOperatorKind BOK = BO_Comma;
18196
18197 ASTContext &Context = S.Context;
18198 // OpenMP [2.14.3.6, reduction clause]
18199 // C
18200 // reduction-identifier is either an identifier or one of the following
18201 // operators: +, -, *, &, |, ^, && and ||
18202 // C++
18203 // reduction-identifier is either an id-expression or one of the following
18204 // operators: +, -, *, &, |, ^, && and ||
18205 switch (OOK) {
18206 case OO_Plus:
18207 BOK = BO_Add;
18208 break;
18209 case OO_Minus:
18210 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18211 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18212 // reduction identifier.
18213 if (S.LangOpts.OpenMP > 52)
18214 BOK = BO_Comma;
18215 else
18216 BOK = BO_Add;
18217 break;
18218 case OO_Star:
18219 BOK = BO_Mul;
18220 break;
18221 case OO_Amp:
18222 BOK = BO_And;
18223 break;
18224 case OO_Pipe:
18225 BOK = BO_Or;
18226 break;
18227 case OO_Caret:
18228 BOK = BO_Xor;
18229 break;
18230 case OO_AmpAmp:
18231 BOK = BO_LAnd;
18232 break;
18233 case OO_PipePipe:
18234 BOK = BO_LOr;
18235 break;
18236 case OO_New:
18237 case OO_Delete:
18238 case OO_Array_New:
18239 case OO_Array_Delete:
18240 case OO_Slash:
18241 case OO_Percent:
18242 case OO_Tilde:
18243 case OO_Exclaim:
18244 case OO_Equal:
18245 case OO_Less:
18246 case OO_Greater:
18247 case OO_LessEqual:
18248 case OO_GreaterEqual:
18249 case OO_PlusEqual:
18250 case OO_MinusEqual:
18251 case OO_StarEqual:
18252 case OO_SlashEqual:
18253 case OO_PercentEqual:
18254 case OO_CaretEqual:
18255 case OO_AmpEqual:
18256 case OO_PipeEqual:
18257 case OO_LessLess:
18258 case OO_GreaterGreater:
18259 case OO_LessLessEqual:
18260 case OO_GreaterGreaterEqual:
18261 case OO_EqualEqual:
18262 case OO_ExclaimEqual:
18263 case OO_Spaceship:
18264 case OO_PlusPlus:
18265 case OO_MinusMinus:
18266 case OO_Comma:
18267 case OO_ArrowStar:
18268 case OO_Arrow:
18269 case OO_Call:
18270 case OO_Subscript:
18271 case OO_Conditional:
18272 case OO_Coawait:
18274 llvm_unreachable("Unexpected reduction identifier");
18275 case OO_None:
18276 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18277 if (II->isStr("max"))
18278 BOK = BO_GT;
18279 else if (II->isStr("min"))
18280 BOK = BO_LT;
18281 }
18282 break;
18283 }
18284
18285 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18286 // A reduction clause with the minus (-) operator was deprecated
18287 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18288 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18289
18290 SourceRange ReductionIdRange;
18291 if (ReductionIdScopeSpec.isValid())
18292 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18293 else
18294 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18295 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18296
18297 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18298 bool FirstIter = true;
18299 for (Expr *RefExpr : VarList) {
18300 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18301 // OpenMP [2.1, C/C++]
18302 // A list item is a variable or array section, subject to the restrictions
18303 // specified in Section 2.4 on page 42 and in each of the sections
18304 // describing clauses and directives for which a list appears.
18305 // OpenMP [2.14.3.3, Restrictions, p.1]
18306 // A variable that is part of another variable (as an array or
18307 // structure element) cannot appear in a private clause.
18308 if (!FirstIter && IR != ER)
18309 ++IR;
18310 FirstIter = false;
18311 SourceLocation ELoc;
18312 SourceRange ERange;
18313 Expr *SimpleRefExpr = RefExpr;
18314 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18315 /*AllowArraySection=*/true);
18316 if (Res.second) {
18317 // Try to find 'declare reduction' corresponding construct before using
18318 // builtin/overloaded operators.
18319 QualType Type = Context.DependentTy;
18320 CXXCastPath BasePath;
18321 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18322 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18323 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18324 Expr *ReductionOp = nullptr;
18325 if (S.CurContext->isDependentContext() &&
18326 (DeclareReductionRef.isUnset() ||
18327 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18328 ReductionOp = DeclareReductionRef.get();
18329 // It will be analyzed later.
18330 RD.push(RefExpr, ReductionOp);
18331 }
18332 ValueDecl *D = Res.first;
18333 if (!D)
18334 continue;
18335
18336 Expr *TaskgroupDescriptor = nullptr;
18337 QualType Type;
18338 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18339 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18340 if (ASE) {
18341 Type = ASE->getType().getNonReferenceType();
18342 } else if (OASE) {
18343 QualType BaseType =
18345 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18346 Type = ATy->getElementType();
18347 else
18348 Type = BaseType->getPointeeType();
18349 Type = Type.getNonReferenceType();
18350 } else {
18351 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
18352 }
18353 auto *VD = dyn_cast<VarDecl>(D);
18354
18355 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18356 // A variable that appears in a private clause must not have an incomplete
18357 // type or a reference type.
18358 if (S.RequireCompleteType(ELoc, D->getType(),
18359 diag::err_omp_reduction_incomplete_type))
18360 continue;
18361 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18362 // A list item that appears in a reduction clause must not be
18363 // const-qualified.
18364 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18365 /*AcceptIfMutable*/ false, ASE || OASE))
18366 continue;
18367
18368 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18369 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18370 // If a list-item is a reference type then it must bind to the same object
18371 // for all threads of the team.
18372 if (!ASE && !OASE) {
18373 if (VD) {
18374 VarDecl *VDDef = VD->getDefinition();
18375 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18376 DSARefChecker Check(Stack);
18377 if (Check.Visit(VDDef->getInit())) {
18378 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18379 << getOpenMPClauseName(ClauseKind) << ERange;
18380 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18381 continue;
18382 }
18383 }
18384 }
18385
18386 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18387 // in a Construct]
18388 // Variables with the predetermined data-sharing attributes may not be
18389 // listed in data-sharing attributes clauses, except for the cases
18390 // listed below. For these exceptions only, listing a predetermined
18391 // variable in a data-sharing attribute clause is allowed and overrides
18392 // the variable's predetermined data-sharing attributes.
18393 // OpenMP [2.14.3.6, Restrictions, p.3]
18394 // Any number of reduction clauses can be specified on the directive,
18395 // but a list item can appear only once in the reduction clauses for that
18396 // directive.
18397 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18398 if (DVar.CKind == OMPC_reduction) {
18399 S.Diag(ELoc, diag::err_omp_once_referenced)
18400 << getOpenMPClauseName(ClauseKind);
18401 if (DVar.RefExpr)
18402 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18403 continue;
18404 }
18405 if (DVar.CKind != OMPC_unknown) {
18406 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18407 << getOpenMPClauseName(DVar.CKind)
18408 << getOpenMPClauseName(OMPC_reduction);
18409 reportOriginalDsa(S, Stack, D, DVar);
18410 continue;
18411 }
18412
18413 // OpenMP [2.14.3.6, Restrictions, p.1]
18414 // A list item that appears in a reduction clause of a worksharing
18415 // construct must be shared in the parallel regions to which any of the
18416 // worksharing regions arising from the worksharing construct bind.
18417 if (isOpenMPWorksharingDirective(CurrDir) &&
18418 !isOpenMPParallelDirective(CurrDir) &&
18419 !isOpenMPTeamsDirective(CurrDir)) {
18420 DVar = Stack->getImplicitDSA(D, true);
18421 if (DVar.CKind != OMPC_shared) {
18422 S.Diag(ELoc, diag::err_omp_required_access)
18423 << getOpenMPClauseName(OMPC_reduction)
18424 << getOpenMPClauseName(OMPC_shared);
18425 reportOriginalDsa(S, Stack, D, DVar);
18426 continue;
18427 }
18428 }
18429 } else {
18430 // Threadprivates cannot be shared between threads, so dignose if the base
18431 // is a threadprivate variable.
18432 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18433 if (DVar.CKind == OMPC_threadprivate) {
18434 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18435 << getOpenMPClauseName(DVar.CKind)
18436 << getOpenMPClauseName(OMPC_reduction);
18437 reportOriginalDsa(S, Stack, D, DVar);
18438 continue;
18439 }
18440 }
18441
18442 // Try to find 'declare reduction' corresponding construct before using
18443 // builtin/overloaded operators.
18444 CXXCastPath BasePath;
18445 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18446 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18447 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18448 if (DeclareReductionRef.isInvalid())
18449 continue;
18450 if (S.CurContext->isDependentContext() &&
18451 (DeclareReductionRef.isUnset() ||
18452 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
18453 RD.push(RefExpr, DeclareReductionRef.get());
18454 continue;
18455 }
18456 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
18457 // Not allowed reduction identifier is found.
18458 if (S.LangOpts.OpenMP > 52)
18459 S.Diag(ReductionId.getBeginLoc(),
18460 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18461 << Type << ReductionIdRange;
18462 else
18463 S.Diag(ReductionId.getBeginLoc(),
18464 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18465 << Type << ReductionIdRange;
18466 continue;
18467 }
18468
18469 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18470 // The type of a list item that appears in a reduction clause must be valid
18471 // for the reduction-identifier. For a max or min reduction in C, the type
18472 // of the list item must be an allowed arithmetic data type: char, int,
18473 // float, double, or _Bool, possibly modified with long, short, signed, or
18474 // unsigned. For a max or min reduction in C++, the type of the list item
18475 // must be an allowed arithmetic data type: char, wchar_t, int, float,
18476 // double, or bool, possibly modified with long, short, signed, or unsigned.
18477 if (DeclareReductionRef.isUnset()) {
18478 if ((BOK == BO_GT || BOK == BO_LT) &&
18479 !(Type->isScalarType() ||
18480 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
18481 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18482 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
18483 if (!ASE && !OASE) {
18484 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18486 S.Diag(D->getLocation(),
18487 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18488 << D;
18489 }
18490 continue;
18491 }
18492 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18493 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
18494 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18495 << getOpenMPClauseName(ClauseKind);
18496 if (!ASE && !OASE) {
18497 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18499 S.Diag(D->getLocation(),
18500 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18501 << D;
18502 }
18503 continue;
18504 }
18505 }
18506
18507 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
18508 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
18509 D->hasAttrs() ? &D->getAttrs() : nullptr);
18510 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
18511 D->hasAttrs() ? &D->getAttrs() : nullptr);
18512 QualType PrivateTy = Type;
18513
18514 // Try if we can determine constant lengths for all array sections and avoid
18515 // the VLA.
18516 bool ConstantLengthOASE = false;
18517 if (OASE) {
18518 bool SingleElement;
18520 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
18521 Context, OASE, SingleElement, ArraySizes);
18522
18523 // If we don't have a single element, we must emit a constant array type.
18524 if (ConstantLengthOASE && !SingleElement) {
18525 for (llvm::APSInt &Size : ArraySizes)
18526 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
18528 /*IndexTypeQuals=*/0);
18529 }
18530 }
18531
18532 if ((OASE && !ConstantLengthOASE) ||
18533 (!OASE && !ASE &&
18534 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18535 if (!Context.getTargetInfo().isVLASupported()) {
18536 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
18537 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18538 S.Diag(ELoc, diag::note_vla_unsupported);
18539 continue;
18540 } else {
18541 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18542 S.targetDiag(ELoc, diag::note_vla_unsupported);
18543 }
18544 }
18545 // For arrays/array sections only:
18546 // Create pseudo array type for private copy. The size for this array will
18547 // be generated during codegen.
18548 // For array subscripts or single variables Private Ty is the same as Type
18549 // (type of the variable or single array element).
18550 PrivateTy = Context.getVariableArrayType(
18551 Type,
18552 new (Context)
18553 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
18554 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
18555 } else if (!ASE && !OASE &&
18556 Context.getAsArrayType(D->getType().getNonReferenceType())) {
18557 PrivateTy = D->getType().getNonReferenceType();
18558 }
18559 // Private copy.
18560 VarDecl *PrivateVD =
18561 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18562 D->hasAttrs() ? &D->getAttrs() : nullptr,
18563 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18564 // Add initializer for private variable.
18565 Expr *Init = nullptr;
18566 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
18567 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
18568 if (DeclareReductionRef.isUsable()) {
18569 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
18570 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18571 if (DRD->getInitializer()) {
18572 Init = DRDRef;
18573 RHSVD->setInit(DRDRef);
18575 }
18576 } else {
18577 switch (BOK) {
18578 case BO_Add:
18579 case BO_Xor:
18580 case BO_Or:
18581 case BO_LOr:
18582 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
18584 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
18585 break;
18586 case BO_Mul:
18587 case BO_LAnd:
18588 if (Type->isScalarType() || Type->isAnyComplexType()) {
18589 // '*' and '&&' reduction ops - initializer is '1'.
18590 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
18591 }
18592 break;
18593 case BO_And: {
18594 // '&' reduction op - initializer is '~0'.
18595 QualType OrigType = Type;
18596 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
18597 Type = ComplexTy->getElementType();
18598 if (Type->isRealFloatingType()) {
18599 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18600 Context.getFloatTypeSemantics(Type));
18601 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18602 Type, ELoc);
18603 } else if (Type->isScalarType()) {
18604 uint64_t Size = Context.getTypeSize(Type);
18605 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
18606 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18607 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18608 }
18609 if (Init && OrigType->isAnyComplexType()) {
18610 // Init = 0xFFFF + 0xFFFFi;
18611 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
18612 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
18613 }
18614 Type = OrigType;
18615 break;
18616 }
18617 case BO_LT:
18618 case BO_GT: {
18619 // 'min' reduction op - initializer is 'Largest representable number in
18620 // the reduction list item type'.
18621 // 'max' reduction op - initializer is 'Least representable number in
18622 // the reduction list item type'.
18623 if (Type->isIntegerType() || Type->isPointerType()) {
18624 bool IsSigned = Type->hasSignedIntegerRepresentation();
18625 uint64_t Size = Context.getTypeSize(Type);
18626 QualType IntTy =
18627 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
18628 llvm::APInt InitValue =
18629 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18630 : llvm::APInt::getMinValue(Size)
18631 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18632 : llvm::APInt::getMaxValue(Size);
18633 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18634 if (Type->isPointerType()) {
18635 // Cast to pointer type.
18637 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
18638 if (CastExpr.isInvalid())
18639 continue;
18640 Init = CastExpr.get();
18641 }
18642 } else if (Type->isRealFloatingType()) {
18643 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18644 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
18645 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18646 Type, ELoc);
18647 }
18648 break;
18649 }
18650 case BO_PtrMemD:
18651 case BO_PtrMemI:
18652 case BO_MulAssign:
18653 case BO_Div:
18654 case BO_Rem:
18655 case BO_Sub:
18656 case BO_Shl:
18657 case BO_Shr:
18658 case BO_LE:
18659 case BO_GE:
18660 case BO_EQ:
18661 case BO_NE:
18662 case BO_Cmp:
18663 case BO_AndAssign:
18664 case BO_XorAssign:
18665 case BO_OrAssign:
18666 case BO_Assign:
18667 case BO_AddAssign:
18668 case BO_SubAssign:
18669 case BO_DivAssign:
18670 case BO_RemAssign:
18671 case BO_ShlAssign:
18672 case BO_ShrAssign:
18673 case BO_Comma:
18674 llvm_unreachable("Unexpected reduction operation");
18675 }
18676 }
18677 if (Init && DeclareReductionRef.isUnset()) {
18678 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
18679 // Store initializer for single element in private copy. Will be used
18680 // during codegen.
18681 PrivateVD->setInit(RHSVD->getInit());
18682 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18683 } else if (!Init) {
18684 S.ActOnUninitializedDecl(RHSVD);
18685 // Store initializer for single element in private copy. Will be used
18686 // during codegen.
18687 PrivateVD->setInit(RHSVD->getInit());
18688 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18689 }
18690 if (RHSVD->isInvalidDecl())
18691 continue;
18692 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
18693 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18694 << Type << ReductionIdRange;
18695 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18697 S.Diag(D->getLocation(),
18698 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18699 << D;
18700 continue;
18701 }
18702 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
18703 ExprResult ReductionOp;
18704 if (DeclareReductionRef.isUsable()) {
18705 QualType RedTy = DeclareReductionRef.get()->getType();
18706 QualType PtrRedTy = Context.getPointerType(RedTy);
18707 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
18708 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
18709 if (!BasePath.empty()) {
18710 LHS = S.DefaultLvalueConversion(LHS.get());
18711 RHS = S.DefaultLvalueConversion(RHS.get());
18713 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
18714 LHS.get()->getValueKind(), FPOptionsOverride());
18716 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
18717 RHS.get()->getValueKind(), FPOptionsOverride());
18718 }
18720 QualType Params[] = {PtrRedTy, PtrRedTy};
18721 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
18722 auto *OVE = new (Context) OpaqueValueExpr(
18723 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
18724 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
18725 Expr *Args[] = {LHS.get(), RHS.get()};
18726 ReductionOp =
18727 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
18729 } else {
18731 if (Type->isRecordType() && CombBOK != BOK) {
18733 ReductionOp =
18734 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18735 CombBOK, LHSDRE, RHSDRE);
18736 }
18737 if (!ReductionOp.isUsable()) {
18738 ReductionOp =
18739 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
18740 LHSDRE, RHSDRE);
18741 if (ReductionOp.isUsable()) {
18742 if (BOK != BO_LT && BOK != BO_GT) {
18743 ReductionOp =
18744 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18745 BO_Assign, LHSDRE, ReductionOp.get());
18746 } else {
18747 auto *ConditionalOp = new (Context)
18748 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
18749 RHSDRE, Type, VK_LValue, OK_Ordinary);
18750 ReductionOp =
18751 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18752 BO_Assign, LHSDRE, ConditionalOp);
18753 }
18754 }
18755 }
18756 if (ReductionOp.isUsable())
18757 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
18758 /*DiscardedValue*/ false);
18759 if (!ReductionOp.isUsable())
18760 continue;
18761 }
18762
18763 // Add copy operations for inscan reductions.
18764 // LHS = RHS;
18765 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18766 if (ClauseKind == OMPC_reduction &&
18767 RD.RedModifier == OMPC_REDUCTION_inscan) {
18768 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
18769 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18770 RHS.get());
18771 if (!CopyOpRes.isUsable())
18772 continue;
18773 CopyOpRes =
18774 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
18775 if (!CopyOpRes.isUsable())
18776 continue;
18777 // For simd directive and simd-based directives in simd mode no need to
18778 // construct temp array, need just a single temp element.
18779 if (Stack->getCurrentDirective() == OMPD_simd ||
18780 (S.getLangOpts().OpenMPSimd &&
18781 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
18782 VarDecl *TempArrayVD =
18783 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18784 D->hasAttrs() ? &D->getAttrs() : nullptr);
18785 // Add a constructor to the temp decl.
18786 S.ActOnUninitializedDecl(TempArrayVD);
18787 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
18788 } else {
18789 // Build temp array for prefix sum.
18790 auto *Dim = new (S.Context)
18793 PrivateTy, Dim, ArraySizeModifier::Normal,
18794 /*IndexTypeQuals=*/0, {ELoc, ELoc});
18795 VarDecl *TempArrayVD =
18796 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
18797 D->hasAttrs() ? &D->getAttrs() : nullptr);
18798 // Add a constructor to the temp decl.
18799 S.ActOnUninitializedDecl(TempArrayVD);
18800 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
18801 TempArrayElem =
18802 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
18803 auto *Idx = new (S.Context)
18805 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
18806 ELoc, Idx, ELoc);
18807 }
18808 }
18809
18810 // OpenMP [2.15.4.6, Restrictions, p.2]
18811 // A list item that appears in an in_reduction clause of a task construct
18812 // must appear in a task_reduction clause of a construct associated with a
18813 // taskgroup region that includes the participating task in its taskgroup
18814 // set. The construct associated with the innermost region that meets this
18815 // condition must specify the same reduction-identifier as the in_reduction
18816 // clause.
18817 if (ClauseKind == OMPC_in_reduction) {
18818 SourceRange ParentSR;
18819 BinaryOperatorKind ParentBOK;
18820 const Expr *ParentReductionOp = nullptr;
18821 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
18822 DSAStackTy::DSAVarData ParentBOKDSA =
18823 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
18824 ParentBOKTD);
18825 DSAStackTy::DSAVarData ParentReductionOpDSA =
18826 Stack->getTopMostTaskgroupReductionData(
18827 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
18828 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
18829 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
18830 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
18831 (DeclareReductionRef.isUsable() && IsParentBOK) ||
18832 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
18833 bool EmitError = true;
18834 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
18835 llvm::FoldingSetNodeID RedId, ParentRedId;
18836 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
18837 DeclareReductionRef.get()->Profile(RedId, Context,
18838 /*Canonical=*/true);
18839 EmitError = RedId != ParentRedId;
18840 }
18841 if (EmitError) {
18842 S.Diag(ReductionId.getBeginLoc(),
18843 diag::err_omp_reduction_identifier_mismatch)
18844 << ReductionIdRange << RefExpr->getSourceRange();
18845 S.Diag(ParentSR.getBegin(),
18846 diag::note_omp_previous_reduction_identifier)
18847 << ParentSR
18848 << (IsParentBOK ? ParentBOKDSA.RefExpr
18849 : ParentReductionOpDSA.RefExpr)
18850 ->getSourceRange();
18851 continue;
18852 }
18853 }
18854 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
18855 }
18856
18857 DeclRefExpr *Ref = nullptr;
18858 Expr *VarsExpr = RefExpr->IgnoreParens();
18859 if (!VD && !S.CurContext->isDependentContext()) {
18860 if (ASE || OASE) {
18861 TransformExprToCaptures RebuildToCapture(S, D);
18862 VarsExpr =
18863 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
18864 Ref = RebuildToCapture.getCapturedExpr();
18865 } else {
18866 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
18867 }
18868 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
18869 RD.ExprCaptures.emplace_back(Ref->getDecl());
18870 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
18871 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
18872 if (!RefRes.isUsable())
18873 continue;
18874 ExprResult PostUpdateRes =
18875 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18876 RefRes.get());
18877 if (!PostUpdateRes.isUsable())
18878 continue;
18879 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
18880 Stack->getCurrentDirective() == OMPD_taskgroup) {
18881 S.Diag(RefExpr->getExprLoc(),
18882 diag::err_omp_reduction_non_addressable_expression)
18883 << RefExpr->getSourceRange();
18884 continue;
18885 }
18886 RD.ExprPostUpdates.emplace_back(
18887 S.IgnoredValueConversions(PostUpdateRes.get()).get());
18888 }
18889 }
18890 }
18891 // All reduction items are still marked as reduction (to do not increase
18892 // code base size).
18893 unsigned Modifier = RD.RedModifier;
18894 // Consider task_reductions as reductions with task modifier. Required for
18895 // correct analysis of in_reduction clauses.
18896 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
18897 Modifier = OMPC_REDUCTION_task;
18898 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
18899 ASE || OASE);
18900 if (Modifier == OMPC_REDUCTION_task &&
18901 (CurrDir == OMPD_taskgroup ||
18902 ((isOpenMPParallelDirective(CurrDir) ||
18903 isOpenMPWorksharingDirective(CurrDir)) &&
18904 !isOpenMPSimdDirective(CurrDir)))) {
18905 if (DeclareReductionRef.isUsable())
18906 Stack->addTaskgroupReductionData(D, ReductionIdRange,
18907 DeclareReductionRef.get());
18908 else
18909 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
18910 }
18911 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
18912 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
18913 TempArrayElem.get());
18914 }
18915 return RD.Vars.empty();
18916}
18917
18920 SourceLocation StartLoc, SourceLocation LParenLoc,
18921 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
18922 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18923 ArrayRef<Expr *> UnresolvedReductions) {
18924 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
18925 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
18926 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
18927 /*Last=*/OMPC_REDUCTION_unknown)
18928 << getOpenMPClauseName(OMPC_reduction);
18929 return nullptr;
18930 }
18931 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
18932 // A reduction clause with the inscan reduction-modifier may only appear on a
18933 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
18934 // construct, a parallel worksharing-loop construct or a parallel
18935 // worksharing-loop SIMD construct.
18936 if (Modifier == OMPC_REDUCTION_inscan &&
18937 (DSAStack->getCurrentDirective() != OMPD_for &&
18938 DSAStack->getCurrentDirective() != OMPD_for_simd &&
18939 DSAStack->getCurrentDirective() != OMPD_simd &&
18940 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
18941 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
18942 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
18943 return nullptr;
18944 }
18945
18946 ReductionData RD(VarList.size(), Modifier);
18947 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
18948 StartLoc, LParenLoc, ColonLoc, EndLoc,
18949 ReductionIdScopeSpec, ReductionId,
18950 UnresolvedReductions, RD))
18951 return nullptr;
18952
18954 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
18955 Modifier, RD.Vars,
18956 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
18957 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
18958 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
18959 buildPreInits(getASTContext(), RD.ExprCaptures),
18960 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
18961}
18962
18964 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18965 SourceLocation ColonLoc, SourceLocation EndLoc,
18966 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18967 ArrayRef<Expr *> UnresolvedReductions) {
18968 ReductionData RD(VarList.size());
18969 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
18970 VarList, StartLoc, LParenLoc, ColonLoc,
18971 EndLoc, ReductionIdScopeSpec, ReductionId,
18972 UnresolvedReductions, RD))
18973 return nullptr;
18974
18976 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
18977 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
18978 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
18979 buildPreInits(getASTContext(), RD.ExprCaptures),
18980 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
18981}
18982
18984 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18985 SourceLocation ColonLoc, SourceLocation EndLoc,
18986 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18987 ArrayRef<Expr *> UnresolvedReductions) {
18988 ReductionData RD(VarList.size());
18989 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
18990 StartLoc, LParenLoc, ColonLoc, EndLoc,
18991 ReductionIdScopeSpec, ReductionId,
18992 UnresolvedReductions, RD))
18993 return nullptr;
18994
18996 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
18997 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
18998 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
18999 buildPreInits(getASTContext(), RD.ExprCaptures),
19000 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19001}
19002
19004 SourceLocation LinLoc) {
19005 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19006 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19007 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19008 << getLangOpts().CPlusPlus;
19009 return true;
19010 }
19011 return false;
19012}
19013
19015 OpenMPLinearClauseKind LinKind,
19016 QualType Type, bool IsDeclareSimd) {
19017 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19018 // A variable must not have an incomplete type or a reference type.
19020 diag::err_omp_linear_incomplete_type))
19021 return true;
19022 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19023 !Type->isReferenceType()) {
19024 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19025 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19026 return true;
19027 }
19028 Type = Type.getNonReferenceType();
19029
19030 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19031 // A variable that is privatized must not have a const-qualified type
19032 // unless it is of class type with a mutable member. This restriction does
19033 // not apply to the firstprivate clause, nor to the linear clause on
19034 // declarative directives (like declare simd).
19035 if (!IsDeclareSimd &&
19036 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19037 return true;
19038
19039 // A list item must be of integral or pointer type.
19040 Type = Type.getUnqualifiedType().getCanonicalType();
19041 const auto *Ty = Type.getTypePtrOrNull();
19042 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19043 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
19044 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19045 if (D) {
19046 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19048 Diag(D->getLocation(),
19049 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19050 << D;
19051 }
19052 return true;
19053 }
19054 return false;
19055}
19056
19058 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19059 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19060 SourceLocation LinLoc, SourceLocation ColonLoc,
19061 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19063 SmallVector<Expr *, 8> Privates;
19065 SmallVector<Decl *, 4> ExprCaptures;
19066 SmallVector<Expr *, 4> ExprPostUpdates;
19067 // OpenMP 5.2 [Section 5.4.6, linear clause]
19068 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19069 // 'ref'
19070 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19071 getLangOpts().OpenMP >= 52)
19072 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19073 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19074 LinKind = OMPC_LINEAR_val;
19075 for (Expr *RefExpr : VarList) {
19076 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19077 SourceLocation ELoc;
19078 SourceRange ERange;
19079 Expr *SimpleRefExpr = RefExpr;
19080 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19081 if (Res.second) {
19082 // It will be analyzed later.
19083 Vars.push_back(RefExpr);
19084 Privates.push_back(nullptr);
19085 Inits.push_back(nullptr);
19086 }
19087 ValueDecl *D = Res.first;
19088 if (!D)
19089 continue;
19090
19091 QualType Type = D->getType();
19092 auto *VD = dyn_cast<VarDecl>(D);
19093
19094 // OpenMP [2.14.3.7, linear clause]
19095 // A list-item cannot appear in more than one linear clause.
19096 // A list-item that appears in a linear clause cannot appear in any
19097 // other data-sharing attribute clause.
19098 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19099 if (DVar.RefExpr) {
19100 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19101 << getOpenMPClauseName(OMPC_linear);
19103 continue;
19104 }
19105
19106 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19107 continue;
19108 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19109
19110 // Build private copy of original var.
19111 VarDecl *Private =
19112 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19113 D->hasAttrs() ? &D->getAttrs() : nullptr,
19114 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19115 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19116 // Build var to save initial value.
19117 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19118 Expr *InitExpr;
19119 DeclRefExpr *Ref = nullptr;
19120 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19121 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19122 if (!isOpenMPCapturedDecl(D)) {
19123 ExprCaptures.push_back(Ref->getDecl());
19124 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19126 if (!RefRes.isUsable())
19127 continue;
19128 ExprResult PostUpdateRes =
19129 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19130 SimpleRefExpr, RefRes.get());
19131 if (!PostUpdateRes.isUsable())
19132 continue;
19133 ExprPostUpdates.push_back(
19134 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19135 }
19136 }
19137 }
19138 if (LinKind == OMPC_LINEAR_uval)
19139 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19140 else
19141 InitExpr = VD ? SimpleRefExpr : Ref;
19144 /*DirectInit=*/false);
19145 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19146
19147 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19148 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19149 ? RefExpr->IgnoreParens()
19150 : Ref);
19151 Privates.push_back(PrivateRef);
19152 Inits.push_back(InitRef);
19153 }
19154
19155 if (Vars.empty())
19156 return nullptr;
19157
19158 Expr *StepExpr = Step;
19159 Expr *CalcStepExpr = nullptr;
19160 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19161 !Step->isInstantiationDependent() &&
19163 SourceLocation StepLoc = Step->getBeginLoc();
19165 if (Val.isInvalid())
19166 return nullptr;
19167 StepExpr = Val.get();
19168
19169 // Build var to save the step value.
19170 VarDecl *SaveVar =
19171 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19172 ExprResult SaveRef =
19173 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19174 ExprResult CalcStep = SemaRef.BuildBinOp(
19175 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19176 CalcStep =
19177 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
19178
19179 // Warn about zero linear step (it would be probably better specified as
19180 // making corresponding variables 'const').
19181 if (std::optional<llvm::APSInt> Result =
19183 if (!Result->isNegative() && !Result->isStrictlyPositive())
19184 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19185 << Vars[0] << (Vars.size() > 1);
19186 } else if (CalcStep.isUsable()) {
19187 // Calculate the step beforehand instead of doing this on each iteration.
19188 // (This is not used if the number of iterations may be kfold-ed).
19189 CalcStepExpr = CalcStep.get();
19190 }
19191 }
19192
19193 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19194 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19195 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19196 buildPreInits(getASTContext(), ExprCaptures),
19197 buildPostUpdate(SemaRef, ExprPostUpdates));
19198}
19199
19201 Expr *NumIterations, Sema &SemaRef,
19202 Scope *S, DSAStackTy *Stack) {
19203 // Walk the vars and build update/final expressions for the CodeGen.
19204 SmallVector<Expr *, 8> Updates;
19206 SmallVector<Expr *, 8> UsedExprs;
19207 Expr *Step = Clause.getStep();
19208 Expr *CalcStep = Clause.getCalcStep();
19209 // OpenMP [2.14.3.7, linear clause]
19210 // If linear-step is not specified it is assumed to be 1.
19211 if (!Step)
19212 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19213 else if (CalcStep)
19214 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19215 bool HasErrors = false;
19216 auto CurInit = Clause.inits().begin();
19217 auto CurPrivate = Clause.privates().begin();
19218 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19219 for (Expr *RefExpr : Clause.varlist()) {
19220 SourceLocation ELoc;
19221 SourceRange ERange;
19222 Expr *SimpleRefExpr = RefExpr;
19223 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19224 ValueDecl *D = Res.first;
19225 if (Res.second || !D) {
19226 Updates.push_back(nullptr);
19227 Finals.push_back(nullptr);
19228 HasErrors = true;
19229 continue;
19230 }
19231 auto &&Info = Stack->isLoopControlVariable(D);
19232 // OpenMP [2.15.11, distribute simd Construct]
19233 // A list item may not appear in a linear clause, unless it is the loop
19234 // iteration variable.
19235 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19236 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19237 SemaRef.Diag(ELoc,
19238 diag::err_omp_linear_distribute_var_non_loop_iteration);
19239 Updates.push_back(nullptr);
19240 Finals.push_back(nullptr);
19241 HasErrors = true;
19242 continue;
19243 }
19244 Expr *InitExpr = *CurInit;
19245
19246 // Build privatized reference to the current linear var.
19247 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19248 Expr *CapturedRef;
19249 if (LinKind == OMPC_LINEAR_uval)
19250 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19251 else
19252 CapturedRef =
19253 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19254 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19255 /*RefersToCapture=*/true);
19256
19257 // Build update: Var = InitExpr + IV * Step
19259 if (!Info.first)
19261 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19262 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19263 else
19264 Update = *CurPrivate;
19265 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19266 /*DiscardedValue*/ false);
19267
19268 // Build final: Var = PrivCopy;
19269 ExprResult Final;
19270 if (!Info.first)
19271 Final = SemaRef.BuildBinOp(
19272 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19273 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19274 else
19275 Final = *CurPrivate;
19276 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19277 /*DiscardedValue*/ false);
19278
19279 if (!Update.isUsable() || !Final.isUsable()) {
19280 Updates.push_back(nullptr);
19281 Finals.push_back(nullptr);
19282 UsedExprs.push_back(nullptr);
19283 HasErrors = true;
19284 } else {
19285 Updates.push_back(Update.get());
19286 Finals.push_back(Final.get());
19287 if (!Info.first)
19288 UsedExprs.push_back(SimpleRefExpr);
19289 }
19290 ++CurInit;
19291 ++CurPrivate;
19292 }
19293 if (Expr *S = Clause.getStep())
19294 UsedExprs.push_back(S);
19295 // Fill the remaining part with the nullptr.
19296 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19297 Clause.setUpdates(Updates);
19298 Clause.setFinals(Finals);
19299 Clause.setUsedExprs(UsedExprs);
19300 return HasErrors;
19301}
19302
19304 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19305 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19307 for (Expr *RefExpr : VarList) {
19308 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19309 SourceLocation ELoc;
19310 SourceRange ERange;
19311 Expr *SimpleRefExpr = RefExpr;
19312 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19313 if (Res.second) {
19314 // It will be analyzed later.
19315 Vars.push_back(RefExpr);
19316 }
19317 ValueDecl *D = Res.first;
19318 if (!D)
19319 continue;
19320
19321 QualType QType = D->getType();
19322 auto *VD = dyn_cast<VarDecl>(D);
19323
19324 // OpenMP [2.8.1, simd construct, Restrictions]
19325 // The type of list items appearing in the aligned clause must be
19326 // array, pointer, reference to array, or reference to pointer.
19328 const Type *Ty = QType.getTypePtrOrNull();
19329 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19330 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19331 << QType << getLangOpts().CPlusPlus << ERange;
19332 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19334 Diag(D->getLocation(),
19335 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19336 << D;
19337 continue;
19338 }
19339
19340 // OpenMP [2.8.1, simd construct, Restrictions]
19341 // A list-item cannot appear in more than one aligned clause.
19342 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19343 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19344 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19345 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19346 << getOpenMPClauseName(OMPC_aligned);
19347 continue;
19348 }
19349
19350 DeclRefExpr *Ref = nullptr;
19351 if (!VD && isOpenMPCapturedDecl(D))
19352 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19353 Vars.push_back(SemaRef
19354 .DefaultFunctionArrayConversion(
19355 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19356 .get());
19357 }
19358
19359 // OpenMP [2.8.1, simd construct, Description]
19360 // The parameter of the aligned clause, alignment, must be a constant
19361 // positive integer expression.
19362 // If no optional parameter is specified, implementation-defined default
19363 // alignments for SIMD instructions on the target platforms are assumed.
19364 if (Alignment != nullptr) {
19365 ExprResult AlignResult =
19366 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19367 if (AlignResult.isInvalid())
19368 return nullptr;
19369 Alignment = AlignResult.get();
19370 }
19371 if (Vars.empty())
19372 return nullptr;
19373
19374 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
19375 ColonLoc, EndLoc, Vars, Alignment);
19376}
19377
19379 SourceLocation StartLoc,
19380 SourceLocation LParenLoc,
19381 SourceLocation EndLoc) {
19383 SmallVector<Expr *, 8> SrcExprs;
19384 SmallVector<Expr *, 8> DstExprs;
19385 SmallVector<Expr *, 8> AssignmentOps;
19386 for (Expr *RefExpr : VarList) {
19387 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19388 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19389 // It will be analyzed later.
19390 Vars.push_back(RefExpr);
19391 SrcExprs.push_back(nullptr);
19392 DstExprs.push_back(nullptr);
19393 AssignmentOps.push_back(nullptr);
19394 continue;
19395 }
19396
19397 SourceLocation ELoc = RefExpr->getExprLoc();
19398 // OpenMP [2.1, C/C++]
19399 // A list item is a variable name.
19400 // OpenMP [2.14.4.1, Restrictions, p.1]
19401 // A list item that appears in a copyin clause must be threadprivate.
19402 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19403 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19404 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19405 << 0 << RefExpr->getSourceRange();
19406 continue;
19407 }
19408
19409 Decl *D = DE->getDecl();
19410 auto *VD = cast<VarDecl>(D);
19411
19412 QualType Type = VD->getType();
19414 // It will be analyzed later.
19415 Vars.push_back(DE);
19416 SrcExprs.push_back(nullptr);
19417 DstExprs.push_back(nullptr);
19418 AssignmentOps.push_back(nullptr);
19419 continue;
19420 }
19421
19422 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19423 // A list item that appears in a copyin clause must be threadprivate.
19424 if (!DSAStack->isThreadPrivate(VD)) {
19425 Diag(ELoc, diag::err_omp_required_access)
19426 << getOpenMPClauseName(OMPC_copyin)
19427 << getOpenMPDirectiveName(OMPD_threadprivate);
19428 continue;
19429 }
19430
19431 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19432 // A variable of class type (or array thereof) that appears in a
19433 // copyin clause requires an accessible, unambiguous copy assignment
19434 // operator for the class type.
19435 QualType ElemType =
19437 VarDecl *SrcVD =
19438 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
19439 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19440 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
19441 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
19442 VarDecl *DstVD =
19443 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
19444 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19445 DeclRefExpr *PseudoDstExpr =
19446 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
19447 // For arrays generate assignment operation for single element and replace
19448 // it by the original array element in CodeGen.
19449 ExprResult AssignmentOp =
19450 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
19451 PseudoDstExpr, PseudoSrcExpr);
19452 if (AssignmentOp.isInvalid())
19453 continue;
19454 AssignmentOp =
19455 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
19456 /*DiscardedValue*/ false);
19457 if (AssignmentOp.isInvalid())
19458 continue;
19459
19460 DSAStack->addDSA(VD, DE, OMPC_copyin);
19461 Vars.push_back(DE);
19462 SrcExprs.push_back(PseudoSrcExpr);
19463 DstExprs.push_back(PseudoDstExpr);
19464 AssignmentOps.push_back(AssignmentOp.get());
19465 }
19466
19467 if (Vars.empty())
19468 return nullptr;
19469
19470 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19471 Vars, SrcExprs, DstExprs, AssignmentOps);
19472}
19473
19475 SourceLocation StartLoc,
19476 SourceLocation LParenLoc,
19477 SourceLocation EndLoc) {
19479 SmallVector<Expr *, 8> SrcExprs;
19480 SmallVector<Expr *, 8> DstExprs;
19481 SmallVector<Expr *, 8> AssignmentOps;
19482 for (Expr *RefExpr : VarList) {
19483 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19484 SourceLocation ELoc;
19485 SourceRange ERange;
19486 Expr *SimpleRefExpr = RefExpr;
19487 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19488 if (Res.second) {
19489 // It will be analyzed later.
19490 Vars.push_back(RefExpr);
19491 SrcExprs.push_back(nullptr);
19492 DstExprs.push_back(nullptr);
19493 AssignmentOps.push_back(nullptr);
19494 }
19495 ValueDecl *D = Res.first;
19496 if (!D)
19497 continue;
19498
19499 QualType Type = D->getType();
19500 auto *VD = dyn_cast<VarDecl>(D);
19501
19502 // OpenMP [2.14.4.2, Restrictions, p.2]
19503 // A list item that appears in a copyprivate clause may not appear in a
19504 // private or firstprivate clause on the single construct.
19505 if (!VD || !DSAStack->isThreadPrivate(VD)) {
19506 DSAStackTy::DSAVarData DVar =
19507 DSAStack->getTopDSA(D, /*FromParent=*/false);
19508 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19509 DVar.RefExpr) {
19510 Diag(ELoc, diag::err_omp_wrong_dsa)
19511 << getOpenMPClauseName(DVar.CKind)
19512 << getOpenMPClauseName(OMPC_copyprivate);
19514 continue;
19515 }
19516
19517 // OpenMP [2.11.4.2, Restrictions, p.1]
19518 // All list items that appear in a copyprivate clause must be either
19519 // threadprivate or private in the enclosing context.
19520 if (DVar.CKind == OMPC_unknown) {
19521 DVar = DSAStack->getImplicitDSA(D, false);
19522 if (DVar.CKind == OMPC_shared) {
19523 Diag(ELoc, diag::err_omp_required_access)
19524 << getOpenMPClauseName(OMPC_copyprivate)
19525 << "threadprivate or private in the enclosing context";
19527 continue;
19528 }
19529 }
19530 }
19531
19532 // Variably modified types are not supported.
19534 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19535 << getOpenMPClauseName(OMPC_copyprivate) << Type
19536 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
19537 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19539 Diag(D->getLocation(),
19540 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19541 << D;
19542 continue;
19543 }
19544
19545 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19546 // A variable of class type (or array thereof) that appears in a
19547 // copyin clause requires an accessible, unambiguous copy assignment
19548 // operator for the class type.
19550 .getBaseElementType(Type.getNonReferenceType())
19552 VarDecl *SrcVD =
19553 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
19554 D->hasAttrs() ? &D->getAttrs() : nullptr);
19555 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
19556 VarDecl *DstVD =
19557 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
19558 D->hasAttrs() ? &D->getAttrs() : nullptr);
19559 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19560 ExprResult AssignmentOp = SemaRef.BuildBinOp(
19561 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19562 if (AssignmentOp.isInvalid())
19563 continue;
19564 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19565 /*DiscardedValue*/ false);
19566 if (AssignmentOp.isInvalid())
19567 continue;
19568
19569 // No need to mark vars as copyprivate, they are already threadprivate or
19570 // implicitly private.
19571 assert(VD || isOpenMPCapturedDecl(D));
19572 Vars.push_back(
19573 VD ? RefExpr->IgnoreParens()
19574 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
19575 SrcExprs.push_back(PseudoSrcExpr);
19576 DstExprs.push_back(PseudoDstExpr);
19577 AssignmentOps.push_back(AssignmentOp.get());
19578 }
19579
19580 if (Vars.empty())
19581 return nullptr;
19582
19583 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
19584 EndLoc, Vars, SrcExprs, DstExprs,
19585 AssignmentOps);
19586}
19587
19589 SourceLocation StartLoc,
19590 SourceLocation LParenLoc,
19591 SourceLocation EndLoc) {
19592 if (VarList.empty())
19593 return nullptr;
19594
19595 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19596 VarList);
19597}
19598
19599/// Tries to find omp_depend_t. type.
19600static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
19601 bool Diagnose = true) {
19602 QualType OMPDependT = Stack->getOMPDependT();
19603 if (!OMPDependT.isNull())
19604 return true;
19605 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
19606 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
19607 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
19608 if (Diagnose)
19609 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
19610 return false;
19611 }
19612 Stack->setOMPDependT(PT.get());
19613 return true;
19614}
19615
19617 SourceLocation StartLoc,
19618 SourceLocation LParenLoc,
19619 SourceLocation EndLoc) {
19620 if (!Depobj)
19621 return nullptr;
19622
19623 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
19624
19625 // OpenMP 5.0, 2.17.10.1 depobj Construct
19626 // depobj is an lvalue expression of type omp_depend_t.
19627 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
19628 !Depobj->isInstantiationDependent() &&
19630 (OMPDependTFound && !getASTContext().typesAreCompatible(
19631 DSAStack->getOMPDependT(), Depobj->getType(),
19632 /*CompareUnqualified=*/true))) {
19633 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19634 << 0 << Depobj->getType() << Depobj->getSourceRange();
19635 }
19636
19637 if (!Depobj->isLValue()) {
19638 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19639 << 1 << Depobj->getSourceRange();
19640 }
19641
19642 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19643 Depobj);
19644}
19645
19646namespace {
19647// Utility struct that gathers the related info for doacross clause.
19648struct DoacrossDataInfoTy {
19649 // The list of expressions.
19651 // The OperatorOffset for doacross loop.
19653 // The depended loop count.
19654 llvm::APSInt TotalDepCount;
19655};
19656} // namespace
19657static DoacrossDataInfoTy
19659 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
19660 SourceLocation EndLoc) {
19661
19664 llvm::APSInt DepCounter(/*BitWidth=*/32);
19665 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19666
19667 if (const Expr *OrderedCountExpr =
19668 Stack->getParentOrderedRegionParam().first) {
19669 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
19670 TotalDepCount.setIsUnsigned(/*Val=*/true);
19671 }
19672
19673 for (Expr *RefExpr : VarList) {
19674 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
19675 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19676 // It will be analyzed later.
19677 Vars.push_back(RefExpr);
19678 continue;
19679 }
19680
19681 SourceLocation ELoc = RefExpr->getExprLoc();
19682 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19683 if (!IsSource) {
19684 if (Stack->getParentOrderedRegionParam().first &&
19685 DepCounter >= TotalDepCount) {
19686 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19687 continue;
19688 }
19689 ++DepCounter;
19690 // OpenMP [2.13.9, Summary]
19691 // depend(dependence-type : vec), where dependence-type is:
19692 // 'sink' and where vec is the iteration vector, which has the form:
19693 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
19694 // where n is the value specified by the ordered clause in the loop
19695 // directive, xi denotes the loop iteration variable of the i-th nested
19696 // loop associated with the loop directive, and di is a constant
19697 // non-negative integer.
19698 if (SemaRef.CurContext->isDependentContext()) {
19699 // It will be analyzed later.
19700 Vars.push_back(RefExpr);
19701 continue;
19702 }
19703 SimpleExpr = SimpleExpr->IgnoreImplicit();
19705 SourceLocation OOLoc;
19706 Expr *LHS = SimpleExpr;
19707 Expr *RHS = nullptr;
19708 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19709 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
19710 OOLoc = BO->getOperatorLoc();
19711 LHS = BO->getLHS()->IgnoreParenImpCasts();
19712 RHS = BO->getRHS()->IgnoreParenImpCasts();
19713 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19714 OOK = OCE->getOperator();
19715 OOLoc = OCE->getOperatorLoc();
19716 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19717 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
19718 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19719 OOK = MCE->getMethodDecl()
19720 ->getNameInfo()
19721 .getName()
19722 .getCXXOverloadedOperator();
19723 OOLoc = MCE->getCallee()->getExprLoc();
19724 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
19725 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19726 }
19727 SourceLocation ELoc;
19728 SourceRange ERange;
19729 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
19730 if (Res.second) {
19731 // It will be analyzed later.
19732 Vars.push_back(RefExpr);
19733 }
19734 ValueDecl *D = Res.first;
19735 if (!D)
19736 continue;
19737
19738 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
19739 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19740 continue;
19741 }
19742 if (RHS) {
19743 ExprResult RHSRes =
19745 RHS, OMPC_depend, /*StrictlyPositive=*/false);
19746 if (RHSRes.isInvalid())
19747 continue;
19748 }
19749 if (!SemaRef.CurContext->isDependentContext() &&
19750 Stack->getParentOrderedRegionParam().first &&
19751 DepCounter != Stack->isParentLoopControlVariable(D).first) {
19752 const ValueDecl *VD =
19753 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19754 if (VD)
19755 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19756 << 1 << VD;
19757 else
19758 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19759 << 0;
19760 continue;
19761 }
19762 OpsOffs.emplace_back(RHS, OOK);
19763 }
19764 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19765 }
19766 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
19767 TotalDepCount > VarList.size() &&
19768 Stack->getParentOrderedRegionParam().first &&
19769 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19770 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19771 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19772 }
19773 return {Vars, OpsOffs, TotalDepCount};
19774}
19775
19777 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
19778 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19779 SourceLocation EndLoc) {
19780 OpenMPDependClauseKind DepKind = Data.DepKind;
19781 SourceLocation DepLoc = Data.DepLoc;
19782 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
19783 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19784 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19785 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19786 return nullptr;
19787 }
19788 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
19789 DepKind == OMPC_DEPEND_mutexinoutset) {
19790 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19791 return nullptr;
19792 }
19793 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
19794 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19795 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
19796 DepKind == OMPC_DEPEND_sink ||
19797 ((getLangOpts().OpenMP < 50 ||
19798 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19799 DepKind == OMPC_DEPEND_depobj))) {
19800 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
19801 OMPC_DEPEND_outallmemory,
19802 OMPC_DEPEND_inoutallmemory};
19803 if (getLangOpts().OpenMP < 50 ||
19804 DSAStack->getCurrentDirective() == OMPD_depobj)
19805 Except.push_back(OMPC_DEPEND_depobj);
19806 if (getLangOpts().OpenMP < 51)
19807 Except.push_back(OMPC_DEPEND_inoutset);
19808 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
19809 ? "depend modifier(iterator) or "
19810 : "";
19811 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19812 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
19813 /*Last=*/OMPC_DEPEND_unknown,
19814 Except)
19815 << getOpenMPClauseName(OMPC_depend);
19816 return nullptr;
19817 }
19818 if (DepModifier &&
19819 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
19820 Diag(DepModifier->getExprLoc(),
19821 diag::err_omp_depend_sink_source_with_modifier);
19822 return nullptr;
19823 }
19824 if (DepModifier &&
19825 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
19826 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
19827
19830 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19831
19832 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
19833 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
19834 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
19835 Vars = VarOffset.Vars;
19836 OpsOffs = VarOffset.OpsOffs;
19837 TotalDepCount = VarOffset.TotalDepCount;
19838 } else {
19839 for (Expr *RefExpr : VarList) {
19840 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19841 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19842 // It will be analyzed later.
19843 Vars.push_back(RefExpr);
19844 continue;
19845 }
19846
19847 SourceLocation ELoc = RefExpr->getExprLoc();
19848 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19849 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
19850 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
19851 if (OMPDependTFound)
19852 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
19853 DepKind == OMPC_DEPEND_depobj);
19854 if (DepKind == OMPC_DEPEND_depobj) {
19855 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
19856 // List items used in depend clauses with the depobj dependence type
19857 // must be expressions of the omp_depend_t type.
19858 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19859 !RefExpr->isInstantiationDependent() &&
19860 !RefExpr->containsUnexpandedParameterPack() &&
19861 (OMPDependTFound &&
19862 !getASTContext().hasSameUnqualifiedType(
19863 DSAStack->getOMPDependT(), RefExpr->getType()))) {
19864 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19865 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
19866 continue;
19867 }
19868 if (!RefExpr->isLValue()) {
19869 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19870 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
19871 continue;
19872 }
19873 } else {
19874 // OpenMP 5.0 [2.17.11, Restrictions]
19875 // List items used in depend clauses cannot be zero-length array
19876 // sections.
19877 QualType ExprTy = RefExpr->getType().getNonReferenceType();
19878 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
19879 if (OASE) {
19880 QualType BaseType =
19882 if (BaseType.isNull())
19883 return nullptr;
19884 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19885 ExprTy = ATy->getElementType();
19886 else
19887 ExprTy = BaseType->getPointeeType();
19888 if (BaseType.isNull() || ExprTy.isNull())
19889 return nullptr;
19890 ExprTy = ExprTy.getNonReferenceType();
19891 const Expr *Length = OASE->getLength();
19893 if (Length && !Length->isValueDependent() &&
19894 Length->EvaluateAsInt(Result, getASTContext()) &&
19895 Result.Val.getInt().isZero()) {
19896 Diag(ELoc,
19897 diag::err_omp_depend_zero_length_array_section_not_allowed)
19898 << SimpleExpr->getSourceRange();
19899 continue;
19900 }
19901 }
19902
19903 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
19904 // List items used in depend clauses with the in, out, inout,
19905 // inoutset, or mutexinoutset dependence types cannot be
19906 // expressions of the omp_depend_t type.
19907 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19908 !RefExpr->isInstantiationDependent() &&
19909 !RefExpr->containsUnexpandedParameterPack() &&
19910 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
19911 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
19912 ExprTy.getTypePtr()))) {
19913 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19914 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19915 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19916 << RefExpr->getSourceRange();
19917 continue;
19918 }
19919
19920 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
19921 if (ASE && !ASE->getBase()->isTypeDependent() &&
19922 !ASE->getBase()
19923 ->getType()
19924 .getNonReferenceType()
19925 ->isPointerType() &&
19926 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
19927 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19928 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19929 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19930 << RefExpr->getSourceRange();
19931 continue;
19932 }
19933
19934 ExprResult Res;
19935 {
19937 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
19938 RefExpr->IgnoreParenImpCasts());
19939 }
19940 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
19941 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
19942 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19943 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19944 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19945 << RefExpr->getSourceRange();
19946 continue;
19947 }
19948 }
19949 }
19950 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19951 }
19952 }
19953
19954 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
19955 DepKind != OMPC_DEPEND_outallmemory &&
19956 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
19957 return nullptr;
19958
19959 auto *C = OMPDependClause::Create(
19960 getASTContext(), StartLoc, LParenLoc, EndLoc,
19961 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
19962 TotalDepCount.getZExtValue());
19963 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
19964 DSAStack->isParentOrderedRegion())
19965 DSAStack->addDoacrossDependClause(C, OpsOffs);
19966 return C;
19967}
19968
19971 SourceLocation LParenLoc, SourceLocation ModifierLoc,
19972 SourceLocation EndLoc) {
19973 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
19974 "Unexpected device modifier in OpenMP < 50.");
19975
19976 bool ErrorFound = false;
19977 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
19978 std::string Values =
19979 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
19980 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
19981 << Values << getOpenMPClauseName(OMPC_device);
19982 ErrorFound = true;
19983 }
19984
19985 Expr *ValExpr = Device;
19986 Stmt *HelperValStmt = nullptr;
19987
19988 // OpenMP [2.9.1, Restrictions]
19989 // The device expression must evaluate to a non-negative integer value.
19990 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
19991 /*StrictlyPositive=*/false) ||
19992 ErrorFound;
19993 if (ErrorFound)
19994 return nullptr;
19995
19996 // OpenMP 5.0 [2.12.5, Restrictions]
19997 // In case of ancestor device-modifier, a requires directive with
19998 // the reverse_offload clause must be specified.
19999 if (Modifier == OMPC_DEVICE_ancestor) {
20000 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20002 StartLoc,
20003 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20004 ErrorFound = true;
20005 }
20006 }
20007
20008 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20009 OpenMPDirectiveKind CaptureRegion =
20010 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20011 if (CaptureRegion != OMPD_unknown &&
20013 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20014 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20015 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20016 HelperValStmt = buildPreInits(getASTContext(), Captures);
20017 }
20018
20019 return new (getASTContext())
20020 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20021 LParenLoc, ModifierLoc, EndLoc);
20022}
20023
20025 DSAStackTy *Stack, QualType QTy,
20026 bool FullCheck = true) {
20027 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20028 return false;
20029 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20030 !QTy.isTriviallyCopyableType(SemaRef.Context))
20031 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20032 return true;
20033}
20034
20035/// Return true if it can be proven that the provided array expression
20036/// (array section or array subscript) does NOT specify the whole size of the
20037/// array whose base type is \a BaseQTy.
20039 const Expr *E,
20040 QualType BaseQTy) {
20041 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20042
20043 // If this is an array subscript, it refers to the whole size if the size of
20044 // the dimension is constant and equals 1. Also, an array section assumes the
20045 // format of an array subscript if no colon is used.
20046 if (isa<ArraySubscriptExpr>(E) ||
20047 (OASE && OASE->getColonLocFirst().isInvalid())) {
20048 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20049 return ATy->getSExtSize() != 1;
20050 // Size can't be evaluated statically.
20051 return false;
20052 }
20053
20054 assert(OASE && "Expecting array section if not an array subscript.");
20055 const Expr *LowerBound = OASE->getLowerBound();
20056 const Expr *Length = OASE->getLength();
20057
20058 // If there is a lower bound that does not evaluates to zero, we are not
20059 // covering the whole dimension.
20060 if (LowerBound) {
20062 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20063 return false; // Can't get the integer value as a constant.
20064
20065 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20066 if (ConstLowerBound.getSExtValue())
20067 return true;
20068 }
20069
20070 // If we don't have a length we covering the whole dimension.
20071 if (!Length)
20072 return false;
20073
20074 // If the base is a pointer, we don't have a way to get the size of the
20075 // pointee.
20076 if (BaseQTy->isPointerType())
20077 return false;
20078
20079 // We can only check if the length is the same as the size of the dimension
20080 // if we have a constant array.
20081 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20082 if (!CATy)
20083 return false;
20084
20086 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20087 return false; // Can't get the integer value as a constant.
20088
20089 llvm::APSInt ConstLength = Result.Val.getInt();
20090 return CATy->getSExtSize() != ConstLength.getSExtValue();
20091}
20092
20093// Return true if it can be proven that the provided array expression (array
20094// section or array subscript) does NOT specify a single element of the array
20095// whose base type is \a BaseQTy.
20097 const Expr *E,
20098 QualType BaseQTy) {
20099 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20100
20101 // An array subscript always refer to a single element. Also, an array section
20102 // assumes the format of an array subscript if no colon is used.
20103 if (isa<ArraySubscriptExpr>(E) ||
20104 (OASE && OASE->getColonLocFirst().isInvalid()))
20105 return false;
20106
20107 assert(OASE && "Expecting array section if not an array subscript.");
20108 const Expr *Length = OASE->getLength();
20109
20110 // If we don't have a length we have to check if the array has unitary size
20111 // for this dimension. Also, we should always expect a length if the base type
20112 // is pointer.
20113 if (!Length) {
20114 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20115 return ATy->getSExtSize() != 1;
20116 // We cannot assume anything.
20117 return false;
20118 }
20119
20120 // Check if the length evaluates to 1.
20122 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20123 return false; // Can't get the integer value as a constant.
20124
20125 llvm::APSInt ConstLength = Result.Val.getInt();
20126 return ConstLength.getSExtValue() != 1;
20127}
20128
20129// The base of elements of list in a map clause have to be either:
20130// - a reference to variable or field.
20131// - a member expression.
20132// - an array expression.
20133//
20134// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20135// reference to 'r'.
20136//
20137// If we have:
20138//
20139// struct SS {
20140// Bla S;
20141// foo() {
20142// #pragma omp target map (S.Arr[:12]);
20143// }
20144// }
20145//
20146// We want to retrieve the member expression 'this->S';
20147
20148// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20149// If a list item is an array section, it must specify contiguous storage.
20150//
20151// For this restriction it is sufficient that we make sure only references
20152// to variables or fields and array expressions, and that no array sections
20153// exist except in the rightmost expression (unless they cover the whole
20154// dimension of the array). E.g. these would be invalid:
20155//
20156// r.ArrS[3:5].Arr[6:7]
20157//
20158// r.ArrS[3:5].x
20159//
20160// but these would be valid:
20161// r.ArrS[3].Arr[6:7]
20162//
20163// r.ArrS[3].x
20164namespace {
20165class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20166 Sema &SemaRef;
20167 OpenMPClauseKind CKind = OMPC_unknown;
20168 OpenMPDirectiveKind DKind = OMPD_unknown;
20170 bool IsNonContiguous = false;
20171 bool NoDiagnose = false;
20172 const Expr *RelevantExpr = nullptr;
20173 bool AllowUnitySizeArraySection = true;
20174 bool AllowWholeSizeArraySection = true;
20175 bool AllowAnotherPtr = true;
20176 SourceLocation ELoc;
20177 SourceRange ERange;
20178
20179 void emitErrorMsg() {
20180 // If nothing else worked, this is not a valid map clause expression.
20181 if (SemaRef.getLangOpts().OpenMP < 50) {
20182 SemaRef.Diag(ELoc,
20183 diag::err_omp_expected_named_var_member_or_array_expression)
20184 << ERange;
20185 } else {
20186 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20187 << getOpenMPClauseName(CKind) << ERange;
20188 }
20189 }
20190
20191public:
20192 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20193 if (!isa<VarDecl>(DRE->getDecl())) {
20194 emitErrorMsg();
20195 return false;
20196 }
20197 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20198 RelevantExpr = DRE;
20199 // Record the component.
20200 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20201 return true;
20202 }
20203
20204 bool VisitMemberExpr(MemberExpr *ME) {
20205 Expr *E = ME;
20206 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20207
20208 if (isa<CXXThisExpr>(BaseE)) {
20209 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20210 // We found a base expression: this->Val.
20211 RelevantExpr = ME;
20212 } else {
20213 E = BaseE;
20214 }
20215
20216 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20217 if (!NoDiagnose) {
20218 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20219 << ME->getSourceRange();
20220 return false;
20221 }
20222 if (RelevantExpr)
20223 return false;
20224 return Visit(E);
20225 }
20226
20227 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20228
20229 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20230 // A bit-field cannot appear in a map clause.
20231 //
20232 if (FD->isBitField()) {
20233 if (!NoDiagnose) {
20234 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20235 << ME->getSourceRange() << getOpenMPClauseName(CKind);
20236 return false;
20237 }
20238 if (RelevantExpr)
20239 return false;
20240 return Visit(E);
20241 }
20242
20243 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20244 // If the type of a list item is a reference to a type T then the type
20245 // will be considered to be T for all purposes of this clause.
20246 QualType CurType = BaseE->getType().getNonReferenceType();
20247
20248 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20249 // A list item cannot be a variable that is a member of a structure with
20250 // a union type.
20251 //
20252 if (CurType->isUnionType()) {
20253 if (!NoDiagnose) {
20254 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20255 << ME->getSourceRange();
20256 return false;
20257 }
20258 return RelevantExpr || Visit(E);
20259 }
20260
20261 // If we got a member expression, we should not expect any array section
20262 // before that:
20263 //
20264 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20265 // If a list item is an element of a structure, only the rightmost symbol
20266 // of the variable reference can be an array section.
20267 //
20268 AllowUnitySizeArraySection = false;
20269 AllowWholeSizeArraySection = false;
20270
20271 // Record the component.
20272 Components.emplace_back(ME, FD, IsNonContiguous);
20273 return RelevantExpr || Visit(E);
20274 }
20275
20276 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20277 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20278
20279 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20280 if (!NoDiagnose) {
20281 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20282 << 0 << AE->getSourceRange();
20283 return false;
20284 }
20285 return RelevantExpr || Visit(E);
20286 }
20287
20288 // If we got an array subscript that express the whole dimension we
20289 // can have any array expressions before. If it only expressing part of
20290 // the dimension, we can only have unitary-size array expressions.
20292 AllowWholeSizeArraySection = false;
20293
20294 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20295 Expr::EvalResult Result;
20296 if (!AE->getIdx()->isValueDependent() &&
20297 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20298 !Result.Val.getInt().isZero()) {
20299 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20300 diag::err_omp_invalid_map_this_expr);
20301 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20302 diag::note_omp_invalid_subscript_on_this_ptr_map);
20303 }
20304 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20305 RelevantExpr = TE;
20306 }
20307
20308 // Record the component - we don't have any declaration associated.
20309 Components.emplace_back(AE, nullptr, IsNonContiguous);
20310
20311 return RelevantExpr || Visit(E);
20312 }
20313
20314 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
20315 // After OMP 5.0 Array section in reduction clause will be implicitly
20316 // mapped
20317 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20318 "Array sections cannot be implicitly mapped.");
20319 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20320 QualType CurType =
20322
20323 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20324 // If the type of a list item is a reference to a type T then the type
20325 // will be considered to be T for all purposes of this clause.
20326 if (CurType->isReferenceType())
20327 CurType = CurType->getPointeeType();
20328
20329 bool IsPointer = CurType->isAnyPointerType();
20330
20331 if (!IsPointer && !CurType->isArrayType()) {
20332 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20333 << 0 << OASE->getSourceRange();
20334 return false;
20335 }
20336
20337 bool NotWhole =
20338 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20339 bool NotUnity =
20340 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20341
20342 if (AllowWholeSizeArraySection) {
20343 // Any array section is currently allowed. Allowing a whole size array
20344 // section implies allowing a unity array section as well.
20345 //
20346 // If this array section refers to the whole dimension we can still
20347 // accept other array sections before this one, except if the base is a
20348 // pointer. Otherwise, only unitary sections are accepted.
20349 if (NotWhole || IsPointer)
20350 AllowWholeSizeArraySection = false;
20351 } else if (DKind == OMPD_target_update &&
20352 SemaRef.getLangOpts().OpenMP >= 50) {
20353 if (IsPointer && !AllowAnotherPtr)
20354 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20355 << /*array of unknown bound */ 1;
20356 else
20357 IsNonContiguous = true;
20358 } else if (AllowUnitySizeArraySection && NotUnity) {
20359 // A unity or whole array section is not allowed and that is not
20360 // compatible with the properties of the current array section.
20361 if (NoDiagnose)
20362 return false;
20363 SemaRef.Diag(ELoc,
20364 diag::err_array_section_does_not_specify_contiguous_storage)
20365 << OASE->getSourceRange();
20366 return false;
20367 }
20368
20369 if (IsPointer)
20370 AllowAnotherPtr = false;
20371
20372 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20373 Expr::EvalResult ResultR;
20374 Expr::EvalResult ResultL;
20375 if (!OASE->getLength()->isValueDependent() &&
20376 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20377 !ResultR.Val.getInt().isOne()) {
20378 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20379 diag::err_omp_invalid_map_this_expr);
20380 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20381 diag::note_omp_invalid_length_on_this_ptr_mapping);
20382 }
20383 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20384 OASE->getLowerBound()->EvaluateAsInt(ResultL,
20385 SemaRef.getASTContext()) &&
20386 !ResultL.Val.getInt().isZero()) {
20387 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20388 diag::err_omp_invalid_map_this_expr);
20389 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20390 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20391 }
20392 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20393 RelevantExpr = TE;
20394 }
20395
20396 // Record the component - we don't have any declaration associated.
20397 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20398 return RelevantExpr || Visit(E);
20399 }
20400 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20401 Expr *Base = E->getBase();
20402
20403 // Record the component - we don't have any declaration associated.
20404 Components.emplace_back(E, nullptr, IsNonContiguous);
20405
20406 return Visit(Base->IgnoreParenImpCasts());
20407 }
20408
20409 bool VisitUnaryOperator(UnaryOperator *UO) {
20410 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20411 UO->getOpcode() != UO_Deref) {
20412 emitErrorMsg();
20413 return false;
20414 }
20415 if (!RelevantExpr) {
20416 // Record the component if haven't found base decl.
20417 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20418 }
20419 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20420 }
20421 bool VisitBinaryOperator(BinaryOperator *BO) {
20422 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20423 emitErrorMsg();
20424 return false;
20425 }
20426
20427 // Pointer arithmetic is the only thing we expect to happen here so after we
20428 // make sure the binary operator is a pointer type, the only thing we need
20429 // to do is to visit the subtree that has the same type as root (so that we
20430 // know the other subtree is just an offset)
20431 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20432 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20433 Components.emplace_back(BO, nullptr, false);
20434 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20435 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20436 "Either LHS or RHS have base decl inside");
20437 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20438 return RelevantExpr || Visit(LE);
20439 return RelevantExpr || Visit(RE);
20440 }
20441 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20442 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20443 RelevantExpr = CTE;
20444 Components.emplace_back(CTE, nullptr, IsNonContiguous);
20445 return true;
20446 }
20447 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20448 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20449 Components.emplace_back(COCE, nullptr, IsNonContiguous);
20450 return true;
20451 }
20452 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20453 Expr *Source = E->getSourceExpr();
20454 if (!Source) {
20455 emitErrorMsg();
20456 return false;
20457 }
20458 return Visit(Source);
20459 }
20460 bool VisitStmt(Stmt *) {
20461 emitErrorMsg();
20462 return false;
20463 }
20464 const Expr *getFoundBase() const { return RelevantExpr; }
20465 explicit MapBaseChecker(
20466 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20468 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20469 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20470 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20471};
20472} // namespace
20473
20474/// Return the expression of the base of the mappable expression or null if it
20475/// cannot be determined and do all the necessary checks to see if the
20476/// expression is valid as a standalone mappable expression. In the process,
20477/// record all the components of the expression.
20479 Sema &SemaRef, Expr *E,
20481 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20482 SourceLocation ELoc = E->getExprLoc();
20483 SourceRange ERange = E->getSourceRange();
20484 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20485 ERange);
20486 if (Checker.Visit(E->IgnoreParens())) {
20487 // Check if the highest dimension array section has length specified
20488 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20489 (CKind == OMPC_to || CKind == OMPC_from)) {
20490 auto CI = CurComponents.rbegin();
20491 auto CE = CurComponents.rend();
20492 for (; CI != CE; ++CI) {
20493 const auto *OASE =
20494 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20495 if (!OASE)
20496 continue;
20497 if (OASE && OASE->getLength())
20498 break;
20499 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
20500 << ERange;
20501 }
20502 }
20503 return Checker.getFoundBase();
20504 }
20505 return nullptr;
20506}
20507
20508// Return true if expression E associated with value VD has conflicts with other
20509// map information.
20511 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
20512 bool CurrentRegionOnly,
20514 OpenMPClauseKind CKind) {
20515 assert(VD && E);
20516 SourceLocation ELoc = E->getExprLoc();
20517 SourceRange ERange = E->getSourceRange();
20518
20519 // In order to easily check the conflicts we need to match each component of
20520 // the expression under test with the components of the expressions that are
20521 // already in the stack.
20522
20523 assert(!CurComponents.empty() && "Map clause expression with no components!");
20524 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20525 "Map clause expression with unexpected base!");
20526
20527 // Variables to help detecting enclosing problems in data environment nests.
20528 bool IsEnclosedByDataEnvironmentExpr = false;
20529 const Expr *EnclosingExpr = nullptr;
20530
20531 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20532 VD, CurrentRegionOnly,
20533 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20534 ERange, CKind, &EnclosingExpr,
20536 StackComponents,
20537 OpenMPClauseKind Kind) {
20538 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
20539 return false;
20540 assert(!StackComponents.empty() &&
20541 "Map clause expression with no components!");
20542 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20543 "Map clause expression with unexpected base!");
20544 (void)VD;
20545
20546 // The whole expression in the stack.
20547 const Expr *RE = StackComponents.front().getAssociatedExpression();
20548
20549 // Expressions must start from the same base. Here we detect at which
20550 // point both expressions diverge from each other and see if we can
20551 // detect if the memory referred to both expressions is contiguous and
20552 // do not overlap.
20553 auto CI = CurComponents.rbegin();
20554 auto CE = CurComponents.rend();
20555 auto SI = StackComponents.rbegin();
20556 auto SE = StackComponents.rend();
20557 for (; CI != CE && SI != SE; ++CI, ++SI) {
20558
20559 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
20560 // At most one list item can be an array item derived from a given
20561 // variable in map clauses of the same construct.
20562 if (CurrentRegionOnly &&
20563 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20564 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20565 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20566 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20567 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20568 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20569 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20570 diag::err_omp_multiple_array_items_in_map_clause)
20571 << CI->getAssociatedExpression()->getSourceRange();
20572 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20573 diag::note_used_here)
20574 << SI->getAssociatedExpression()->getSourceRange();
20575 return true;
20576 }
20577
20578 // Do both expressions have the same kind?
20579 if (CI->getAssociatedExpression()->getStmtClass() !=
20580 SI->getAssociatedExpression()->getStmtClass())
20581 break;
20582
20583 // Are we dealing with different variables/fields?
20584 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20585 break;
20586 }
20587 // Check if the extra components of the expressions in the enclosing
20588 // data environment are redundant for the current base declaration.
20589 // If they are, the maps completely overlap, which is legal.
20590 for (; SI != SE; ++SI) {
20591 QualType Type;
20592 if (const auto *ASE =
20593 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20594 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20595 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
20596 SI->getAssociatedExpression())) {
20597 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20598 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20599 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20600 SI->getAssociatedExpression())) {
20601 Type = OASE->getBase()->getType()->getPointeeType();
20602 }
20603 if (Type.isNull() || Type->isAnyPointerType() ||
20605 SemaRef, SI->getAssociatedExpression(), Type))
20606 break;
20607 }
20608
20609 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20610 // List items of map clauses in the same construct must not share
20611 // original storage.
20612 //
20613 // If the expressions are exactly the same or one is a subset of the
20614 // other, it means they are sharing storage.
20615 if (CI == CE && SI == SE) {
20616 if (CurrentRegionOnly) {
20617 if (CKind == OMPC_map) {
20618 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20619 } else {
20620 assert(CKind == OMPC_to || CKind == OMPC_from);
20621 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20622 << ERange;
20623 }
20624 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20625 << RE->getSourceRange();
20626 return true;
20627 }
20628 // If we find the same expression in the enclosing data environment,
20629 // that is legal.
20630 IsEnclosedByDataEnvironmentExpr = true;
20631 return false;
20632 }
20633
20634 QualType DerivedType =
20635 std::prev(CI)->getAssociatedDeclaration()->getType();
20636 SourceLocation DerivedLoc =
20637 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20638
20639 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20640 // If the type of a list item is a reference to a type T then the type
20641 // will be considered to be T for all purposes of this clause.
20642 DerivedType = DerivedType.getNonReferenceType();
20643
20644 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
20645 // A variable for which the type is pointer and an array section
20646 // derived from that variable must not appear as list items of map
20647 // clauses of the same construct.
20648 //
20649 // Also, cover one of the cases in:
20650 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20651 // If any part of the original storage of a list item has corresponding
20652 // storage in the device data environment, all of the original storage
20653 // must have corresponding storage in the device data environment.
20654 //
20655 if (DerivedType->isAnyPointerType()) {
20656 if (CI == CE || SI == SE) {
20657 SemaRef.Diag(
20658 DerivedLoc,
20659 diag::err_omp_pointer_mapped_along_with_derived_section)
20660 << DerivedLoc;
20661 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20662 << RE->getSourceRange();
20663 return true;
20664 }
20665 if (CI->getAssociatedExpression()->getStmtClass() !=
20666 SI->getAssociatedExpression()->getStmtClass() ||
20667 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20668 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20669 assert(CI != CE && SI != SE);
20670 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20671 << DerivedLoc;
20672 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20673 << RE->getSourceRange();
20674 return true;
20675 }
20676 }
20677
20678 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20679 // List items of map clauses in the same construct must not share
20680 // original storage.
20681 //
20682 // An expression is a subset of the other.
20683 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20684 if (CKind == OMPC_map) {
20685 if (CI != CE || SI != SE) {
20686 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
20687 // a pointer.
20688 auto Begin =
20689 CI != CE ? CurComponents.begin() : StackComponents.begin();
20690 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20691 auto It = Begin;
20692 while (It != End && !It->getAssociatedDeclaration())
20693 std::advance(It, 1);
20694 assert(It != End &&
20695 "Expected at least one component with the declaration.");
20696 if (It != Begin && It->getAssociatedDeclaration()
20697 ->getType()
20698 .getCanonicalType()
20699 ->isAnyPointerType()) {
20700 IsEnclosedByDataEnvironmentExpr = false;
20701 EnclosingExpr = nullptr;
20702 return false;
20703 }
20704 }
20705 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20706 } else {
20707 assert(CKind == OMPC_to || CKind == OMPC_from);
20708 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20709 << ERange;
20710 }
20711 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20712 << RE->getSourceRange();
20713 return true;
20714 }
20715
20716 // The current expression uses the same base as other expression in the
20717 // data environment but does not contain it completely.
20718 if (!CurrentRegionOnly && SI != SE)
20719 EnclosingExpr = RE;
20720
20721 // The current expression is a subset of the expression in the data
20722 // environment.
20723 IsEnclosedByDataEnvironmentExpr |=
20724 (!CurrentRegionOnly && CI != CE && SI == SE);
20725
20726 return false;
20727 });
20728
20729 if (CurrentRegionOnly)
20730 return FoundError;
20731
20732 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20733 // If any part of the original storage of a list item has corresponding
20734 // storage in the device data environment, all of the original storage must
20735 // have corresponding storage in the device data environment.
20736 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
20737 // If a list item is an element of a structure, and a different element of
20738 // the structure has a corresponding list item in the device data environment
20739 // prior to a task encountering the construct associated with the map clause,
20740 // then the list item must also have a corresponding list item in the device
20741 // data environment prior to the task encountering the construct.
20742 //
20743 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20744 SemaRef.Diag(ELoc,
20745 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20746 << ERange;
20747 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
20748 << EnclosingExpr->getSourceRange();
20749 return true;
20750 }
20751
20752 return FoundError;
20753}
20754
20755// Look up the user-defined mapper given the mapper name and mapped type, and
20756// build a reference to it.
20758 CXXScopeSpec &MapperIdScopeSpec,
20759 const DeclarationNameInfo &MapperId,
20760 QualType Type,
20761 Expr *UnresolvedMapper) {
20762 if (MapperIdScopeSpec.isInvalid())
20763 return ExprError();
20764 // Get the actual type for the array type.
20765 if (Type->isArrayType()) {
20766 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
20768 }
20769 // Find all user-defined mappers with the given MapperId.
20770 SmallVector<UnresolvedSet<8>, 4> Lookups;
20771 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
20772 Lookup.suppressDiagnostics();
20773 if (S) {
20774 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
20775 /*ObjectType=*/QualType())) {
20776 NamedDecl *D = Lookup.getRepresentativeDecl();
20777 while (S && !S->isDeclScope(D))
20778 S = S->getParent();
20779 if (S)
20780 S = S->getParent();
20781 Lookups.emplace_back();
20782 Lookups.back().append(Lookup.begin(), Lookup.end());
20783 Lookup.clear();
20784 }
20785 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20786 // Extract the user-defined mappers with the given MapperId.
20787 Lookups.push_back(UnresolvedSet<8>());
20788 for (NamedDecl *D : ULE->decls()) {
20789 auto *DMD = cast<OMPDeclareMapperDecl>(D);
20790 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
20791 Lookups.back().addDecl(DMD);
20792 }
20793 }
20794 // Defer the lookup for dependent types. The results will be passed through
20795 // UnresolvedMapper on instantiation.
20796 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
20799 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
20800 return !D->isInvalidDecl() &&
20801 (D->getType()->isDependentType() ||
20802 D->getType()->isInstantiationDependentType() ||
20803 D->getType()->containsUnexpandedParameterPack());
20804 })) {
20805 UnresolvedSet<8> URS;
20806 for (const UnresolvedSet<8> &Set : Lookups) {
20807 if (Set.empty())
20808 continue;
20809 URS.append(Set.begin(), Set.end());
20810 }
20812 SemaRef.Context, /*NamingClass=*/nullptr,
20813 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
20814 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
20815 /*KnownInstantiationDependent=*/false);
20816 }
20817 SourceLocation Loc = MapperId.getLoc();
20818 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
20819 // The type must be of struct, union or class type in C and C++
20821 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
20822 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
20823 return ExprError();
20824 }
20825 // Perform argument dependent lookup.
20826 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
20827 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
20828 // Return the first user-defined mapper with the desired type.
20829 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20830 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
20831 if (!D->isInvalidDecl() &&
20832 SemaRef.Context.hasSameType(D->getType(), Type))
20833 return D;
20834 return nullptr;
20835 }))
20836 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
20837 // Find the first user-defined mapper with a type derived from the desired
20838 // type.
20839 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20840 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
20841 if (!D->isInvalidDecl() &&
20842 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
20843 !Type.isMoreQualifiedThan(D->getType()))
20844 return D;
20845 return nullptr;
20846 })) {
20847 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
20848 /*DetectVirtual=*/false);
20849 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
20850 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
20851 VD->getType().getUnqualifiedType()))) {
20852 if (SemaRef.CheckBaseClassAccess(
20853 Loc, VD->getType(), Type, Paths.front(),
20854 /*DiagID=*/0) != Sema::AR_inaccessible) {
20855 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
20856 }
20857 }
20858 }
20859 }
20860 // Report error if a mapper is specified, but cannot be found.
20861 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
20862 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
20863 << Type << MapperId.getName();
20864 return ExprError();
20865 }
20866 return ExprEmpty();
20867}
20868
20869namespace {
20870// Utility struct that gathers all the related lists associated with a mappable
20871// expression.
20872struct MappableVarListInfo {
20873 // The list of expressions.
20874 ArrayRef<Expr *> VarList;
20875 // The list of processed expressions.
20876 SmallVector<Expr *, 16> ProcessedVarList;
20877 // The mappble components for each expression.
20879 // The base declaration of the variable.
20880 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
20881 // The reference to the user-defined mapper associated with every expression.
20882 SmallVector<Expr *, 16> UDMapperList;
20883
20884 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
20885 // We have a list of components and base declarations for each entry in the
20886 // variable list.
20887 VarComponents.reserve(VarList.size());
20888 VarBaseDeclarations.reserve(VarList.size());
20889 }
20890};
20891} // namespace
20892
20894 DSAStackTy *Stack,
20896
20897 const RecordDecl *RD = BaseType->getAsRecordDecl();
20899 DeclarationNameInfo ImplicitName;
20900 // Dummy variable _s for Mapper.
20901 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
20902 DeclRefExpr *MapperVarRef =
20903 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
20904
20905 // Create implicit map clause for mapper.
20907 for (auto *FD : RD->fields()) {
20908 Expr *BE = S.BuildMemberExpr(
20909 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
20912 /*HadMultipleCandidates=*/false,
20914 FD->getType(), VK_LValue, OK_Ordinary);
20915 SExprs.push_back(BE);
20916 }
20917 CXXScopeSpec MapperIdScopeSpec;
20918 DeclarationNameInfo MapperId;
20919 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
20920
20921 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
20922 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
20923 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
20924 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
20925 OMPVarListLocTy());
20926 Maps.push_back(MapClause);
20927 return MapperVarRef;
20928}
20929
20931 DSAStackTy *Stack) {
20932
20933 // Build impilicit map for mapper
20935 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
20936
20937 const RecordDecl *RD = BaseType->getAsRecordDecl();
20938 // AST context is RD's ParentASTContext().
20939 ASTContext &Ctx = RD->getParentASTContext();
20940 // DeclContext is RD's DeclContext.
20941 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
20942
20943 // Create implicit default mapper for "RD".
20944 DeclarationName MapperId;
20945 auto &DeclNames = Ctx.DeclarationNames;
20946 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
20947 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
20948 BaseType, MapperId, Maps, nullptr);
20949 Scope *Scope = S.getScopeForContext(DCT);
20950 if (Scope)
20951 S.PushOnScopeChains(DMD, Scope, /*AddToContext*/ false);
20952 DCT->addDecl(DMD);
20953 DMD->setAccess(clang::AS_none);
20954 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
20955 VD->setDeclContext(DMD);
20956 VD->setLexicalDeclContext(DMD);
20957 DMD->addDecl(VD);
20958 DMD->setMapperVarRef(MapperVarRef);
20959 FieldDecl *FD = *RD->field_begin();
20960 // create mapper refence.
20962 DMD, false, SourceLocation(), BaseType, VK_LValue);
20963}
20964
20965// Look up the user-defined mapper given the mapper name and mapper type,
20966// return true if found one.
20967static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
20968 CXXScopeSpec &MapperIdScopeSpec,
20969 const DeclarationNameInfo &MapperId,
20970 QualType Type) {
20971 // Find all user-defined mappers with the given MapperId.
20972 SmallVector<UnresolvedSet<8>, 4> Lookups;
20973 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
20974 Lookup.suppressDiagnostics();
20975 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
20976 /*ObjectType=*/QualType())) {
20977 NamedDecl *D = Lookup.getRepresentativeDecl();
20978 while (S && !S->isDeclScope(D))
20979 S = S->getParent();
20980 if (S)
20981 S = S->getParent();
20982 Lookups.emplace_back();
20983 Lookups.back().append(Lookup.begin(), Lookup.end());
20984 Lookup.clear();
20985 }
20986 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
20989 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
20990 return !D->isInvalidDecl() &&
20991 (D->getType()->isDependentType() ||
20992 D->getType()->isInstantiationDependentType() ||
20993 D->getType()->containsUnexpandedParameterPack());
20994 }))
20995 return false;
20996 // Perform argument dependent lookup.
20997 SourceLocation Loc = MapperId.getLoc();
20998 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
20999 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21000 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21001 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21002 if (!D->isInvalidDecl() &&
21003 SemaRef.Context.hasSameType(D->getType(), Type))
21004 return D;
21005 return nullptr;
21006 }))
21007 return true;
21008 // Find the first user-defined mapper with a type derived from the desired
21009 // type.
21010 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21011 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21012 if (!D->isInvalidDecl() &&
21013 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21014 !Type.isMoreQualifiedThan(D->getType()))
21015 return D;
21016 return nullptr;
21017 });
21018 if (!VD)
21019 return false;
21020 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21021 /*DetectVirtual=*/false);
21022 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21023 bool IsAmbiguous = !Paths.isAmbiguous(
21025 if (IsAmbiguous)
21026 return false;
21027 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
21028 /*DiagID=*/0) != Sema::AR_inaccessible)
21029 return true;
21030 }
21031 return false;
21032}
21033
21034static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21035 QualType CanonType, const Expr *E) {
21036
21037 // DFS over data members in structures/classes.
21039 {CanonType, nullptr});
21040 llvm::DenseMap<const Type *, bool> Visited;
21041 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21042 while (!Types.empty()) {
21043 auto [BaseType, CurFD] = Types.pop_back_val();
21044 while (ParentChain.back().second == 0)
21045 ParentChain.pop_back();
21046 --ParentChain.back().second;
21047 if (BaseType.isNull())
21048 continue;
21049 // Only structs/classes are allowed to have mappers.
21050 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21051 if (!RD)
21052 continue;
21053 auto It = Visited.find(BaseType.getTypePtr());
21054 if (It == Visited.end()) {
21055 // Try to find the associated user-defined mapper.
21056 CXXScopeSpec MapperIdScopeSpec;
21057 DeclarationNameInfo DefaultMapperId;
21059 &S.Context.Idents.get("default")));
21060 DefaultMapperId.setLoc(E->getExprLoc());
21061 bool HasUDMapper =
21062 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
21063 DefaultMapperId, BaseType);
21064 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21065 }
21066 // Found default mapper.
21067 if (It->second)
21068 return true;
21069 // Check for the "default" mapper for data members.
21070 bool FirstIter = true;
21071 for (FieldDecl *FD : RD->fields()) {
21072 if (!FD)
21073 continue;
21074 QualType FieldTy = FD->getType();
21075 if (FieldTy.isNull() ||
21076 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21077 continue;
21078 if (FirstIter) {
21079 FirstIter = false;
21080 ParentChain.emplace_back(CurFD, 1);
21081 } else {
21082 ++ParentChain.back().second;
21083 }
21084 Types.emplace_back(FieldTy, FD);
21085 }
21086 }
21087 return false;
21088}
21089
21090// Check the validity of the provided variable list for the provided clause kind
21091// \a CKind. In the check process the valid expressions, mappable expression
21092// components, variables, and user-defined mappers are extracted and used to
21093// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21094// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21095// and \a MapperId are expected to be valid if the clause kind is 'map'.
21097 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21098 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21099 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21100 ArrayRef<Expr *> UnresolvedMappers,
21102 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
21103 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21104 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21105 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21106 "Unexpected clause kind with mappable expressions!");
21107
21108 // If the identifier of user-defined mapper is not specified, it is "default".
21109 // We do not change the actual name in this clause to distinguish whether a
21110 // mapper is specified explicitly, i.e., it is not explicitly specified when
21111 // MapperId.getName() is empty.
21112 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21113 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21114 MapperId.setName(DeclNames.getIdentifier(
21115 &SemaRef.getASTContext().Idents.get("default")));
21116 MapperId.setLoc(StartLoc);
21117 }
21118
21119 // Iterators to find the current unresolved mapper expression.
21120 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21121 bool UpdateUMIt = false;
21122 Expr *UnresolvedMapper = nullptr;
21123
21124 bool HasHoldModifier =
21125 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21126
21127 // Keep track of the mappable components and base declarations in this clause.
21128 // Each entry in the list is going to have a list of components associated. We
21129 // record each set of the components so that we can build the clause later on.
21130 // In the end we should have the same amount of declarations and component
21131 // lists.
21132
21133 for (Expr *RE : MVLI.VarList) {
21134 assert(RE && "Null expr in omp to/from/map clause");
21135 SourceLocation ELoc = RE->getExprLoc();
21136
21137 // Find the current unresolved mapper expression.
21138 if (UpdateUMIt && UMIt != UMEnd) {
21139 UMIt++;
21140 assert(
21141 UMIt != UMEnd &&
21142 "Expect the size of UnresolvedMappers to match with that of VarList");
21143 }
21144 UpdateUMIt = true;
21145 if (UMIt != UMEnd)
21146 UnresolvedMapper = *UMIt;
21147
21148 const Expr *VE = RE->IgnoreParenLValueCasts();
21149
21150 if (VE->isValueDependent() || VE->isTypeDependent() ||
21153 // Try to find the associated user-defined mapper.
21155 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21156 VE->getType().getCanonicalType(), UnresolvedMapper);
21157 if (ER.isInvalid())
21158 continue;
21159 MVLI.UDMapperList.push_back(ER.get());
21160 // We can only analyze this information once the missing information is
21161 // resolved.
21162 MVLI.ProcessedVarList.push_back(RE);
21163 continue;
21164 }
21165
21166 Expr *SimpleExpr = RE->IgnoreParenCasts();
21167
21168 if (!RE->isLValue()) {
21169 if (SemaRef.getLangOpts().OpenMP < 50) {
21170 SemaRef.Diag(
21171 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21172 << RE->getSourceRange();
21173 } else {
21174 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21175 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21176 }
21177 continue;
21178 }
21179
21181 ValueDecl *CurDeclaration = nullptr;
21182
21183 // Obtain the array or member expression bases if required. Also, fill the
21184 // components array with all the components identified in the process.
21185 const Expr *BE =
21186 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21187 DSAS->getCurrentDirective(), NoDiagnose);
21188 if (!BE)
21189 continue;
21190
21191 assert(!CurComponents.empty() &&
21192 "Invalid mappable expression information.");
21193
21194 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21195 // Add store "this" pointer to class in DSAStackTy for future checking
21196 DSAS->addMappedClassesQualTypes(TE->getType());
21197 // Try to find the associated user-defined mapper.
21199 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21200 VE->getType().getCanonicalType(), UnresolvedMapper);
21201 if (ER.isInvalid())
21202 continue;
21203 MVLI.UDMapperList.push_back(ER.get());
21204 // Skip restriction checking for variable or field declarations
21205 MVLI.ProcessedVarList.push_back(RE);
21206 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21207 MVLI.VarComponents.back().append(CurComponents.begin(),
21208 CurComponents.end());
21209 MVLI.VarBaseDeclarations.push_back(nullptr);
21210 continue;
21211 }
21212
21213 // For the following checks, we rely on the base declaration which is
21214 // expected to be associated with the last component. The declaration is
21215 // expected to be a variable or a field (if 'this' is being mapped).
21216 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21217 assert(CurDeclaration && "Null decl on map clause.");
21218 assert(
21219 CurDeclaration->isCanonicalDecl() &&
21220 "Expecting components to have associated only canonical declarations.");
21221
21222 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21223 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21224
21225 assert((VD || FD) && "Only variables or fields are expected here!");
21226 (void)FD;
21227
21228 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21229 // threadprivate variables cannot appear in a map clause.
21230 // OpenMP 4.5 [2.10.5, target update Construct]
21231 // threadprivate variables cannot appear in a from clause.
21232 if (VD && DSAS->isThreadPrivate(VD)) {
21233 if (NoDiagnose)
21234 continue;
21235 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21236 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21237 << getOpenMPClauseName(CKind);
21238 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21239 continue;
21240 }
21241
21242 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21243 // A list item cannot appear in both a map clause and a data-sharing
21244 // attribute clause on the same construct.
21245
21246 // Check conflicts with other map clause expressions. We check the conflicts
21247 // with the current construct separately from the enclosing data
21248 // environment, because the restrictions are different. We only have to
21249 // check conflicts across regions for the map clauses.
21250 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21251 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21252 break;
21253 if (CKind == OMPC_map &&
21254 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21255 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21256 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21257 break;
21258
21259 // OpenMP 4.5 [2.10.5, target update Construct]
21260 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21261 // If the type of a list item is a reference to a type T then the type will
21262 // be considered to be T for all purposes of this clause.
21263 auto I = llvm::find_if(
21264 CurComponents,
21266 return MC.getAssociatedDeclaration();
21267 });
21268 assert(I != CurComponents.end() && "Null decl on map clause.");
21269 (void)I;
21270 QualType Type;
21271 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21272 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
21273 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21274 if (ASE) {
21275 Type = ASE->getType().getNonReferenceType();
21276 } else if (OASE) {
21277 QualType BaseType =
21279 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21280 Type = ATy->getElementType();
21281 else
21282 Type = BaseType->getPointeeType();
21283 Type = Type.getNonReferenceType();
21284 } else if (OAShE) {
21285 Type = OAShE->getBase()->getType()->getPointeeType();
21286 } else {
21287 Type = VE->getType();
21288 }
21289
21290 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21291 // A list item in a to or from clause must have a mappable type.
21292 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21293 // A list item must have a mappable type.
21294 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21295 DSAS, Type, /*FullCheck=*/true))
21296 continue;
21297
21298 if (CKind == OMPC_map) {
21299 // target enter data
21300 // OpenMP [2.10.2, Restrictions, p. 99]
21301 // A map-type must be specified in all map clauses and must be either
21302 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21303 // no map type is present.
21304 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21305 if (DKind == OMPD_target_enter_data &&
21306 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21307 SemaRef.getLangOpts().OpenMP >= 52)) {
21308 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21309 << (IsMapTypeImplicit ? 1 : 0)
21310 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21311 << getOpenMPDirectiveName(DKind);
21312 continue;
21313 }
21314
21315 // target exit_data
21316 // OpenMP [2.10.3, Restrictions, p. 102]
21317 // A map-type must be specified in all map clauses and must be either
21318 // from, release, or delete. Starting with OpenMP 5.2 the default map
21319 // type is `from` if no map type is present.
21320 if (DKind == OMPD_target_exit_data &&
21321 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21322 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21323 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21324 << (IsMapTypeImplicit ? 1 : 0)
21325 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21326 << getOpenMPDirectiveName(DKind);
21327 continue;
21328 }
21329
21330 // The 'ompx_hold' modifier is specifically intended to be used on a
21331 // 'target' or 'target data' directive to prevent data from being unmapped
21332 // during the associated statement. It is not permitted on a 'target
21333 // enter data' or 'target exit data' directive, which have no associated
21334 // statement.
21335 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21336 HasHoldModifier) {
21337 SemaRef.Diag(StartLoc,
21338 diag::err_omp_invalid_map_type_modifier_for_directive)
21340 OMPC_MAP_MODIFIER_ompx_hold)
21341 << getOpenMPDirectiveName(DKind);
21342 continue;
21343 }
21344
21345 // target, target data
21346 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21347 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21348 // A map-type in a map clause must be to, from, tofrom or alloc
21349 if ((DKind == OMPD_target_data ||
21351 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21352 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21353 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21354 << (IsMapTypeImplicit ? 1 : 0)
21355 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21356 << getOpenMPDirectiveName(DKind);
21357 continue;
21358 }
21359
21360 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21361 // A list item cannot appear in both a map clause and a data-sharing
21362 // attribute clause on the same construct
21363 //
21364 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21365 // A list item cannot appear in both a map clause and a data-sharing
21366 // attribute clause on the same construct unless the construct is a
21367 // combined construct.
21368 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21370 DKind == OMPD_target)) {
21371 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21372 if (isOpenMPPrivate(DVar.CKind)) {
21373 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21374 << getOpenMPClauseName(DVar.CKind)
21375 << getOpenMPClauseName(OMPC_map)
21376 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21377 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21378 continue;
21379 }
21380 }
21381 }
21382
21383 // Try to find the associated user-defined mapper.
21385 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21386 Type.getCanonicalType(), UnresolvedMapper);
21387 if (ER.isInvalid())
21388 continue;
21389 if (!ER.get() && isa<ArraySectionExpr>(VE)) {
21390 // Create implicit mapper as needed.
21391 QualType BaseType = VE->getType().getCanonicalType();
21392 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
21393 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
21395 QualType ElemType;
21396 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
21397 ElemType = ATy->getElementType();
21398 else
21399 ElemType = BType->getPointeeType();
21400 BaseType = ElemType.getCanonicalType();
21401 }
21402 if (BaseType->getAsRecordDecl() &&
21403 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
21404 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
21405 }
21406 }
21407 MVLI.UDMapperList.push_back(ER.get());
21408
21409 // Save the current expression.
21410 MVLI.ProcessedVarList.push_back(RE);
21411
21412 // Store the components in the stack so that they can be used to check
21413 // against other clauses later on.
21414 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21415 /*WhereFoundClauseKind=*/OMPC_map);
21416
21417 // Save the components and declaration to create the clause. For purposes of
21418 // the clause creation, any component list that has base 'this' uses
21419 // null as base declaration.
21420 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21421 MVLI.VarComponents.back().append(CurComponents.begin(),
21422 CurComponents.end());
21423 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21424 : CurDeclaration);
21425 }
21426}
21427
21429 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21430 ArrayRef<SourceLocation> MapTypeModifiersLoc,
21431 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21432 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21433 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21434 const OMPVarListLocTy &Locs, bool NoDiagnose,
21435 ArrayRef<Expr *> UnresolvedMappers) {
21436 OpenMPMapModifierKind Modifiers[] = {
21441
21442 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
21443 BuiltinType::OMPIterator))
21444 Diag(IteratorModifier->getExprLoc(),
21445 diag::err_omp_map_modifier_not_iterator);
21446
21447 // Process map-type-modifiers, flag errors for duplicate modifiers.
21448 unsigned Count = 0;
21449 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21450 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21451 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21452 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21453 continue;
21454 }
21455 assert(Count < NumberOfOMPMapClauseModifiers &&
21456 "Modifiers exceed the allowed number of map type modifiers");
21457 Modifiers[Count] = MapTypeModifiers[I];
21458 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21459 ++Count;
21460 }
21461
21462 MappableVarListInfo MVLI(VarList);
21464 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21465 MapType, Modifiers, IsMapTypeImplicit,
21466 NoDiagnose);
21467
21468 // We need to produce a map clause even if we don't have variables so that
21469 // other diagnostics related with non-existing map clauses are accurate.
21470 return OMPMapClause::Create(
21471 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21472 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21473 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
21474 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21475}
21476
21479 assert(ParsedType.isUsable());
21480
21481 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
21482 if (ReductionType.isNull())
21483 return QualType();
21484
21485 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21486 // A type name in a declare reduction directive cannot be a function type, an
21487 // array type, a reference type, or a type qualified with const, volatile or
21488 // restrict.
21489 if (ReductionType.hasQualifiers()) {
21490 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21491 return QualType();
21492 }
21493
21494 if (ReductionType->isFunctionType()) {
21495 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21496 return QualType();
21497 }
21498 if (ReductionType->isReferenceType()) {
21499 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21500 return QualType();
21501 }
21502 if (ReductionType->isArrayType()) {
21503 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21504 return QualType();
21505 }
21506 return ReductionType;
21507}
21508
21511 Scope *S, DeclContext *DC, DeclarationName Name,
21512 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21513 AccessSpecifier AS, Decl *PrevDeclInScope) {
21515 Decls.reserve(ReductionTypes.size());
21516
21517 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21520 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21521 // A reduction-identifier may not be re-declared in the current scope for the
21522 // same type or for a type that is compatible according to the base language
21523 // rules.
21524 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21525 OMPDeclareReductionDecl *PrevDRD = nullptr;
21526 bool InCompoundScope = true;
21527 if (S != nullptr) {
21528 // Find previous declaration with the same name not referenced in other
21529 // declarations.
21531 InCompoundScope =
21532 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21533 SemaRef.LookupName(Lookup, S);
21534 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21535 /*AllowInlineNamespace=*/false);
21536 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21537 LookupResult::Filter Filter = Lookup.makeFilter();
21538 while (Filter.hasNext()) {
21539 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21540 if (InCompoundScope) {
21541 auto I = UsedAsPrevious.find(PrevDecl);
21542 if (I == UsedAsPrevious.end())
21543 UsedAsPrevious[PrevDecl] = false;
21544 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21545 UsedAsPrevious[D] = true;
21546 }
21547 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21548 PrevDecl->getLocation();
21549 }
21550 Filter.done();
21551 if (InCompoundScope) {
21552 for (const auto &PrevData : UsedAsPrevious) {
21553 if (!PrevData.second) {
21554 PrevDRD = PrevData.first;
21555 break;
21556 }
21557 }
21558 }
21559 } else if (PrevDeclInScope != nullptr) {
21560 auto *PrevDRDInScope = PrevDRD =
21561 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21562 do {
21563 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21564 PrevDRDInScope->getLocation();
21565 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21566 } while (PrevDRDInScope != nullptr);
21567 }
21568 for (const auto &TyData : ReductionTypes) {
21569 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21570 bool Invalid = false;
21571 if (I != PreviousRedeclTypes.end()) {
21572 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21573 << TyData.first;
21574 Diag(I->second, diag::note_previous_definition);
21575 Invalid = true;
21576 }
21577 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21579 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21580 DC->addDecl(DRD);
21581 DRD->setAccess(AS);
21582 Decls.push_back(DRD);
21583 if (Invalid)
21584 DRD->setInvalidDecl();
21585 else
21586 PrevDRD = DRD;
21587 }
21588
21589 return DeclGroupPtrTy::make(
21590 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
21591}
21592
21594 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21595
21596 // Enter new function scope.
21600
21601 if (S != nullptr)
21602 SemaRef.PushDeclContext(S, DRD);
21603 else
21604 SemaRef.CurContext = DRD;
21605
21608
21609 QualType ReductionType = DRD->getType();
21610 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21611 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21612 // uses semantics of argument handles by value, but it should be passed by
21613 // reference. C lang does not support references, so pass all parameters as
21614 // pointers.
21615 // Create 'T omp_in;' variable.
21616 VarDecl *OmpInParm =
21617 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
21618 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21619 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21620 // uses semantics of argument handles by value, but it should be passed by
21621 // reference. C lang does not support references, so pass all parameters as
21622 // pointers.
21623 // Create 'T omp_out;' variable.
21624 VarDecl *OmpOutParm =
21625 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
21626 if (S != nullptr) {
21627 SemaRef.PushOnScopeChains(OmpInParm, S);
21628 SemaRef.PushOnScopeChains(OmpOutParm, S);
21629 } else {
21630 DRD->addDecl(OmpInParm);
21631 DRD->addDecl(OmpOutParm);
21632 }
21633 Expr *InE =
21634 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
21635 Expr *OutE =
21636 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
21637 DRD->setCombinerData(InE, OutE);
21638}
21639
21641 Expr *Combiner) {
21642 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21645
21648
21649 if (Combiner != nullptr)
21650 DRD->setCombiner(Combiner);
21651 else
21652 DRD->setInvalidDecl();
21653}
21654
21656 Decl *D) {
21657 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21658
21659 // Enter new function scope.
21662
21663 if (S != nullptr)
21664 SemaRef.PushDeclContext(S, DRD);
21665 else
21666 SemaRef.CurContext = DRD;
21667
21670
21671 QualType ReductionType = DRD->getType();
21672 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21673 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21674 // uses semantics of argument handles by value, but it should be passed by
21675 // reference. C lang does not support references, so pass all parameters as
21676 // pointers.
21677 // Create 'T omp_priv;' variable.
21678 VarDecl *OmpPrivParm =
21679 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
21680 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21681 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21682 // uses semantics of argument handles by value, but it should be passed by
21683 // reference. C lang does not support references, so pass all parameters as
21684 // pointers.
21685 // Create 'T omp_orig;' variable.
21686 VarDecl *OmpOrigParm =
21687 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
21688 if (S != nullptr) {
21689 SemaRef.PushOnScopeChains(OmpPrivParm, S);
21690 SemaRef.PushOnScopeChains(OmpOrigParm, S);
21691 } else {
21692 DRD->addDecl(OmpPrivParm);
21693 DRD->addDecl(OmpOrigParm);
21694 }
21695 Expr *OrigE =
21696 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
21697 Expr *PrivE =
21698 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
21699 DRD->setInitializerData(OrigE, PrivE);
21700 return OmpPrivParm;
21701}
21702
21704 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
21705 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21708
21711
21712 if (Initializer != nullptr) {
21713 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
21714 } else if (OmpPrivParm->hasInit()) {
21715 DRD->setInitializer(OmpPrivParm->getInit(),
21716 OmpPrivParm->isDirectInit()
21719 } else {
21720 DRD->setInvalidDecl();
21721 }
21722}
21723
21725 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
21726 for (Decl *D : DeclReductions.get()) {
21727 if (IsValid) {
21728 if (S)
21729 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
21730 /*AddToContext=*/false);
21731 } else {
21732 D->setInvalidDecl();
21733 }
21734 }
21735 return DeclReductions;
21736}
21737
21739 Declarator &D) {
21741 QualType T = TInfo->getType();
21742 if (D.isInvalidType())
21743 return true;
21744
21745 if (getLangOpts().CPlusPlus) {
21746 // Check that there are no default arguments (C++ only).
21748 }
21749
21750 return SemaRef.CreateParsedType(T, TInfo);
21751}
21752
21755 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
21756
21758 assert(!MapperType.isNull() && "Expect valid mapper type");
21759
21760 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21761 // The type must be of struct, union or class type in C and C++
21762 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
21763 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21764 return QualType();
21765 }
21766 return MapperType;
21767}
21768
21770 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
21772 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
21773 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21776 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21777 // A mapper-identifier may not be redeclared in the current scope for the
21778 // same type or for a type that is compatible according to the base language
21779 // rules.
21780 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21781 OMPDeclareMapperDecl *PrevDMD = nullptr;
21782 bool InCompoundScope = true;
21783 if (S != nullptr) {
21784 // Find previous declaration with the same name not referenced in other
21785 // declarations.
21787 InCompoundScope =
21788 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21789 SemaRef.LookupName(Lookup, S);
21790 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21791 /*AllowInlineNamespace=*/false);
21792 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21793 LookupResult::Filter Filter = Lookup.makeFilter();
21794 while (Filter.hasNext()) {
21795 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21796 if (InCompoundScope) {
21797 auto I = UsedAsPrevious.find(PrevDecl);
21798 if (I == UsedAsPrevious.end())
21799 UsedAsPrevious[PrevDecl] = false;
21800 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
21801 UsedAsPrevious[D] = true;
21802 }
21803 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21804 PrevDecl->getLocation();
21805 }
21806 Filter.done();
21807 if (InCompoundScope) {
21808 for (const auto &PrevData : UsedAsPrevious) {
21809 if (!PrevData.second) {
21810 PrevDMD = PrevData.first;
21811 break;
21812 }
21813 }
21814 }
21815 } else if (PrevDeclInScope) {
21816 auto *PrevDMDInScope = PrevDMD =
21817 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
21818 do {
21819 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
21820 PrevDMDInScope->getLocation();
21821 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
21822 } while (PrevDMDInScope != nullptr);
21823 }
21824 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
21825 bool Invalid = false;
21826 if (I != PreviousRedeclTypes.end()) {
21827 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
21828 << MapperType << Name;
21829 Diag(I->second, diag::note_previous_definition);
21830 Invalid = true;
21831 }
21832 // Build expressions for implicit maps of data members with 'default'
21833 // mappers.
21834 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
21835 if (getLangOpts().OpenMP >= 50)
21837 ClausesWithImplicit);
21838 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
21839 MapperType, VN, ClausesWithImplicit,
21840 PrevDMD);
21841 if (S)
21842 SemaRef.PushOnScopeChains(DMD, S);
21843 else
21844 DC->addDecl(DMD);
21845 DMD->setAccess(AS);
21846 if (Invalid)
21847 DMD->setInvalidDecl();
21848
21849 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21850 VD->setDeclContext(DMD);
21851 VD->setLexicalDeclContext(DMD);
21852 DMD->addDecl(VD);
21853 DMD->setMapperVarRef(MapperVarRef);
21854
21856}
21857
21859 Scope *S, QualType MapperType, SourceLocation StartLoc,
21860 DeclarationName VN) {
21861 TypeSourceInfo *TInfo =
21862 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
21863 auto *VD = VarDecl::Create(
21864 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
21865 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
21866 if (S)
21867 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
21868 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
21869 DSAStack->addDeclareMapperVarRef(E);
21870 return E;
21871}
21872
21874 if (DSAStack->getDeclareMapperVarRef())
21875 DSAStack->addIteratorVarDecl(VD);
21876}
21877
21879 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
21880 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
21881 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
21882 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
21883 return true;
21885 return true;
21886 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
21887 return true;
21888 return false;
21889 }
21890 return true;
21891}
21892
21894 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
21895 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
21896}
21897
21899 SourceLocation StartLoc,
21900 SourceLocation LParenLoc,
21901 SourceLocation EndLoc) {
21902 if (VarList.empty())
21903 return nullptr;
21904
21905 for (Expr *ValExpr : VarList) {
21906 // OpenMP [teams Constrcut, Restrictions]
21907 // The num_teams expression must evaluate to a positive integer value.
21908 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
21909 /*StrictlyPositive=*/true))
21910 return nullptr;
21911 }
21912
21913 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21915 DKind, OMPC_num_teams, getLangOpts().OpenMP);
21916 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
21917 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
21918 LParenLoc, EndLoc, VarList,
21919 /*PreInit=*/nullptr);
21920
21921 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21923 for (Expr *ValExpr : VarList) {
21924 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21925 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21926 Vars.push_back(ValExpr);
21927 }
21928
21929 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
21930 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
21931 LParenLoc, EndLoc, Vars, PreInit);
21932}
21933
21935 SourceLocation StartLoc,
21936 SourceLocation LParenLoc,
21937 SourceLocation EndLoc) {
21938 if (VarList.empty())
21939 return nullptr;
21940
21941 for (Expr *ValExpr : VarList) {
21942 // OpenMP [teams Constrcut, Restrictions]
21943 // The thread_limit expression must evaluate to a positive integer value.
21944 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
21945 /*StrictlyPositive=*/true))
21946 return nullptr;
21947 }
21948
21949 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21951 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
21952 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
21953 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
21954 StartLoc, LParenLoc, EndLoc, VarList,
21955 /*PreInit=*/nullptr);
21956
21957 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21959 for (Expr *ValExpr : VarList) {
21960 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21961 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21962 Vars.push_back(ValExpr);
21963 }
21964
21965 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
21966 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
21967 LParenLoc, EndLoc, Vars, PreInit);
21968}
21969
21971 SourceLocation StartLoc,
21972 SourceLocation LParenLoc,
21973 SourceLocation EndLoc) {
21974 Expr *ValExpr = Priority;
21975 Stmt *HelperValStmt = nullptr;
21976 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
21977
21978 // OpenMP [2.9.1, task Constrcut]
21979 // The priority-value is a non-negative numerical scalar expression.
21981 ValExpr, SemaRef, OMPC_priority,
21982 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
21983 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
21984 return nullptr;
21985
21986 return new (getASTContext()) OMPPriorityClause(
21987 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21988}
21989
21991 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
21992 SourceLocation StartLoc, SourceLocation LParenLoc,
21993 SourceLocation ModifierLoc, SourceLocation EndLoc) {
21994 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
21995 "Unexpected grainsize modifier in OpenMP < 51.");
21996
21997 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
21998 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22000 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22001 << Values << getOpenMPClauseName(OMPC_grainsize);
22002 return nullptr;
22003 }
22004
22005 Expr *ValExpr = Grainsize;
22006 Stmt *HelperValStmt = nullptr;
22007 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22008
22009 // OpenMP [2.9.2, taskloop Constrcut]
22010 // The parameter of the grainsize clause must be a positive integer
22011 // expression.
22012 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22013 /*StrictlyPositive=*/true,
22014 /*BuildCapture=*/true,
22015 DSAStack->getCurrentDirective(),
22016 &CaptureRegion, &HelperValStmt))
22017 return nullptr;
22018
22019 return new (getASTContext())
22020 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22021 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22022}
22023
22025 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22026 SourceLocation StartLoc, SourceLocation LParenLoc,
22027 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22028 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22029 "Unexpected num_tasks modifier in OpenMP < 51.");
22030
22031 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22032 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22034 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22035 << Values << getOpenMPClauseName(OMPC_num_tasks);
22036 return nullptr;
22037 }
22038
22039 Expr *ValExpr = NumTasks;
22040 Stmt *HelperValStmt = nullptr;
22041 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22042
22043 // OpenMP [2.9.2, taskloop Constrcut]
22044 // The parameter of the num_tasks clause must be a positive integer
22045 // expression.
22047 ValExpr, SemaRef, OMPC_num_tasks,
22048 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22049 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22050 return nullptr;
22051
22052 return new (getASTContext())
22053 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22054 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22055}
22056
22058 SourceLocation StartLoc,
22059 SourceLocation LParenLoc,
22060 SourceLocation EndLoc) {
22061 // OpenMP [2.13.2, critical construct, Description]
22062 // ... where hint-expression is an integer constant expression that evaluates
22063 // to a valid lock hint.
22064 ExprResult HintExpr =
22065 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22066 if (HintExpr.isInvalid())
22067 return nullptr;
22068 return new (getASTContext())
22069 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22070}
22071
22072/// Tries to find omp_event_handle_t type.
22074 DSAStackTy *Stack) {
22075 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22076 if (!OMPEventHandleT.isNull())
22077 return true;
22078 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22079 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22080 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22081 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22082 return false;
22083 }
22084 Stack->setOMPEventHandleT(PT.get());
22085 return true;
22086}
22087
22089 SourceLocation StartLoc,
22090 SourceLocation LParenLoc,
22091 SourceLocation EndLoc) {
22092 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22093 !Evt->isInstantiationDependent() &&
22096 return nullptr;
22097 // OpenMP 5.0, 2.10.1 task Construct.
22098 // event-handle is a variable of the omp_event_handle_t type.
22099 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22100 if (!Ref) {
22101 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22102 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22103 return nullptr;
22104 }
22105 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22106 if (!VD) {
22107 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22108 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22109 return nullptr;
22110 }
22111 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22112 VD->getType()) ||
22113 VD->getType().isConstant(getASTContext())) {
22114 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22115 << "omp_event_handle_t" << 1 << VD->getType()
22116 << Evt->getSourceRange();
22117 return nullptr;
22118 }
22119 // OpenMP 5.0, 2.10.1 task Construct
22120 // [detach clause]... The event-handle will be considered as if it was
22121 // specified on a firstprivate clause.
22122 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22123 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22124 DVar.RefExpr) {
22125 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22126 << getOpenMPClauseName(DVar.CKind)
22127 << getOpenMPClauseName(OMPC_firstprivate);
22129 return nullptr;
22130 }
22131 }
22132
22133 return new (getASTContext())
22134 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22135}
22136
22138 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22139 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22140 SourceLocation EndLoc) {
22141 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22142 std::string Values;
22143 Values += "'";
22144 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22145 Values += "'";
22146 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22147 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22148 return nullptr;
22149 }
22150 Expr *ValExpr = ChunkSize;
22151 Stmt *HelperValStmt = nullptr;
22152 if (ChunkSize) {
22153 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22154 !ChunkSize->isInstantiationDependent() &&
22155 !ChunkSize->containsUnexpandedParameterPack()) {
22156 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22157 ExprResult Val =
22158 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22159 if (Val.isInvalid())
22160 return nullptr;
22161
22162 ValExpr = Val.get();
22163
22164 // OpenMP [2.7.1, Restrictions]
22165 // chunk_size must be a loop invariant integer expression with a positive
22166 // value.
22167 if (std::optional<llvm::APSInt> Result =
22169 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22170 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22171 << "dist_schedule" << ChunkSize->getSourceRange();
22172 return nullptr;
22173 }
22175 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22176 getLangOpts().OpenMP) != OMPD_unknown &&
22178 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22179 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22180 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22181 HelperValStmt = buildPreInits(getASTContext(), Captures);
22182 }
22183 }
22184 }
22185
22186 return new (getASTContext())
22187 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22188 Kind, ValExpr, HelperValStmt);
22189}
22190
22193 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22194 SourceLocation KindLoc, SourceLocation EndLoc) {
22195 if (getLangOpts().OpenMP < 50) {
22196 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22197 Kind != OMPC_DEFAULTMAP_scalar) {
22198 std::string Value;
22200 Value += "'";
22201 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22202 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22203 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22204 Loc = MLoc;
22205 } else {
22206 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22207 OMPC_DEFAULTMAP_scalar);
22208 Loc = KindLoc;
22209 }
22210 Value += "'";
22211 Diag(Loc, diag::err_omp_unexpected_clause_value)
22212 << Value << getOpenMPClauseName(OMPC_defaultmap);
22213 return nullptr;
22214 }
22215 } else {
22216 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22217 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22218 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22219 if (!isDefaultmapKind || !isDefaultmapModifier) {
22220 StringRef KindValue = getLangOpts().OpenMP < 52
22221 ? "'scalar', 'aggregate', 'pointer'"
22222 : "'scalar', 'aggregate', 'pointer', 'all'";
22223 if (getLangOpts().OpenMP == 50) {
22224 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22225 "'firstprivate', 'none', 'default'";
22226 if (!isDefaultmapKind && isDefaultmapModifier) {
22227 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22228 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22229 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22230 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22231 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22232 } else {
22233 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22234 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22235 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22236 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22237 }
22238 } else {
22239 StringRef ModifierValue =
22240 "'alloc', 'from', 'to', 'tofrom', "
22241 "'firstprivate', 'none', 'default', 'present'";
22242 if (!isDefaultmapKind && isDefaultmapModifier) {
22243 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22244 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22245 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22246 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22247 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22248 } else {
22249 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22250 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22251 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22252 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22253 }
22254 }
22255 return nullptr;
22256 }
22257
22258 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22259 // At most one defaultmap clause for each category can appear on the
22260 // directive.
22261 if (DSAStack->checkDefaultmapCategory(Kind)) {
22262 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22263 return nullptr;
22264 }
22265 }
22266 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
22267 // Variable category is not specified - mark all categories.
22268 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22269 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22270 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22271 } else {
22272 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22273 }
22274
22275 return new (getASTContext())
22276 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22277}
22278
22281 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22282 if (!CurLexicalContext->isFileContext() &&
22283 !CurLexicalContext->isExternCContext() &&
22284 !CurLexicalContext->isExternCXXContext() &&
22285 !isa<CXXRecordDecl>(CurLexicalContext) &&
22286 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22287 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22288 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22289 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22290 return false;
22291 }
22292
22293 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22294 if (getLangOpts().HIP)
22295 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
22296
22297 DeclareTargetNesting.push_back(DTCI);
22298 return true;
22299}
22300
22303 assert(!DeclareTargetNesting.empty() &&
22304 "check isInOpenMPDeclareTargetContext() first!");
22305 return DeclareTargetNesting.pop_back_val();
22306}
22307
22310 for (auto &It : DTCI.ExplicitlyMapped)
22311 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22312}
22313
22315 if (DeclareTargetNesting.empty())
22316 return;
22317 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22318 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22319 << getOpenMPDirectiveName(DTCI.Kind);
22320}
22321
22323 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
22325 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
22326 /*ObjectType=*/QualType(),
22327 /*AllowBuiltinCreation=*/true);
22328
22329 if (Lookup.isAmbiguous())
22330 return nullptr;
22331 Lookup.suppressDiagnostics();
22332
22333 if (!Lookup.isSingleResult()) {
22334 VarOrFuncDeclFilterCCC CCC(SemaRef);
22335 if (TypoCorrection Corrected =
22336 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
22338 SemaRef.diagnoseTypo(Corrected,
22339 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
22340 << Id.getName());
22341 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22342 return nullptr;
22343 }
22344
22345 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22346 return nullptr;
22347 }
22348
22349 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22350 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22351 !isa<FunctionTemplateDecl>(ND)) {
22352 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22353 return nullptr;
22354 }
22355 return ND;
22356}
22357
22359 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
22361 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22362 isa<FunctionTemplateDecl>(ND)) &&
22363 "Expected variable, function or function template.");
22364
22365 if (auto *VD = dyn_cast<VarDecl>(ND)) {
22366 // Only global variables can be marked as declare target.
22367 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22368 !VD->isStaticDataMember()) {
22369 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
22370 << VD->getNameAsString();
22371 return;
22372 }
22373 }
22374 // Diagnose marking after use as it may lead to incorrect diagnosis and
22375 // codegen.
22376 if (getLangOpts().OpenMP >= 50 &&
22377 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22378 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22379
22380 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22381 if (getLangOpts().HIP)
22382 Diag(Loc, diag::warn_hip_omp_target_directives);
22383
22384 // Explicit declare target lists have precedence.
22385 const unsigned Level = -1;
22386
22387 auto *VD = cast<ValueDecl>(ND);
22388 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22389 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22390 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22391 (*ActiveAttr)->getLevel() == Level) {
22392 Diag(Loc, diag::err_omp_device_type_mismatch)
22393 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22394 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22395 (*ActiveAttr)->getDevType());
22396 return;
22397 }
22398 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22399 (*ActiveAttr)->getLevel() == Level) {
22400 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22401 return;
22402 }
22403
22404 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22405 return;
22406
22407 Expr *IndirectE = nullptr;
22408 bool IsIndirect = false;
22409 if (DTCI.Indirect) {
22410 IndirectE = *DTCI.Indirect;
22411 if (!IndirectE)
22412 IsIndirect = true;
22413 }
22414 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22415 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
22416 SourceRange(Loc, Loc));
22417 ND->addAttr(A);
22418 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22419 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22421 if (auto *VD = dyn_cast<VarDecl>(ND);
22422 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
22423 VD->hasGlobalStorage())
22425}
22426
22428 Sema &SemaRef, Decl *D) {
22429 if (!D || !isa<VarDecl>(D))
22430 return;
22431 auto *VD = cast<VarDecl>(D);
22432 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22433 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22434 if (SemaRef.LangOpts.OpenMP >= 50 &&
22435 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22436 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22437 VD->hasGlobalStorage()) {
22438 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22439 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22440 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22441 // If a lambda declaration and definition appears between a
22442 // declare target directive and the matching end declare target
22443 // directive, all variables that are captured by the lambda
22444 // expression must also appear in a to clause.
22445 SemaRef.Diag(VD->getLocation(),
22446 diag::err_omp_lambda_capture_in_declare_target_not_to);
22447 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22448 << VD << 0 << SR;
22449 return;
22450 }
22451 }
22452 if (MapTy)
22453 return;
22454 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22455 SemaRef.Diag(SL, diag::note_used_here) << SR;
22456}
22457
22459 Sema &SemaRef, DSAStackTy *Stack,
22460 ValueDecl *VD) {
22461 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22462 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22463 /*FullCheck=*/false);
22464}
22465
22467 SourceLocation IdLoc) {
22468 if (!D || D->isInvalidDecl())
22469 return;
22471 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22472 if (auto *VD = dyn_cast<VarDecl>(D)) {
22473 // Only global variables can be marked as declare target.
22474 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22475 !VD->isStaticDataMember())
22476 return;
22477 // 2.10.6: threadprivate variable cannot appear in a declare target
22478 // directive.
22479 if (DSAStack->isThreadPrivate(VD)) {
22480 Diag(SL, diag::err_omp_threadprivate_in_target);
22481 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22482 return;
22483 }
22484 }
22485 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22486 D = FTD->getTemplatedDecl();
22487 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22488 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22489 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22490 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22491 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22492 Diag(FD->getLocation(), diag::note_defined_here) << FD;
22493 return;
22494 }
22495 }
22496 if (auto *VD = dyn_cast<ValueDecl>(D)) {
22497 // Problem if any with var declared with incomplete type will be reported
22498 // as normal, so no need to check it here.
22499 if ((E || !VD->getType()->isIncompleteType()) &&
22501 return;
22503 // Checking declaration inside declare target region.
22504 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22505 isa<FunctionTemplateDecl>(D)) {
22506 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22507 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22508 unsigned Level = DeclareTargetNesting.size();
22509 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22510 return;
22511 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22512 Expr *IndirectE = nullptr;
22513 bool IsIndirect = false;
22514 if (DTCI.Indirect) {
22515 IndirectE = *DTCI.Indirect;
22516 if (!IndirectE)
22517 IsIndirect = true;
22518 }
22519 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22520 getASTContext(),
22521 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22522 : OMPDeclareTargetDeclAttr::MT_To,
22523 DTCI.DT, IndirectE, IsIndirect, Level,
22524 SourceRange(DTCI.Loc, DTCI.Loc));
22525 D->addAttr(A);
22526 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22527 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22528 }
22529 return;
22530 }
22531 }
22532 if (!E)
22533 return;
22535}
22536
22537/// This class visits every VarDecl that the initializer references and adds
22538/// OMPDeclareTargetDeclAttr to each of them.
22539class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
22540 SmallVector<VarDecl *> DeclVector;
22541 Attr *A;
22542
22543public:
22544 /// A StmtVisitor class function that visits all DeclRefExpr and adds
22545 /// OMPDeclareTargetDeclAttr to them.
22547 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
22548 VD->addAttr(A);
22549 DeclVector.push_back(VD);
22550 }
22551 }
22552 /// A function that iterates across each of the Expr's children.
22553 void VisitExpr(Expr *Ex) {
22554 for (auto *Child : Ex->children()) {
22555 Visit(Child);
22556 }
22557 }
22558 /// A function that keeps a record of all the Decls that are variables, has
22559 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
22560 /// each Decl one at a time and use the inherited 'visit' functions to look
22561 /// for DeclRefExpr.
22563 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
22564 DeclVector.push_back(cast<VarDecl>(TD));
22565 while (!DeclVector.empty()) {
22566 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22567 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
22568 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
22569 if (Expr *Ex = TargetVarDecl->getInit())
22570 Visit(Ex);
22571 }
22572 }
22573 }
22574};
22575
22576/// Adding OMPDeclareTargetDeclAttr to variables with static storage
22577/// duration that are referenced in the initializer expression list of
22578/// variables with static storage duration in declare target directive.
22580 GlobalDeclRefChecker Checker;
22581 if (isa<VarDecl>(TargetDecl))
22582 Checker.declareTargetInitializer(TargetDecl);
22583}
22584
22586 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22587 ArrayRef<SourceLocation> MotionModifiersLoc,
22588 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22589 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22590 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22594
22595 // Process motion-modifiers, flag errors for duplicate modifiers.
22596 unsigned Count = 0;
22597 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22598 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22599 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22600 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22601 continue;
22602 }
22603 assert(Count < NumberOfOMPMotionModifiers &&
22604 "Modifiers exceed the allowed number of motion modifiers");
22605 Modifiers[Count] = MotionModifiers[I];
22606 ModifiersLoc[Count] = MotionModifiersLoc[I];
22607 ++Count;
22608 }
22609
22610 MappableVarListInfo MVLI(VarList);
22612 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22613 if (MVLI.ProcessedVarList.empty())
22614 return nullptr;
22615
22616 return OMPToClause::Create(
22617 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22618 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22619 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22620}
22621
22623 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22624 ArrayRef<SourceLocation> MotionModifiersLoc,
22625 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22626 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22627 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22631
22632 // Process motion-modifiers, flag errors for duplicate modifiers.
22633 unsigned Count = 0;
22634 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22635 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22636 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22637 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22638 continue;
22639 }
22640 assert(Count < NumberOfOMPMotionModifiers &&
22641 "Modifiers exceed the allowed number of motion modifiers");
22642 Modifiers[Count] = MotionModifiers[I];
22643 ModifiersLoc[Count] = MotionModifiersLoc[I];
22644 ++Count;
22645 }
22646
22647 MappableVarListInfo MVLI(VarList);
22648 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22649 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22650 if (MVLI.ProcessedVarList.empty())
22651 return nullptr;
22652
22653 return OMPFromClause::Create(
22654 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22655 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22656 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22657}
22658
22659OMPClause *
22661 const OMPVarListLocTy &Locs) {
22662 MappableVarListInfo MVLI(VarList);
22663 SmallVector<Expr *, 8> PrivateCopies;
22665
22666 for (Expr *RefExpr : VarList) {
22667 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22668 SourceLocation ELoc;
22669 SourceRange ERange;
22670 Expr *SimpleRefExpr = RefExpr;
22671 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22672 if (Res.second) {
22673 // It will be analyzed later.
22674 MVLI.ProcessedVarList.push_back(RefExpr);
22675 PrivateCopies.push_back(nullptr);
22676 Inits.push_back(nullptr);
22677 }
22678 ValueDecl *D = Res.first;
22679 if (!D)
22680 continue;
22681
22682 QualType Type = D->getType();
22683 Type = Type.getNonReferenceType().getUnqualifiedType();
22684
22685 auto *VD = dyn_cast<VarDecl>(D);
22686
22687 // Item should be a pointer or reference to pointer.
22688 if (!Type->isPointerType()) {
22689 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22690 << 0 << RefExpr->getSourceRange();
22691 continue;
22692 }
22693
22694 // Build the private variable and the expression that refers to it.
22695 auto VDPrivate =
22696 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
22697 D->hasAttrs() ? &D->getAttrs() : nullptr,
22698 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22699 if (VDPrivate->isInvalidDecl())
22700 continue;
22701
22702 SemaRef.CurContext->addDecl(VDPrivate);
22703 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22704 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22705
22706 // Add temporary variable to initialize the private copy of the pointer.
22707 VarDecl *VDInit =
22708 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
22709 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22710 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22712 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
22713 /*DirectInit=*/false);
22714
22715 // If required, build a capture to implement the privatization initialized
22716 // with the current list item value.
22717 DeclRefExpr *Ref = nullptr;
22718 if (!VD)
22719 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22720 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22721 PrivateCopies.push_back(VDPrivateRefExpr);
22722 Inits.push_back(VDInitRefExpr);
22723
22724 // We need to add a data sharing attribute for this variable to make sure it
22725 // is correctly captured. A variable that shows up in a use_device_ptr has
22726 // similar properties of a first private variable.
22727 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22728
22729 // Create a mappable component for the list item. List items in this clause
22730 // only need a component.
22731 MVLI.VarBaseDeclarations.push_back(D);
22732 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22733 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22734 /*IsNonContiguous=*/false);
22735 }
22736
22737 if (MVLI.ProcessedVarList.empty())
22738 return nullptr;
22739
22741 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22742 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22743}
22744
22745OMPClause *
22747 const OMPVarListLocTy &Locs) {
22748 MappableVarListInfo MVLI(VarList);
22749
22750 for (Expr *RefExpr : VarList) {
22751 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22752 SourceLocation ELoc;
22753 SourceRange ERange;
22754 Expr *SimpleRefExpr = RefExpr;
22755 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22756 /*AllowArraySection=*/true);
22757 if (Res.second) {
22758 // It will be analyzed later.
22759 MVLI.ProcessedVarList.push_back(RefExpr);
22760 }
22761 ValueDecl *D = Res.first;
22762 if (!D)
22763 continue;
22764 auto *VD = dyn_cast<VarDecl>(D);
22765
22766 // If required, build a capture to implement the privatization initialized
22767 // with the current list item value.
22768 DeclRefExpr *Ref = nullptr;
22769 if (!VD)
22770 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22771 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22772
22773 // We need to add a data sharing attribute for this variable to make sure it
22774 // is correctly captured. A variable that shows up in a use_device_addr has
22775 // similar properties of a first private variable.
22776 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22777
22778 // Create a mappable component for the list item. List items in this clause
22779 // only need a component.
22780 MVLI.VarBaseDeclarations.push_back(D);
22781 MVLI.VarComponents.emplace_back();
22782 Expr *Component = SimpleRefExpr;
22783 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22784 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22785 Component =
22787 MVLI.VarComponents.back().emplace_back(Component, D,
22788 /*IsNonContiguous=*/false);
22789 }
22790
22791 if (MVLI.ProcessedVarList.empty())
22792 return nullptr;
22793
22795 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22796 MVLI.VarComponents);
22797}
22798
22799OMPClause *
22801 const OMPVarListLocTy &Locs) {
22802 MappableVarListInfo MVLI(VarList);
22803 for (Expr *RefExpr : VarList) {
22804 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
22805 SourceLocation ELoc;
22806 SourceRange ERange;
22807 Expr *SimpleRefExpr = RefExpr;
22808 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22809 if (Res.second) {
22810 // It will be analyzed later.
22811 MVLI.ProcessedVarList.push_back(RefExpr);
22812 }
22813 ValueDecl *D = Res.first;
22814 if (!D)
22815 continue;
22816
22817 QualType Type = D->getType();
22818 // item should be a pointer or array or reference to pointer or array
22819 if (!Type.getNonReferenceType()->isPointerType() &&
22820 !Type.getNonReferenceType()->isArrayType()) {
22821 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22822 << 0 << RefExpr->getSourceRange();
22823 continue;
22824 }
22825
22826 // Check if the declaration in the clause does not show up in any data
22827 // sharing attribute.
22828 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22829 if (isOpenMPPrivate(DVar.CKind)) {
22830 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22831 << getOpenMPClauseName(DVar.CKind)
22832 << getOpenMPClauseName(OMPC_is_device_ptr)
22833 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22835 continue;
22836 }
22837
22838 const Expr *ConflictExpr;
22839 if (DSAStack->checkMappableExprComponentListsForDecl(
22840 D, /*CurrentRegionOnly=*/true,
22841 [&ConflictExpr](
22843 OpenMPClauseKind) -> bool {
22844 ConflictExpr = R.front().getAssociatedExpression();
22845 return true;
22846 })) {
22847 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22848 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22849 << ConflictExpr->getSourceRange();
22850 continue;
22851 }
22852
22853 // Store the components in the stack so that they can be used to check
22854 // against other clauses later on.
22856 SimpleRefExpr, D, /*IsNonContiguous=*/false);
22857 DSAStack->addMappableExpressionComponents(
22858 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
22859
22860 // Record the expression we've just processed.
22861 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
22862
22863 // Create a mappable component for the list item. List items in this clause
22864 // only need a component. We use a null declaration to signal fields in
22865 // 'this'.
22866 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22867 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22868 "Unexpected device pointer expression!");
22869 MVLI.VarBaseDeclarations.push_back(
22870 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
22871 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22872 MVLI.VarComponents.back().push_back(MC);
22873 }
22874
22875 if (MVLI.ProcessedVarList.empty())
22876 return nullptr;
22877
22879 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22880 MVLI.VarComponents);
22881}
22882
22883OMPClause *
22885 const OMPVarListLocTy &Locs) {
22886 MappableVarListInfo MVLI(VarList);
22887 for (Expr *RefExpr : VarList) {
22888 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
22889 SourceLocation ELoc;
22890 SourceRange ERange;
22891 Expr *SimpleRefExpr = RefExpr;
22892 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22893 /*AllowArraySection=*/true);
22894 if (Res.second) {
22895 // It will be analyzed later.
22896 MVLI.ProcessedVarList.push_back(RefExpr);
22897 }
22898 ValueDecl *D = Res.first;
22899 if (!D)
22900 continue;
22901
22902 // Check if the declaration in the clause does not show up in any data
22903 // sharing attribute.
22904 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22905 if (isOpenMPPrivate(DVar.CKind)) {
22906 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22907 << getOpenMPClauseName(DVar.CKind)
22908 << getOpenMPClauseName(OMPC_has_device_addr)
22909 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22911 continue;
22912 }
22913
22914 const Expr *ConflictExpr;
22915 if (DSAStack->checkMappableExprComponentListsForDecl(
22916 D, /*CurrentRegionOnly=*/true,
22917 [&ConflictExpr](
22919 OpenMPClauseKind) -> bool {
22920 ConflictExpr = R.front().getAssociatedExpression();
22921 return true;
22922 })) {
22923 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22924 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22925 << ConflictExpr->getSourceRange();
22926 continue;
22927 }
22928
22929 // Store the components in the stack so that they can be used to check
22930 // against other clauses later on.
22931 Expr *Component = SimpleRefExpr;
22932 auto *VD = dyn_cast<VarDecl>(D);
22933 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22934 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22935 Component =
22938 Component, D, /*IsNonContiguous=*/false);
22939 DSAStack->addMappableExpressionComponents(
22940 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
22941
22942 // Record the expression we've just processed.
22943 if (!VD && !SemaRef.CurContext->isDependentContext()) {
22944 DeclRefExpr *Ref =
22945 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22946 assert(Ref && "has_device_addr capture failed");
22947 MVLI.ProcessedVarList.push_back(Ref);
22948 } else
22949 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
22950
22951 // Create a mappable component for the list item. List items in this clause
22952 // only need a component. We use a null declaration to signal fields in
22953 // 'this'.
22954 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22955 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22956 "Unexpected device pointer expression!");
22957 MVLI.VarBaseDeclarations.push_back(
22958 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
22959 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22960 MVLI.VarComponents.back().push_back(MC);
22961 }
22962
22963 if (MVLI.ProcessedVarList.empty())
22964 return nullptr;
22965
22967 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22968 MVLI.VarComponents);
22969}
22970
22972 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
22973 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
22974 if (Allocator) {
22975 // OpenMP [2.11.4 allocate Clause, Description]
22976 // allocator is an expression of omp_allocator_handle_t type.
22977 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
22978 return nullptr;
22979
22980 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
22981 if (AllocatorRes.isInvalid())
22982 return nullptr;
22983 AllocatorRes = SemaRef.PerformImplicitConversion(
22984 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
22986 /*AllowExplicit=*/true);
22987 if (AllocatorRes.isInvalid())
22988 return nullptr;
22989 Allocator = AllocatorRes.get();
22990 } else {
22991 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
22992 // allocate clauses that appear on a target construct or on constructs in a
22993 // target region must specify an allocator expression unless a requires
22994 // directive with the dynamic_allocators clause is present in the same
22995 // compilation unit.
22996 if (getLangOpts().OpenMPIsTargetDevice &&
22997 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
22998 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
22999 }
23000 // Analyze and build list of variables.
23002 for (Expr *RefExpr : VarList) {
23003 assert(RefExpr && "NULL expr in OpenMP private clause.");
23004 SourceLocation ELoc;
23005 SourceRange ERange;
23006 Expr *SimpleRefExpr = RefExpr;
23007 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23008 if (Res.second) {
23009 // It will be analyzed later.
23010 Vars.push_back(RefExpr);
23011 }
23012 ValueDecl *D = Res.first;
23013 if (!D)
23014 continue;
23015
23016 auto *VD = dyn_cast<VarDecl>(D);
23017 DeclRefExpr *Ref = nullptr;
23018 if (!VD && !SemaRef.CurContext->isDependentContext())
23019 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
23020 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
23021 ? RefExpr->IgnoreParens()
23022 : Ref);
23023 }
23024
23025 if (Vars.empty())
23026 return nullptr;
23027
23028 if (Allocator)
23029 DSAStack->addInnerAllocatorExpr(Allocator);
23030 return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc,
23031 Allocator, ColonLoc, EndLoc, Vars);
23032}
23033
23035 SourceLocation StartLoc,
23036 SourceLocation LParenLoc,
23037 SourceLocation EndLoc) {
23039 for (Expr *RefExpr : VarList) {
23040 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23041 SourceLocation ELoc;
23042 SourceRange ERange;
23043 Expr *SimpleRefExpr = RefExpr;
23044 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23045 if (Res.second)
23046 // It will be analyzed later.
23047 Vars.push_back(RefExpr);
23048 ValueDecl *D = Res.first;
23049 if (!D)
23050 continue;
23051
23052 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23053 // A list-item cannot appear in more than one nontemporal clause.
23054 if (const Expr *PrevRef =
23055 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23056 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23057 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23058 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23059 << getOpenMPClauseName(OMPC_nontemporal);
23060 continue;
23061 }
23062
23063 Vars.push_back(RefExpr);
23064 }
23065
23066 if (Vars.empty())
23067 return nullptr;
23068
23069 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
23070 EndLoc, Vars);
23071}
23072
23074 Stmt *AStmt,
23075 SourceLocation StartLoc,
23076 SourceLocation EndLoc) {
23077 if (!AStmt)
23078 return StmtError();
23079
23081
23082 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
23083 AStmt);
23084}
23085
23087 SourceLocation StartLoc,
23088 SourceLocation LParenLoc,
23089 SourceLocation EndLoc) {
23091 for (Expr *RefExpr : VarList) {
23092 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23093 SourceLocation ELoc;
23094 SourceRange ERange;
23095 Expr *SimpleRefExpr = RefExpr;
23096 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23097 /*AllowArraySection=*/true);
23098 if (Res.second)
23099 // It will be analyzed later.
23100 Vars.push_back(RefExpr);
23101 ValueDecl *D = Res.first;
23102 if (!D)
23103 continue;
23104
23105 const DSAStackTy::DSAVarData DVar =
23106 DSAStack->getTopDSA(D, /*FromParent=*/true);
23107 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23108 // A list item that appears in the inclusive or exclusive clause must appear
23109 // in a reduction clause with the inscan modifier on the enclosing
23110 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23111 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23112 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23113 << RefExpr->getSourceRange();
23114
23115 if (DSAStack->getParentDirective() != OMPD_unknown)
23116 DSAStack->markDeclAsUsedInScanDirective(D);
23117 Vars.push_back(RefExpr);
23118 }
23119
23120 if (Vars.empty())
23121 return nullptr;
23122
23123 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23124 EndLoc, Vars);
23125}
23126
23128 SourceLocation StartLoc,
23129 SourceLocation LParenLoc,
23130 SourceLocation EndLoc) {
23132 for (Expr *RefExpr : VarList) {
23133 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23134 SourceLocation ELoc;
23135 SourceRange ERange;
23136 Expr *SimpleRefExpr = RefExpr;
23137 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23138 /*AllowArraySection=*/true);
23139 if (Res.second)
23140 // It will be analyzed later.
23141 Vars.push_back(RefExpr);
23142 ValueDecl *D = Res.first;
23143 if (!D)
23144 continue;
23145
23146 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23147 DSAStackTy::DSAVarData DVar;
23148 if (ParentDirective != OMPD_unknown)
23149 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23150 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23151 // A list item that appears in the inclusive or exclusive clause must appear
23152 // in a reduction clause with the inscan modifier on the enclosing
23153 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23154 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23155 DVar.Modifier != OMPC_REDUCTION_inscan) {
23156 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23157 << RefExpr->getSourceRange();
23158 } else {
23159 DSAStack->markDeclAsUsedInScanDirective(D);
23160 }
23161 Vars.push_back(RefExpr);
23162 }
23163
23164 if (Vars.empty())
23165 return nullptr;
23166
23167 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23168 EndLoc, Vars);
23169}
23170
23171/// Tries to find omp_alloctrait_t type.
23172static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23173 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23174 if (!OMPAlloctraitT.isNull())
23175 return true;
23176 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23177 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23178 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23179 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23180 return false;
23181 }
23182 Stack->setOMPAlloctraitT(PT.get());
23183 return true;
23184}
23185
23187 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23189 ASTContext &Context = getASTContext();
23190 // OpenMP [2.12.5, target Construct]
23191 // allocator is an identifier of omp_allocator_handle_t type.
23192 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
23193 return nullptr;
23194 // OpenMP [2.12.5, target Construct]
23195 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23196 if (llvm::any_of(
23197 Data,
23198 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23199 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
23200 return nullptr;
23201 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23202 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23203 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23204 StringRef Allocator =
23205 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23206 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23207 PredefinedAllocators.insert(SemaRef.LookupSingleName(
23208 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23209 }
23210
23212 for (const UsesAllocatorsData &D : Data) {
23213 Expr *AllocatorExpr = nullptr;
23214 // Check allocator expression.
23215 if (D.Allocator->isTypeDependent()) {
23216 AllocatorExpr = D.Allocator;
23217 } else {
23218 // Traits were specified - need to assign new allocator to the specified
23219 // allocator, so it must be an lvalue.
23220 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23221 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23222 bool IsPredefinedAllocator = false;
23223 if (DRE) {
23224 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23225 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
23226 IsPredefinedAllocator =
23227 AllocatorTy !=
23228 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23229 }
23230 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23231 QualType AllocatorExprType = AllocatorExpr->getType();
23232 bool IsTypeCompatible = IsPredefinedAllocator;
23233 IsTypeCompatible = IsTypeCompatible ||
23234 Context.hasSameUnqualifiedType(AllocatorExprType,
23235 OMPAllocatorHandleT);
23236 IsTypeCompatible =
23237 IsTypeCompatible ||
23238 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23239 bool IsNonConstantLValue =
23240 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23241 if (!DRE || !IsTypeCompatible ||
23242 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23243 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23244 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23245 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23246 continue;
23247 }
23248 // OpenMP [2.12.5, target Construct]
23249 // Predefined allocators appearing in a uses_allocators clause cannot have
23250 // traits specified.
23251 if (IsPredefinedAllocator && D.AllocatorTraits) {
23252 Diag(D.AllocatorTraits->getExprLoc(),
23253 diag::err_omp_predefined_allocator_with_traits)
23254 << D.AllocatorTraits->getSourceRange();
23255 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23256 << cast<NamedDecl>(DRE->getDecl())->getName()
23257 << D.Allocator->getSourceRange();
23258 continue;
23259 }
23260 // OpenMP [2.12.5, target Construct]
23261 // Non-predefined allocators appearing in a uses_allocators clause must
23262 // have traits specified.
23263 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23264 Diag(D.Allocator->getExprLoc(),
23265 diag::err_omp_nonpredefined_allocator_without_traits);
23266 continue;
23267 }
23268 // No allocator traits - just convert it to rvalue.
23269 if (!D.AllocatorTraits)
23270 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
23271 DSAStack->addUsesAllocatorsDecl(
23272 DRE->getDecl(),
23273 IsPredefinedAllocator
23274 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23275 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23276 }
23277 Expr *AllocatorTraitsExpr = nullptr;
23278 if (D.AllocatorTraits) {
23279 if (D.AllocatorTraits->isTypeDependent()) {
23280 AllocatorTraitsExpr = D.AllocatorTraits;
23281 } else {
23282 // OpenMP [2.12.5, target Construct]
23283 // Arrays that contain allocator traits that appear in a uses_allocators
23284 // clause must be constant arrays, have constant values and be defined
23285 // in the same scope as the construct in which the clause appears.
23286 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23287 // Check that traits expr is a constant array.
23288 QualType TraitTy;
23289 if (const ArrayType *Ty =
23290 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23291 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23292 TraitTy = ConstArrayTy->getElementType();
23293 if (TraitTy.isNull() ||
23294 !(Context.hasSameUnqualifiedType(TraitTy,
23295 DSAStack->getOMPAlloctraitT()) ||
23296 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23297 /*CompareUnqualified=*/true))) {
23298 Diag(D.AllocatorTraits->getExprLoc(),
23299 diag::err_omp_expected_array_alloctraits)
23300 << AllocatorTraitsExpr->getType();
23301 continue;
23302 }
23303 // Do not map by default allocator traits if it is a standalone
23304 // variable.
23305 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23306 DSAStack->addUsesAllocatorsDecl(
23307 DRE->getDecl(),
23308 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23309 }
23310 }
23311 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23312 NewD.Allocator = AllocatorExpr;
23313 NewD.AllocatorTraits = AllocatorTraitsExpr;
23314 NewD.LParenLoc = D.LParenLoc;
23315 NewD.RParenLoc = D.RParenLoc;
23316 }
23317 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
23318 EndLoc, NewData);
23319}
23320
23322 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23323 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23325 for (Expr *RefExpr : Locators) {
23326 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23327 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23328 // It will be analyzed later.
23329 Vars.push_back(RefExpr);
23330 continue;
23331 }
23332
23333 SourceLocation ELoc = RefExpr->getExprLoc();
23334 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23335
23336 if (!SimpleExpr->isLValue()) {
23337 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23338 << 1 << 0 << RefExpr->getSourceRange();
23339 continue;
23340 }
23341
23342 ExprResult Res;
23343 {
23345 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23346 }
23347 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23348 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23349 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23350 << 1 << 0 << RefExpr->getSourceRange();
23351 continue;
23352 }
23353 Vars.push_back(SimpleExpr);
23354 }
23355
23356 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
23357 ColonLoc, EndLoc, Modifier, Vars);
23358}
23359
23361 SourceLocation KindLoc,
23362 SourceLocation StartLoc,
23363 SourceLocation LParenLoc,
23364 SourceLocation EndLoc) {
23365 if (Kind == OMPC_BIND_unknown) {
23366 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23367 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23368 /*Last=*/unsigned(OMPC_BIND_unknown))
23369 << getOpenMPClauseName(OMPC_bind);
23370 return nullptr;
23371 }
23372
23373 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
23374 LParenLoc, EndLoc);
23375}
23376
23378 SourceLocation StartLoc,
23379 SourceLocation LParenLoc,
23380 SourceLocation EndLoc) {
23381 Expr *ValExpr = Size;
23382 Stmt *HelperValStmt = nullptr;
23383
23384 // OpenMP [2.5, Restrictions]
23385 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23386 // value.
23387 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
23388 /*StrictlyPositive=*/false))
23389 return nullptr;
23390
23391 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23393 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
23394 if (CaptureRegion != OMPD_unknown &&
23396 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23397 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23398 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23399 HelperValStmt = buildPreInits(getASTContext(), Captures);
23400 }
23401
23403 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23404}
23405
23408 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23409 SourceLocation LParenLoc, SourceLocation EndLoc) {
23410
23411 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
23412 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23413 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23414 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23415 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23416 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23417 return nullptr;
23418 }
23419
23422 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23423 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
23424 SemaRef,
23425 DepType == OMPC_DOACROSS_source ||
23426 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23427 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23428 VarList, DSAStack, EndLoc);
23429 Vars = VarOffset.Vars;
23430 OpsOffs = VarOffset.OpsOffs;
23431 TotalDepCount = VarOffset.TotalDepCount;
23432 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
23433 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23434 TotalDepCount.getZExtValue());
23435 if (DSAStack->isParentOrderedRegion())
23436 DSAStack->addDoacrossDependClause(C, OpsOffs);
23437 return C;
23438}
23439
23441 SourceLocation StartLoc,
23442 SourceLocation LParenLoc,
23443 SourceLocation EndLoc) {
23444 return new (getASTContext())
23445 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
23446}
23447
23449 SourceLocation EndLoc) {
23450 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
23451}
23452
23454 SourceLocation LParenLoc,
23455 SourceLocation EndLoc) {
23456 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
23457}
23458
23462 switch (CK) {
23463 case OMPC_absent:
23464 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23465 case OMPC_contains:
23466 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23467 default:
23468 llvm_unreachable("Unexpected OpenMP clause");
23469 }
23470}
23471
23474 SourceLocation RLoc) {
23475 switch (CK) {
23476 case OMPC_no_openmp:
23477 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
23478 case OMPC_no_openmp_routines:
23479 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
23480 case OMPC_no_parallelism:
23481 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
23482 default:
23483 llvm_unreachable("Unexpected OpenMP clause");
23484 }
23485}
23486
23488 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
23489 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
23490 Expr *Stride, SourceLocation RBLoc) {
23491 ASTContext &Context = getASTContext();
23492 if (Base->hasPlaceholderType() &&
23493 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23495 if (Result.isInvalid())
23496 return ExprError();
23497 Base = Result.get();
23498 }
23499 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
23501 if (Result.isInvalid())
23502 return ExprError();
23504 if (Result.isInvalid())
23505 return ExprError();
23506 LowerBound = Result.get();
23507 }
23508 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23510 if (Result.isInvalid())
23511 return ExprError();
23513 if (Result.isInvalid())
23514 return ExprError();
23515 Length = Result.get();
23516 }
23517 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
23519 if (Result.isInvalid())
23520 return ExprError();
23522 if (Result.isInvalid())
23523 return ExprError();
23524 Stride = Result.get();
23525 }
23526
23527 // Build an unanalyzed expression if either operand is type-dependent.
23528 if (Base->isTypeDependent() ||
23529 (LowerBound &&
23530 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
23531 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23532 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
23533 return new (Context) ArraySectionExpr(
23534 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
23535 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23536 }
23537
23538 // Perform default conversions.
23540 QualType ResultTy;
23541 if (OriginalTy->isAnyPointerType()) {
23542 ResultTy = OriginalTy->getPointeeType();
23543 } else if (OriginalTy->isArrayType()) {
23544 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
23545 } else {
23546 return ExprError(
23547 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23548 << Base->getSourceRange());
23549 }
23550 // C99 6.5.2.1p1
23551 if (LowerBound) {
23552 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
23553 LowerBound);
23554 if (Res.isInvalid())
23555 return ExprError(Diag(LowerBound->getExprLoc(),
23556 diag::err_omp_typecheck_section_not_integer)
23557 << 0 << LowerBound->getSourceRange());
23558 LowerBound = Res.get();
23559
23560 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23561 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23562 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
23563 << 0 << LowerBound->getSourceRange();
23564 }
23565 if (Length) {
23566 auto Res =
23567 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
23568 if (Res.isInvalid())
23569 return ExprError(Diag(Length->getExprLoc(),
23570 diag::err_omp_typecheck_section_not_integer)
23571 << 1 << Length->getSourceRange());
23572 Length = Res.get();
23573
23574 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23575 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23576 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23577 << 1 << Length->getSourceRange();
23578 }
23579 if (Stride) {
23580 ExprResult Res =
23582 if (Res.isInvalid())
23583 return ExprError(Diag(Stride->getExprLoc(),
23584 diag::err_omp_typecheck_section_not_integer)
23585 << 1 << Stride->getSourceRange());
23586 Stride = Res.get();
23587
23588 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23589 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23590 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
23591 << 1 << Stride->getSourceRange();
23592 }
23593
23594 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
23595 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
23596 // type. Note that functions are not objects, and that (in C99 parlance)
23597 // incomplete types are not object types.
23598 if (ResultTy->isFunctionType()) {
23599 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
23600 << ResultTy << Base->getSourceRange();
23601 return ExprError();
23602 }
23603
23604 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
23605 diag::err_omp_section_incomplete_type, Base))
23606 return ExprError();
23607
23608 if (LowerBound && !OriginalTy->isAnyPointerType()) {
23610 if (LowerBound->EvaluateAsInt(Result, Context)) {
23611 // OpenMP 5.0, [2.1.5 Array Sections]
23612 // The array section must be a subset of the original array.
23613 llvm::APSInt LowerBoundValue = Result.Val.getInt();
23614 if (LowerBoundValue.isNegative()) {
23615 Diag(LowerBound->getExprLoc(),
23616 diag::err_omp_section_not_subset_of_array)
23617 << LowerBound->getSourceRange();
23618 return ExprError();
23619 }
23620 }
23621 }
23622
23623 if (Length) {
23625 if (Length->EvaluateAsInt(Result, Context)) {
23626 // OpenMP 5.0, [2.1.5 Array Sections]
23627 // The length must evaluate to non-negative integers.
23628 llvm::APSInt LengthValue = Result.Val.getInt();
23629 if (LengthValue.isNegative()) {
23630 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23631 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
23632 << Length->getSourceRange();
23633 return ExprError();
23634 }
23635 }
23636 } else if (ColonLocFirst.isValid() &&
23637 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
23638 !OriginalTy->isVariableArrayType()))) {
23639 // OpenMP 5.0, [2.1.5 Array Sections]
23640 // When the size of the array dimension is not known, the length must be
23641 // specified explicitly.
23642 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23643 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
23644 return ExprError();
23645 }
23646
23647 if (Stride) {
23649 if (Stride->EvaluateAsInt(Result, Context)) {
23650 // OpenMP 5.0, [2.1.5 Array Sections]
23651 // The stride must evaluate to a positive integer.
23652 llvm::APSInt StrideValue = Result.Val.getInt();
23653 if (!StrideValue.isStrictlyPositive()) {
23654 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
23655 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
23656 << Stride->getSourceRange();
23657 return ExprError();
23658 }
23659 }
23660 }
23661
23662 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23664 if (Result.isInvalid())
23665 return ExprError();
23666 Base = Result.get();
23667 }
23668 return new (Context) ArraySectionExpr(
23669 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
23670 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23671}
23672
23674 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
23675 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
23676 ASTContext &Context = getASTContext();
23677 if (Base->hasPlaceholderType()) {
23679 if (Result.isInvalid())
23680 return ExprError();
23682 if (Result.isInvalid())
23683 return ExprError();
23684 Base = Result.get();
23685 }
23686 QualType BaseTy = Base->getType();
23687 // Delay analysis of the types/expressions if instantiation/specialization is
23688 // required.
23689 if (!BaseTy->isPointerType() && Base->isTypeDependent())
23690 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
23691 LParenLoc, RParenLoc, Dims, Brackets);
23692 if (!BaseTy->isPointerType() ||
23693 (!Base->isTypeDependent() &&
23694 BaseTy->getPointeeType()->isIncompleteType()))
23695 return ExprError(Diag(Base->getExprLoc(),
23696 diag::err_omp_non_pointer_type_array_shaping_base)
23697 << Base->getSourceRange());
23698
23699 SmallVector<Expr *, 4> NewDims;
23700 bool ErrorFound = false;
23701 for (Expr *Dim : Dims) {
23702 if (Dim->hasPlaceholderType()) {
23704 if (Result.isInvalid()) {
23705 ErrorFound = true;
23706 continue;
23707 }
23709 if (Result.isInvalid()) {
23710 ErrorFound = true;
23711 continue;
23712 }
23713 Dim = Result.get();
23714 }
23715 if (!Dim->isTypeDependent()) {
23717 PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
23718 if (Result.isInvalid()) {
23719 ErrorFound = true;
23720 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23721 << Dim->getSourceRange();
23722 continue;
23723 }
23724 Dim = Result.get();
23725 Expr::EvalResult EvResult;
23726 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23727 // OpenMP 5.0, [2.1.4 Array Shaping]
23728 // Each si is an integral type expression that must evaluate to a
23729 // positive integer.
23730 llvm::APSInt Value = EvResult.Val.getInt();
23731 if (!Value.isStrictlyPositive()) {
23732 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23733 << toString(Value, /*Radix=*/10, /*Signed=*/true)
23734 << Dim->getSourceRange();
23735 ErrorFound = true;
23736 continue;
23737 }
23738 }
23739 }
23740 NewDims.push_back(Dim);
23741 }
23742 if (ErrorFound)
23743 return ExprError();
23744 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
23745 LParenLoc, RParenLoc, NewDims, Brackets);
23746}
23747
23749 SourceLocation IteratorKwLoc,
23750 SourceLocation LLoc,
23751 SourceLocation RLoc,
23753 ASTContext &Context = getASTContext();
23755 bool IsCorrect = true;
23756 for (const OMPIteratorData &D : Data) {
23757 TypeSourceInfo *TInfo = nullptr;
23758 SourceLocation StartLoc;
23759 QualType DeclTy;
23760 if (!D.Type.getAsOpaquePtr()) {
23761 // OpenMP 5.0, 2.1.6 Iterators
23762 // In an iterator-specifier, if the iterator-type is not specified then
23763 // the type of that iterator is of int type.
23764 DeclTy = Context.IntTy;
23765 StartLoc = D.DeclIdentLoc;
23766 } else {
23767 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
23768 StartLoc = TInfo->getTypeLoc().getBeginLoc();
23769 }
23770
23771 bool IsDeclTyDependent = DeclTy->isDependentType() ||
23772 DeclTy->containsUnexpandedParameterPack() ||
23773 DeclTy->isInstantiationDependentType();
23774 if (!IsDeclTyDependent) {
23775 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23776 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23777 // The iterator-type must be an integral or pointer type.
23778 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23779 << DeclTy;
23780 IsCorrect = false;
23781 continue;
23782 }
23783 if (DeclTy.isConstant(Context)) {
23784 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23785 // The iterator-type must not be const qualified.
23786 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23787 << DeclTy;
23788 IsCorrect = false;
23789 continue;
23790 }
23791 }
23792
23793 // Iterator declaration.
23794 assert(D.DeclIdent && "Identifier expected.");
23795 // Always try to create iterator declarator to avoid extra error messages
23796 // about unknown declarations use.
23797 auto *VD =
23798 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
23799 D.DeclIdent, DeclTy, TInfo, SC_None);
23800 VD->setImplicit();
23801 if (S) {
23802 // Check for conflicting previous declaration.
23803 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
23805 RedeclarationKind::ForVisibleRedeclaration);
23806 Previous.suppressDiagnostics();
23808
23810 /*ConsiderLinkage=*/false,
23811 /*AllowInlineNamespace=*/false);
23812 if (!Previous.empty()) {
23813 NamedDecl *Old = Previous.getRepresentativeDecl();
23814 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
23815 Diag(Old->getLocation(), diag::note_previous_definition);
23816 } else {
23818 }
23819 } else {
23821 }
23822
23823 /// Act on the iterator variable declaration.
23825
23826 Expr *Begin = D.Range.Begin;
23827 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
23828 ExprResult BeginRes =
23830 Begin = BeginRes.get();
23831 }
23832 Expr *End = D.Range.End;
23833 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
23834 ExprResult EndRes =
23836 End = EndRes.get();
23837 }
23838 Expr *Step = D.Range.Step;
23839 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
23840 if (!Step->getType()->isIntegralType(Context)) {
23841 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
23842 << Step << Step->getSourceRange();
23843 IsCorrect = false;
23844 continue;
23845 }
23846 std::optional<llvm::APSInt> Result =
23847 Step->getIntegerConstantExpr(Context);
23848 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
23849 // If the step expression of a range-specification equals zero, the
23850 // behavior is unspecified.
23851 if (Result && Result->isZero()) {
23852 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
23853 << Step << Step->getSourceRange();
23854 IsCorrect = false;
23855 continue;
23856 }
23857 }
23858 if (!Begin || !End || !IsCorrect) {
23859 IsCorrect = false;
23860 continue;
23861 }
23862 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
23863 IDElem.IteratorDecl = VD;
23864 IDElem.AssignmentLoc = D.AssignLoc;
23865 IDElem.Range.Begin = Begin;
23866 IDElem.Range.End = End;
23867 IDElem.Range.Step = Step;
23868 IDElem.ColonLoc = D.ColonLoc;
23869 IDElem.SecondColonLoc = D.SecColonLoc;
23870 }
23871 if (!IsCorrect) {
23872 // Invalidate all created iterator declarations if error is found.
23873 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
23874 if (Decl *ID = D.IteratorDecl)
23875 ID->setInvalidDecl();
23876 }
23877 return ExprError();
23878 }
23881 // Build number of ityeration for each iteration range.
23882 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
23883 // ((Begini-Stepi-1-Endi) / -Stepi);
23885 // (Endi - Begini)
23886 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
23887 D.Range.End, D.Range.Begin);
23888 if (!Res.isUsable()) {
23889 IsCorrect = false;
23890 continue;
23891 }
23892 ExprResult St, St1;
23893 if (D.Range.Step) {
23894 St = D.Range.Step;
23895 // (Endi - Begini) + Stepi
23896 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
23897 St.get());
23898 if (!Res.isUsable()) {
23899 IsCorrect = false;
23900 continue;
23901 }
23902 // (Endi - Begini) + Stepi - 1
23904 D.AssignmentLoc, BO_Sub, Res.get(),
23905 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
23906 if (!Res.isUsable()) {
23907 IsCorrect = false;
23908 continue;
23909 }
23910 // ((Endi - Begini) + Stepi - 1) / Stepi
23911 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
23912 St.get());
23913 if (!Res.isUsable()) {
23914 IsCorrect = false;
23915 continue;
23916 }
23917 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
23918 D.Range.Step);
23919 // (Begini - Endi)
23921 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
23922 if (!Res1.isUsable()) {
23923 IsCorrect = false;
23924 continue;
23925 }
23926 // (Begini - Endi) - Stepi
23927 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
23928 St1.get());
23929 if (!Res1.isUsable()) {
23930 IsCorrect = false;
23931 continue;
23932 }
23933 // (Begini - Endi) - Stepi - 1
23935 D.AssignmentLoc, BO_Sub, Res1.get(),
23936 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
23937 if (!Res1.isUsable()) {
23938 IsCorrect = false;
23939 continue;
23940 }
23941 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
23942 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
23943 St1.get());
23944 if (!Res1.isUsable()) {
23945 IsCorrect = false;
23946 continue;
23947 }
23948 // Stepi > 0.
23950 D.AssignmentLoc, BO_GT, D.Range.Step,
23951 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
23952 if (!CmpRes.isUsable()) {
23953 IsCorrect = false;
23954 continue;
23955 }
23956 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
23957 CmpRes.get(), Res.get(), Res1.get());
23958 if (!Res.isUsable()) {
23959 IsCorrect = false;
23960 continue;
23961 }
23962 }
23963 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
23964 if (!Res.isUsable()) {
23965 IsCorrect = false;
23966 continue;
23967 }
23968
23969 // Build counter update.
23970 // Build counter.
23971 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
23972 D.IteratorDecl->getBeginLoc(),
23973 D.IteratorDecl->getBeginLoc(), nullptr,
23974 Res.get()->getType(), nullptr, SC_None);
23975 CounterVD->setImplicit();
23976 ExprResult RefRes =
23977 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
23978 D.IteratorDecl->getBeginLoc());
23979 // Build counter update.
23980 // I = Begini + counter * Stepi;
23981 ExprResult UpdateRes;
23982 if (D.Range.Step) {
23983 UpdateRes = SemaRef.CreateBuiltinBinOp(
23984 D.AssignmentLoc, BO_Mul,
23985 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
23986 } else {
23987 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
23988 }
23989 if (!UpdateRes.isUsable()) {
23990 IsCorrect = false;
23991 continue;
23992 }
23993 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
23994 D.Range.Begin, UpdateRes.get());
23995 if (!UpdateRes.isUsable()) {
23996 IsCorrect = false;
23997 continue;
23998 }
23999 ExprResult VDRes =
24000 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
24001 cast<VarDecl>(D.IteratorDecl)->getType(),
24002 VK_LValue, D.IteratorDecl->getBeginLoc());
24003 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
24004 VDRes.get(), UpdateRes.get());
24005 if (!UpdateRes.isUsable()) {
24006 IsCorrect = false;
24007 continue;
24008 }
24009 UpdateRes =
24010 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
24011 if (!UpdateRes.isUsable()) {
24012 IsCorrect = false;
24013 continue;
24014 }
24015 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24016 D.AssignmentLoc, UO_PreInc, RefRes.get());
24017 if (!CounterUpdateRes.isUsable()) {
24018 IsCorrect = false;
24019 continue;
24020 }
24021 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
24022 /*DiscardedValue=*/true);
24023 if (!CounterUpdateRes.isUsable()) {
24024 IsCorrect = false;
24025 continue;
24026 }
24027 OMPIteratorHelperData &HD = Helpers.emplace_back();
24028 HD.CounterVD = CounterVD;
24029 HD.Upper = Res.get();
24030 HD.Update = UpdateRes.get();
24031 HD.CounterUpdate = CounterUpdateRes.get();
24032 }
24033 } else {
24034 Helpers.assign(ID.size(), {});
24035 }
24036 if (!IsCorrect) {
24037 // Invalidate all created iterator declarations if error is found.
24038 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24039 if (Decl *ID = D.IteratorDecl)
24040 ID->setInvalidDecl();
24041 }
24042 return ExprError();
24043 }
24044 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
24045 LLoc, RLoc, ID, Helpers);
24046}
24047
24048/// Check if \p AssumptionStr is a known assumption and warn if not.
24050 StringRef AssumptionStr) {
24051 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24052 return;
24053
24054 unsigned BestEditDistance = 3;
24055 StringRef Suggestion;
24056 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24057 unsigned EditDistance =
24058 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24059 if (EditDistance < BestEditDistance) {
24060 Suggestion = KnownAssumptionIt.getKey();
24061 BestEditDistance = EditDistance;
24062 }
24063 }
24064
24065 if (!Suggestion.empty())
24066 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24067 << AssumptionStr << Suggestion;
24068 else
24069 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
24070 << AssumptionStr;
24071}
24072
24074 // Handle the case where the attribute has a text message.
24075 StringRef Str;
24076 SourceLocation AttrStrLoc;
24077 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
24078 return;
24079
24080 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
24081
24082 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24083}
24084
24086 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3341
NodeId Parent
Definition: ASTDiff.cpp:191
DynTypedNode Node
StringRef P
const Decl * D
Expr * E
enum clang::sema::@1658::IndirectLocalPathEntry::EntryKind Kind
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:3005
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:146
unsigned Iter
Definition: HTMLLogger.cpp:154
static const Decl * getCanonicalDecl(const Decl *D)
#define X(type, name)
Definition: Value.h:143
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
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:22
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
uint32_t Id
Definition: SemaARM.cpp:1143
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:757
SourceLocation Loc
Definition: SemaObjC.cpp:758
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, StringRef DiagType="")
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude=std::nullopt)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static 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.
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
#define DSAStack
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static VarDecl * buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, StringRef Name, const AttrVec *Attrs=nullptr, DeclRefExpr *OrigRef=nullptr)
Build a variable declaration for OpenMP loop iteration variable.
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers=std::nullopt, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void 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)
Allows QualTypes to be sorted and hence used in maps and sets.
SourceLocation Begin
StateNode * Previous
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
APSInt & getInt()
Definition: APValue.h:423
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:664
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const
Return a non-unique reference to the type for a variable array of the specified element type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
Definition: ASTContext.h:1242
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2628
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2644
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:1160
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1146
void Deallocate(void *Ptr) const
Definition: ASTContext.h:740
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:1147
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
Definition: ASTContext.h:1637
CanQualType OMPIteratorTy
Definition: ASTContext.h:1160
IdentifierTable & Idents
Definition: ASTContext.h:660
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:1159
CanQualType BoolTy
Definition: ASTContext.h:1120
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType BoundMemberTy
Definition: ASTContext.h:1147
CanQualType IntTy
Definition: ASTContext.h:1128
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2675
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2394
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1119
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:1615
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:779
bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified=false)
Compatibility predicates used to check assignment expressions.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
bool isUnset() const
Definition: Ownership.h:167
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition: Expr.h:6916
Expr * getBase()
Get base of the array section.
Definition: Expr.h:6982
Expr * getLength()
Get length of array section.
Definition: Expr.h:6992
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5086
Expr * getLowerBound()
Get lower bound of array section.
Definition: Expr.h:6986
SourceLocation getColonLocFirst() const
Definition: Expr.h:7013
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2674
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3566
QualType getElementType() const
Definition: Type.h:3578
Attr - This represents one attribute.
Definition: Attr.h:42
Represents an attribute applied to a statement.
Definition: Stmt.h:2085
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition: Stmt.cpp:425
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3860
Expr * getLHS() const
Definition: Expr.h:3909
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:2181
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition: Expr.h:4006
bool isRelationalOp() const
Definition: Expr.h:3954
SourceLocation getOperatorLoc() const
Definition: Expr.h:3901
SourceLocation getExprLoc() const
Definition: Expr.h:3900
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:3978
Expr * getRHS() const
Definition: Expr.h:3911
Opcode getOpcode() const
Definition: Expr.h:3904
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2143
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2539
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2866
A call to an overloaded operator written using operator syntax.
Definition: ExprCXX.h:81
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition: DeclCXX.h:1238
bool hasDefinition() const
Definition: DeclCXX.h:572
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition: DeclSpec.h:215
SourceLocation getBeginLoc() const
Definition: DeclSpec.h:84
bool isSet() const
Deprecated.
Definition: DeclSpec.h:228
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition: DeclSpec.cpp:152
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition: DeclSpec.h:213
Represents the this expression in C++.
Definition: ExprCXX.h:1152
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2830
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition: Expr.cpp:1494
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1638
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3000
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:350
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition: Decl.h:4670
unsigned getNumParams() const
Definition: Decl.h:4712
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5443
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4714
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition: Stmt.h:3775
This captures a statement into a function.
Definition: Stmt.h:3762
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1407
SourceRange getSourceRange() const LLVM_READONLY
Definition: Stmt.h:3965
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3866
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition: Stmt.cpp:1431
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:3957
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3498
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition: Type.h:3134
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1606
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition: Stmt.cpp:383
ConditionalOperator - The ?: ternary operator.
Definition: Expr.h:4203
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:195
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1369
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2090
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2219
bool isFileContext() const
Definition: DeclBase.h:2161
ASTContext & getParentASTContext() const
Definition: DeclBase.h:2119
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1399
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1333
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
Definition: DeclBase.h:2106
bool isNamespace() const
Definition: DeclBase.h:2179
bool isTranslationUnit() const
Definition: DeclBase.h:2166
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1766
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2350
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1384
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
Definition: DeclBase.cpp:1403
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1740
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition: DeclGroup.h:68
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1265
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:551
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition: Expr.cpp:488
ValueDecl * getDecl()
Definition: Expr.h:1333
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Expr.cpp:556
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1497
SourceLocation getEndLoc() const
Definition: Stmt.h:1520
const DeclGroupRef getDeclGroup() const
Definition: Stmt.h:1515
const Decl * getSingleDecl() const
Definition: Stmt.h:1512
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:1523
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:580
bool hasAttrs() const
Definition: DeclBase.h:525
void addAttr(Attr *A)
Definition: DeclBase.cpp:1013
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:600
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:154
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition: DeclBase.cpp:567
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition: DeclBase.cpp:577
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition: DeclBase.h:974
bool isInvalidDecl() const
Definition: DeclBase.h:595
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:566
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:509
SourceLocation getLocation() const
Definition: DeclBase.h:446
void setImplicit(bool I=true)
Definition: DeclBase.h:601
void setReferenced(bool R=true)
Definition: DeclBase.h:630
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: DeclBase.h:1039
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition: DeclBase.cpp:552
DeclContext * getDeclContext()
Definition: DeclBase.h:455
AccessSpecifier getAccess() const
Definition: DeclBase.h:514
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:438
AttrVec & getAttrs()
Definition: DeclBase.h:531
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition: DeclBase.cpp:358
bool hasAttr() const
Definition: DeclBase.h:584
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:362
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:968
Kind getKind() const
Definition: DeclBase.h:449
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:434
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1903
RAII object that enters a new expression evaluation context.
The return type of classify().
Definition: Expr.h:330
This represents one expression.
Definition: Expr.h:110
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isGLValue() const
Definition: Expr.h:280
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition: Expr.h:671
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3075
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition: Expr.h:437
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition: Expr.h:239
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition: Expr.cpp:3087
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3070
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3058
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition: Expr.h:245
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3066
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:277
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:444
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3050
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition: Expr.h:142
Represents difference between two FPOptions values.
Definition: LangOptions.h:919
Represents a member of a struct/union/class.
Definition: Decl.h:3030
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3121
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4652
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3258
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1078
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2786
Represents a function declaration or definition.
Definition: Decl.h:1932
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2669
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2646
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2395
bool isConsteval() const
Definition: Decl.h:2407
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3678
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5002
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2143
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition: Expr.h:1717
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2074
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition: Overload.h:567
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Definition: SemaInit.cpp:7521
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition: Expr.cpp:977
Describes the capture of a variable or of this, or of a C++1y init-capture.
Definition: LambdaCapture.h:25
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:461
A class for iterating through a result set and possibly filtering out results.
Definition: Lookup.h:675
Represents the results of name lookup.
Definition: Lookup.h:46
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition: Lookup.h:605
DeclClass * getAsSingle() const
Definition: Lookup.h:558
bool empty() const
Return true if no decls were found.
Definition: Lookup.h:362
Filter makeFilter()
Create a filter for this result set.
Definition: Lookup.h:749
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition: Lookup.h:568
bool isAmbiguous() const
Definition: Lookup.h:324
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
Definition: Lookup.h:331
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition: Lookup.h:575
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition: Lookup.h:634
iterator end() const
Definition: Lookup.h:359
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
iterator begin() const
Definition: Lookup.h:358
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3187
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3270
Expr * getBase() const
Definition: Expr.h:3264
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:3248
This represents a decl that may have a name.
Definition: Decl.h:249
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:315
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition: Decl.h:292
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
Definition: Decl.cpp:1811
A C++ nested-name-specifier augmented with source location information.
static OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
Definition: OpenMPClause.h:575
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
Definition: DeclOpenMP.cpp:57
This represents 'allocator' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:414
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
Definition: ExprOpenMP.h:24
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Definition: Expr.cpp:5167
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
Definition: StmtOpenMP.cpp:802
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:970
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:834
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:890
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Definition: StmtOpenMP.cpp:876
static OMPCanonicalLoop * create(const ASTContext &Ctx, Stmt *LoopStmt, CapturedStmt *DistanceFunc, CapturedStmt *LoopVarFunc, DeclRefExpr *LoopVarRef)
Create a new OMPCanonicalLoop.
Definition: StmtOpenMP.h:163
This represents 'capture' clause in the '#pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
Definition: DeclOpenMP.h:383
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Definition: DeclOpenMP.cpp:176
Class that represents a component of a mappable expression.
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'shedule', 'firstprivate' etc.
Definition: OpenMPClause.h:195
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
Definition: OpenMPClause.h:71
SourceLocation getEndLoc() const
Returns the ending location of the clause.
Definition: OpenMPClause.h:74
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
Definition: OpenMPClause.h:83
This represents 'collapse' clause in the '#pragma omp ...' directive.
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:619
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:921
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:819
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This is a basic class for representing single OpenMP executable directive.
Definition: StmtOpenMP.h:266
OpenMPDirectiveKind getDirectiveKind() const
Definition: StmtOpenMP.h:556
This represents 'fail' clause in the '#pragma omp atomic' directive.
This represents 'filter' clause in the '#pragma omp ...' directive.
This represents 'final' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:690
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:906
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:489
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Representation of the 'full' clause of the '#pragma omp unroll' directive.
Definition: OpenMPClause.h:939
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:587
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:468
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:5296
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the '#pragma omp ...' directives.
Expr * getStep()
Returns linear step.
void setUpdates(ArrayRef< Expr * > UL)
Sets the list of update expressions for linear variables.
privates_range privates()
void setFinals(ArrayRef< Expr * > FL)
Sets the list of final update expressions for linear variables.
void setUsedExprs(ArrayRef< Expr * > UE)
Sets the list of used expressions for the linear clause.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
Expr * getCalcStep()
Returns expression to calculate linear step.
OpenMPLinearClauseKind getModifier() const
Return modifier.
The base class for all loop-based directives, including loop transformation directives.
Definition: StmtOpenMP.h:683
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
Definition: StmtOpenMP.cpp:125
The base class for all loop transformation directives.
Definition: StmtOpenMP.h:960
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:604
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'mergeable' clause in the '#pragma omp ...' directive.
This represents 'message' clause in the '#pragma omp error' directive.
Expr * getMessageString() const
Returns message string of the clause.
This represents the 'no_openmp' clause in the '#pragma omp assume' directive.
This represents the 'no_openmp_routines' clause in the '#pragma omp assume' directive.
This represents the 'no_parallelism' clause in the '#pragma omp assume' directive.
This represents 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
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:736
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:951
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:635
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:680
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:740
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:724
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:756
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
Definition: OpenMPClause.h:967
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 represents 'priority' clause in the '#pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents 'read' clause in the '#pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
This represents '#pragma omp requires...' directive.
Definition: DeclOpenMP.h:417
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
Definition: DeclOpenMP.cpp:86
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp reverse'.
Definition: StmtOpenMP.cpp:451
This represents 'reverse_offload' clause in the '#pragma omp requires' directive.
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:781
Expr * getSafelen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:801
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:936
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:570
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
Definition: StmtOpenMP.cpp:552
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:532
This represents 'seq_cst' clause in the '#pragma omp atomic' directive.
This represents 'severity' clause in the '#pragma omp error' directive.
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:301
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:816
Expr * getSimdlen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:836
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:587
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:995
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:775
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:860
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
Definition: StmtOpenMP.cpp:846
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:791
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents '#pragma omp threadprivate ...' directive.
Definition: DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
Definition: DeclOpenMP.cpp:28
This represents 'threads' clause in the '#pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp tile'.
Definition: StmtOpenMP.cpp:408
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the '#pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the '#pragma omp requires' directive.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp unroll'.
Definition: StmtOpenMP.cpp:429
This represents 'untied' clause in the '#pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
This represents the 'use' clause in '#pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
varlist_range varlist()
Definition: OpenMPClause.h:319
SourceLocation getLParenLoc() const
Returns the location of '('.
Definition: OpenMPClause.h:335
unsigned varlist_size() const
Definition: OpenMPClause.h:316
This represents 'weak' clause in the '#pragma omp atomic' directives.
This represents 'write' clause in the '#pragma omp atomic' directive.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the '#pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the '#pragma omp target ...' directive.
Wrapper for void* pointer.
Definition: Ownership.h:50
void * getAsOpaquePtr() const
Definition: Ownership.h:90
PtrTy get() const
Definition: Ownership.h:80
static OpaquePtr make(PtrTy P)
Definition: Ownership.h:60
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1173
void setIsUnique(bool V)
Definition: Expr.h:1225
Represents a parameter to a function.
Definition: Decl.h:1722
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:2903
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
Definition: Expr.cpp:4898
A (possibly-)qualified type.
Definition: Type.h:941
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition: Type.cpp:2751
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: Type.h:7839
QualType withRestrict() const
Definition: Type.h:1182
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition: Type.cpp:3476
QualType withConst() const
Definition: Type.h:1166
void addConst()
Add the const type qualifier to this QualType.
Definition: Type.h:1163
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:1008
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7750
bool isConstant(const ASTContext &Ctx) const
Definition: Type.h:1101
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: Type.h:7951
QualType getCanonicalType() const
Definition: Type.h:7802
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7844
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition: Type.h:7922
const Type * getTypePtrOrNull() const
Definition: Type.h:7754
Represents a struct/union/class.
Definition: Decl.h:4145
field_range fields() const
Definition: Decl.h:4351
field_iterator field_begin() const
Definition: Decl.cpp:5068
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5965
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Definition: Redeclarable.h:205
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Definition: Redeclarable.h:227
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3428
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition: Scope.h:381
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition: Scope.h:305
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition: Scope.h:530
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition: Scope.h:270
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition: Scope.h:523
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition: Scope.h:150
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:110
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition: SemaBase.cpp:32
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'reduction' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the '#pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * 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)
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'from' clause.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'to' clause.
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition: SemaOpenMP.h:110
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
OMPClause * ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
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.
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:242
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.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'task_reduction' clause.
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition: SemaOpenMP.h:54
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
std::pair< StringRef, QualType > CapturedParamNameType
Definition: SemaOpenMP.h:55
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition: SemaOpenMP.h:370
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp tile' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
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:430
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
Definition: Sema.h:1011
Expr * get() const
Definition: Sema.h:7342
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:12180
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:7291
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:535
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
Definition: SemaType.cpp:6327
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:805
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:1557
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
Definition: SemaExpr.cpp:3582
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15280
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:9057
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:9098
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:9100
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:9102
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
SemaOpenMP & OpenMP()
Definition: Sema.h:1221
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition: Sema.h:4378
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17174
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:20125
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:942
@ AR_inaccessible
Definition: Sema.h:1356
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:2295
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition: Sema.cpp:2164
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:6206
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
Definition: SemaExpr.cpp:16932
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1752
void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables=false, ArrayRef< const Expr * > StopAt=std::nullopt)
Mark any declarations that appear within this expression or any potentially-evaluated subexpressions ...
Definition: SemaExpr.cpp:19912
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:1566
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ASTContext & Context
Definition: Sema.h:1004
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4566
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:71
@ AllowFold
Definition: Sema.h:7307
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1495
void CleanupVarDeclMarking()
Definition: SemaExpr.cpp:19406
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:751
ASTContext & getASTContext() const
Definition: Sema.h:602
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15559
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:18688
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:19654
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:17595
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:910
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2190
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:2183
const LangOptions & getLangOpts() const
Definition: Sema.h:595
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:1003
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:6400
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:1002
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2408
DeclContext * getCurLexicalContext() const
Definition: Sema.h:809
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
Definition: SemaCast.cpp:3341
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
Definition: SemaStmt.cpp:4477
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:1035
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:639
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition: Sema.h:15025
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20199
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2364
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1139
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4581
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4085
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:20709
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:13532
@ TryCapture_ExplicitByVal
Definition: Sema.h:6657
@ AA_Initializing
Definition: Sema.h:6542
@ AA_Converting
Definition: Sema.h:6541
@ AA_Casting
Definition: Sema.h:6544
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:11087
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:8697
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:14980
@ CTK_ErrorRecovery
Definition: Sema.h:9451
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2349
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:10981
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:287
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5094
@ 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:5651
void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery=true)
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition: SemaStmt.cpp:79
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:8905
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:965
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:17673
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1306
void PopDeclContext()
Definition: SemaDecl.cpp:1313
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:1577
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:13832
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13272
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition: Sema.cpp:1966
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
Definition: SemaExpr.cpp:15127
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
Definition: SemaExpr.cpp:14592
bool IsDerivedFrom(SourceLocation Loc, QualType Derived, QualType Base)
Determine whether the type Derived is a C++ class that is derived from the type Base.
sema::FunctionScopeInfo * getEnclosingFunction() const
Definition: Sema.cpp:2379
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2737
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:2729
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:415
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:7356
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:8335
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:185
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:350
child_range children()
Definition: Stmt.cpp:287
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
Definition: Stmt.cpp:197
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4719
bool isTLSSupported() const
Whether the target supports thread-local storage.
Definition: TargetInfo.h:1576
bool isVLASupported() const
Whether target supports variable-length arrays.
Definition: TargetInfo.h:1587
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition: Decl.h:3367
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7721
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:7732
The base class of the type hierarchy.
Definition: Type.h:1829
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1882
bool isConstantArrayType() const
Definition: Type.h:8079
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:2021
bool isArrayType() const
Definition: Type.h:8075
bool isArithmeticType() const
Definition: Type.cpp:2281
bool isPointerType() const
Definition: Type.h:8003
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8359
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8607
bool isReferenceType() const
Definition: Type.h:8021
bool isEnumeralType() const
Definition: Type.h:8107
bool isScalarType() const
Definition: Type.h:8418
bool isVariableArrayType() const
Definition: Type.h:8087
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2058
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2236
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: Type.h:8313
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2703
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:8288
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2695
bool isAnyComplexType() const
Definition: Type.h:8111
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: Type.h:2354
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2186
bool isFunctionProtoType() const
Definition: Type.h:2528
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition: Type.h:8460
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: Type.h:2713
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8593
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition: Type.cpp:2362
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition: Type.h:8557
bool isFunctionType() const
Definition: Type.h:7999
bool isStructureOrClassType() const
Definition: Type.cpp:657
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2266
bool isFloatingType() const
Definition: Type.cpp:2249
bool isAnyPointerType() const
Definition: Type.h:8011
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8540
bool isRecordType() const
Definition: Type.h:8103
bool isUnionType() const
Definition: Type.cpp:671
bool isFunctionNoProtoType() const
Definition: Type.h:2527
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1886
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:2188
Expr * getSubExpr() const
Definition: Expr.h:2233
Opcode getOpcode() const
Definition: Expr.h:2228
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:420
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
Definition: UnresolvedSet.h:92
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:667
void setType(QualType newType)
Definition: Decl.h:679
QualType getType() const
Definition: Decl.h:678
Represents a variable declaration or definition.
Definition: Decl.h:879
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition: Decl.cpp:2133
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition: Decl.h:1215
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1510
TLSKind getTLSKind() const
Definition: Decl.cpp:2150
bool hasInit() const
Definition: Decl.cpp:2380
void setInitStyle(InitializationStyle Style)
Definition: Decl.h:1393
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition: Decl.h:1407
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition: Decl.cpp:2242
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:2172
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition: Decl.cpp:2239
@ CInit
C-style initialization with assignment.
Definition: Decl.h:884
@ CallInit
Call-style initialization (C++98)
Definition: Decl.h:887
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition: Decl.h:1231
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition: Decl.h:1174
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition: Decl.h:1156
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition: Decl.h:1290
const Expr * getInit() const
Definition: Decl.h:1316
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1132
@ TLS_None
Not a TLS variable.
Definition: Decl.h:899
void setInit(Expr *I)
Definition: Decl.cpp:2442
@ DeclarationOnly
This declaration is only a declaration.
Definition: Decl.h:1243
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition: Decl.h:1201
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition: Decl.h:1412
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition: Decl.h:1177
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition: Decl.h:1116
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:2493
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition: Decl.h:1210
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition: Decl.h:1306
Directive - Abstract class representing a parsed verify directive.
Retains information about a captured region.
Definition: ScopeInfo.h:810
Retains information about a function, method, or block that is currently being parsed.
Definition: ScopeInfo.h:104
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
Definition: ScopeInfo.h:228
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Definition: AttrIterator.h:33
Defines the clang::TargetInfo interface.
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1109
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
@ NUM_OVERLOADED_OPERATORS
Definition: OperatorKinds.h:26
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
@ CPlusPlus
Definition: LangStandard.h:56
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:24
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
Definition: OpenMPKinds.h:118
@ OMPC_DEFAULTMAP_MODIFIER_last
Definition: OpenMPKinds.h:123
@ OMPC_DEFAULTMAP_MODIFIER_unknown
Definition: OpenMPKinds.h:119
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
Definition: OpenMPKinds.h:171
@ OMPC_ORDER_MODIFIER_unknown
Definition: OpenMPKinds.h:172
@ OMPC_ORDER_MODIFIER_last
Definition: OpenMPKinds.h:175
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition: Specifiers.h: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:135
@ OMPC_AT_unknown
Definition: OpenMPKinds.h:138
Expr * AssertSuccess(ExprResult R)
Definition: Ownership.h:274
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
Definition: Lambda.h:37
@ LCK_This
Capturing the *this object by reference.
Definition: Lambda.h:34
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
Definition: OpenMPKinds.h:186
@ OMPC_REDUCTION_unknown
Definition: OpenMPKinds.h:189
BinaryOperatorKind
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition: OpenMPKinds.h:38
@ OMPC_SCHEDULE_MODIFIER_last
Definition: OpenMPKinds.h:43
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition: OpenMPKinds.h:39
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:27
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
@ CR_Default
Definition: CapturedStmt.h:17
@ CR_OpenMP
Definition: CapturedStmt.h:19
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
@ SC_Auto
Definition: Specifiers.h:256
@ SC_Register
Definition: Specifiers.h:257
@ SC_None
Definition: Specifiers.h:250
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
Definition: OpenMPKinds.h:103
@ OMPC_DIST_SCHEDULE_unknown
Definition: OpenMPKinds.h:106
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition: Decl.h:5031
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
Definition: OpenMPKinds.h:219
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
Definition: OpenMPKinds.h:87
ExprResult ExprEmpty()
Definition: Ownership.h:271
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
StmtResult StmtError()
Definition: Ownership.h:265
@ SD_Static
Static storage duration.
Definition: Specifiers.h:331
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
Definition: OpenMPKinds.h:200
@ OMPC_BIND_unknown
Definition: OpenMPKinds.h:203
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
Definition: OpenMPKinds.h:157
@ OMPC_LASTPRIVATE_unknown
Definition: OpenMPKinds.h:160
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition: OpenMPKinds.h:54
@ OMPC_DEPEND_unknown
Definition: OpenMPKinds.h:58
OpenMPGrainsizeClauseModifier
Definition: OpenMPKinds.h:206
@ OMPC_GRAINSIZE_unknown
Definition: OpenMPKinds.h:209
OpenMPNumTasksClauseModifier
Definition: OpenMPKinds.h:212
@ OMPC_NUMTASKS_unknown
Definition: OpenMPKinds.h:215
ActionResult< Expr * > ExprResult
Definition: Ownership.h:248
ExprResult ExprError()
Definition: Ownership.h:264
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
Definition: OpenMPKinds.h:142
@ OMPC_SEVERITY_unknown
Definition: OpenMPKinds.h:145
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
Definition: OpenMPKinds.h:99
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition: OpenMPKinds.h:91
@ OMPC_MOTION_MODIFIER_unknown
Definition: OpenMPKinds.h:95
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
Definition: OpenMPKinds.h:110
@ OMPC_DEFAULTMAP_unknown
Definition: OpenMPKinds.h:114
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition: OpenMPKinds.h:62
@ OMPC_LINEAR_unknown
Definition: OpenMPKinds.h:66
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:132
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
for(const auto &A :T->param_types())
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
Definition: OpenMPKinds.h:127
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
Definition: OpenMPKinds.h:131
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ActionResult< Decl * > DeclResult
Definition: Ownership.h:254
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
Definition: OpenMPKinds.h:47
@ OMPC_DEVICE_unknown
Definition: OpenMPKinds.h:50
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition: OpenMPKinds.h:78
@ OMPC_MAP_MODIFIER_unknown
Definition: OpenMPKinds.h:79
bool isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a combined construct for which the first construct is a parallel...
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
Definition: OpenMPKinds.h:164
@ OMPC_ORDER_unknown
Definition: OpenMPKinds.h:167
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition: OpenMPKinds.h:30
@ OMPC_SCHEDULE_unknown
Definition: OpenMPKinds.h:34
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:123
@ AS_public
Definition: Specifiers.h:124
@ AS_none
Definition: Specifiers.h:127
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition: OpenMPKinds.h:70
@ OMPC_MAP_unknown
Definition: OpenMPKinds.h:74
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition: Specifiers.h:177
unsigned long uint64_t
#define true
Definition: stdbool.h:25
#define false
Definition: stdbool.h:26
#define bool
Definition: stdbool.h:24
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
const Expr * RHS
The original right-hand side.
Definition: ExprCXX.h:310
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition: ExprCXX.h:306
const Expr * LHS
The original left-hand side.
Definition: ExprCXX.h:308
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:642
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:644
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:630
Extra information about a function prototype.
Definition: Type.h:5087
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:232
Iterator definition representation.
Definition: ExprOpenMP.h:160
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Definition: ExprOpenMP.h:111
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Definition: ExprOpenMP.h:121
Expr * Upper
Normalized upper bound.
Definition: ExprOpenMP.h:116
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
Definition: ExprOpenMP.h:119
VarDecl * CounterVD
Internal normalized counter.
Definition: ExprOpenMP.h:113
Expr * ParForInDistCond
'omp parallel for' loop condition used when composed with 'omp distribute' in the same construct and ...
Definition: StmtOpenMP.h:736
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:710
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Definition: StmtOpenMP.h:720
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:729
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Definition: StmtOpenMP.h:716
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:713
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:726
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Definition: StmtOpenMP.h:732
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:723
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Definition: StmtOpenMP.h:741
Expr * LastIteration
Loop last iteration number.
Definition: StmtOpenMP.h:745
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:803
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Definition: StmtOpenMP.h:793
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Definition: StmtOpenMP.h:787
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Definition: StmtOpenMP.h:781
Expr * IL
IsLastIteration - local flag variable passed to runtime.
Definition: StmtOpenMP.h:759
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
Definition: StmtOpenMP.h:791
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Definition: StmtOpenMP.h:815
Expr * CalcLastIteration
Calculation of last iteration.
Definition: StmtOpenMP.h:749
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Definition: StmtOpenMP.h:795
Expr * ST
Stride - local variable passed to runtime.
Definition: StmtOpenMP.h:765
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
Definition: StmtOpenMP.h:797
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:806
Expr * PreCond
Loop pre-condition.
Definition: StmtOpenMP.h:751
Stmt * PreInits
Init statement for all captured expressions.
Definition: StmtOpenMP.h:808
Expr * IterationVarRef
Loop iteration variable.
Definition: StmtOpenMP.h:743
Expr * NumIterations
Loop number of iterations.
Definition: StmtOpenMP.h:747
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Definition: StmtOpenMP.h:789
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:769
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:777
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
Definition: StmtOpenMP.h:811
void clear(unsigned Size)
Initialize all the fields to null.
Definition: StmtOpenMP.h:825
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Definition: StmtOpenMP.h:767
Expr * UB
UpperBound - local variable passed to runtime.
Definition: StmtOpenMP.h:763
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:771
Expr * LB
LowerBound - local variable passed to runtime.
Definition: StmtOpenMP.h:761
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:774
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:800
Expr * Init
Loop iteration variable init.
Definition: StmtOpenMP.h:755
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
This structure contains most locations needed for by an OMPVarListClause.
Definition: OpenMPClause.h:259
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
Definition: OpenMPClause.h:261
SourceLocation LParenLoc
Location of '('.
Definition: OpenMPClause.h:263
SourceLocation EndLoc
Ending location of the clause.
Definition: OpenMPClause.h:265
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition: SemaOpenMP.h:315
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition: SemaOpenMP.h:312
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition: SemaOpenMP.h:309
SourceLocation Loc
The directive location.
Definition: SemaOpenMP.h:318
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition: SemaOpenMP.h:306
Data structure for iterator expression.
Definition: SemaOpenMP.h:1380
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1124
Data for list of allocators.
Definition: SemaOpenMP.h:1320
Clang specific specialization of the OMPContext to lookup target features.