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 }
806 return true;
807 }
808 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
810 switch (Kind) {
811 case OMPC_DEFAULTMAP_scalar:
812 case OMPC_DEFAULTMAP_pointer:
813 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
814 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
815 (M == OMPC_DEFAULTMAP_MODIFIER_default);
816 case OMPC_DEFAULTMAP_aggregate:
817 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
818 default:
819 break;
820 }
821 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
822 }
823 bool mustBeFirstprivateAtLevel(unsigned Level,
824 OpenMPDefaultmapClauseKind Kind) const {
826 getDefaultmapModifierAtLevel(Level, Kind);
827 return mustBeFirstprivateBase(M, Kind);
828 }
829 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
830 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
831 return mustBeFirstprivateBase(M, Kind);
832 }
833
834 /// Checks if the specified variable is a threadprivate.
835 bool isThreadPrivate(VarDecl *D) {
836 const DSAVarData DVar = getTopDSA(D, false);
837 return isOpenMPThreadPrivate(DVar.CKind);
838 }
839
840 /// Marks current region as ordered (it has an 'ordered' clause).
841 void setOrderedRegion(bool IsOrdered, const Expr *Param,
842 OMPOrderedClause *Clause) {
843 if (IsOrdered)
844 getTopOfStack().OrderedRegion.emplace(Param, Clause);
845 else
846 getTopOfStack().OrderedRegion.reset();
847 }
848 /// Returns true, if region is ordered (has associated 'ordered' clause),
849 /// false - otherwise.
850 bool isOrderedRegion() const {
851 if (const SharingMapTy *Top = getTopOfStackOrNull())
852 return Top->OrderedRegion.has_value();
853 return false;
854 }
855 /// Returns optional parameter for the ordered region.
856 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
857 if (const SharingMapTy *Top = getTopOfStackOrNull())
858 if (Top->OrderedRegion)
859 return *Top->OrderedRegion;
860 return std::make_pair(nullptr, nullptr);
861 }
862 /// Returns true, if parent region is ordered (has associated
863 /// 'ordered' clause), false - otherwise.
864 bool isParentOrderedRegion() const {
865 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
866 return Parent->OrderedRegion.has_value();
867 return false;
868 }
869 /// Returns optional parameter for the ordered region.
870 std::pair<const Expr *, OMPOrderedClause *>
871 getParentOrderedRegionParam() const {
872 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
873 if (Parent->OrderedRegion)
874 return *Parent->OrderedRegion;
875 return std::make_pair(nullptr, nullptr);
876 }
877 /// Marks current region as having an 'order' clause.
878 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
879 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
880 }
881 /// Returns true, if parent region is order (has associated
882 /// 'order' clause), false - otherwise.
883 bool isParentOrderConcurrent() const {
884 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
885 return Parent->RegionHasOrderConcurrent;
886 return false;
887 }
888 /// Marks current region as nowait (it has a 'nowait' clause).
889 void setNowaitRegion(bool IsNowait = true) {
890 getTopOfStack().NowaitRegion = IsNowait;
891 }
892 /// Returns true, if parent region is nowait (has associated
893 /// 'nowait' clause), false - otherwise.
894 bool isParentNowaitRegion() const {
895 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
896 return Parent->NowaitRegion;
897 return false;
898 }
899 /// Marks current region as untied (it has a 'untied' clause).
900 void setUntiedRegion(bool IsUntied = true) {
901 getTopOfStack().UntiedRegion = IsUntied;
902 }
903 /// Return true if current region is untied.
904 bool isUntiedRegion() const {
905 const SharingMapTy *Top = getTopOfStackOrNull();
906 return Top ? Top->UntiedRegion : false;
907 }
908 /// Marks parent region as cancel region.
909 void setParentCancelRegion(bool Cancel = true) {
910 if (SharingMapTy *Parent = getSecondOnStackOrNull())
911 Parent->CancelRegion |= Cancel;
912 }
913 /// Return true if current region has inner cancel construct.
914 bool isCancelRegion() const {
915 const SharingMapTy *Top = getTopOfStackOrNull();
916 return Top ? Top->CancelRegion : false;
917 }
918
919 /// Mark that parent region already has scan directive.
920 void setParentHasScanDirective(SourceLocation Loc) {
921 if (SharingMapTy *Parent = getSecondOnStackOrNull())
922 Parent->PrevScanLocation = Loc;
923 }
924 /// Return true if current region has inner cancel construct.
925 bool doesParentHasScanDirective() const {
926 const SharingMapTy *Top = getSecondOnStackOrNull();
927 return Top ? Top->PrevScanLocation.isValid() : false;
928 }
929 /// Return true if current region has inner cancel construct.
930 SourceLocation getParentScanDirectiveLoc() const {
931 const SharingMapTy *Top = getSecondOnStackOrNull();
932 return Top ? Top->PrevScanLocation : SourceLocation();
933 }
934 /// Mark that parent region already has ordered directive.
935 void setParentHasOrderedDirective(SourceLocation Loc) {
936 if (SharingMapTy *Parent = getSecondOnStackOrNull())
937 Parent->PrevOrderedLocation = Loc;
938 }
939 /// Return true if current region has inner ordered construct.
940 bool doesParentHasOrderedDirective() const {
941 const SharingMapTy *Top = getSecondOnStackOrNull();
942 return Top ? Top->PrevOrderedLocation.isValid() : false;
943 }
944 /// Returns the location of the previously specified ordered directive.
945 SourceLocation getParentOrderedDirectiveLoc() const {
946 const SharingMapTy *Top = getSecondOnStackOrNull();
947 return Top ? Top->PrevOrderedLocation : SourceLocation();
948 }
949
950 /// Set collapse value for the region.
951 void setAssociatedLoops(unsigned Val) {
952 getTopOfStack().AssociatedLoops = Val;
953 if (Val > 1)
954 getTopOfStack().HasMutipleLoops = true;
955 }
956 /// Return collapse value for region.
957 unsigned getAssociatedLoops() const {
958 const SharingMapTy *Top = getTopOfStackOrNull();
959 return Top ? Top->AssociatedLoops : 0;
960 }
961 /// Returns true if the construct is associated with multiple loops.
962 bool hasMutipleLoops() const {
963 const SharingMapTy *Top = getTopOfStackOrNull();
964 return Top ? Top->HasMutipleLoops : false;
965 }
966
967 /// Marks current target region as one with closely nested teams
968 /// region.
969 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
970 if (SharingMapTy *Parent = getSecondOnStackOrNull())
971 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
972 }
973 /// Returns true, if current region has closely nested teams region.
974 bool hasInnerTeamsRegion() const {
975 return getInnerTeamsRegionLoc().isValid();
976 }
977 /// Returns location of the nested teams region (if any).
978 SourceLocation getInnerTeamsRegionLoc() const {
979 const SharingMapTy *Top = getTopOfStackOrNull();
980 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
981 }
982
983 Scope *getCurScope() const {
984 const SharingMapTy *Top = getTopOfStackOrNull();
985 return Top ? Top->CurScope : nullptr;
986 }
987 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
988 SourceLocation getConstructLoc() const {
989 const SharingMapTy *Top = getTopOfStackOrNull();
990 return Top ? Top->ConstructLoc : SourceLocation();
991 }
992
993 /// Do the check specified in \a Check to all component lists and return true
994 /// if any issue is found.
995 bool checkMappableExprComponentListsForDecl(
996 const ValueDecl *VD, bool CurrentRegionOnly,
997 const llvm::function_ref<
1000 Check) const {
1001 if (isStackEmpty())
1002 return false;
1003 auto SI = begin();
1004 auto SE = end();
1005
1006 if (SI == SE)
1007 return false;
1008
1009 if (CurrentRegionOnly)
1010 SE = std::next(SI);
1011 else
1012 std::advance(SI, 1);
1013
1014 for (; SI != SE; ++SI) {
1015 auto MI = SI->MappedExprComponents.find(VD);
1016 if (MI != SI->MappedExprComponents.end())
1018 MI->second.Components)
1019 if (Check(L, MI->second.Kind))
1020 return true;
1021 }
1022 return false;
1023 }
1024
1025 /// Do the check specified in \a Check to all component lists at a given level
1026 /// and return true if any issue is found.
1027 bool checkMappableExprComponentListsForDeclAtLevel(
1028 const ValueDecl *VD, unsigned Level,
1029 const llvm::function_ref<
1032 Check) const {
1033 if (getStackSize() <= Level)
1034 return false;
1035
1036 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1037 auto MI = StackElem.MappedExprComponents.find(VD);
1038 if (MI != StackElem.MappedExprComponents.end())
1040 MI->second.Components)
1041 if (Check(L, MI->second.Kind))
1042 return true;
1043 return false;
1044 }
1045
1046 /// Create a new mappable expression component list associated with a given
1047 /// declaration and initialize it with the provided list of components.
1048 void addMappableExpressionComponents(
1049 const ValueDecl *VD,
1051 OpenMPClauseKind WhereFoundClauseKind) {
1052 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1053 // Create new entry and append the new components there.
1054 MEC.Components.resize(MEC.Components.size() + 1);
1055 MEC.Components.back().append(Components.begin(), Components.end());
1056 MEC.Kind = WhereFoundClauseKind;
1057 }
1058
1059 unsigned getNestingLevel() const {
1060 assert(!isStackEmpty());
1061 return getStackSize() - 1;
1062 }
1063 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1064 SharingMapTy *Parent = getSecondOnStackOrNull();
1065 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1066 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1067 }
1068 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1069 getDoacrossDependClauses() const {
1070 const SharingMapTy &StackElem = getTopOfStack();
1071 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1072 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1073 return llvm::make_range(Ref.begin(), Ref.end());
1074 }
1075 return llvm::make_range(StackElem.DoacrossDepends.end(),
1076 StackElem.DoacrossDepends.end());
1077 }
1078
1079 // Store types of classes which have been explicitly mapped
1080 void addMappedClassesQualTypes(QualType QT) {
1081 SharingMapTy &StackElem = getTopOfStack();
1082 StackElem.MappedClassesQualTypes.insert(QT);
1083 }
1084
1085 // Return set of mapped classes types
1086 bool isClassPreviouslyMapped(QualType QT) const {
1087 const SharingMapTy &StackElem = getTopOfStack();
1088 return StackElem.MappedClassesQualTypes.contains(QT);
1089 }
1090
1091 /// Adds global declare target to the parent target region.
1092 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1093 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1094 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1095 "Expected declare target link global.");
1096 for (auto &Elem : *this) {
1097 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1098 Elem.DeclareTargetLinkVarDecls.push_back(E);
1099 return;
1100 }
1101 }
1102 }
1103
1104 /// Returns the list of globals with declare target link if current directive
1105 /// is target.
1106 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1107 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1108 "Expected target executable directive.");
1109 return getTopOfStack().DeclareTargetLinkVarDecls;
1110 }
1111
1112 /// Adds list of allocators expressions.
1113 void addInnerAllocatorExpr(Expr *E) {
1114 getTopOfStack().InnerUsedAllocators.push_back(E);
1115 }
1116 /// Return list of used allocators.
1117 ArrayRef<Expr *> getInnerAllocators() const {
1118 return getTopOfStack().InnerUsedAllocators;
1119 }
1120 /// Marks the declaration as implicitly firstprivate nin the task-based
1121 /// regions.
1122 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1123 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1124 }
1125 /// Checks if the decl is implicitly firstprivate in the task-based region.
1126 bool isImplicitTaskFirstprivate(Decl *D) const {
1127 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1128 }
1129
1130 /// Marks decl as used in uses_allocators clause as the allocator.
1131 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1132 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1133 }
1134 /// Checks if specified decl is used in uses allocator clause as the
1135 /// allocator.
1136 std::optional<UsesAllocatorsDeclKind>
1137 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1138 const SharingMapTy &StackElem = getTopOfStack();
1139 auto I = StackElem.UsesAllocatorsDecls.find(D);
1140 if (I == StackElem.UsesAllocatorsDecls.end())
1141 return std::nullopt;
1142 return I->getSecond();
1143 }
1144 std::optional<UsesAllocatorsDeclKind>
1145 isUsesAllocatorsDecl(const Decl *D) const {
1146 const SharingMapTy &StackElem = getTopOfStack();
1147 auto I = StackElem.UsesAllocatorsDecls.find(D);
1148 if (I == StackElem.UsesAllocatorsDecls.end())
1149 return std::nullopt;
1150 return I->getSecond();
1151 }
1152
1153 void addDeclareMapperVarRef(Expr *Ref) {
1154 SharingMapTy &StackElem = getTopOfStack();
1155 StackElem.DeclareMapperVar = Ref;
1156 }
1157 const Expr *getDeclareMapperVarRef() const {
1158 const SharingMapTy *Top = getTopOfStackOrNull();
1159 return Top ? Top->DeclareMapperVar : nullptr;
1160 }
1161
1162 /// Add a new iterator variable.
1163 void addIteratorVarDecl(VarDecl *VD) {
1164 SharingMapTy &StackElem = getTopOfStack();
1165 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1166 }
1167 /// Check if variable declaration is an iterator VarDecl.
1168 bool isIteratorVarDecl(const VarDecl *VD) const {
1169 const SharingMapTy *Top = getTopOfStackOrNull();
1170 if (!Top)
1171 return false;
1172
1173 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1174 }
1175 /// get captured field from ImplicitDefaultFirstprivateFDs
1176 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1177 const_iterator I = begin();
1178 const_iterator EndI = end();
1179 size_t StackLevel = getStackSize();
1180 for (; I != EndI; ++I) {
1181 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1182 break;
1183 StackLevel--;
1184 }
1185 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1186 if (I == EndI)
1187 return nullptr;
1188 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1189 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1190 return IFD.VD;
1191 return nullptr;
1192 }
1193 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1194 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1195 const_iterator I = begin();
1196 const_iterator EndI = end();
1197 for (; I != EndI; ++I)
1198 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1199 break;
1200 if (I == EndI)
1201 return false;
1202 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1203 if (IFD.VD == VD)
1204 return true;
1205 return false;
1206 }
1207 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1208 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1209 iterator I = begin();
1210 const_iterator EndI = end();
1211 size_t StackLevel = getStackSize();
1212 for (; I != EndI; ++I) {
1213 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1214 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1215 break;
1216 }
1217 StackLevel--;
1218 }
1219 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1220 }
1221};
1222
1223bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1224 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1225}
1226
1227bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1228 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1229 DKind == OMPD_unknown;
1230}
1231
1232} // namespace
1233
1234static const Expr *getExprAsWritten(const Expr *E) {
1235 if (const auto *FE = dyn_cast<FullExpr>(E))
1236 E = FE->getSubExpr();
1237
1238 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1239 E = MTE->getSubExpr();
1240
1241 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1242 E = Binder->getSubExpr();
1243
1244 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1245 E = ICE->getSubExprAsWritten();
1246 return E->IgnoreParens();
1247}
1248
1250 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1251}
1252
1253static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1254 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1255 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1256 D = ME->getMemberDecl();
1257 const auto *VD = dyn_cast<VarDecl>(D);
1258 const auto *FD = dyn_cast<FieldDecl>(D);
1259 if (VD != nullptr) {
1260 VD = VD->getCanonicalDecl();
1261 D = VD;
1262 } else {
1263 assert(FD);
1264 FD = FD->getCanonicalDecl();
1265 D = FD;
1266 }
1267 return D;
1268}
1269
1271 return const_cast<ValueDecl *>(
1272 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1273}
1274
1275DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1276 ValueDecl *D) const {
1277 D = getCanonicalDecl(D);
1278 auto *VD = dyn_cast<VarDecl>(D);
1279 const auto *FD = dyn_cast<FieldDecl>(D);
1280 DSAVarData DVar;
1281 if (Iter == end()) {
1282 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1283 // in a region but not in construct]
1284 // File-scope or namespace-scope variables referenced in called routines
1285 // in the region are shared unless they appear in a threadprivate
1286 // directive.
1287 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1288 DVar.CKind = OMPC_shared;
1289
1290 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1291 // in a region but not in construct]
1292 // Variables with static storage duration that are declared in called
1293 // routines in the region are shared.
1294 if (VD && VD->hasGlobalStorage())
1295 DVar.CKind = OMPC_shared;
1296
1297 // Non-static data members are shared by default.
1298 if (FD)
1299 DVar.CKind = OMPC_shared;
1300
1301 return DVar;
1302 }
1303
1304 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1305 // in a Construct, C/C++, predetermined, p.1]
1306 // Variables with automatic storage duration that are declared in a scope
1307 // inside the construct are private.
1308 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1309 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1310 DVar.CKind = OMPC_private;
1311 return DVar;
1312 }
1313
1314 DVar.DKind = Iter->Directive;
1315 // Explicitly specified attributes and local variables with predetermined
1316 // attributes.
1317 if (Iter->SharingMap.count(D)) {
1318 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1319 DVar.RefExpr = Data.RefExpr.getPointer();
1320 DVar.PrivateCopy = Data.PrivateCopy;
1321 DVar.CKind = Data.Attributes;
1322 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1323 DVar.Modifier = Data.Modifier;
1324 DVar.AppliedToPointee = Data.AppliedToPointee;
1325 return DVar;
1326 }
1327
1328 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1329 // in a Construct, C/C++, implicitly determined, p.1]
1330 // In a parallel or task construct, the data-sharing attributes of these
1331 // variables are determined by the default clause, if present.
1332 switch (Iter->DefaultAttr) {
1333 case DSA_shared:
1334 DVar.CKind = OMPC_shared;
1335 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1336 return DVar;
1337 case DSA_none:
1338 return DVar;
1339 case DSA_firstprivate:
1340 if (VD && VD->getStorageDuration() == SD_Static &&
1341 VD->getDeclContext()->isFileContext()) {
1342 DVar.CKind = OMPC_unknown;
1343 } else {
1344 DVar.CKind = OMPC_firstprivate;
1345 }
1346 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1347 return DVar;
1348 case DSA_private:
1349 // each variable with static storage duration that is declared
1350 // in a namespace or global scope and referenced in the construct,
1351 // and that does not have a predetermined data-sharing attribute
1352 if (VD && VD->getStorageDuration() == SD_Static &&
1353 VD->getDeclContext()->isFileContext()) {
1354 DVar.CKind = OMPC_unknown;
1355 } else {
1356 DVar.CKind = OMPC_private;
1357 }
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 return DVar;
1360 case DSA_unspecified:
1361 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1362 // in a Construct, implicitly determined, p.2]
1363 // In a parallel construct, if no default clause is present, these
1364 // variables are shared.
1365 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1366 if ((isOpenMPParallelDirective(DVar.DKind) &&
1367 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1368 isOpenMPTeamsDirective(DVar.DKind)) {
1369 DVar.CKind = OMPC_shared;
1370 return DVar;
1371 }
1372
1373 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1374 // in a Construct, implicitly determined, p.4]
1375 // In a task construct, if no default clause is present, a variable that in
1376 // the enclosing context is determined to be shared by all implicit tasks
1377 // bound to the current team is shared.
1378 if (isOpenMPTaskingDirective(DVar.DKind)) {
1379 DSAVarData DVarTemp;
1380 const_iterator I = Iter, E = end();
1381 do {
1382 ++I;
1383 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1384 // Referenced in a Construct, implicitly determined, p.6]
1385 // In a task construct, if no default clause is present, a variable
1386 // whose data-sharing attribute is not determined by the rules above is
1387 // firstprivate.
1388 DVarTemp = getDSA(I, D);
1389 if (DVarTemp.CKind != OMPC_shared) {
1390 DVar.RefExpr = nullptr;
1391 DVar.CKind = OMPC_firstprivate;
1392 return DVar;
1393 }
1394 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1395 DVar.CKind =
1396 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1397 return DVar;
1398 }
1399 }
1400 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1401 // in a Construct, implicitly determined, p.3]
1402 // For constructs other than task, if no default clause is present, these
1403 // variables inherit their data-sharing attributes from the enclosing
1404 // context.
1405 return getDSA(++Iter, D);
1406}
1407
1408const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1409 const Expr *NewDE) {
1410 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1411 D = getCanonicalDecl(D);
1412 SharingMapTy &StackElem = getTopOfStack();
1413 auto It = StackElem.AlignedMap.find(D);
1414 if (It == StackElem.AlignedMap.end()) {
1415 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1416 StackElem.AlignedMap[D] = NewDE;
1417 return nullptr;
1418 }
1419 assert(It->second && "Unexpected nullptr expr in the aligned map");
1420 return It->second;
1421}
1422
1423const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1424 const Expr *NewDE) {
1425 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1426 D = getCanonicalDecl(D);
1427 SharingMapTy &StackElem = getTopOfStack();
1428 auto It = StackElem.NontemporalMap.find(D);
1429 if (It == StackElem.NontemporalMap.end()) {
1430 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1431 StackElem.NontemporalMap[D] = NewDE;
1432 return nullptr;
1433 }
1434 assert(It->second && "Unexpected nullptr expr in the aligned map");
1435 return It->second;
1436}
1437
1438void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1439 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1440 D = getCanonicalDecl(D);
1441 SharingMapTy &StackElem = getTopOfStack();
1442 StackElem.LCVMap.try_emplace(
1443 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1444}
1445
1446const DSAStackTy::LCDeclInfo
1447DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1448 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1449 D = getCanonicalDecl(D);
1450 const SharingMapTy &StackElem = getTopOfStack();
1451 auto It = StackElem.LCVMap.find(D);
1452 if (It != StackElem.LCVMap.end())
1453 return It->second;
1454 return {0, nullptr};
1455}
1456
1457const DSAStackTy::LCDeclInfo
1458DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1459 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1460 D = getCanonicalDecl(D);
1461 for (unsigned I = Level + 1; I > 0; --I) {
1462 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1463 auto It = StackElem.LCVMap.find(D);
1464 if (It != StackElem.LCVMap.end())
1465 return It->second;
1466 }
1467 return {0, nullptr};
1468}
1469
1470const DSAStackTy::LCDeclInfo
1471DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1472 const SharingMapTy *Parent = getSecondOnStackOrNull();
1473 assert(Parent && "Data-sharing attributes stack is empty");
1474 D = getCanonicalDecl(D);
1475 auto It = Parent->LCVMap.find(D);
1476 if (It != Parent->LCVMap.end())
1477 return It->second;
1478 return {0, nullptr};
1479}
1480
1481const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1482 const SharingMapTy *Parent = getSecondOnStackOrNull();
1483 assert(Parent && "Data-sharing attributes stack is empty");
1484 if (Parent->LCVMap.size() < I)
1485 return nullptr;
1486 for (const auto &Pair : Parent->LCVMap)
1487 if (Pair.second.first == I)
1488 return Pair.first;
1489 return nullptr;
1490}
1491
1492void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1493 DeclRefExpr *PrivateCopy, unsigned Modifier,
1494 bool AppliedToPointee) {
1495 D = getCanonicalDecl(D);
1496 if (A == OMPC_threadprivate) {
1497 DSAInfo &Data = Threadprivates[D];
1498 Data.Attributes = A;
1499 Data.RefExpr.setPointer(E);
1500 Data.PrivateCopy = nullptr;
1501 Data.Modifier = Modifier;
1502 } else {
1503 DSAInfo &Data = getTopOfStack().SharingMap[D];
1504 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1505 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1506 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1507 (isLoopControlVariable(D).first && A == OMPC_private));
1508 Data.Modifier = Modifier;
1509 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1510 Data.RefExpr.setInt(/*IntVal=*/true);
1511 return;
1512 }
1513 const bool IsLastprivate =
1514 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1515 Data.Attributes = A;
1516 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1517 Data.PrivateCopy = PrivateCopy;
1518 Data.AppliedToPointee = AppliedToPointee;
1519 if (PrivateCopy) {
1520 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1521 Data.Modifier = Modifier;
1522 Data.Attributes = A;
1523 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1524 Data.PrivateCopy = nullptr;
1525 Data.AppliedToPointee = AppliedToPointee;
1526 }
1527 }
1528}
1529
1530/// Build a variable declaration for OpenMP loop iteration variable.
1532 StringRef Name, const AttrVec *Attrs = nullptr,
1533 DeclRefExpr *OrigRef = nullptr) {
1534 DeclContext *DC = SemaRef.CurContext;
1535 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1537 auto *Decl =
1538 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1539 if (Attrs) {
1540 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1541 I != E; ++I)
1542 Decl->addAttr(*I);
1543 }
1544 Decl->setImplicit();
1545 if (OrigRef) {
1546 Decl->addAttr(
1547 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1548 }
1549 return Decl;
1550}
1551
1554 bool RefersToCapture = false) {
1555 D->setReferenced();
1556 D->markUsed(S.Context);
1558 SourceLocation(), D, RefersToCapture, Loc, Ty,
1559 VK_LValue);
1560}
1561
1562void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1563 BinaryOperatorKind BOK) {
1564 D = getCanonicalDecl(D);
1565 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1566 assert(
1567 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1568 "Additional reduction info may be specified only for reduction items.");
1569 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1570 assert(ReductionData.ReductionRange.isInvalid() &&
1571 (getTopOfStack().Directive == OMPD_taskgroup ||
1572 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1573 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1574 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1575 "Additional reduction info may be specified only once for reduction "
1576 "items.");
1577 ReductionData.set(BOK, SR);
1578 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1579 if (!TaskgroupReductionRef) {
1580 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1581 SemaRef.Context.VoidPtrTy, ".task_red.");
1582 TaskgroupReductionRef =
1583 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1584 }
1585}
1586
1587void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1588 const Expr *ReductionRef) {
1589 D = getCanonicalDecl(D);
1590 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1591 assert(
1592 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1593 "Additional reduction info may be specified only for reduction items.");
1594 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1595 assert(ReductionData.ReductionRange.isInvalid() &&
1596 (getTopOfStack().Directive == OMPD_taskgroup ||
1597 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1598 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1599 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1600 "Additional reduction info may be specified only once for reduction "
1601 "items.");
1602 ReductionData.set(ReductionRef, SR);
1603 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1604 if (!TaskgroupReductionRef) {
1605 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1606 SemaRef.Context.VoidPtrTy, ".task_red.");
1607 TaskgroupReductionRef =
1608 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1609 }
1610}
1611
1612const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1613 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1614 Expr *&TaskgroupDescriptor) const {
1615 D = getCanonicalDecl(D);
1616 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1617 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1618 const DSAInfo &Data = I->SharingMap.lookup(D);
1619 if (Data.Attributes != OMPC_reduction ||
1620 Data.Modifier != OMPC_REDUCTION_task)
1621 continue;
1622 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1623 if (!ReductionData.ReductionOp ||
1624 ReductionData.ReductionOp.is<const Expr *>())
1625 return DSAVarData();
1626 SR = ReductionData.ReductionRange;
1627 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1628 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1629 "expression for the descriptor is not "
1630 "set.");
1631 TaskgroupDescriptor = I->TaskgroupReductionRef;
1632 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1633 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1634 /*AppliedToPointee=*/false);
1635 }
1636 return DSAVarData();
1637}
1638
1639const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1640 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1641 Expr *&TaskgroupDescriptor) const {
1642 D = getCanonicalDecl(D);
1643 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1644 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1645 const DSAInfo &Data = I->SharingMap.lookup(D);
1646 if (Data.Attributes != OMPC_reduction ||
1647 Data.Modifier != OMPC_REDUCTION_task)
1648 continue;
1649 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1650 if (!ReductionData.ReductionOp ||
1651 !ReductionData.ReductionOp.is<const Expr *>())
1652 return DSAVarData();
1653 SR = ReductionData.ReductionRange;
1654 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1655 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1656 "expression for the descriptor is not "
1657 "set.");
1658 TaskgroupDescriptor = I->TaskgroupReductionRef;
1659 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1660 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1661 /*AppliedToPointee=*/false);
1662 }
1663 return DSAVarData();
1664}
1665
1666bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1667 D = D->getCanonicalDecl();
1668 for (const_iterator E = end(); I != E; ++I) {
1669 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1670 isOpenMPTargetExecutionDirective(I->Directive)) {
1671 if (I->CurScope) {
1672 Scope *TopScope = I->CurScope->getParent();
1673 Scope *CurScope = getCurScope();
1674 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1675 CurScope = CurScope->getParent();
1676 return CurScope != TopScope;
1677 }
1678 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1679 if (I->Context == DC)
1680 return true;
1681 return false;
1682 }
1683 }
1684 return false;
1685}
1686
1688 bool AcceptIfMutable = true,
1689 bool *IsClassType = nullptr) {
1690 ASTContext &Context = SemaRef.getASTContext();
1691 Type = Type.getNonReferenceType().getCanonicalType();
1692 bool IsConstant = Type.isConstant(Context);
1693 Type = Context.getBaseElementType(Type);
1694 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1696 : nullptr;
1697 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1698 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1699 RD = CTD->getTemplatedDecl();
1700 if (IsClassType)
1701 *IsClassType = RD;
1702 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1703 RD->hasDefinition() && RD->hasMutableFields());
1704}
1705
1706static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1708 SourceLocation ELoc,
1709 bool AcceptIfMutable = true,
1710 bool ListItemNotVar = false) {
1711 ASTContext &Context = SemaRef.getASTContext();
1712 bool IsClassType;
1713 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1714 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1715 : IsClassType ? diag::err_omp_const_not_mutable_variable
1716 : diag::err_omp_const_variable;
1717 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1718 if (!ListItemNotVar && D) {
1719 const VarDecl *VD = dyn_cast<VarDecl>(D);
1720 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1722 SemaRef.Diag(D->getLocation(),
1723 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1724 << D;
1725 }
1726 return true;
1727 }
1728 return false;
1729}
1730
1731const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1732 bool FromParent) {
1733 D = getCanonicalDecl(D);
1734 DSAVarData DVar;
1735
1736 auto *VD = dyn_cast<VarDecl>(D);
1737 auto TI = Threadprivates.find(D);
1738 if (TI != Threadprivates.end()) {
1739 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1740 DVar.CKind = OMPC_threadprivate;
1741 DVar.Modifier = TI->getSecond().Modifier;
1742 return DVar;
1743 }
1744 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1745 DVar.RefExpr = buildDeclRefExpr(
1746 SemaRef, VD, D->getType().getNonReferenceType(),
1747 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1748 DVar.CKind = OMPC_threadprivate;
1749 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1750 return DVar;
1751 }
1752 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1753 // in a Construct, C/C++, predetermined, p.1]
1754 // Variables appearing in threadprivate directives are threadprivate.
1755 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1756 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1757 SemaRef.getLangOpts().OpenMPUseTLS &&
1758 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1759 (VD && VD->getStorageClass() == SC_Register &&
1760 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1761 DVar.RefExpr = buildDeclRefExpr(
1762 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1763 DVar.CKind = OMPC_threadprivate;
1764 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1765 return DVar;
1766 }
1767 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1768 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1769 !isLoopControlVariable(D).first) {
1770 const_iterator IterTarget =
1771 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1772 return isOpenMPTargetExecutionDirective(Data.Directive);
1773 });
1774 if (IterTarget != end()) {
1775 const_iterator ParentIterTarget = IterTarget + 1;
1776 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1777 if (isOpenMPLocal(VD, Iter)) {
1778 DVar.RefExpr =
1779 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1780 D->getLocation());
1781 DVar.CKind = OMPC_threadprivate;
1782 return DVar;
1783 }
1784 }
1785 if (!isClauseParsingMode() || IterTarget != begin()) {
1786 auto DSAIter = IterTarget->SharingMap.find(D);
1787 if (DSAIter != IterTarget->SharingMap.end() &&
1788 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1789 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1790 DVar.CKind = OMPC_threadprivate;
1791 return DVar;
1792 }
1793 const_iterator End = end();
1794 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1795 D, std::distance(ParentIterTarget, End),
1796 /*OpenMPCaptureLevel=*/0)) {
1797 DVar.RefExpr =
1798 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1799 IterTarget->ConstructLoc);
1800 DVar.CKind = OMPC_threadprivate;
1801 return DVar;
1802 }
1803 }
1804 }
1805 }
1806
1807 if (isStackEmpty())
1808 // Not in OpenMP execution region and top scope was already checked.
1809 return DVar;
1810
1811 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1812 // in a Construct, C/C++, predetermined, p.4]
1813 // Static data members are shared.
1814 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1815 // in a Construct, C/C++, predetermined, p.7]
1816 // Variables with static storage duration that are declared in a scope
1817 // inside the construct are shared.
1818 if (VD && VD->isStaticDataMember()) {
1819 // Check for explicitly specified attributes.
1820 const_iterator I = begin();
1821 const_iterator EndI = end();
1822 if (FromParent && I != EndI)
1823 ++I;
1824 if (I != EndI) {
1825 auto It = I->SharingMap.find(D);
1826 if (It != I->SharingMap.end()) {
1827 const DSAInfo &Data = It->getSecond();
1828 DVar.RefExpr = Data.RefExpr.getPointer();
1829 DVar.PrivateCopy = Data.PrivateCopy;
1830 DVar.CKind = Data.Attributes;
1831 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1832 DVar.DKind = I->Directive;
1833 DVar.Modifier = Data.Modifier;
1834 DVar.AppliedToPointee = Data.AppliedToPointee;
1835 return DVar;
1836 }
1837 }
1838
1839 DVar.CKind = OMPC_shared;
1840 return DVar;
1841 }
1842
1843 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1844 // The predetermined shared attribute for const-qualified types having no
1845 // mutable members was removed after OpenMP 3.1.
1846 if (SemaRef.LangOpts.OpenMP <= 31) {
1847 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1848 // in a Construct, C/C++, predetermined, p.6]
1849 // Variables with const qualified type having no mutable member are
1850 // shared.
1851 if (isConstNotMutableType(SemaRef, D->getType())) {
1852 // Variables with const-qualified type having no mutable member may be
1853 // listed in a firstprivate clause, even if they are static data members.
1854 DSAVarData DVarTemp = hasInnermostDSA(
1855 D,
1856 [](OpenMPClauseKind C, bool) {
1857 return C == OMPC_firstprivate || C == OMPC_shared;
1858 },
1859 MatchesAlways, FromParent);
1860 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1861 return DVarTemp;
1862
1863 DVar.CKind = OMPC_shared;
1864 return DVar;
1865 }
1866 }
1867
1868 // Explicitly specified attributes and local variables with predetermined
1869 // attributes.
1870 const_iterator I = begin();
1871 const_iterator EndI = end();
1872 if (FromParent && I != EndI)
1873 ++I;
1874 if (I == EndI)
1875 return DVar;
1876 auto It = I->SharingMap.find(D);
1877 if (It != I->SharingMap.end()) {
1878 const DSAInfo &Data = It->getSecond();
1879 DVar.RefExpr = Data.RefExpr.getPointer();
1880 DVar.PrivateCopy = Data.PrivateCopy;
1881 DVar.CKind = Data.Attributes;
1882 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1883 DVar.DKind = I->Directive;
1884 DVar.Modifier = Data.Modifier;
1885 DVar.AppliedToPointee = Data.AppliedToPointee;
1886 }
1887
1888 return DVar;
1889}
1890
1891const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1892 bool FromParent) const {
1893 if (isStackEmpty()) {
1894 const_iterator I;
1895 return getDSA(I, D);
1896 }
1897 D = getCanonicalDecl(D);
1898 const_iterator StartI = begin();
1899 const_iterator EndI = end();
1900 if (FromParent && StartI != EndI)
1901 ++StartI;
1902 return getDSA(StartI, D);
1903}
1904
1905const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1906 unsigned Level) const {
1907 if (getStackSize() <= Level)
1908 return DSAVarData();
1909 D = getCanonicalDecl(D);
1910 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1911 return getDSA(StartI, D);
1912}
1913
1914const DSAStackTy::DSAVarData
1915DSAStackTy::hasDSA(ValueDecl *D,
1916 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1917 DefaultDataSharingAttributes)>
1918 CPred,
1919 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1920 bool FromParent) const {
1921 if (isStackEmpty())
1922 return {};
1923 D = getCanonicalDecl(D);
1924 const_iterator I = begin();
1925 const_iterator EndI = end();
1926 if (FromParent && I != EndI)
1927 ++I;
1928 for (; I != EndI; ++I) {
1929 if (!DPred(I->Directive) &&
1930 !isImplicitOrExplicitTaskingRegion(I->Directive))
1931 continue;
1932 const_iterator NewI = I;
1933 DSAVarData DVar = getDSA(NewI, D);
1934 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1935 return DVar;
1936 }
1937 return {};
1938}
1939
1940const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1941 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1942 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1943 bool FromParent) const {
1944 if (isStackEmpty())
1945 return {};
1946 D = getCanonicalDecl(D);
1947 const_iterator StartI = begin();
1948 const_iterator EndI = end();
1949 if (FromParent && StartI != EndI)
1950 ++StartI;
1951 if (StartI == EndI || !DPred(StartI->Directive))
1952 return {};
1953 const_iterator NewI = StartI;
1954 DSAVarData DVar = getDSA(NewI, D);
1955 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1956 ? DVar
1957 : DSAVarData();
1958}
1959
1960bool DSAStackTy::hasExplicitDSA(
1961 const ValueDecl *D,
1962 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1963 unsigned Level, bool NotLastprivate) const {
1964 if (getStackSize() <= Level)
1965 return false;
1966 D = getCanonicalDecl(D);
1967 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1968 auto I = StackElem.SharingMap.find(D);
1969 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1970 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1971 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1972 return true;
1973 // Check predetermined rules for the loop control variables.
1974 auto LI = StackElem.LCVMap.find(D);
1975 if (LI != StackElem.LCVMap.end())
1976 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1977 return false;
1978}
1979
1980bool DSAStackTy::hasExplicitDirective(
1981 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1982 unsigned Level) const {
1983 if (getStackSize() <= Level)
1984 return false;
1985 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1986 return DPred(StackElem.Directive);
1987}
1988
1989bool DSAStackTy::hasDirective(
1990 const llvm::function_ref<bool(OpenMPDirectiveKind,
1992 DPred,
1993 bool FromParent) const {
1994 // We look only in the enclosing region.
1995 size_t Skip = FromParent ? 2 : 1;
1996 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1997 I != E; ++I) {
1998 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1999 return true;
2000 }
2001 return false;
2002}
2003
2004void SemaOpenMP::InitDataSharingAttributesStack() {
2005 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2006}
2007
2008#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2009
2010void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2011
2012void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2013 DSAStack->popFunction(OldFSI);
2014}
2015
2017 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2018 "Expected OpenMP device compilation.");
2020}
2021
2022namespace {
2023/// Status of the function emission on the host/device.
2024enum class FunctionEmissionStatus {
2025 Emitted,
2026 Discarded,
2027 Unknown,
2028};
2029} // anonymous namespace
2030
2033 const FunctionDecl *FD) {
2034 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2035 "Expected OpenMP device compilation.");
2036
2037 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2038 if (FD) {
2040 switch (FES) {
2042 Kind = SemaDiagnosticBuilder::K_Immediate;
2043 break;
2045 // TODO: We should always delay diagnostics here in case a target
2046 // region is in a function we do not emit. However, as the
2047 // current diagnostics are associated with the function containing
2048 // the target region and we do not emit that one, we would miss out
2049 // on diagnostics for the target region itself. We need to anchor
2050 // the diagnostics with the new generated function *or* ensure we
2051 // emit diagnostics associated with the surrounding function.
2053 ? SemaDiagnosticBuilder::K_Deferred
2054 : SemaDiagnosticBuilder::K_Immediate;
2055 break;
2058 Kind = SemaDiagnosticBuilder::K_Nop;
2059 break;
2061 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2062 break;
2063 }
2064 }
2065
2066 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2067}
2068
2071 const FunctionDecl *FD) {
2072 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2073 "Expected OpenMP host compilation.");
2074
2075 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2076 if (FD) {
2078 switch (FES) {
2080 Kind = SemaDiagnosticBuilder::K_Immediate;
2081 break;
2083 Kind = SemaDiagnosticBuilder::K_Deferred;
2084 break;
2088 Kind = SemaDiagnosticBuilder::K_Nop;
2089 break;
2090 }
2091 }
2092
2093 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2094}
2095
2098 if (LO.OpenMP <= 45) {
2100 return OMPC_DEFAULTMAP_scalar;
2101 return OMPC_DEFAULTMAP_aggregate;
2102 }
2104 return OMPC_DEFAULTMAP_pointer;
2106 return OMPC_DEFAULTMAP_scalar;
2107 return OMPC_DEFAULTMAP_aggregate;
2108}
2109
2111 unsigned OpenMPCaptureLevel) const {
2112 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2113
2114 ASTContext &Ctx = getASTContext();
2115 bool IsByRef = true;
2116
2117 // Find the directive that is associated with the provided scope.
2118 D = cast<ValueDecl>(D->getCanonicalDecl());
2119 QualType Ty = D->getType();
2120
2121 bool IsVariableUsedInMapClause = false;
2122 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2123 // This table summarizes how a given variable should be passed to the device
2124 // given its type and the clauses where it appears. This table is based on
2125 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2126 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2127 //
2128 // =========================================================================
2129 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2130 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2131 // =========================================================================
2132 // | scl | | | | - | | bycopy|
2133 // | scl | | - | x | - | - | bycopy|
2134 // | scl | | x | - | - | - | null |
2135 // | scl | x | | | - | | byref |
2136 // | scl | x | - | x | - | - | bycopy|
2137 // | scl | x | x | - | - | - | null |
2138 // | scl | | - | - | - | x | byref |
2139 // | scl | x | - | - | - | x | byref |
2140 //
2141 // | agg | n.a. | | | - | | byref |
2142 // | agg | n.a. | - | x | - | - | byref |
2143 // | agg | n.a. | x | - | - | - | null |
2144 // | agg | n.a. | - | - | - | x | byref |
2145 // | agg | n.a. | - | - | - | x[] | byref |
2146 //
2147 // | ptr | n.a. | | | - | | bycopy|
2148 // | ptr | n.a. | - | x | - | - | bycopy|
2149 // | ptr | n.a. | x | - | - | - | null |
2150 // | ptr | n.a. | - | - | - | x | byref |
2151 // | ptr | n.a. | - | - | - | x[] | bycopy|
2152 // | ptr | n.a. | - | - | x | | bycopy|
2153 // | ptr | n.a. | - | - | x | x | bycopy|
2154 // | ptr | n.a. | - | - | x | x[] | bycopy|
2155 // =========================================================================
2156 // Legend:
2157 // scl - scalar
2158 // ptr - pointer
2159 // agg - aggregate
2160 // x - applies
2161 // - - invalid in this combination
2162 // [] - mapped with an array section
2163 // byref - should be mapped by reference
2164 // byval - should be mapped by value
2165 // null - initialize a local variable to null on the device
2166 //
2167 // Observations:
2168 // - All scalar declarations that show up in a map clause have to be passed
2169 // by reference, because they may have been mapped in the enclosing data
2170 // environment.
2171 // - If the scalar value does not fit the size of uintptr, it has to be
2172 // passed by reference, regardless the result in the table above.
2173 // - For pointers mapped by value that have either an implicit map or an
2174 // array section, the runtime library may pass the NULL value to the
2175 // device instead of the value passed to it by the compiler.
2176
2177 if (Ty->isReferenceType())
2178 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2179
2180 // Locate map clauses and see if the variable being captured is referred to
2181 // in any of those clauses. Here we only care about variables, not fields,
2182 // because fields are part of aggregates.
2183 bool IsVariableAssociatedWithSection = false;
2184
2185 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2186 D, Level,
2187 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2189 MapExprComponents,
2190 OpenMPClauseKind WhereFoundClauseKind) {
2191 // Both map and has_device_addr clauses information influences how a
2192 // variable is captured. E.g. is_device_ptr does not require changing
2193 // the default behavior.
2194 if (WhereFoundClauseKind != OMPC_map &&
2195 WhereFoundClauseKind != OMPC_has_device_addr)
2196 return false;
2197
2198 auto EI = MapExprComponents.rbegin();
2199 auto EE = MapExprComponents.rend();
2200
2201 assert(EI != EE && "Invalid map expression!");
2202
2203 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2204 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2205
2206 ++EI;
2207 if (EI == EE)
2208 return false;
2209 auto Last = std::prev(EE);
2210 const auto *UO =
2211 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2212 if ((UO && UO->getOpcode() == UO_Deref) ||
2213 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2214 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2215 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2216 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2217 IsVariableAssociatedWithSection = true;
2218 // There is nothing more we need to know about this variable.
2219 return true;
2220 }
2221
2222 // Keep looking for more map info.
2223 return false;
2224 });
2225
2226 if (IsVariableUsedInMapClause) {
2227 // If variable is identified in a map clause it is always captured by
2228 // reference except if it is a pointer that is dereferenced somehow.
2229 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2230 } else {
2231 // By default, all the data that has a scalar type is mapped by copy
2232 // (except for reduction variables).
2233 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2234 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2235 !Ty->isAnyPointerType()) ||
2236 !Ty->isScalarType() ||
2237 DSAStack->isDefaultmapCapturedByRef(
2239 DSAStack->hasExplicitDSA(
2240 D,
2241 [](OpenMPClauseKind K, bool AppliedToPointee) {
2242 return K == OMPC_reduction && !AppliedToPointee;
2243 },
2244 Level);
2245 }
2246 }
2247
2248 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2249 IsByRef =
2250 ((IsVariableUsedInMapClause &&
2251 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2252 OMPD_target) ||
2253 !(DSAStack->hasExplicitDSA(
2254 D,
2255 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2256 return K == OMPC_firstprivate ||
2257 (K == OMPC_reduction && AppliedToPointee);
2258 },
2259 Level, /*NotLastprivate=*/true) ||
2260 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2261 // If the variable is artificial and must be captured by value - try to
2262 // capture by value.
2263 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2264 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2265 // If the variable is implicitly firstprivate and scalar - capture by
2266 // copy
2267 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2268 DSAStack->getDefaultDSA() == DSA_private) &&
2269 !DSAStack->hasExplicitDSA(
2270 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2271 Level) &&
2272 !DSAStack->isLoopControlVariable(D, Level).first);
2273 }
2274
2275 // When passing data by copy, we need to make sure it fits the uintptr size
2276 // and alignment, because the runtime library only deals with uintptr types.
2277 // If it does not fit the uintptr size, we need to pass the data by reference
2278 // instead.
2279 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2281 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2282 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2283 IsByRef = true;
2284 }
2285
2286 return IsByRef;
2287}
2288
2289unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2290 assert(getLangOpts().OpenMP);
2291 return DSAStack->getNestingLevel();
2292}
2293
2295 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2296 DSAStack->isUntiedRegion();
2297}
2298
2300 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2301 !DSAStack->isClauseParsingMode()) ||
2302 DSAStack->hasDirective(
2304 SourceLocation) -> bool {
2306 },
2307 false);
2308}
2309
2311 // Only rebuild for Field.
2312 if (!dyn_cast<FieldDecl>(D))
2313 return false;
2314 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2315 D,
2316 [](OpenMPClauseKind C, bool AppliedToPointee,
2317 DefaultDataSharingAttributes DefaultAttr) {
2318 return isOpenMPPrivate(C) && !AppliedToPointee &&
2319 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2320 },
2321 [](OpenMPDirectiveKind) { return true; },
2322 DSAStack->isClauseParsingMode());
2323 if (DVarPrivate.CKind != OMPC_unknown)
2324 return true;
2325 return false;
2326}
2327
2329 Expr *CaptureExpr, bool WithInit,
2330 DeclContext *CurContext,
2331 bool AsExpression);
2332
2334 unsigned StopAt) {
2335 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2336 D = getCanonicalDecl(D);
2337
2338 auto *VD = dyn_cast<VarDecl>(D);
2339 // Do not capture constexpr variables.
2340 if (VD && VD->isConstexpr())
2341 return nullptr;
2342
2343 // If we want to determine whether the variable should be captured from the
2344 // perspective of the current capturing scope, and we've already left all the
2345 // capturing scopes of the top directive on the stack, check from the
2346 // perspective of its parent directive (if any) instead.
2347 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2348 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2349
2350 // If we are attempting to capture a global variable in a directive with
2351 // 'target' we return true so that this global is also mapped to the device.
2352 //
2353 if (VD && !VD->hasLocalStorage() &&
2355 SemaRef.getCurLambda())) {
2357 DSAStackTy::DSAVarData DVarTop =
2358 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2359 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2360 return VD;
2361 // If the declaration is enclosed in a 'declare target' directive,
2362 // then it should not be captured.
2363 //
2364 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2365 return nullptr;
2366 CapturedRegionScopeInfo *CSI = nullptr;
2367 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2368 llvm::reverse(SemaRef.FunctionScopes),
2369 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2370 : 0)) {
2371 if (!isa<CapturingScopeInfo>(FSI))
2372 return nullptr;
2373 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2374 if (RSI->CapRegionKind == CR_OpenMP) {
2375 CSI = RSI;
2376 break;
2377 }
2378 }
2379 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2382 DSAStack->getDirective(CSI->OpenMPLevel));
2383 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2384 return VD;
2385 }
2387 // Try to mark variable as declare target if it is used in capturing
2388 // regions.
2389 if (getLangOpts().OpenMP <= 45 &&
2390 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2392 return nullptr;
2393 }
2394 }
2395
2396 if (CheckScopeInfo) {
2397 bool OpenMPFound = false;
2398 for (unsigned I = StopAt + 1; I > 0; --I) {
2400 if (!isa<CapturingScopeInfo>(FSI))
2401 return nullptr;
2402 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2403 if (RSI->CapRegionKind == CR_OpenMP) {
2404 OpenMPFound = true;
2405 break;
2406 }
2407 }
2408 if (!OpenMPFound)
2409 return nullptr;
2410 }
2411
2412 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2413 (!DSAStack->isClauseParsingMode() ||
2414 DSAStack->getParentDirective() != OMPD_unknown)) {
2415 auto &&Info = DSAStack->isLoopControlVariable(D);
2416 if (Info.first ||
2417 (VD && VD->hasLocalStorage() &&
2418 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2419 (VD && DSAStack->isForceVarCapturing()))
2420 return VD ? VD : Info.second;
2421 DSAStackTy::DSAVarData DVarTop =
2422 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2423 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2424 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2425 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2426 // Threadprivate variables must not be captured.
2427 if (isOpenMPThreadPrivate(DVarTop.CKind))
2428 return nullptr;
2429 // The variable is not private or it is the variable in the directive with
2430 // default(none) clause and not used in any clause.
2431 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2432 D,
2433 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2434 return isOpenMPPrivate(C) && !AppliedToPointee;
2435 },
2436 [](OpenMPDirectiveKind) { return true; },
2437 DSAStack->isClauseParsingMode());
2438 // Global shared must not be captured.
2439 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2440 ((DSAStack->getDefaultDSA() != DSA_none &&
2441 DSAStack->getDefaultDSA() != DSA_private &&
2442 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2443 DVarTop.CKind == OMPC_shared))
2444 return nullptr;
2445 auto *FD = dyn_cast<FieldDecl>(D);
2446 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2447 !DVarPrivate.PrivateCopy) {
2448 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2449 D,
2450 [](OpenMPClauseKind C, bool AppliedToPointee,
2451 DefaultDataSharingAttributes DefaultAttr) {
2452 return isOpenMPPrivate(C) && !AppliedToPointee &&
2453 (DefaultAttr == DSA_firstprivate ||
2454 DefaultAttr == DSA_private);
2455 },
2456 [](OpenMPDirectiveKind) { return true; },
2457 DSAStack->isClauseParsingMode());
2458 if (DVarPrivate.CKind == OMPC_unknown)
2459 return nullptr;
2460
2461 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2462 if (VD)
2463 return VD;
2465 return nullptr;
2468 /*IsImplicit=*/true);
2469 const CXXScopeSpec CS = CXXScopeSpec();
2471 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2474 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2477 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2478 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2479 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2481 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2482 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2483 return VD;
2484 }
2485 if (DVarPrivate.CKind != OMPC_unknown ||
2486 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2487 DSAStack->getDefaultDSA() == DSA_private ||
2488 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2489 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2490 }
2491 return nullptr;
2492}
2493
2494void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2495 unsigned Level) const {
2496 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2497}
2498
2500 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2501 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2502 DSAStack->loopInit();
2503}
2504
2506 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2507 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2508 DSAStack->resetPossibleLoopCounter();
2509 DSAStack->loopStart();
2510 }
2511}
2512
2514 unsigned CapLevel) const {
2515 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2516 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2517 (!DSAStack->isClauseParsingMode() ||
2518 DSAStack->getParentDirective() != OMPD_unknown)) {
2519 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2520 D,
2521 [](OpenMPClauseKind C, bool AppliedToPointee,
2522 DefaultDataSharingAttributes DefaultAttr) {
2523 return isOpenMPPrivate(C) && !AppliedToPointee &&
2524 DefaultAttr == DSA_private;
2525 },
2526 [](OpenMPDirectiveKind) { return true; },
2527 DSAStack->isClauseParsingMode());
2528 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2529 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2530 !DSAStack->isLoopControlVariable(D).first)
2531 return OMPC_private;
2532 }
2533 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2534 bool IsTriviallyCopyable =
2535 D->getType().getNonReferenceType().isTriviallyCopyableType(
2536 getASTContext()) &&
2537 !D->getType()
2538 .getNonReferenceType()
2539 .getCanonicalType()
2540 ->getAsCXXRecordDecl();
2541 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2543 getOpenMPCaptureRegions(CaptureRegions, DKind);
2544 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2545 (IsTriviallyCopyable ||
2546 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2547 if (DSAStack->hasExplicitDSA(
2548 D,
2549 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2550 Level, /*NotLastprivate=*/true))
2551 return OMPC_firstprivate;
2552 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2553 if (DVar.CKind != OMPC_shared &&
2554 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2555 DSAStack->addImplicitTaskFirstprivate(Level, D);
2556 return OMPC_firstprivate;
2557 }
2558 }
2559 }
2560 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2561 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2562 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2563 DSAStack->resetPossibleLoopCounter(D);
2564 DSAStack->loopStart();
2565 return OMPC_private;
2566 }
2567 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2568 DSAStack->isLoopControlVariable(D).first) &&
2569 !DSAStack->hasExplicitDSA(
2570 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2571 Level) &&
2572 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2573 return OMPC_private;
2574 }
2575 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2576 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2577 DSAStack->isForceVarCapturing() &&
2578 !DSAStack->hasExplicitDSA(
2579 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2580 Level))
2581 return OMPC_private;
2582 }
2583 // User-defined allocators are private since they must be defined in the
2584 // context of target region.
2585 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2586 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2587 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2588 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2589 return OMPC_private;
2590 return (DSAStack->hasExplicitDSA(
2591 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2592 Level) ||
2593 (DSAStack->isClauseParsingMode() &&
2594 DSAStack->getClauseParsingMode() == OMPC_private) ||
2595 // Consider taskgroup reduction descriptor variable a private
2596 // to avoid possible capture in the region.
2597 (DSAStack->hasExplicitDirective(
2598 [](OpenMPDirectiveKind K) {
2599 return K == OMPD_taskgroup ||
2600 ((isOpenMPParallelDirective(K) ||
2601 isOpenMPWorksharingDirective(K)) &&
2602 !isOpenMPSimdDirective(K));
2603 },
2604 Level) &&
2605 DSAStack->isTaskgroupReductionRef(D, Level)))
2606 ? OMPC_private
2607 : OMPC_unknown;
2608}
2609
2611 unsigned Level) {
2612 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2613 D = getCanonicalDecl(D);
2614 OpenMPClauseKind OMPC = OMPC_unknown;
2615 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2616 const unsigned NewLevel = I - 1;
2617 if (DSAStack->hasExplicitDSA(
2618 D,
2619 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2620 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2621 OMPC = K;
2622 return true;
2623 }
2624 return false;
2625 },
2626 NewLevel))
2627 break;
2628 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2629 D, NewLevel,
2631 OpenMPClauseKind) { return true; })) {
2632 OMPC = OMPC_map;
2633 break;
2634 }
2635 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2636 NewLevel)) {
2637 OMPC = OMPC_map;
2638 if (DSAStack->mustBeFirstprivateAtLevel(
2640 OMPC = OMPC_firstprivate;
2641 break;
2642 }
2643 }
2644 if (OMPC != OMPC_unknown)
2645 FD->addAttr(
2646 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2647}
2648
2650 unsigned CaptureLevel) const {
2651 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2652 // Return true if the current level is no longer enclosed in a target region.
2653
2655 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2656 const auto *VD = dyn_cast<VarDecl>(D);
2657 return VD && !VD->hasLocalStorage() &&
2658 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2659 Level) &&
2660 Regions[CaptureLevel] != OMPD_task;
2661}
2662
2664 unsigned CaptureLevel) const {
2665 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2666 // Return true if the current level is no longer enclosed in a target region.
2667
2668 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2669 if (!VD->hasLocalStorage()) {
2671 return true;
2672 DSAStackTy::DSAVarData TopDVar =
2673 DSAStack->getTopDSA(D, /*FromParent=*/false);
2674 unsigned NumLevels =
2675 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2676 if (Level == 0)
2677 // non-file scope static variable with default(firstprivate)
2678 // should be global captured.
2679 return (NumLevels == CaptureLevel + 1 &&
2680 (TopDVar.CKind != OMPC_shared ||
2681 DSAStack->getDefaultDSA() == DSA_firstprivate));
2682 do {
2683 --Level;
2684 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2685 if (DVar.CKind != OMPC_shared)
2686 return true;
2687 } while (Level > 0);
2688 }
2689 }
2690 return true;
2691}
2692
2693void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2694
2696 OMPTraitInfo &TI) {
2697 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2698}
2699
2702 "Not in OpenMP declare variant scope!");
2703
2704 OMPDeclareVariantScopes.pop_back();
2705}
2706
2708 const FunctionDecl *Callee,
2710 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2711 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2712 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2713 // Ignore host functions during device analysis.
2714 if (getLangOpts().OpenMPIsTargetDevice &&
2715 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2716 return;
2717 // Ignore nohost functions during host analysis.
2718 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2719 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2720 return;
2721 const FunctionDecl *FD = Callee->getMostRecentDecl();
2722 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2723 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2724 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2725 // Diagnose host function called during device codegen.
2726 StringRef HostDevTy =
2727 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2728 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2729 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2730 diag::note_omp_marked_device_type_here)
2731 << HostDevTy;
2732 return;
2733 }
2734 if (!getLangOpts().OpenMPIsTargetDevice &&
2735 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2736 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2737 // In OpenMP 5.2 or later, if the function has a host variant then allow
2738 // that to be called instead
2739 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2740 for (OMPDeclareVariantAttr *A :
2741 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2742 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2743 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2744 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2745 OMPDeclareTargetDeclAttr::getDeviceType(
2746 VariantFD->getMostRecentDecl());
2747 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2748 return true;
2749 }
2750 return false;
2751 };
2752 if (getLangOpts().OpenMP >= 52 &&
2753 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2754 return;
2755 // Diagnose nohost function called during host codegen.
2756 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2757 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2758 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2759 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2760 diag::note_omp_marked_device_type_here)
2761 << NoHostDevTy;
2762 }
2763}
2764
2766 const DeclarationNameInfo &DirName,
2767 Scope *CurScope, SourceLocation Loc) {
2768 DSAStack->push(DKind, DirName, CurScope, Loc);
2771}
2772
2774 DSAStack->setClauseParsingMode(K);
2775}
2776
2778 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2780}
2781
2782static std::pair<ValueDecl *, bool>
2783getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2784 SourceRange &ERange, bool AllowArraySection = false,
2785 StringRef DiagType = "");
2786
2787/// Check consistency of the reduction clauses.
2788static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2789 ArrayRef<OMPClause *> Clauses) {
2790 bool InscanFound = false;
2791 SourceLocation InscanLoc;
2792 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2793 // A reduction clause without the inscan reduction-modifier may not appear on
2794 // a construct on which a reduction clause with the inscan reduction-modifier
2795 // appears.
2796 for (OMPClause *C : Clauses) {
2797 if (C->getClauseKind() != OMPC_reduction)
2798 continue;
2799 auto *RC = cast<OMPReductionClause>(C);
2800 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2801 InscanFound = true;
2802 InscanLoc = RC->getModifierLoc();
2803 continue;
2804 }
2805 if (RC->getModifier() == OMPC_REDUCTION_task) {
2806 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2807 // A reduction clause with the task reduction-modifier may only appear on
2808 // a parallel construct, a worksharing construct or a combined or
2809 // composite construct for which any of the aforementioned constructs is a
2810 // constituent construct and simd or loop are not constituent constructs.
2811 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2812 if (!(isOpenMPParallelDirective(CurDir) ||
2814 isOpenMPSimdDirective(CurDir))
2815 S.Diag(RC->getModifierLoc(),
2816 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2817 continue;
2818 }
2819 }
2820 if (InscanFound) {
2821 for (OMPClause *C : Clauses) {
2822 if (C->getClauseKind() != OMPC_reduction)
2823 continue;
2824 auto *RC = cast<OMPReductionClause>(C);
2825 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2826 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2827 ? RC->getBeginLoc()
2828 : RC->getModifierLoc(),
2829 diag::err_omp_inscan_reduction_expected);
2830 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2831 continue;
2832 }
2833 for (Expr *Ref : RC->varlists()) {
2834 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2835 SourceLocation ELoc;
2836 SourceRange ERange;
2837 Expr *SimpleRefExpr = Ref;
2838 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2839 /*AllowArraySection=*/true);
2840 ValueDecl *D = Res.first;
2841 if (!D)
2842 continue;
2843 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2844 S.Diag(Ref->getExprLoc(),
2845 diag::err_omp_reduction_not_inclusive_exclusive)
2846 << Ref->getSourceRange();
2847 }
2848 }
2849 }
2850 }
2851}
2852
2853static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2854 ArrayRef<OMPClause *> Clauses);
2855static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2856 bool WithInit);
2857
2858static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2859 const ValueDecl *D,
2860 const DSAStackTy::DSAVarData &DVar,
2861 bool IsLoopIterVar = false);
2862
2864 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2865 // A variable of class type (or array thereof) that appears in a lastprivate
2866 // clause requires an accessible, unambiguous default constructor for the
2867 // class type, unless the list item is also specified in a firstprivate
2868 // clause.
2869 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2870 for (OMPClause *C : D->clauses()) {
2871 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2872 SmallVector<Expr *, 8> PrivateCopies;
2873 for (Expr *DE : Clause->varlists()) {
2874 if (DE->isValueDependent() || DE->isTypeDependent()) {
2875 PrivateCopies.push_back(nullptr);
2876 continue;
2877 }
2878 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2879 auto *VD = cast<VarDecl>(DRE->getDecl());
2881 const DSAStackTy::DSAVarData DVar =
2882 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2883 if (DVar.CKind == OMPC_lastprivate) {
2884 // Generate helper private variable and initialize it with the
2885 // default value. The address of the original variable is replaced
2886 // by the address of the new private variable in CodeGen. This new
2887 // variable is not added to IdResolver, so the code in the OpenMP
2888 // region uses original variable for proper diagnostics.
2889 VarDecl *VDPrivate = buildVarDecl(
2890 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(),
2891 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2893 if (VDPrivate->isInvalidDecl()) {
2894 PrivateCopies.push_back(nullptr);
2895 continue;
2896 }
2897 PrivateCopies.push_back(buildDeclRefExpr(
2898 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2899 } else {
2900 // The variable is also a firstprivate, so initialization sequence
2901 // for private copy is generated already.
2902 PrivateCopies.push_back(nullptr);
2903 }
2904 }
2905 Clause->setPrivateCopies(PrivateCopies);
2906 continue;
2907 }
2908 // Finalize nontemporal clause by handling private copies, if any.
2909 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2910 SmallVector<Expr *, 8> PrivateRefs;
2911 for (Expr *RefExpr : Clause->varlists()) {
2912 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2913 SourceLocation ELoc;
2914 SourceRange ERange;
2915 Expr *SimpleRefExpr = RefExpr;
2916 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2917 if (Res.second)
2918 // It will be analyzed later.
2919 PrivateRefs.push_back(RefExpr);
2920 ValueDecl *D = Res.first;
2921 if (!D)
2922 continue;
2923
2924 const DSAStackTy::DSAVarData DVar =
2925 DSAStack->getTopDSA(D, /*FromParent=*/false);
2926 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2927 : SimpleRefExpr);
2928 }
2929 Clause->setPrivateRefs(PrivateRefs);
2930 continue;
2931 }
2932 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2933 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2934 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2935 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2936 if (!DRE)
2937 continue;
2938 ValueDecl *VD = DRE->getDecl();
2939 if (!VD || !isa<VarDecl>(VD))
2940 continue;
2941 DSAStackTy::DSAVarData DVar =
2942 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2943 // OpenMP [2.12.5, target Construct]
2944 // Memory allocators that appear in a uses_allocators clause cannot
2945 // appear in other data-sharing attribute clauses or data-mapping
2946 // attribute clauses in the same construct.
2947 Expr *MapExpr = nullptr;
2948 if (DVar.RefExpr ||
2949 DSAStack->checkMappableExprComponentListsForDecl(
2950 VD, /*CurrentRegionOnly=*/true,
2951 [VD, &MapExpr](
2953 MapExprComponents,
2955 auto MI = MapExprComponents.rbegin();
2956 auto ME = MapExprComponents.rend();
2957 if (MI != ME &&
2958 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2959 VD->getCanonicalDecl()) {
2960 MapExpr = MI->getAssociatedExpression();
2961 return true;
2962 }
2963 return false;
2964 })) {
2965 Diag(D.Allocator->getExprLoc(),
2966 diag::err_omp_allocator_used_in_clauses)
2967 << D.Allocator->getSourceRange();
2968 if (DVar.RefExpr)
2970 else
2971 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2972 << MapExpr->getSourceRange();
2973 }
2974 }
2975 continue;
2976 }
2977 }
2978 // Check allocate clauses.
2980 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
2982 }
2983
2984 DSAStack->pop();
2987}
2988
2990 Expr *NumIterations, Sema &SemaRef,
2991 Scope *S, DSAStackTy *Stack);
2992
2993static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
2995 DSAStackTy *Stack) {
2996 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
2997 "loop exprs were not built");
2998
2999 if (SemaRef.CurContext->isDependentContext())
3000 return false;
3001
3002 // Finalize the clauses that need pre-built expressions for CodeGen.
3003 for (OMPClause *C : Clauses) {
3004 auto *LC = dyn_cast<OMPLinearClause>(C);
3005 if (!LC)
3006 continue;
3007 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3008 B.NumIterations, SemaRef,
3009 SemaRef.getCurScope(), Stack))
3010 return true;
3011 }
3012
3013 return false;
3014}
3015
3016namespace {
3017
3018class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3019private:
3020 Sema &SemaRef;
3021
3022public:
3023 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3024 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3025 NamedDecl *ND = Candidate.getCorrectionDecl();
3026 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3027 return VD->hasGlobalStorage() &&
3028 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3029 SemaRef.getCurScope());
3030 }
3031 return false;
3032 }
3033
3034 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3035 return std::make_unique<VarDeclFilterCCC>(*this);
3036 }
3037};
3038
3039class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3040private:
3041 Sema &SemaRef;
3042
3043public:
3044 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3045 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3046 NamedDecl *ND = Candidate.getCorrectionDecl();
3047 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3048 isa<FunctionDecl>(ND))) {
3049 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3050 SemaRef.getCurScope());
3051 }
3052 return false;
3053 }
3054
3055 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3056 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3057 }
3058};
3059
3060} // namespace
3061
3063 CXXScopeSpec &ScopeSpec,
3064 const DeclarationNameInfo &Id,
3065 OpenMPDirectiveKind Kind) {
3066 ASTContext &Context = getASTContext();
3068 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3069 /*ObjectType=*/QualType(),
3070 /*AllowBuiltinCreation=*/true);
3071
3072 if (Lookup.isAmbiguous())
3073 return ExprError();
3074
3075 VarDecl *VD;
3076 if (!Lookup.isSingleResult()) {
3077 VarDeclFilterCCC CCC(SemaRef);
3078 if (TypoCorrection Corrected =
3079 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3081 SemaRef.diagnoseTypo(Corrected,
3082 PDiag(Lookup.empty()
3083 ? diag::err_undeclared_var_use_suggest
3084 : diag::err_omp_expected_var_arg_suggest)
3085 << Id.getName());
3086 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3087 } else {
3088 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3089 : diag::err_omp_expected_var_arg)
3090 << Id.getName();
3091 return ExprError();
3092 }
3093 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3094 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3095 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3096 return ExprError();
3097 }
3098 Lookup.suppressDiagnostics();
3099
3100 // OpenMP [2.9.2, Syntax, C/C++]
3101 // Variables must be file-scope, namespace-scope, or static block-scope.
3102 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3103 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3104 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3105 bool IsDecl =
3107 Diag(VD->getLocation(),
3108 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3109 << VD;
3110 return ExprError();
3111 }
3112
3113 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3114 NamedDecl *ND = CanonicalVD;
3115 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3116 // A threadprivate directive for file-scope variables must appear outside
3117 // any definition or declaration.
3118 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3120 Diag(Id.getLoc(), diag::err_omp_var_scope)
3121 << getOpenMPDirectiveName(Kind) << VD;
3122 bool IsDecl =
3124 Diag(VD->getLocation(),
3125 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3126 << VD;
3127 return ExprError();
3128 }
3129 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3130 // A threadprivate directive for static class member variables must appear
3131 // in the class definition, in the same scope in which the member
3132 // variables are declared.
3133 if (CanonicalVD->isStaticDataMember() &&
3134 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3135 Diag(Id.getLoc(), diag::err_omp_var_scope)
3136 << getOpenMPDirectiveName(Kind) << VD;
3137 bool IsDecl =
3139 Diag(VD->getLocation(),
3140 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3141 << VD;
3142 return ExprError();
3143 }
3144 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3145 // A threadprivate directive for namespace-scope variables must appear
3146 // outside any definition or declaration other than the namespace
3147 // definition itself.
3148 if (CanonicalVD->getDeclContext()->isNamespace() &&
3151 CanonicalVD->getDeclContext()))) {
3152 Diag(Id.getLoc(), diag::err_omp_var_scope)
3153 << getOpenMPDirectiveName(Kind) << VD;
3154 bool IsDecl =
3156 Diag(VD->getLocation(),
3157 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3158 << VD;
3159 return ExprError();
3160 }
3161 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3162 // A threadprivate directive for static block-scope variables must appear
3163 // in the scope of the variable and not in a nested scope.
3164 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3166 Diag(Id.getLoc(), diag::err_omp_var_scope)
3167 << getOpenMPDirectiveName(Kind) << VD;
3168 bool IsDecl =
3170 Diag(VD->getLocation(),
3171 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3172 << VD;
3173 return ExprError();
3174 }
3175
3176 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3177 // A threadprivate directive must lexically precede all references to any
3178 // of the variables in its list.
3179 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3180 !DSAStack->isThreadPrivate(VD)) {
3181 Diag(Id.getLoc(), diag::err_omp_var_used)
3182 << getOpenMPDirectiveName(Kind) << VD;
3183 return ExprError();
3184 }
3185
3186 QualType ExprType = VD->getType().getNonReferenceType();
3188 SourceLocation(), VD,
3189 /*RefersToEnclosingVariableOrCapture=*/false,
3190 Id.getLoc(), ExprType, VK_LValue);
3191}
3192
3195 ArrayRef<Expr *> VarList) {
3199 }
3200 return nullptr;
3201}
3202
3203namespace {
3204class LocalVarRefChecker final
3205 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3206 Sema &SemaRef;
3207
3208public:
3209 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3210 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3211 if (VD->hasLocalStorage()) {
3212 SemaRef.Diag(E->getBeginLoc(),
3213 diag::err_omp_local_var_in_threadprivate_init)
3214 << E->getSourceRange();
3215 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3216 << VD << VD->getSourceRange();
3217 return true;
3218 }
3219 }
3220 return false;
3221 }
3222 bool VisitStmt(const Stmt *S) {
3223 for (const Stmt *Child : S->children()) {
3224 if (Child && Visit(Child))
3225 return true;
3226 }
3227 return false;
3228 }
3229 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3230};
3231} // namespace
3232
3235 ArrayRef<Expr *> VarList) {
3236 ASTContext &Context = getASTContext();
3238 for (Expr *RefExpr : VarList) {
3239 auto *DE = cast<DeclRefExpr>(RefExpr);
3240 auto *VD = cast<VarDecl>(DE->getDecl());
3241 SourceLocation ILoc = DE->getExprLoc();
3242
3243 // Mark variable as used.
3244 VD->setReferenced();
3245 VD->markUsed(Context);
3246
3247 QualType QType = VD->getType();
3248 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3249 // It will be analyzed later.
3250 Vars.push_back(DE);
3251 continue;
3252 }
3253
3254 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3255 // A threadprivate variable must not have an incomplete type.
3257 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3258 continue;
3259 }
3260
3261 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3262 // A threadprivate variable must not have a reference type.
3263 if (VD->getType()->isReferenceType()) {
3264 Diag(ILoc, diag::err_omp_ref_type_arg)
3265 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3266 bool IsDecl =
3268 Diag(VD->getLocation(),
3269 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3270 << VD;
3271 continue;
3272 }
3273
3274 // Check if this is a TLS variable. If TLS is not being supported, produce
3275 // the corresponding diagnostic.
3276 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3277 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3278 getLangOpts().OpenMPUseTLS &&
3279 getASTContext().getTargetInfo().isTLSSupported())) ||
3280 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3281 !VD->isLocalVarDecl())) {
3282 Diag(ILoc, diag::err_omp_var_thread_local)
3283 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3284 bool IsDecl =
3286 Diag(VD->getLocation(),
3287 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3288 << VD;
3289 continue;
3290 }
3291
3292 // Check if initial value of threadprivate variable reference variable with
3293 // local storage (it is not supported by runtime).
3294 if (const Expr *Init = VD->getAnyInitializer()) {
3295 LocalVarRefChecker Checker(SemaRef);
3296 if (Checker.Visit(Init))
3297 continue;
3298 }
3299
3300 Vars.push_back(RefExpr);
3301 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3302 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3303 Context, SourceRange(Loc, Loc)));
3304 if (ASTMutationListener *ML = Context.getASTMutationListener())
3305 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3306 }
3307 OMPThreadPrivateDecl *D = nullptr;
3308 if (!Vars.empty()) {
3310 Loc, Vars);
3312 }
3313 return D;
3314}
3315
3316static OMPAllocateDeclAttr::AllocatorTypeTy
3317getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3318 if (!Allocator)
3319 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3320 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3321 Allocator->isInstantiationDependent() ||
3322 Allocator->containsUnexpandedParameterPack())
3323 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3324 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3325 llvm::FoldingSetNodeID AEId;
3326 const Expr *AE = Allocator->IgnoreParenImpCasts();
3327 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3328 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3329 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3330 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3331 llvm::FoldingSetNodeID DAEId;
3332 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3333 /*Canonical=*/true);
3334 if (AEId == DAEId) {
3335 AllocatorKindRes = AllocatorKind;
3336 break;
3337 }
3338 }
3339 return AllocatorKindRes;
3340}
3341
3343 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3344 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3345 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3346 return false;
3347 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3348 Expr *PrevAllocator = A->getAllocator();
3349 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3350 getAllocatorKind(S, Stack, PrevAllocator);
3351 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3352 if (AllocatorsMatch &&
3353 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3354 Allocator && PrevAllocator) {
3355 const Expr *AE = Allocator->IgnoreParenImpCasts();
3356 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3357 llvm::FoldingSetNodeID AEId, PAEId;
3358 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3359 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3360 AllocatorsMatch = AEId == PAEId;
3361 }
3362 if (!AllocatorsMatch) {
3363 SmallString<256> AllocatorBuffer;
3364 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3365 if (Allocator)
3366 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3367 SmallString<256> PrevAllocatorBuffer;
3368 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3369 if (PrevAllocator)
3370 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3371 S.getPrintingPolicy());
3372
3373 SourceLocation AllocatorLoc =
3374 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3375 SourceRange AllocatorRange =
3376 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3377 SourceLocation PrevAllocatorLoc =
3378 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3379 SourceRange PrevAllocatorRange =
3380 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3381 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3382 << (Allocator ? 1 : 0) << AllocatorStream.str()
3383 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3384 << AllocatorRange;
3385 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3386 << PrevAllocatorRange;
3387 return true;
3388 }
3389 return false;
3390}
3391
3392static void
3394 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3395 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3396 if (VD->hasAttr<OMPAllocateDeclAttr>())
3397 return;
3398 if (Alignment &&
3399 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3400 Alignment->isInstantiationDependent() ||
3401 Alignment->containsUnexpandedParameterPack()))
3402 // Apply later when we have a usable value.
3403 return;
3404 if (Allocator &&
3405 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3406 Allocator->isInstantiationDependent() ||
3407 Allocator->containsUnexpandedParameterPack()))
3408 return;
3409 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3410 Allocator, Alignment, SR);
3411 VD->addAttr(A);
3413 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3414}
3415
3418 DeclContext *Owner) {
3419 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3420 Expr *Alignment = nullptr;
3421 Expr *Allocator = nullptr;
3422 if (Clauses.empty()) {
3423 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3424 // allocate directives that appear in a target region must specify an
3425 // allocator clause unless a requires directive with the dynamic_allocators
3426 // clause is present in the same compilation unit.
3427 if (getLangOpts().OpenMPIsTargetDevice &&
3428 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3429 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3430 } else {
3431 for (const OMPClause *C : Clauses)
3432 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3433 Allocator = AC->getAllocator();
3434 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3435 Alignment = AC->getAlignment();
3436 else
3437 llvm_unreachable("Unexpected clause on allocate directive");
3438 }
3439 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3440 getAllocatorKind(SemaRef, DSAStack, Allocator);
3442 for (Expr *RefExpr : VarList) {
3443 auto *DE = cast<DeclRefExpr>(RefExpr);
3444 auto *VD = cast<VarDecl>(DE->getDecl());
3445
3446 // Check if this is a TLS variable or global register.
3447 if (VD->getTLSKind() != VarDecl::TLS_None ||
3448 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3449 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3450 !VD->isLocalVarDecl()))
3451 continue;
3452
3453 // If the used several times in the allocate directive, the same allocator
3454 // must be used.
3456 AllocatorKind, Allocator))
3457 continue;
3458
3459 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3460 // If a list item has a static storage type, the allocator expression in the
3461 // allocator clause must be a constant expression that evaluates to one of
3462 // the predefined memory allocator values.
3463 if (Allocator && VD->hasGlobalStorage()) {
3464 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3465 Diag(Allocator->getExprLoc(),
3466 diag::err_omp_expected_predefined_allocator)
3467 << Allocator->getSourceRange();
3468 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3470 Diag(VD->getLocation(),
3471 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3472 << VD;
3473 continue;
3474 }
3475 }
3476
3477 Vars.push_back(RefExpr);
3478 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3479 DE->getSourceRange());
3480 }
3481 if (Vars.empty())
3482 return nullptr;
3483 if (!Owner)
3484 Owner = SemaRef.getCurLexicalContext();
3485 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3487 Owner->addDecl(D);
3489}
3490
3493 ArrayRef<OMPClause *> ClauseList) {
3494 OMPRequiresDecl *D = nullptr;
3496 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3497 } else {
3498 D = CheckOMPRequiresDecl(Loc, ClauseList);
3499 if (D) {
3501 DSAStack->addRequiresDecl(D);
3502 }
3503 }
3505}
3506
3508 OpenMPDirectiveKind DKind,
3509 ArrayRef<std::string> Assumptions,
3510 bool SkippedClauses) {
3511 if (!SkippedClauses && Assumptions.empty())
3512 Diag(Loc, diag::err_omp_no_clause_for_directive)
3513 << llvm::omp::getAllAssumeClauseOptions()
3514 << llvm::omp::getOpenMPDirectiveName(DKind);
3515
3516 auto *AA =
3517 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3518 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3519 OMPAssumeScoped.push_back(AA);
3520 return;
3521 }
3522
3523 // Global assumes without assumption clauses are ignored.
3524 if (Assumptions.empty())
3525 return;
3526
3527 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3528 "Unexpected omp assumption directive!");
3529 OMPAssumeGlobal.push_back(AA);
3530
3531 // The OMPAssumeGlobal scope above will take care of new declarations but
3532 // we also want to apply the assumption to existing ones, e.g., to
3533 // declarations in included headers. To this end, we traverse all existing
3534 // declaration contexts and annotate function declarations here.
3535 SmallVector<DeclContext *, 8> DeclContexts;
3536 auto *Ctx = SemaRef.CurContext;
3537 while (Ctx->getLexicalParent())
3538 Ctx = Ctx->getLexicalParent();
3539 DeclContexts.push_back(Ctx);
3540 while (!DeclContexts.empty()) {
3541 DeclContext *DC = DeclContexts.pop_back_val();
3542 for (auto *SubDC : DC->decls()) {
3543 if (SubDC->isInvalidDecl())
3544 continue;
3545 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3546 DeclContexts.push_back(CTD->getTemplatedDecl());
3547 llvm::append_range(DeclContexts, CTD->specializations());
3548 continue;
3549 }
3550 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3551 DeclContexts.push_back(DC);
3552 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3553 F->addAttr(AA);
3554 continue;
3555 }
3556 }
3557 }
3558}
3559
3561 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3562 OMPAssumeScoped.pop_back();
3563}
3564
3567 ArrayRef<OMPClause *> ClauseList) {
3568 /// For target specific clauses, the requires directive cannot be
3569 /// specified after the handling of any of the target regions in the
3570 /// current compilation unit.
3571 ArrayRef<SourceLocation> TargetLocations =
3572 DSAStack->getEncounteredTargetLocs();
3573 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3574 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3575 for (const OMPClause *CNew : ClauseList) {
3576 // Check if any of the requires clauses affect target regions.
3577 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3578 isa<OMPUnifiedAddressClause>(CNew) ||
3579 isa<OMPReverseOffloadClause>(CNew) ||
3580 isa<OMPDynamicAllocatorsClause>(CNew)) {
3581 Diag(Loc, diag::err_omp_directive_before_requires)
3582 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3583 for (SourceLocation TargetLoc : TargetLocations) {
3584 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3585 << "target";
3586 }
3587 } else if (!AtomicLoc.isInvalid() &&
3588 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3589 Diag(Loc, diag::err_omp_directive_before_requires)
3590 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3591 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3592 << "atomic";
3593 }
3594 }
3595 }
3596
3597 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3599 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3600 return nullptr;
3601}
3602
3603static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3604 const ValueDecl *D,
3605 const DSAStackTy::DSAVarData &DVar,
3606 bool IsLoopIterVar) {
3607 if (DVar.RefExpr) {
3608 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3609 << getOpenMPClauseName(DVar.CKind);
3610 return;
3611 }
3612 enum {
3613 PDSA_StaticMemberShared,
3614 PDSA_StaticLocalVarShared,
3615 PDSA_LoopIterVarPrivate,
3616 PDSA_LoopIterVarLinear,
3617 PDSA_LoopIterVarLastprivate,
3618 PDSA_ConstVarShared,
3619 PDSA_GlobalVarShared,
3620 PDSA_TaskVarFirstprivate,
3621 PDSA_LocalVarPrivate,
3622 PDSA_Implicit
3623 } Reason = PDSA_Implicit;
3624 bool ReportHint = false;
3625 auto ReportLoc = D->getLocation();
3626 auto *VD = dyn_cast<VarDecl>(D);
3627 if (IsLoopIterVar) {
3628 if (DVar.CKind == OMPC_private)
3629 Reason = PDSA_LoopIterVarPrivate;
3630 else if (DVar.CKind == OMPC_lastprivate)
3631 Reason = PDSA_LoopIterVarLastprivate;
3632 else
3633 Reason = PDSA_LoopIterVarLinear;
3634 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3635 DVar.CKind == OMPC_firstprivate) {
3636 Reason = PDSA_TaskVarFirstprivate;
3637 ReportLoc = DVar.ImplicitDSALoc;
3638 } else if (VD && VD->isStaticLocal())
3639 Reason = PDSA_StaticLocalVarShared;
3640 else if (VD && VD->isStaticDataMember())
3641 Reason = PDSA_StaticMemberShared;
3642 else if (VD && VD->isFileVarDecl())
3643 Reason = PDSA_GlobalVarShared;
3644 else if (D->getType().isConstant(SemaRef.getASTContext()))
3645 Reason = PDSA_ConstVarShared;
3646 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3647 ReportHint = true;
3648 Reason = PDSA_LocalVarPrivate;
3649 }
3650 if (Reason != PDSA_Implicit) {
3651 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3652 << Reason << ReportHint
3653 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3654 } else if (DVar.ImplicitDSALoc.isValid()) {
3655 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3656 << getOpenMPClauseName(DVar.CKind);
3657 }
3658}
3659
3662 bool IsAggregateOrDeclareTarget) {
3664 switch (M) {
3665 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3666 Kind = OMPC_MAP_alloc;
3667 break;
3668 case OMPC_DEFAULTMAP_MODIFIER_to:
3669 Kind = OMPC_MAP_to;
3670 break;
3671 case OMPC_DEFAULTMAP_MODIFIER_from:
3672 Kind = OMPC_MAP_from;
3673 break;
3674 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3675 Kind = OMPC_MAP_tofrom;
3676 break;
3677 case OMPC_DEFAULTMAP_MODIFIER_present:
3678 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3679 // If implicit-behavior is present, each variable referenced in the
3680 // construct in the category specified by variable-category is treated as if
3681 // it had been listed in a map clause with the map-type of alloc and
3682 // map-type-modifier of present.
3683 Kind = OMPC_MAP_alloc;
3684 break;
3685 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3687 llvm_unreachable("Unexpected defaultmap implicit behavior");
3688 case OMPC_DEFAULTMAP_MODIFIER_none:
3689 case OMPC_DEFAULTMAP_MODIFIER_default:
3691 // IsAggregateOrDeclareTarget could be true if:
3692 // 1. the implicit behavior for aggregate is tofrom
3693 // 2. it's a declare target link
3694 if (IsAggregateOrDeclareTarget) {
3695 Kind = OMPC_MAP_tofrom;
3696 break;
3697 }
3698 llvm_unreachable("Unexpected defaultmap implicit behavior");
3699 }
3700 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3701 return Kind;
3702}
3703
3704namespace {
3705class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3706 DSAStackTy *Stack;
3707 Sema &SemaRef;
3708 bool ErrorFound = false;
3709 bool TryCaptureCXXThisMembers = false;
3710 CapturedStmt *CS = nullptr;
3711 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3712 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3713 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3714 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3716 ImplicitMapModifier[DefaultmapKindNum];
3717 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3718 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3719
3720 void VisitSubCaptures(OMPExecutableDirective *S) {
3721 // Check implicitly captured variables.
3722 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3723 return;
3724 if (S->getDirectiveKind() == OMPD_atomic ||
3725 S->getDirectiveKind() == OMPD_critical ||
3726 S->getDirectiveKind() == OMPD_section ||
3727 S->getDirectiveKind() == OMPD_master ||
3728 S->getDirectiveKind() == OMPD_masked ||
3729 S->getDirectiveKind() == OMPD_scope ||
3730 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3731 Visit(S->getAssociatedStmt());
3732 return;
3733 }
3734 visitSubCaptures(S->getInnermostCapturedStmt());
3735 // Try to capture inner this->member references to generate correct mappings
3736 // and diagnostics.
3737 if (TryCaptureCXXThisMembers ||
3738 (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
3739 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3740 [](const CapturedStmt::Capture &C) {
3741 return C.capturesThis();
3742 }))) {
3743 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3744 TryCaptureCXXThisMembers = true;
3745 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3746 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3747 }
3748 // In tasks firstprivates are not captured anymore, need to analyze them
3749 // explicitly.
3750 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3751 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3752 for (OMPClause *C : S->clauses())
3753 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3754 for (Expr *Ref : FC->varlists())
3755 Visit(Ref);
3756 }
3757 }
3758 }
3759
3760public:
3761 void VisitDeclRefExpr(DeclRefExpr *E) {
3762 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3765 E->isNonOdrUse() == clang::NOUR_Unevaluated)
3766 return;
3767 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3768 // Check the datasharing rules for the expressions in the clauses.
3769 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3770 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3771 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3772 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3773 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3774 Visit(CED->getInit());
3775 return;
3776 }
3777 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3778 // Do not analyze internal variables and do not enclose them into
3779 // implicit clauses.
3780 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3781 return;
3782 VD = VD->getCanonicalDecl();
3783 // Skip internally declared variables.
3784 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3785 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3786 !Stack->isImplicitTaskFirstprivate(VD))
3787 return;
3788 // Skip allocators in uses_allocators clauses.
3789 if (Stack->isUsesAllocatorsDecl(VD))
3790 return;
3791
3792 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3793 // Check if the variable has explicit DSA set and stop analysis if it so.
3794 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3795 return;
3796
3797 // Skip internally declared static variables.
3798 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3799 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3800 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3801 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3802 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3803 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3804 !Stack->isImplicitTaskFirstprivate(VD))
3805 return;
3806
3807 SourceLocation ELoc = E->getExprLoc();
3808 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3809 // The default(none) clause requires that each variable that is referenced
3810 // in the construct, and does not have a predetermined data-sharing
3811 // attribute, must have its data-sharing attribute explicitly determined
3812 // by being listed in a data-sharing attribute clause.
3813 if (DVar.CKind == OMPC_unknown &&
3814 (Stack->getDefaultDSA() == DSA_none ||
3815 Stack->getDefaultDSA() == DSA_private ||
3816 Stack->getDefaultDSA() == DSA_firstprivate) &&
3817 isImplicitOrExplicitTaskingRegion(DKind) &&
3818 VarsWithInheritedDSA.count(VD) == 0) {
3819 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3820 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3821 Stack->getDefaultDSA() == DSA_private)) {
3822 DSAStackTy::DSAVarData DVar =
3823 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3824 InheritedDSA = DVar.CKind == OMPC_unknown;
3825 }
3826 if (InheritedDSA)
3827 VarsWithInheritedDSA[VD] = E;
3828 if (Stack->getDefaultDSA() == DSA_none)
3829 return;
3830 }
3831
3832 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3833 // If implicit-behavior is none, each variable referenced in the
3834 // construct that does not have a predetermined data-sharing attribute
3835 // and does not appear in a to or link clause on a declare target
3836 // directive must be listed in a data-mapping attribute clause, a
3837 // data-sharing attribute clause (including a data-sharing attribute
3838 // clause on a combined construct where target. is one of the
3839 // constituent constructs), or an is_device_ptr clause.
3840 OpenMPDefaultmapClauseKind ClauseKind =
3842 if (SemaRef.getLangOpts().OpenMP >= 50) {
3843 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3844 OMPC_DEFAULTMAP_MODIFIER_none;
3845 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3846 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3847 // Only check for data-mapping attribute and is_device_ptr here
3848 // since we have already make sure that the declaration does not
3849 // have a data-sharing attribute above
3850 if (!Stack->checkMappableExprComponentListsForDecl(
3851 VD, /*CurrentRegionOnly=*/true,
3853 MapExprComponents,
3855 auto MI = MapExprComponents.rbegin();
3856 auto ME = MapExprComponents.rend();
3857 return MI != ME && MI->getAssociatedDeclaration() == VD;
3858 })) {
3859 VarsWithInheritedDSA[VD] = E;
3860 return;
3861 }
3862 }
3863 }
3864 if (SemaRef.getLangOpts().OpenMP > 50) {
3865 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3866 OMPC_DEFAULTMAP_MODIFIER_present;
3867 if (IsModifierPresent) {
3868 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3869 OMPC_MAP_MODIFIER_present)) {
3870 ImplicitMapModifier[ClauseKind].push_back(
3871 OMPC_MAP_MODIFIER_present);
3872 }
3873 }
3874 }
3875
3877 !Stack->isLoopControlVariable(VD).first) {
3878 if (!Stack->checkMappableExprComponentListsForDecl(
3879 VD, /*CurrentRegionOnly=*/true,
3881 StackComponents,
3883 if (SemaRef.LangOpts.OpenMP >= 50)
3884 return !StackComponents.empty();
3885 // Variable is used if it has been marked as an array, array
3886 // section, array shaping or the variable itself.
3887 return StackComponents.size() == 1 ||
3888 llvm::all_of(
3889 llvm::drop_begin(llvm::reverse(StackComponents)),
3890 [](const OMPClauseMappableExprCommon::
3891 MappableComponent &MC) {
3892 return MC.getAssociatedDeclaration() ==
3893 nullptr &&
3894 (isa<ArraySectionExpr>(
3895 MC.getAssociatedExpression()) ||
3896 isa<OMPArrayShapingExpr>(
3897 MC.getAssociatedExpression()) ||
3898 isa<ArraySubscriptExpr>(
3899 MC.getAssociatedExpression()));
3900 });
3901 })) {
3902 bool IsFirstprivate = false;
3903 // By default lambdas are captured as firstprivates.
3904 if (const auto *RD =
3906 IsFirstprivate = RD->isLambda();
3907 IsFirstprivate =
3908 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3909 if (IsFirstprivate) {
3910 ImplicitFirstprivate.emplace_back(E);
3911 } else {
3913 Stack->getDefaultmapModifier(ClauseKind);
3915 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3916 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3917 }
3918 return;
3919 }
3920 }
3921
3922 // OpenMP [2.9.3.6, Restrictions, p.2]
3923 // A list item that appears in a reduction clause of the innermost
3924 // enclosing worksharing or parallel construct may not be accessed in an
3925 // explicit task.
3926 DVar = Stack->hasInnermostDSA(
3927 VD,
3928 [](OpenMPClauseKind C, bool AppliedToPointee) {
3929 return C == OMPC_reduction && !AppliedToPointee;
3930 },
3931 [](OpenMPDirectiveKind K) {
3932 return isOpenMPParallelDirective(K) ||
3934 },
3935 /*FromParent=*/true);
3936 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3937 ErrorFound = true;
3938 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3939 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3940 return;
3941 }
3942
3943 // Define implicit data-sharing attributes for task.
3944 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3945 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3946 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3947 DVar.CKind == OMPC_firstprivate) ||
3948 (Stack->getDefaultDSA() == DSA_private &&
3949 DVar.CKind == OMPC_private)) &&
3950 !DVar.RefExpr)) &&
3951 !Stack->isLoopControlVariable(VD).first) {
3952 if (Stack->getDefaultDSA() == DSA_private)
3953 ImplicitPrivate.push_back(E);
3954 else
3955 ImplicitFirstprivate.push_back(E);
3956 return;
3957 }
3958
3959 // Store implicitly used globals with declare target link for parent
3960 // target.
3961 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3962 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3963 Stack->addToParentTargetRegionLinkGlobals(E);
3964 return;
3965 }
3966 }
3967 }
3968 void VisitMemberExpr(MemberExpr *E) {
3969 if (E->isTypeDependent() || E->isValueDependent() ||
3971 return;
3972 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3973 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
3974 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3975 if (!FD)
3976 return;
3977 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3978 // Check if the variable has explicit DSA set and stop analysis if it
3979 // so.
3980 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3981 return;
3982
3984 !Stack->isLoopControlVariable(FD).first &&
3985 !Stack->checkMappableExprComponentListsForDecl(
3986 FD, /*CurrentRegionOnly=*/true,
3988 StackComponents,
3990 return isa<CXXThisExpr>(
3991 cast<MemberExpr>(
3992 StackComponents.back().getAssociatedExpression())
3993 ->getBase()
3994 ->IgnoreParens());
3995 })) {
3996 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
3997 // A bit-field cannot appear in a map clause.
3998 //
3999 if (FD->isBitField())
4000 return;
4001
4002 // Check to see if the member expression is referencing a class that
4003 // has already been explicitly mapped
4004 if (Stack->isClassPreviouslyMapped(TE->getType()))
4005 return;
4006
4008 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4009 OpenMPDefaultmapClauseKind ClauseKind =
4012 Modifier, /*IsAggregateOrDeclareTarget*/ true);
4013 ImplicitMap[ClauseKind][Kind].emplace_back(E);
4014 return;
4015 }
4016
4017 SourceLocation ELoc = E->getExprLoc();
4018 // OpenMP [2.9.3.6, Restrictions, p.2]
4019 // A list item that appears in a reduction clause of the innermost
4020 // enclosing worksharing or parallel construct may not be accessed in
4021 // an explicit task.
4022 DVar = Stack->hasInnermostDSA(
4023 FD,
4024 [](OpenMPClauseKind C, bool AppliedToPointee) {
4025 return C == OMPC_reduction && !AppliedToPointee;
4026 },
4027 [](OpenMPDirectiveKind K) {
4028 return isOpenMPParallelDirective(K) ||
4030 },
4031 /*FromParent=*/true);
4032 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4033 ErrorFound = true;
4034 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4035 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4036 return;
4037 }
4038
4039 // Define implicit data-sharing attributes for task.
4040 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4041 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4042 !Stack->isLoopControlVariable(FD).first) {
4043 // Check if there is a captured expression for the current field in the
4044 // region. Do not mark it as firstprivate unless there is no captured
4045 // expression.
4046 // TODO: try to make it firstprivate.
4047 if (DVar.CKind != OMPC_unknown)
4048 ImplicitFirstprivate.push_back(E);
4049 }
4050 return;
4051 }
4054 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4055 Stack->getCurrentDirective(),
4056 /*NoDiagnose=*/true))
4057 return;
4058 const auto *VD = cast<ValueDecl>(
4059 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4060 if (!Stack->checkMappableExprComponentListsForDecl(
4061 VD, /*CurrentRegionOnly=*/true,
4062 [&CurComponents](
4064 StackComponents,
4066 auto CCI = CurComponents.rbegin();
4067 auto CCE = CurComponents.rend();
4068 for (const auto &SC : llvm::reverse(StackComponents)) {
4069 // Do both expressions have the same kind?
4070 if (CCI->getAssociatedExpression()->getStmtClass() !=
4071 SC.getAssociatedExpression()->getStmtClass())
4072 if (!((isa<ArraySectionExpr>(
4073 SC.getAssociatedExpression()) ||
4074 isa<OMPArrayShapingExpr>(
4075 SC.getAssociatedExpression())) &&
4076 isa<ArraySubscriptExpr>(
4077 CCI->getAssociatedExpression())))
4078 return false;
4079
4080 const Decl *CCD = CCI->getAssociatedDeclaration();
4081 const Decl *SCD = SC.getAssociatedDeclaration();
4082 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4083 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4084 if (SCD != CCD)
4085 return false;
4086 std::advance(CCI, 1);
4087 if (CCI == CCE)
4088 break;
4089 }
4090 return true;
4091 })) {
4092 Visit(E->getBase());
4093 }
4094 } else if (!TryCaptureCXXThisMembers) {
4095 Visit(E->getBase());
4096 }
4097 }
4098 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4099 for (OMPClause *C : S->clauses()) {
4100 // Skip analysis of arguments of private clauses for task|target
4101 // directives.
4102 if (isa_and_nonnull<OMPPrivateClause>(C))
4103 continue;
4104 // Skip analysis of arguments of implicitly defined firstprivate clause
4105 // for task|target directives.
4106 // Skip analysis of arguments of implicitly defined map clause for target
4107 // directives.
4108 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4109 C->isImplicit() &&
4110 !isOpenMPTaskingDirective(Stack->getCurrentDirective()))) {
4111 for (Stmt *CC : C->children()) {
4112 if (CC)
4113 Visit(CC);
4114 }
4115 }
4116 }
4117 // Check implicitly captured variables.
4118 VisitSubCaptures(S);
4119 }
4120
4121 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4122 // Loop transformation directives do not introduce data sharing
4123 VisitStmt(S);
4124 }
4125
4126 void VisitCallExpr(CallExpr *S) {
4127 for (Stmt *C : S->arguments()) {
4128 if (C) {
4129 // Check implicitly captured variables in the task-based directives to
4130 // check if they must be firstprivatized.
4131 Visit(C);
4132 }
4133 }
4134 if (Expr *Callee = S->getCallee()) {
4135 auto *CI = Callee->IgnoreParenImpCasts();
4136 if (auto *CE = dyn_cast<MemberExpr>(CI))
4137 Visit(CE->getBase());
4138 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4139 Visit(CE);
4140 }
4141 }
4142 void VisitStmt(Stmt *S) {
4143 for (Stmt *C : S->children()) {
4144 if (C) {
4145 // Check implicitly captured variables in the task-based directives to
4146 // check if they must be firstprivatized.
4147 Visit(C);
4148 }
4149 }
4150 }
4151
4152 void visitSubCaptures(CapturedStmt *S) {
4153 for (const CapturedStmt::Capture &Cap : S->captures()) {
4154 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4155 continue;
4156 VarDecl *VD = Cap.getCapturedVar();
4157 // Do not try to map the variable if it or its sub-component was mapped
4158 // already.
4159 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
4160 Stack->checkMappableExprComponentListsForDecl(
4161 VD, /*CurrentRegionOnly=*/true,
4163 OpenMPClauseKind) { return true; }))
4164 continue;
4166 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4167 Cap.getLocation(), /*RefersToCapture=*/true);
4168 Visit(DRE);
4169 }
4170 }
4171 bool isErrorFound() const { return ErrorFound; }
4172 ArrayRef<Expr *> getImplicitFirstprivate() const {
4173 return ImplicitFirstprivate;
4174 }
4175 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4177 OpenMPMapClauseKind MK) const {
4178 return ImplicitMap[DK][MK];
4179 }
4181 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4182 return ImplicitMapModifier[Kind];
4183 }
4184 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4185 return VarsWithInheritedDSA;
4186 }
4187
4188 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4189 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4190 // Process declare target link variables for the target directives.
4191 if (isOpenMPTargetExecutionDirective(S->getCurrentDirective())) {
4192 for (DeclRefExpr *E : Stack->getLinkGlobals())
4193 Visit(E);
4194 }
4195 }
4196};
4197} // namespace
4198
4199static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4200 OpenMPDirectiveKind DKind,
4201 bool ScopeEntry) {
4204 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4205 if (isOpenMPTeamsDirective(DKind))
4206 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4207 if (isOpenMPParallelDirective(DKind))
4208 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4210 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4211 if (isOpenMPSimdDirective(DKind))
4212 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4213 Stack->handleConstructTrait(Traits, ScopeEntry);
4214}
4215
4217getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4218 ASTContext &Context = SemaRef.getASTContext();
4219 QualType KmpInt32Ty =
4220 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4221 QualType KmpInt32PtrTy =
4222 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4224 std::make_pair(".global_tid.", KmpInt32PtrTy),
4225 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4226 };
4227 if (LoopBoundSharing) {
4228 QualType KmpSizeTy = Context.getSizeType().withConst();
4229 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4230 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4231 }
4232
4233 // __context with shared vars
4234 Params.push_back(std::make_pair(StringRef(), QualType()));
4235 return Params;
4236}
4237
4240 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4241}
4242
4245 ASTContext &Context = SemaRef.getASTContext();
4246 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4247 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4248 QualType KmpInt32PtrTy =
4249 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4250 QualType Args[] = {VoidPtrTy};
4252 EPI.Variadic = true;
4253 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4255 std::make_pair(".global_tid.", KmpInt32Ty),
4256 std::make_pair(".part_id.", KmpInt32PtrTy),
4257 std::make_pair(".privates.", VoidPtrTy),
4258 std::make_pair(
4259 ".copy_fn.",
4260 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4261 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4262 std::make_pair(StringRef(), QualType()) // __context with shared vars
4263 };
4264 return Params;
4265}
4266
4269 ASTContext &Context = SemaRef.getASTContext();
4271 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4272 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4273 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4274 }
4275 // __context with shared vars
4276 Params.push_back(std::make_pair(StringRef(), QualType()));
4277 return Params;
4278}
4279
4283 std::make_pair(StringRef(), QualType()) // __context with shared vars
4284 };
4285 return Params;
4286}
4287
4290 ASTContext &Context = SemaRef.getASTContext();
4291 QualType KmpInt32Ty =
4292 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4293 QualType KmpUInt64Ty =
4294 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4295 QualType KmpInt64Ty =
4296 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4297 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4298 QualType KmpInt32PtrTy =
4299 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4300 QualType Args[] = {VoidPtrTy};
4302 EPI.Variadic = true;
4303 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4305 std::make_pair(".global_tid.", KmpInt32Ty),
4306 std::make_pair(".part_id.", KmpInt32PtrTy),
4307 std::make_pair(".privates.", VoidPtrTy),
4308 std::make_pair(
4309 ".copy_fn.",
4310 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4311 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4312 std::make_pair(".lb.", KmpUInt64Ty),
4313 std::make_pair(".ub.", KmpUInt64Ty),
4314 std::make_pair(".st.", KmpInt64Ty),
4315 std::make_pair(".liter.", KmpInt32Ty),
4316 std::make_pair(".reductions.", VoidPtrTy),
4317 std::make_pair(StringRef(), QualType()) // __context with shared vars
4318 };
4319 return Params;
4320}
4321
4323 Scope *CurScope, SourceLocation Loc) {
4325 getOpenMPCaptureRegions(Regions, DKind);
4326
4327 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4328
4329 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4330 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4331 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4332 };
4333
4334 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4335 switch (RKind) {
4336 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4337 // are listed here.
4338 case OMPD_parallel:
4340 Loc, CurScope, CR_OpenMP,
4341 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4342 break;
4343 case OMPD_teams:
4344 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4345 getTeamsRegionParams(SemaRef), Level);
4346 break;
4347 case OMPD_task:
4348 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4349 getTaskRegionParams(SemaRef), Level);
4350 // Mark this captured region as inlined, because we don't use outlined
4351 // function directly.
4352 MarkAsInlined(SemaRef.getCurCapturedRegion());
4353 break;
4354 case OMPD_taskloop:
4355 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4356 getTaskloopRegionParams(SemaRef), Level);
4357 // Mark this captured region as inlined, because we don't use outlined
4358 // function directly.
4359 MarkAsInlined(SemaRef.getCurCapturedRegion());
4360 break;
4361 case OMPD_target:
4362 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4363 getTargetRegionParams(SemaRef), Level);
4364 break;
4365 case OMPD_unknown:
4366 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4367 getUnknownRegionParams(SemaRef));
4368 break;
4369 case OMPD_metadirective:
4370 case OMPD_nothing:
4371 default:
4372 llvm_unreachable("Unexpected capture region");
4373 }
4374 }
4375}
4376
4378 Scope *CurScope) {
4379 switch (DKind) {
4380 case OMPD_atomic:
4381 case OMPD_critical:
4382 case OMPD_masked:
4383 case OMPD_master:
4384 case OMPD_section:
4385 case OMPD_tile:
4386 case OMPD_unroll:
4387 case OMPD_reverse:
4388 case OMPD_interchange:
4389 break;
4390 default:
4391 processCapturedRegions(SemaRef, DKind, CurScope,
4392 DSAStack->getConstructLoc());
4393 break;
4394 }
4395
4396 DSAStack->setContext(SemaRef.CurContext);
4397 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4398}
4399
4400int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4401 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4402}
4403
4406 getOpenMPCaptureRegions(CaptureRegions, DKind);
4407 return CaptureRegions.size();
4408}
4409
4411 Expr *CaptureExpr, bool WithInit,
4412 DeclContext *CurContext,
4413 bool AsExpression) {
4414 assert(CaptureExpr);
4415 ASTContext &C = S.getASTContext();
4416 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4417 QualType Ty = Init->getType();
4418 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4419 if (S.getLangOpts().CPlusPlus) {
4420 Ty = C.getLValueReferenceType(Ty);
4421 } else {
4422 Ty = C.getPointerType(Ty);
4423 ExprResult Res =
4424 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4425 if (!Res.isUsable())
4426 return nullptr;
4427 Init = Res.get();
4428 }
4429 WithInit = true;
4430 }
4431 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4432 CaptureExpr->getBeginLoc());
4433 if (!WithInit)
4434 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4435 CurContext->addHiddenDecl(CED);
4437 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4438 return CED;
4439}
4440
4441static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4442 bool WithInit) {
4444 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4445 CD = cast<OMPCapturedExprDecl>(VD);
4446 else
4447 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4448 S.CurContext,
4449 /*AsExpression=*/false);
4450 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4451 CaptureExpr->getExprLoc());
4452}
4453
4454static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4455 StringRef Name) {
4456 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4457 if (!Ref) {
4459 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4460 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4461 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4462 CaptureExpr->getExprLoc());
4463 }
4464 ExprResult Res = Ref;
4465 if (!S.getLangOpts().CPlusPlus &&
4466 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4467 Ref->getType()->isPointerType()) {
4468 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4469 if (!Res.isUsable())
4470 return ExprError();
4471 }
4472 return S.DefaultLvalueConversion(Res.get());
4473}
4474
4475namespace {
4476// OpenMP directives parsed in this section are represented as a
4477// CapturedStatement with an associated statement. If a syntax error
4478// is detected during the parsing of the associated statement, the
4479// compiler must abort processing and close the CapturedStatement.
4480//
4481// Combined directives such as 'target parallel' have more than one
4482// nested CapturedStatements. This RAII ensures that we unwind out
4483// of all the nested CapturedStatements when an error is found.
4484class CaptureRegionUnwinderRAII {
4485private:
4486 Sema &S;
4487 bool &ErrorFound;
4488 OpenMPDirectiveKind DKind = OMPD_unknown;
4489
4490public:
4491 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4492 OpenMPDirectiveKind DKind)
4493 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4494 ~CaptureRegionUnwinderRAII() {
4495 if (ErrorFound) {
4496 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4497 while (--ThisCaptureLevel >= 0)
4499 }
4500 }
4501};
4502} // namespace
4503
4505 // Capture variables captured by reference in lambdas for target-based
4506 // directives.
4508 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4510 DSAStack->getCurrentDirective()))) {
4511 QualType Type = V->getType();
4512 if (const auto *RD = Type.getCanonicalType()
4513 .getNonReferenceType()
4514 ->getAsCXXRecordDecl()) {
4515 bool SavedForceCaptureByReferenceInTargetExecutable =
4516 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4517 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4518 /*V=*/true);
4519 if (RD->isLambda()) {
4520 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4521 FieldDecl *ThisCapture;
4522 RD->getCaptureFields(Captures, ThisCapture);
4523 for (const LambdaCapture &LC : RD->captures()) {
4524 if (LC.getCaptureKind() == LCK_ByRef) {
4525 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4526 DeclContext *VDC = VD->getDeclContext();
4527 if (!VDC->Encloses(SemaRef.CurContext))
4528 continue;
4529 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4530 } else if (LC.getCaptureKind() == LCK_This) {
4532 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4533 ThisTy, ThisCapture->getType()))
4534 SemaRef.CheckCXXThisCapture(LC.getLocation());
4535 }
4536 }
4537 }
4538 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4539 SavedForceCaptureByReferenceInTargetExecutable);
4540 }
4541 }
4542}
4543
4545 const ArrayRef<OMPClause *> Clauses) {
4546 const OMPOrderedClause *Ordered = nullptr;
4547 const OMPOrderClause *Order = nullptr;
4548
4549 for (const OMPClause *Clause : Clauses) {
4550 if (Clause->getClauseKind() == OMPC_ordered)
4551 Ordered = cast<OMPOrderedClause>(Clause);
4552 else if (Clause->getClauseKind() == OMPC_order) {
4553 Order = cast<OMPOrderClause>(Clause);
4554 if (Order->getKind() != OMPC_ORDER_concurrent)
4555 Order = nullptr;
4556 }
4557 if (Ordered && Order)
4558 break;
4559 }
4560
4561 if (Ordered && Order) {
4562 S.Diag(Order->getKindKwLoc(),
4563 diag::err_omp_simple_clause_incompatible_with_ordered)
4564 << getOpenMPClauseName(OMPC_order)
4565 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4566 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4567 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4568 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4569 return true;
4570 }
4571 return false;
4572}
4573
4575 ArrayRef<OMPClause *> Clauses) {
4577 /* ScopeEntry */ false);
4578 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4579 return S;
4580
4581 bool ErrorFound = false;
4582 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4583 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4584 if (!S.isUsable()) {
4585 ErrorFound = true;
4586 return StmtError();
4587 }
4588
4590 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4591 OMPOrderedClause *OC = nullptr;
4592 OMPScheduleClause *SC = nullptr;
4595 // This is required for proper codegen.
4596 for (OMPClause *Clause : Clauses) {
4597 if (!getLangOpts().OpenMPSimd &&
4598 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4599 DSAStack->getCurrentDirective() == OMPD_target) &&
4600 Clause->getClauseKind() == OMPC_in_reduction) {
4601 // Capture taskgroup task_reduction descriptors inside the tasking regions
4602 // with the corresponding in_reduction items.
4603 auto *IRC = cast<OMPInReductionClause>(Clause);
4604 for (Expr *E : IRC->taskgroup_descriptors())
4605 if (E)
4607 }
4608 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4609 Clause->getClauseKind() == OMPC_copyprivate ||
4610 (getLangOpts().OpenMPUseTLS &&
4611 getASTContext().getTargetInfo().isTLSSupported() &&
4612 Clause->getClauseKind() == OMPC_copyin)) {
4613 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4614 // Mark all variables in private list clauses as used in inner region.
4615 for (Stmt *VarRef : Clause->children()) {
4616 if (auto *E = cast_or_null<Expr>(VarRef)) {
4618 }
4619 }
4620 DSAStack->setForceVarCapturing(/*V=*/false);
4621 } else if (CaptureRegions.size() > 1 ||
4622 CaptureRegions.back() != OMPD_unknown) {
4623 if (auto *C = OMPClauseWithPreInit::get(Clause))
4624 PICs.push_back(C);
4625 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4626 if (Expr *E = C->getPostUpdateExpr())
4628 }
4629 }
4630 if (Clause->getClauseKind() == OMPC_schedule)
4631 SC = cast<OMPScheduleClause>(Clause);
4632 else if (Clause->getClauseKind() == OMPC_ordered)
4633 OC = cast<OMPOrderedClause>(Clause);
4634 else if (Clause->getClauseKind() == OMPC_linear)
4635 LCs.push_back(cast<OMPLinearClause>(Clause));
4636 }
4637 // Capture allocator expressions if used.
4638 for (Expr *E : DSAStack->getInnerAllocators())
4640 // OpenMP, 2.7.1 Loop Construct, Restrictions
4641 // The nonmonotonic modifier cannot be specified if an ordered clause is
4642 // specified.
4643 if (SC &&
4644 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4646 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4647 OC) {
4648 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4651 diag::err_omp_simple_clause_incompatible_with_ordered)
4652 << getOpenMPClauseName(OMPC_schedule)
4653 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4654 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4655 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4656 ErrorFound = true;
4657 }
4658 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4659 // If an order(concurrent) clause is present, an ordered clause may not appear
4660 // on the same directive.
4661 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4662 ErrorFound = true;
4663 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4664 for (const OMPLinearClause *C : LCs) {
4665 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4666 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4667 }
4668 ErrorFound = true;
4669 }
4670 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4671 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4672 OC->getNumForLoops()) {
4673 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4674 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4675 ErrorFound = true;
4676 }
4677 if (ErrorFound) {
4678 return StmtError();
4679 }
4680 StmtResult SR = S;
4681 unsigned CompletedRegions = 0;
4682 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4683 // Mark all variables in private list clauses as used in inner region.
4684 // Required for proper codegen of combined directives.
4685 // TODO: add processing for other clauses.
4686 if (ThisCaptureRegion != OMPD_unknown) {
4687 for (const clang::OMPClauseWithPreInit *C : PICs) {
4688 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4689 // Find the particular capture region for the clause if the
4690 // directive is a combined one with multiple capture regions.
4691 // If the directive is not a combined one, the capture region
4692 // associated with the clause is OMPD_unknown and is generated
4693 // only once.
4694 if (CaptureRegion == ThisCaptureRegion ||
4695 CaptureRegion == OMPD_unknown) {
4696 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4697 for (Decl *D : DS->decls())
4699 cast<VarDecl>(D));
4700 }
4701 }
4702 }
4703 }
4704 if (ThisCaptureRegion == OMPD_target) {
4705 // Capture allocator traits in the target region. They are used implicitly
4706 // and, thus, are not captured by default.
4707 for (OMPClause *C : Clauses) {
4708 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4709 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4710 ++I) {
4711 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4712 if (Expr *E = D.AllocatorTraits)
4714 }
4715 continue;
4716 }
4717 }
4718 }
4719 if (ThisCaptureRegion == OMPD_parallel) {
4720 // Capture temp arrays for inscan reductions and locals in aligned
4721 // clauses.
4722 for (OMPClause *C : Clauses) {
4723 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4724 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4725 continue;
4726 for (Expr *E : RC->copy_array_temps())
4727 if (E)
4729 }
4730 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4731 for (Expr *E : AC->varlists())
4733 }
4734 }
4735 }
4736 if (++CompletedRegions == CaptureRegions.size())
4737 DSAStack->setBodyComplete();
4739 }
4740 return SR;
4741}
4742
4743static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4744 OpenMPDirectiveKind CancelRegion,
4745 SourceLocation StartLoc) {
4746 // CancelRegion is only needed for cancel and cancellation_point.
4747 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4748 return false;
4749
4750 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4751 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4752 return false;
4753
4754 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4755 << getOpenMPDirectiveName(CancelRegion);
4756 return true;
4757}
4758
4759static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4760 OpenMPDirectiveKind CurrentRegion,
4761 const DeclarationNameInfo &CurrentName,
4762 OpenMPDirectiveKind CancelRegion,
4763 OpenMPBindClauseKind BindKind,
4764 SourceLocation StartLoc) {
4765 if (!Stack->getCurScope())
4766 return false;
4767
4768 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4769 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4770 bool NestingProhibited = false;
4771 bool CloseNesting = true;
4772 bool OrphanSeen = false;
4773 enum {
4774 NoRecommend,
4775 ShouldBeInParallelRegion,
4776 ShouldBeInOrderedRegion,
4777 ShouldBeInTargetRegion,
4778 ShouldBeInTeamsRegion,
4779 ShouldBeInLoopSimdRegion,
4780 } Recommend = NoRecommend;
4781
4784 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4785 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4786
4787 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4788 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4789 CurrentRegion != OMPD_parallel &&
4790 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
4791 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4792 << getOpenMPDirectiveName(CurrentRegion);
4793 return true;
4794 }
4795 if (isOpenMPSimdDirective(ParentRegion) &&
4796 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4797 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4798 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4799 CurrentRegion != OMPD_scan))) {
4800 // OpenMP [2.16, Nesting of Regions]
4801 // OpenMP constructs may not be nested inside a simd region.
4802 // OpenMP [2.8.1,simd Construct, Restrictions]
4803 // An ordered construct with the simd clause is the only OpenMP
4804 // construct that can appear in the simd region.
4805 // Allowing a SIMD construct nested in another SIMD construct is an
4806 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4807 // message.
4808 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4809 // The only OpenMP constructs that can be encountered during execution of
4810 // a simd region are the atomic construct, the loop construct, the simd
4811 // construct and the ordered construct with the simd clause.
4812 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4813 ? diag::err_omp_prohibited_region_simd
4814 : diag::warn_omp_nesting_simd)
4815 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4816 return CurrentRegion != OMPD_simd;
4817 }
4818 if (EnclosingConstruct == OMPD_atomic) {
4819 // OpenMP [2.16, Nesting of Regions]
4820 // OpenMP constructs may not be nested inside an atomic region.
4821 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4822 return true;
4823 }
4824 if (CurrentRegion == OMPD_section) {
4825 // OpenMP [2.7.2, sections Construct, Restrictions]
4826 // Orphaned section directives are prohibited. That is, the section
4827 // directives must appear within the sections construct and must not be
4828 // encountered elsewhere in the sections region.
4829 if (EnclosingConstruct != OMPD_sections) {
4830 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4831 << (ParentRegion != OMPD_unknown)
4832 << getOpenMPDirectiveName(ParentRegion);
4833 return true;
4834 }
4835 return false;
4836 }
4837 // Allow some constructs (except teams and cancellation constructs) to be
4838 // orphaned (they could be used in functions, called from OpenMP regions
4839 // with the required preconditions).
4840 if (ParentRegion == OMPD_unknown &&
4841 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4842 CurrentRegion != OMPD_cancellation_point &&
4843 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4844 return false;
4845 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4846 // for a detailed explanation
4847 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4848 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4849 (isOpenMPWorksharingDirective(ParentRegion) ||
4850 EnclosingConstruct == OMPD_loop)) {
4851 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4852 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4853 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4854 << getOpenMPDirectiveName(CurrentRegion);
4855 return true;
4856 }
4857 if (CurrentRegion == OMPD_cancellation_point ||
4858 CurrentRegion == OMPD_cancel) {
4859 // OpenMP [2.16, Nesting of Regions]
4860 // A cancellation point construct for which construct-type-clause is
4861 // taskgroup must be nested inside a task construct. A cancellation
4862 // point construct for which construct-type-clause is not taskgroup must
4863 // be closely nested inside an OpenMP construct that matches the type
4864 // specified in construct-type-clause.
4865 // A cancel construct for which construct-type-clause is taskgroup must be
4866 // nested inside a task construct. A cancel construct for which
4867 // construct-type-clause is not taskgroup must be closely nested inside an
4868 // OpenMP construct that matches the type specified in
4869 // construct-type-clause.
4870 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4871 if (CancelRegion == OMPD_taskgroup) {
4872 NestingProhibited = EnclosingConstruct != OMPD_task &&
4873 (SemaRef.getLangOpts().OpenMP < 50 ||
4874 EnclosingConstruct != OMPD_taskloop);
4875 } else if (CancelRegion == OMPD_sections) {
4876 NestingProhibited = EnclosingConstruct != OMPD_section &&
4877 EnclosingConstruct != OMPD_sections;
4878 } else {
4879 NestingProhibited = CancelRegion != Leafs.back();
4880 }
4881 OrphanSeen = ParentRegion == OMPD_unknown;
4882 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4883 // OpenMP 5.1 [2.22, Nesting of Regions]
4884 // A masked region may not be closely nested inside a worksharing, loop,
4885 // atomic, task, or taskloop region.
4886 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4887 isOpenMPGenericLoopDirective(ParentRegion) ||
4888 isOpenMPTaskingDirective(ParentRegion);
4889 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4890 // OpenMP [2.16, Nesting of Regions]
4891 // A critical region may not be nested (closely or otherwise) inside a
4892 // critical region with the same name. Note that this restriction is not
4893 // sufficient to prevent deadlock.
4894 SourceLocation PreviousCriticalLoc;
4895 bool DeadLock = Stack->hasDirective(
4896 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4897 const DeclarationNameInfo &DNI,
4899 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4900 PreviousCriticalLoc = Loc;
4901 return true;
4902 }
4903 return false;
4904 },
4905 false /* skip top directive */);
4906 if (DeadLock) {
4907 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4908 << CurrentName.getName();
4909 if (PreviousCriticalLoc.isValid())
4910 SemaRef.Diag(PreviousCriticalLoc,
4911 diag::note_omp_previous_critical_region);
4912 return true;
4913 }
4914 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4915 // OpenMP 5.1 [2.22, Nesting of Regions]
4916 // A scope region may not be closely nested inside a worksharing, loop,
4917 // task, taskloop, critical, ordered, atomic, or masked region.
4918 // OpenMP 5.1 [2.22, Nesting of Regions]
4919 // A barrier region may not be closely nested inside a worksharing, loop,
4920 // task, taskloop, critical, ordered, atomic, or masked region.
4921 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4922 isOpenMPGenericLoopDirective(ParentRegion) ||
4923 isOpenMPTaskingDirective(ParentRegion) ||
4924 llvm::is_contained({OMPD_masked, OMPD_master,
4925 OMPD_critical, OMPD_ordered},
4926 EnclosingConstruct);
4927 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4928 !isOpenMPParallelDirective(CurrentRegion) &&
4929 !isOpenMPTeamsDirective(CurrentRegion)) {
4930 // OpenMP 5.1 [2.22, Nesting of Regions]
4931 // A loop region that binds to a parallel region or a worksharing region
4932 // may not be closely nested inside a worksharing, loop, task, taskloop,
4933 // critical, ordered, atomic, or masked region.
4934 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4935 isOpenMPGenericLoopDirective(ParentRegion) ||
4936 isOpenMPTaskingDirective(ParentRegion) ||
4937 llvm::is_contained({OMPD_masked, OMPD_master,
4938 OMPD_critical, OMPD_ordered},
4939 EnclosingConstruct);
4940 Recommend = ShouldBeInParallelRegion;
4941 } else if (CurrentRegion == OMPD_ordered) {
4942 // OpenMP [2.16, Nesting of Regions]
4943 // An ordered region may not be closely nested inside a critical,
4944 // atomic, or explicit task region.
4945 // An ordered region must be closely nested inside a loop region (or
4946 // parallel loop region) with an ordered clause.
4947 // OpenMP [2.8.1,simd Construct, Restrictions]
4948 // An ordered construct with the simd clause is the only OpenMP construct
4949 // that can appear in the simd region.
4950 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4951 isOpenMPTaskingDirective(ParentRegion) ||
4952 !(isOpenMPSimdDirective(ParentRegion) ||
4953 Stack->isParentOrderedRegion());
4954 Recommend = ShouldBeInOrderedRegion;
4955 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4956 // OpenMP [2.16, Nesting of Regions]
4957 // If specified, a teams construct must be contained within a target
4958 // construct.
4959 NestingProhibited =
4960 (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4961 (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4962 EnclosingConstruct != OMPD_target);
4963 OrphanSeen = ParentRegion == OMPD_unknown;
4964 Recommend = ShouldBeInTargetRegion;
4965 } else if (CurrentRegion == OMPD_scan) {
4966 if (SemaRef.LangOpts.OpenMP >= 50) {
4967 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4968 // simd, or for simd. This has to take into account combined directives.
4969 // In 5.2 this seems to be implied by the fact that the specified
4970 // separated constructs are do, for, and simd.
4971 NestingProhibited = !llvm::is_contained(
4972 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4973 } else {
4974 NestingProhibited = true;
4975 }
4976 OrphanSeen = ParentRegion == OMPD_unknown;
4977 Recommend = ShouldBeInLoopSimdRegion;
4978 }
4979 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
4980 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
4981 EnclosingConstruct == OMPD_teams) {
4982 // OpenMP [5.1, 2.22, Nesting of Regions]
4983 // distribute, distribute simd, distribute parallel worksharing-loop,
4984 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
4985 // including any parallel regions arising from combined constructs,
4986 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
4987 // only OpenMP regions that may be strictly nested inside the teams
4988 // region.
4989 //
4990 // As an extension, we permit atomic within teams as well.
4991 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
4992 !isOpenMPDistributeDirective(CurrentRegion) &&
4993 CurrentRegion != OMPD_loop &&
4994 !(SemaRef.getLangOpts().OpenMPExtensions &&
4995 CurrentRegion == OMPD_atomic);
4996 Recommend = ShouldBeInParallelRegion;
4997 }
4998 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
4999 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5000 // If the bind clause is present on the loop construct and binding is
5001 // teams then the corresponding loop region must be strictly nested inside
5002 // a teams region.
5003 NestingProhibited =
5004 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5005 Recommend = ShouldBeInTeamsRegion;
5006 }
5007 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5008 // OpenMP 4.5 [2.17 Nesting of Regions]
5009 // The region associated with the distribute construct must be strictly
5010 // nested inside a teams region
5011 NestingProhibited = EnclosingConstruct != OMPD_teams;
5012 Recommend = ShouldBeInTeamsRegion;
5013 }
5014 if (!NestingProhibited &&
5015 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5016 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5017 // OpenMP 4.5 [2.17 Nesting of Regions]
5018 // If a target, target update, target data, target enter data, or
5019 // target exit data construct is encountered during execution of a
5020 // target region, the behavior is unspecified.
5021 NestingProhibited = Stack->hasDirective(
5022 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5025 OffendingRegion = K;
5026 return true;
5027 }
5028 return false;
5029 },
5030 false /* don't skip top directive */);
5031 CloseNesting = false;
5032 }
5033 if (NestingProhibited) {
5034 if (OrphanSeen) {
5035 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5036 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5037 } else {
5038 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5039 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5040 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5041 }
5042 return true;
5043 }
5044 return false;
5045}
5046
5049 unsigned operator()(argument_type DK) { return unsigned(DK); }
5050};
5052 ArrayRef<OMPClause *> Clauses,
5053 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5054 bool ErrorFound = false;
5055 unsigned NamedModifiersNumber = 0;
5056 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5057 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5058 SmallVector<SourceLocation, 4> NameModifierLoc;
5059 for (const OMPClause *C : Clauses) {
5060 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5061 // At most one if clause without a directive-name-modifier can appear on
5062 // the directive.
5063 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5064 if (FoundNameModifiers[CurNM]) {
5065 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5066 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5067 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5068 ErrorFound = true;
5069 } else if (CurNM != OMPD_unknown) {
5070 NameModifierLoc.push_back(IC->getNameModifierLoc());
5071 ++NamedModifiersNumber;
5072 }
5073 FoundNameModifiers[CurNM] = IC;
5074 if (CurNM == OMPD_unknown)
5075 continue;
5076 // Check if the specified name modifier is allowed for the current
5077 // directive.
5078 // At most one if clause with the particular directive-name-modifier can
5079 // appear on the directive.
5080 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5081 S.Diag(IC->getNameModifierLoc(),
5082 diag::err_omp_wrong_if_directive_name_modifier)
5083 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5084 ErrorFound = true;
5085 }
5086 }
5087 }
5088 // If any if clause on the directive includes a directive-name-modifier then
5089 // all if clauses on the directive must include a directive-name-modifier.
5090 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5091 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5092 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5093 diag::err_omp_no_more_if_clause);
5094 } else {
5095 std::string Values;
5096 std::string Sep(", ");
5097 unsigned AllowedCnt = 0;
5098 unsigned TotalAllowedNum =
5099 AllowedNameModifiers.size() - NamedModifiersNumber;
5100 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5101 ++Cnt) {
5102 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5103 if (!FoundNameModifiers[NM]) {
5104 Values += "'";
5105 Values += getOpenMPDirectiveName(NM);
5106 Values += "'";
5107 if (AllowedCnt + 2 == TotalAllowedNum)
5108 Values += " or ";
5109 else if (AllowedCnt + 1 != TotalAllowedNum)
5110 Values += Sep;
5111 ++AllowedCnt;
5112 }
5113 }
5114 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5115 diag::err_omp_unnamed_if_clause)
5116 << (TotalAllowedNum > 1) << Values;
5117 }
5118 for (SourceLocation Loc : NameModifierLoc) {
5119 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5120 }
5121 ErrorFound = true;
5122 }
5123 return ErrorFound;
5124}
5125
5126static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5127 SourceLocation &ELoc,
5128 SourceRange &ERange,
5129 bool AllowArraySection,
5130 StringRef DiagType) {
5131 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5133 return std::make_pair(nullptr, true);
5134
5135 // OpenMP [3.1, C/C++]
5136 // A list item is a variable name.
5137 // OpenMP [2.9.3.3, Restrictions, p.1]
5138 // A variable that is part of another variable (as an array or
5139 // structure element) cannot appear in a private clause.
5140 RefExpr = RefExpr->IgnoreParens();
5141 enum {
5142 NoArrayExpr = -1,
5143 ArraySubscript = 0,
5144 OMPArraySection = 1
5145 } IsArrayExpr = NoArrayExpr;
5146 if (AllowArraySection) {
5147 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5148 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5149 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5150 Base = TempASE->getBase()->IgnoreParenImpCasts();
5151 RefExpr = Base;
5152 IsArrayExpr = ArraySubscript;
5153 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5154 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5155 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5156 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5157 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5158 Base = TempASE->getBase()->IgnoreParenImpCasts();
5159 RefExpr = Base;
5160 IsArrayExpr = OMPArraySection;
5161 }
5162 }
5163 ELoc = RefExpr->getExprLoc();
5164 ERange = RefExpr->getSourceRange();
5165 RefExpr = RefExpr->IgnoreParenImpCasts();
5166 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5167 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5168 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5169 (S.getCurrentThisType().isNull() || !ME ||
5170 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5171 !isa<FieldDecl>(ME->getMemberDecl()))) {
5172 if (IsArrayExpr != NoArrayExpr) {
5173 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5174 << IsArrayExpr << ERange;
5175 } else if (!DiagType.empty()) {
5176 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5177 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5178 : 0;
5179 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5180 << DiagSelect << DiagType << ERange;
5181 } else {
5182 S.Diag(ELoc,
5183 AllowArraySection
5184 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5185 : diag::err_omp_expected_var_name_member_expr)
5186 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5187 }
5188 return std::make_pair(nullptr, false);
5189 }
5190 return std::make_pair(
5191 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5192}
5193
5194namespace {
5195/// Checks if the allocator is used in uses_allocators clause to be allowed in
5196/// target regions.
5197class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5198 DSAStackTy *S = nullptr;
5199
5200public:
5201 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5202 return S->isUsesAllocatorsDecl(E->getDecl())
5203 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5204 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5205 }
5206 bool VisitStmt(const Stmt *S) {
5207 for (const Stmt *Child : S->children()) {
5208 if (Child && Visit(Child))
5209 return true;
5210 }
5211 return false;
5212 }
5213 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5214};
5215} // namespace
5216
5217static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5218 ArrayRef<OMPClause *> Clauses) {
5219 assert(!S.CurContext->isDependentContext() &&
5220 "Expected non-dependent context.");
5221 auto AllocateRange =
5222 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5223 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5224 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5225 return isOpenMPPrivate(C->getClauseKind());
5226 });
5227 for (OMPClause *Cl : PrivateRange) {
5229 if (Cl->getClauseKind() == OMPC_private) {
5230 auto *PC = cast<OMPPrivateClause>(Cl);
5231 I = PC->private_copies().begin();
5232 It = PC->varlist_begin();
5233 Et = PC->varlist_end();
5234 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5235 auto *PC = cast<OMPFirstprivateClause>(Cl);
5236 I = PC->private_copies().begin();
5237 It = PC->varlist_begin();
5238 Et = PC->varlist_end();
5239 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5240 auto *PC = cast<OMPLastprivateClause>(Cl);
5241 I = PC->private_copies().begin();
5242 It = PC->varlist_begin();
5243 Et = PC->varlist_end();
5244 } else if (Cl->getClauseKind() == OMPC_linear) {
5245 auto *PC = cast<OMPLinearClause>(Cl);
5246 I = PC->privates().begin();
5247 It = PC->varlist_begin();
5248 Et = PC->varlist_end();
5249 } else if (Cl->getClauseKind() == OMPC_reduction) {
5250 auto *PC = cast<OMPReductionClause>(Cl);
5251 I = PC->privates().begin();
5252 It = PC->varlist_begin();
5253 Et = PC->varlist_end();
5254 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5255 auto *PC = cast<OMPTaskReductionClause>(Cl);
5256 I = PC->privates().begin();
5257 It = PC->varlist_begin();
5258 Et = PC->varlist_end();
5259 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5260 auto *PC = cast<OMPInReductionClause>(Cl);
5261 I = PC->privates().begin();
5262 It = PC->varlist_begin();
5263 Et = PC->varlist_end();
5264 } else {
5265 llvm_unreachable("Expected private clause.");
5266 }
5267 for (Expr *E : llvm::make_range(It, Et)) {
5268 if (!*I) {
5269 ++I;
5270 continue;
5271 }
5272 SourceLocation ELoc;
5273 SourceRange ERange;
5274 Expr *SimpleRefExpr = E;
5275 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5276 /*AllowArraySection=*/true);
5277 DeclToCopy.try_emplace(Res.first,
5278 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5279 ++I;
5280 }
5281 }
5282 for (OMPClause *C : AllocateRange) {
5283 auto *AC = cast<OMPAllocateClause>(C);
5284 if (S.getLangOpts().OpenMP >= 50 &&
5285 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5286 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5287 AC->getAllocator()) {
5288 Expr *Allocator = AC->getAllocator();
5289 // OpenMP, 2.12.5 target Construct
5290 // Memory allocators that do not appear in a uses_allocators clause cannot
5291 // appear as an allocator in an allocate clause or be used in the target
5292 // region unless a requires directive with the dynamic_allocators clause
5293 // is present in the same compilation unit.
5294 AllocatorChecker Checker(Stack);
5295 if (Checker.Visit(Allocator))
5296 S.Diag(Allocator->getExprLoc(),
5297 diag::err_omp_allocator_not_in_uses_allocators)
5298 << Allocator->getSourceRange();
5299 }
5300 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5301 getAllocatorKind(S, Stack, AC->getAllocator());
5302 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5303 // For task, taskloop or target directives, allocation requests to memory
5304 // allocators with the trait access set to thread result in unspecified
5305 // behavior.
5306 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5307 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5308 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5309 S.Diag(AC->getAllocator()->getExprLoc(),
5310 diag::warn_omp_allocate_thread_on_task_target_directive)
5311 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5312 }
5313 for (Expr *E : AC->varlists()) {
5314 SourceLocation ELoc;
5315 SourceRange ERange;
5316 Expr *SimpleRefExpr = E;
5317 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5318 ValueDecl *VD = Res.first;
5319 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5320 if (!isOpenMPPrivate(Data.CKind)) {
5321 S.Diag(E->getExprLoc(),
5322 diag::err_omp_expected_private_copy_for_allocate);
5323 continue;
5324 }
5325 VarDecl *PrivateVD = DeclToCopy[VD];
5326 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5327 AllocatorKind, AC->getAllocator()))
5328 continue;
5329 // Placeholder until allocate clause supports align modifier.
5330 Expr *Alignment = nullptr;
5331 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5332 Alignment, E->getSourceRange());
5333 }
5334 }
5335}
5336
5337namespace {
5338/// Rewrite statements and expressions for Sema \p Actions CurContext.
5339///
5340/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5341/// context. DeclRefExpr used inside the new context are changed to refer to the
5342/// captured variable instead.
5343class CaptureVars : public TreeTransform<CaptureVars> {
5344 using BaseTransform = TreeTransform<CaptureVars>;
5345
5346public:
5347 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5348
5349 bool AlwaysRebuild() { return true; }
5350};
5351} // namespace
5352
5353static VarDecl *precomputeExpr(Sema &Actions,
5354 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5355 StringRef Name) {
5356 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5357 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5358 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5359 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5360 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5361 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5362 BodyStmts.push_back(NewDeclStmt);
5363 return NewVar;
5364}
5365
5366/// Create a closure that computes the number of iterations of a loop.
5367///
5368/// \param Actions The Sema object.
5369/// \param LogicalTy Type for the logical iteration number.
5370/// \param Rel Comparison operator of the loop condition.
5371/// \param StartExpr Value of the loop counter at the first iteration.
5372/// \param StopExpr Expression the loop counter is compared against in the loop
5373/// condition. \param StepExpr Amount of increment after each iteration.
5374///
5375/// \return Closure (CapturedStmt) of the distance calculation.
5376static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5378 Expr *StartExpr, Expr *StopExpr,
5379 Expr *StepExpr) {
5380 ASTContext &Ctx = Actions.getASTContext();
5381 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5382
5383 // Captured regions currently don't support return values, we use an
5384 // out-parameter instead. All inputs are implicit captures.
5385 // TODO: Instead of capturing each DeclRefExpr occurring in
5386 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5387 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5388 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5389 {StringRef(), QualType()}};
5390 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5391
5392 Stmt *Body;
5393 {
5394 Sema::CompoundScopeRAII CompoundScope(Actions);
5395 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5396
5397 // Get the LValue expression for the result.
5398 ImplicitParamDecl *DistParam = CS->getParam(0);
5399 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5400 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5401
5402 SmallVector<Stmt *, 4> BodyStmts;
5403
5404 // Capture all referenced variable references.
5405 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5406 // CapturedStmt, we could compute them before and capture the result, to be
5407 // used jointly with the LoopVar function.
5408 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5409 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5410 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5411 auto BuildVarRef = [&](VarDecl *VD) {
5412 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5413 };
5414
5416 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5418 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5419 Expr *Dist;
5420 if (Rel == BO_NE) {
5421 // When using a != comparison, the increment can be +1 or -1. This can be
5422 // dynamic at runtime, so we need to check for the direction.
5423 Expr *IsNegStep = AssertSuccess(
5424 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5425
5426 // Positive increment.
5427 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5428 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5429 ForwardRange = AssertSuccess(
5430 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5431 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5432 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5433
5434 // Negative increment.
5435 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5436 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5437 BackwardRange = AssertSuccess(
5438 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5439 Expr *NegIncAmount = AssertSuccess(
5440 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5441 Expr *BackwardDist = AssertSuccess(
5442 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5443
5444 // Use the appropriate case.
5445 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5446 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5447 } else {
5448 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5449 "Expected one of these relational operators");
5450
5451 // We can derive the direction from any other comparison operator. It is
5452 // non well-formed OpenMP if Step increments/decrements in the other
5453 // directions. Whether at least the first iteration passes the loop
5454 // condition.
5455 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5456 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5457
5458 // Compute the range between first and last counter value.
5459 Expr *Range;
5460 if (Rel == BO_GE || Rel == BO_GT)
5461 Range = AssertSuccess(Actions.BuildBinOp(
5462 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5463 else
5464 Range = AssertSuccess(Actions.BuildBinOp(
5465 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5466
5467 // Ensure unsigned range space.
5468 Range =
5469 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5470
5471 if (Rel == BO_LE || Rel == BO_GE) {
5472 // Add one to the range if the relational operator is inclusive.
5473 Range =
5474 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5475 }
5476
5477 // Divide by the absolute step amount. If the range is not a multiple of
5478 // the step size, rounding-up the effective upper bound ensures that the
5479 // last iteration is included.
5480 // Note that the rounding-up may cause an overflow in a temporary that
5481 // could be avoided, but would have occurred in a C-style for-loop as
5482 // well.
5483 Expr *Divisor = BuildVarRef(NewStep);
5484 if (Rel == BO_GE || Rel == BO_GT)
5485 Divisor =
5486 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5487 Expr *DivisorMinusOne =
5488 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5489 Expr *RangeRoundUp = AssertSuccess(
5490 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5491 Dist = AssertSuccess(
5492 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5493
5494 // If there is not at least one iteration, the range contains garbage. Fix
5495 // to zero in this case.
5496 Dist = AssertSuccess(
5497 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5498 }
5499
5500 // Assign the result to the out-parameter.
5501 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5502 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5503 BodyStmts.push_back(ResultAssign);
5504
5505 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5506 }
5507
5508 return cast<CapturedStmt>(
5509 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5510}
5511
5512/// Create a closure that computes the loop variable from the logical iteration
5513/// number.
5514///
5515/// \param Actions The Sema object.
5516/// \param LoopVarTy Type for the loop variable used for result value.
5517/// \param LogicalTy Type for the logical iteration number.
5518/// \param StartExpr Value of the loop counter at the first iteration.
5519/// \param Step Amount of increment after each iteration.
5520/// \param Deref Whether the loop variable is a dereference of the loop
5521/// counter variable.
5522///
5523/// \return Closure (CapturedStmt) of the loop value calculation.
5524static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5525 QualType LogicalTy,
5526 DeclRefExpr *StartExpr, Expr *Step,
5527 bool Deref) {
5528 ASTContext &Ctx = Actions.getASTContext();
5529
5530 // Pass the result as an out-parameter. Passing as return value would require
5531 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5532 // invoke a copy constructor.
5533 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5534 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5535 {"Logical", LogicalTy},
5536 {StringRef(), QualType()}};
5537 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5538
5539 // Capture the initial iterator which represents the LoopVar value at the
5540 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5541 // it in every iteration, capture it by value before it is modified.
5542 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5543 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5545 (void)Invalid;
5546 assert(!Invalid && "Expecting capture-by-value to work.");
5547
5548 Expr *Body;
5549 {
5550 Sema::CompoundScopeRAII CompoundScope(Actions);
5551 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5552
5553 ImplicitParamDecl *TargetParam = CS->getParam(0);
5554 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5555 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5556 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5557 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5558 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5559
5560 // Capture the Start expression.
5561 CaptureVars Recap(Actions);
5562 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5563 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5564
5565 Expr *Skip = AssertSuccess(
5566 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5567 // TODO: Explicitly cast to the iterator's difference_type instead of
5568 // relying on implicit conversion.
5569 Expr *Advanced =
5570 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5571
5572 if (Deref) {
5573 // For range-based for-loops convert the loop counter value to a concrete
5574 // loop variable value by dereferencing the iterator.
5575 Advanced =
5576 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5577 }
5578
5579 // Assign the result to the output parameter.
5580 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5581 BO_Assign, TargetRef, Advanced));
5582 }
5583 return cast<CapturedStmt>(
5584 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5585}
5586
5588 ASTContext &Ctx = getASTContext();
5589
5590 // Extract the common elements of ForStmt and CXXForRangeStmt:
5591 // Loop variable, repeat condition, increment
5592 Expr *Cond, *Inc;
5593 VarDecl *LIVDecl, *LUVDecl;
5594 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5595 Stmt *Init = For->getInit();
5596 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5597 // For statement declares loop variable.
5598 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5599 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5600 // For statement reuses variable.
5601 assert(LCAssign->getOpcode() == BO_Assign &&
5602 "init part must be a loop variable assignment");
5603 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5604 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5605 } else
5606 llvm_unreachable("Cannot determine loop variable");
5607 LUVDecl = LIVDecl;
5608
5609 Cond = For->getCond();
5610 Inc = For->getInc();
5611 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5612 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5613 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5614 LUVDecl = RangeFor->getLoopVariable();
5615
5616 Cond = RangeFor->getCond();
5617 Inc = RangeFor->getInc();
5618 } else
5619 llvm_unreachable("unhandled kind of loop");
5620
5621 QualType CounterTy = LIVDecl->getType();
5622 QualType LVTy = LUVDecl->getType();
5623
5624 // Analyze the loop condition.
5625 Expr *LHS, *RHS;
5626 BinaryOperator::Opcode CondRel;
5627 Cond = Cond->IgnoreImplicit();
5628 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5629 LHS = CondBinExpr->getLHS();
5630 RHS = CondBinExpr->getRHS();
5631 CondRel = CondBinExpr->getOpcode();
5632 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5633 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5634 LHS = CondCXXOp->getArg(0);
5635 RHS = CondCXXOp->getArg(1);
5636 switch (CondCXXOp->getOperator()) {
5637 case OO_ExclaimEqual:
5638 CondRel = BO_NE;
5639 break;
5640 case OO_Less:
5641 CondRel = BO_LT;
5642 break;
5643 case OO_LessEqual:
5644 CondRel = BO_LE;
5645 break;
5646 case OO_Greater:
5647 CondRel = BO_GT;
5648 break;
5649 case OO_GreaterEqual:
5650 CondRel = BO_GE;
5651 break;
5652 default:
5653 llvm_unreachable("unexpected iterator operator");
5654 }
5655 } else
5656 llvm_unreachable("unexpected loop condition");
5657
5658 // Normalize such that the loop counter is on the LHS.
5659 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5660 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5661 std::swap(LHS, RHS);
5662 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5663 }
5664 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5665
5666 // Decide the bit width for the logical iteration counter. By default use the
5667 // unsigned ptrdiff_t integer size (for iterators and pointers).
5668 // TODO: For iterators, use iterator::difference_type,
5669 // std::iterator_traits<>::difference_type or decltype(it - end).
5670 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5671 if (CounterTy->isIntegerType()) {
5672 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5673 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5674 }
5675
5676 // Analyze the loop increment.
5677 Expr *Step;
5678 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5679 int Direction;
5680 switch (IncUn->getOpcode()) {
5681 case UO_PreInc:
5682 case UO_PostInc:
5683 Direction = 1;
5684 break;
5685 case UO_PreDec:
5686 case UO_PostDec:
5687 Direction = -1;
5688 break;
5689 default:
5690 llvm_unreachable("unhandled unary increment operator");
5691 }
5693 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5694 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5695 if (IncBin->getOpcode() == BO_AddAssign) {
5696 Step = IncBin->getRHS();
5697 } else if (IncBin->getOpcode() == BO_SubAssign) {
5698 Step = AssertSuccess(
5699 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5700 } else
5701 llvm_unreachable("unhandled binary increment operator");
5702 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5703 switch (CondCXXOp->getOperator()) {
5704 case OO_PlusPlus:
5706 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5707 break;
5708 case OO_MinusMinus:
5710 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5711 break;
5712 case OO_PlusEqual:
5713 Step = CondCXXOp->getArg(1);
5714 break;
5715 case OO_MinusEqual:
5716 Step = AssertSuccess(
5717 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5718 break;
5719 default:
5720 llvm_unreachable("unhandled overloaded increment operator");
5721 }
5722 } else
5723 llvm_unreachable("unknown increment expression");
5724
5725 CapturedStmt *DistanceFunc =
5726 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5727 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5728 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5729 DeclRefExpr *LVRef =
5730 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5731 nullptr, nullptr, {}, nullptr);
5732 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5733 LoopVarFunc, LVRef);
5734}
5735
5737 // Handle a literal loop.
5738 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5739 return ActOnOpenMPCanonicalLoop(AStmt);
5740
5741 // If not a literal loop, it must be the result of a loop transformation.
5742 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5743 assert(
5745 "Loop transformation directive expected");
5746 return LoopTransform;
5747}
5748
5750 CXXScopeSpec &MapperIdScopeSpec,
5751 const DeclarationNameInfo &MapperId,
5752 QualType Type,
5753 Expr *UnresolvedMapper);
5754
5755/// Perform DFS through the structure/class data members trying to find
5756/// member(s) with user-defined 'default' mapper and generate implicit map
5757/// clauses for such members with the found 'default' mapper.
5758static void
5761 // Check for the default mapper for data members.
5762 if (S.getLangOpts().OpenMP < 50)
5763 return;
5764 SmallVector<OMPClause *, 4> ImplicitMaps;
5765 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5766 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5767 if (!C)
5768 continue;
5769 SmallVector<Expr *, 4> SubExprs;
5770 auto *MI = C->mapperlist_begin();
5771 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5772 ++I, ++MI) {
5773 // Expression is mapped using mapper - skip it.
5774 if (*MI)
5775 continue;
5776 Expr *E = *I;
5777 // Expression is dependent - skip it, build the mapper when it gets
5778 // instantiated.
5779 if (E->isTypeDependent() || E->isValueDependent() ||
5781 continue;
5782 // Array section - need to check for the mapping of the array section
5783 // element.
5784 QualType CanonType = E->getType().getCanonicalType();
5785 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5786 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5787 QualType BaseType =
5789 QualType ElemType;
5790 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5791 ElemType = ATy->getElementType();
5792 else
5793 ElemType = BaseType->getPointeeType();
5794 CanonType = ElemType;
5795 }
5796
5797 // DFS over data members in structures/classes.
5799 1, {CanonType, nullptr});
5800 llvm::DenseMap<const Type *, Expr *> Visited;
5802 1, {nullptr, 1});
5803 while (!Types.empty()) {
5804 QualType BaseType;
5805 FieldDecl *CurFD;
5806 std::tie(BaseType, CurFD) = Types.pop_back_val();
5807 while (ParentChain.back().second == 0)
5808 ParentChain.pop_back();
5809 --ParentChain.back().second;
5810 if (BaseType.isNull())
5811 continue;
5812 // Only structs/classes are allowed to have mappers.
5813 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5814 if (!RD)
5815 continue;
5816 auto It = Visited.find(BaseType.getTypePtr());
5817 if (It == Visited.end()) {
5818 // Try to find the associated user-defined mapper.
5819 CXXScopeSpec MapperIdScopeSpec;
5820 DeclarationNameInfo DefaultMapperId;
5822 &S.Context.Idents.get("default")));
5823 DefaultMapperId.setLoc(E->getExprLoc());
5825 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5826 BaseType, /*UnresolvedMapper=*/nullptr);
5827 if (ER.isInvalid())
5828 continue;
5829 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5830 }
5831 // Found default mapper.
5832 if (It->second) {
5833 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5835 OE->setIsUnique(/*V=*/true);
5836 Expr *BaseExpr = OE;
5837 for (const auto &P : ParentChain) {
5838 if (P.first) {
5839 BaseExpr = S.BuildMemberExpr(
5840 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5842 DeclAccessPair::make(P.first, P.first->getAccess()),
5843 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5844 P.first->getType(), VK_LValue, OK_Ordinary);
5845 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5846 }
5847 }
5848 if (CurFD)
5849 BaseExpr = S.BuildMemberExpr(
5850 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5852 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5853 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5854 CurFD->getType(), VK_LValue, OK_Ordinary);
5855 SubExprs.push_back(BaseExpr);
5856 continue;
5857 }
5858 // Check for the "default" mapper for data members.
5859 bool FirstIter = true;
5860 for (FieldDecl *FD : RD->fields()) {
5861 if (!FD)
5862 continue;
5863 QualType FieldTy = FD->getType();
5864 if (FieldTy.isNull() ||
5865 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5866 continue;
5867 if (FirstIter) {
5868 FirstIter = false;
5869 ParentChain.emplace_back(CurFD, 1);
5870 } else {
5871 ++ParentChain.back().second;
5872 }
5873 Types.emplace_back(FieldTy, FD);
5874 }
5875 }
5876 }
5877 if (SubExprs.empty())
5878 continue;
5879 CXXScopeSpec MapperIdScopeSpec;
5880 DeclarationNameInfo MapperId;
5881 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5882 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
5883 MapperIdScopeSpec, MapperId, C->getMapType(),
5884 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
5885 SubExprs, OMPVarListLocTy()))
5886 Clauses.push_back(NewClause);
5887 }
5888}
5889
5890namespace {
5891/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5892/// call in the associated loop-nest cannot be a 'parallel for'.
5893class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5894 Sema &SemaRef;
5895
5896public:
5897 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5898
5899 // Is there a nested OpenMP loop bind(parallel)
5900 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5901 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5902 if (const auto *C = D->getSingleClause<OMPBindClause>())
5903 if (C->getBindKind() == OMPC_BIND_parallel) {
5904 TeamsLoopCanBeParallelFor = false;
5905 // No need to continue visiting any more
5906 return;
5907 }
5908 }
5909 for (const Stmt *Child : D->children())
5910 if (Child)
5911 Visit(Child);
5912 }
5913
5914 void VisitCallExpr(const CallExpr *C) {
5915 // Function calls inhibit parallel loop translation of 'target teams loop'
5916 // unless the assume-no-nested-parallelism flag has been specified.
5917 // OpenMP API runtime library calls do not inhibit parallel loop
5918 // translation, regardless of the assume-no-nested-parallelism.
5919 bool IsOpenMPAPI = false;
5920 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
5921 if (FD) {
5922 std::string Name = FD->getNameInfo().getAsString();
5923 IsOpenMPAPI = Name.find("omp_") == 0;
5924 }
5925 TeamsLoopCanBeParallelFor =
5926 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5927 if (!TeamsLoopCanBeParallelFor)
5928 return;
5929
5930 for (const Stmt *Child : C->children())
5931 if (Child)
5932 Visit(Child);
5933 }
5934
5935 void VisitCapturedStmt(const CapturedStmt *S) {
5936 if (!S)
5937 return;
5938 Visit(S->getCapturedDecl()->getBody());
5939 }
5940
5941 void VisitStmt(const Stmt *S) {
5942 if (!S)
5943 return;
5944 for (const Stmt *Child : S->children())
5945 if (Child)
5946 Visit(Child);
5947 }
5948 explicit TeamsLoopChecker(Sema &SemaRef)
5949 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5950
5951private:
5952 bool TeamsLoopCanBeParallelFor;
5953};
5954} // namespace
5955
5956static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5957 TeamsLoopChecker Checker(SemaRef);
5958 Checker.Visit(AStmt);
5959 return Checker.teamsLoopCanBeParallelFor();
5960}
5961
5963 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5964 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5965 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5966 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5967
5968 StmtResult Res = StmtError();
5970 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5971
5972 if (const OMPBindClause *BC =
5973 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5974 BindKind = BC->getBindKind();
5975
5976 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
5977 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
5978
5979 // Setting the enclosing teams or parallel construct for the loop
5980 // directive without bind clause.
5981 // [5.0:129:25-28] If the bind clause is not present on the construct and
5982 // the loop construct is closely nested inside a teams or parallel
5983 // construct, the binding region is the corresponding teams or parallel
5984 // region. If none of those conditions hold, the binding region is not
5985 // defined.
5986 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
5987 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
5988 getLeafConstructsOrSelf(ParentDirective);
5989
5990 if (ParentDirective == OMPD_unknown) {
5991 Diag(DSAStack->getDefaultDSALocation(),
5992 diag::err_omp_bind_required_on_loop);
5993 } else if (ParentLeafs.back() == OMPD_parallel) {
5994 BindKind = OMPC_BIND_parallel;
5995 } else if (ParentLeafs.back() == OMPD_teams) {
5996 BindKind = OMPC_BIND_teams;
5997 }
5998
5999 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6000
6001 OMPClause *C =
6004 ClausesWithImplicit.push_back(C);
6005 }
6006
6007 // Diagnose "loop bind(teams)" with "reduction".
6008 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6009 for (OMPClause *C : Clauses) {
6010 if (C->getClauseKind() == OMPC_reduction)
6011 Diag(DSAStack->getDefaultDSALocation(),
6012 diag::err_omp_loop_reduction_clause);
6013 }
6014 }
6015
6016 // First check CancelRegion which is then used in checkNestingOfRegions.
6017 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6018 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6019 BindKind, StartLoc)) {
6020 return StmtError();
6021 }
6022
6023 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6026 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6027
6028 VarsWithInheritedDSAType VarsWithInheritedDSA;
6029 bool ErrorFound = false;
6030 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6031
6032 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6034 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6035
6036 // Check default data sharing attributes for referenced variables.
6037 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6038 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6039 Stmt *S = AStmt;
6040 while (--ThisCaptureLevel >= 0)
6041 S = cast<CapturedStmt>(S)->getCapturedStmt();
6042 DSAChecker.Visit(S);
6044 !isOpenMPTaskingDirective(Kind)) {
6045 // Visit subcaptures to generate implicit clauses for captured vars.
6046 auto *CS = cast<CapturedStmt>(AStmt);
6048 getOpenMPCaptureRegions(CaptureRegions, Kind);
6049 // Ignore outer tasking regions for target directives.
6050 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6051 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6052 DSAChecker.visitSubCaptures(CS);
6053 }
6054 if (DSAChecker.isErrorFound())
6055 return StmtError();
6056 // Generate list of implicitly defined firstprivate variables.
6057 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6058
6059 SmallVector<Expr *, 4> ImplicitFirstprivates(
6060 DSAChecker.getImplicitFirstprivate().begin(),
6061 DSAChecker.getImplicitFirstprivate().end());
6062 SmallVector<Expr *, 4> ImplicitPrivates(
6063 DSAChecker.getImplicitPrivate().begin(),
6064 DSAChecker.getImplicitPrivate().end());
6065 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6066 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6068 ImplicitMapModifiers[DefaultmapKindNum];
6070 ImplicitMapModifiersLoc[DefaultmapKindNum];
6071 // Get the original location of present modifier from Defaultmap clause.
6072 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6073 for (OMPClause *C : Clauses) {
6074 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6075 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6076 PresentModifierLocs[DMC->getDefaultmapKind()] =
6077 DMC->getDefaultmapModifierLoc();
6078 }
6079 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6080 auto K = static_cast<OpenMPDefaultmapClauseKind>(VC);
6081 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6082 ArrayRef<Expr *> ImplicitMap =
6083 DSAChecker.getImplicitMap(K, static_cast<OpenMPMapClauseKind>(I));
6084 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6085 }
6086 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6087 DSAChecker.getImplicitMapModifier(K);
6088 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6089 ImplicitModifier.end());
6090 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6091 ImplicitModifier.size(), PresentModifierLocs[VC]);
6092 }
6093 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6094 for (OMPClause *C : Clauses) {
6095 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6096 for (Expr *E : IRC->taskgroup_descriptors())
6097 if (E)
6098 ImplicitFirstprivates.emplace_back(E);
6099 }
6100 // OpenMP 5.0, 2.10.1 task Construct
6101 // [detach clause]... The event-handle will be considered as if it was
6102 // specified on a firstprivate clause.
6103 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6104 ImplicitFirstprivates.push_back(DC->getEventHandler());
6105 }
6106 if (!ImplicitFirstprivates.empty()) {
6108 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6109 SourceLocation())) {
6110 ClausesWithImplicit.push_back(Implicit);
6111 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6112 ImplicitFirstprivates.size();
6113 } else {
6114 ErrorFound = true;
6115 }
6116 }
6117 if (!ImplicitPrivates.empty()) {
6118 if (OMPClause *Implicit =
6119 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6121 ClausesWithImplicit.push_back(Implicit);
6122 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6123 ImplicitPrivates.size();
6124 } else {
6125 ErrorFound = true;
6126 }
6127 }
6128 // OpenMP 5.0 [2.19.7]
6129 // If a list item appears in a reduction, lastprivate or linear
6130 // clause on a combined target construct then it is treated as
6131 // if it also appears in a map clause with a map-type of tofrom
6132 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6134 SmallVector<Expr *, 4> ImplicitExprs;
6135 for (OMPClause *C : Clauses) {
6136 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6137 for (Expr *E : RC->varlists())
6138 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6139 ImplicitExprs.emplace_back(E);
6140 }
6141 if (!ImplicitExprs.empty()) {
6142 ArrayRef<Expr *> Exprs = ImplicitExprs;
6143 CXXScopeSpec MapperIdScopeSpec;
6144 DeclarationNameInfo MapperId;
6147 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6148 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6149 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6150 ClausesWithImplicit.emplace_back(Implicit);
6151 }
6152 }
6153 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6154 int ClauseKindCnt = -1;
6155 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6156 ++ClauseKindCnt;
6157 if (ImplicitMap.empty())
6158 continue;
6159 CXXScopeSpec MapperIdScopeSpec;
6160 DeclarationNameInfo MapperId;
6161 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6163 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6164 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6165 SourceLocation(), SourceLocation(), ImplicitMap,
6166 OMPVarListLocTy())) {
6167 ClausesWithImplicit.emplace_back(Implicit);
6168 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6169 ImplicitMap.size();
6170 } else {
6171 ErrorFound = true;
6172 }
6173 }
6174 }
6175 // Build expressions for implicit maps of data members with 'default'
6176 // mappers.
6177 if (getLangOpts().OpenMP >= 50)
6179 ClausesWithImplicit);
6180 }
6181
6182 switch (Kind) {
6183 case OMPD_parallel:
6184 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6185 EndLoc);
6186 break;
6187 case OMPD_simd:
6188 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6189 VarsWithInheritedDSA);
6190 break;
6191 case OMPD_tile:
6192 Res =
6193 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6194 break;
6195 case OMPD_unroll:
6196 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6197 EndLoc);
6198 break;
6199 case OMPD_reverse:
6200 assert(ClausesWithImplicit.empty() &&
6201 "reverse directive does not support any clauses");
6202 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6203 break;
6204 case OMPD_interchange:
6205 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6206 EndLoc);
6207 break;
6208 case OMPD_for:
6209 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6210 VarsWithInheritedDSA);
6211 break;
6212 case OMPD_for_simd:
6213 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6214 EndLoc, VarsWithInheritedDSA);
6215 break;
6216 case OMPD_sections:
6217 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6218 EndLoc);
6219 break;
6220 case OMPD_section:
6221 assert(ClausesWithImplicit.empty() &&
6222 "No clauses are allowed for 'omp section' directive");
6223 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6224 break;
6225 case OMPD_single:
6226 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6227 EndLoc);
6228 break;
6229 case OMPD_master:
6230 assert(ClausesWithImplicit.empty() &&
6231 "No clauses are allowed for 'omp master' directive");
6232 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6233 break;
6234 case OMPD_masked:
6235 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6236 EndLoc);
6237 break;
6238 case OMPD_critical:
6239 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6240 StartLoc, EndLoc);
6241 break;
6242 case OMPD_parallel_for:
6243 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6244 EndLoc, VarsWithInheritedDSA);
6245 break;
6246 case OMPD_parallel_for_simd:
6248 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6249 break;
6250 case OMPD_scope:
6251 Res =
6252 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6253 break;
6254 case OMPD_parallel_master:
6255 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6256 StartLoc, EndLoc);
6257 break;
6258 case OMPD_parallel_masked:
6259 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6260 StartLoc, EndLoc);
6261 break;
6262 case OMPD_parallel_sections:
6263 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6264 StartLoc, EndLoc);
6265 break;
6266 case OMPD_task:
6267 Res =
6268 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6269 break;
6270 case OMPD_taskyield:
6271 assert(ClausesWithImplicit.empty() &&
6272 "No clauses are allowed for 'omp taskyield' directive");
6273 assert(AStmt == nullptr &&
6274 "No associated statement allowed for 'omp taskyield' directive");
6275 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6276 break;
6277 case OMPD_error:
6278 assert(AStmt == nullptr &&
6279 "No associated statement allowed for 'omp error' directive");
6280 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6281 break;
6282 case OMPD_barrier:
6283 assert(ClausesWithImplicit.empty() &&
6284 "No clauses are allowed for 'omp barrier' directive");
6285 assert(AStmt == nullptr &&
6286 "No associated statement allowed for 'omp barrier' directive");
6287 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6288 break;
6289 case OMPD_taskwait:
6290 assert(AStmt == nullptr &&
6291 "No associated statement allowed for 'omp taskwait' directive");
6292 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6293 break;
6294 case OMPD_taskgroup:
6295 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6296 EndLoc);
6297 break;
6298 case OMPD_flush:
6299 assert(AStmt == nullptr &&
6300 "No associated statement allowed for 'omp flush' directive");
6301 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6302 break;
6303 case OMPD_depobj:
6304 assert(AStmt == nullptr &&
6305 "No associated statement allowed for 'omp depobj' directive");
6306 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6307 break;
6308 case OMPD_scan:
6309 assert(AStmt == nullptr &&
6310 "No associated statement allowed for 'omp scan' directive");
6311 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6312 break;
6313 case OMPD_ordered:
6314 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6315 EndLoc);
6316 break;
6317 case OMPD_atomic:
6318 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6319 EndLoc);
6320 break;
6321 case OMPD_teams:
6322 Res =
6323 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6324 break;
6325 case OMPD_target:
6326 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6327 EndLoc);
6328 break;
6329 case OMPD_target_parallel:
6330 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6331 StartLoc, EndLoc);
6332 break;
6333 case OMPD_target_parallel_for:
6335 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6336 break;
6337 case OMPD_cancellation_point:
6338 assert(ClausesWithImplicit.empty() &&
6339 "No clauses are allowed for 'omp cancellation point' directive");
6340 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6341 "cancellation point' directive");
6342 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6343 break;
6344 case OMPD_cancel:
6345 assert(AStmt == nullptr &&
6346 "No associated statement allowed for 'omp cancel' directive");
6347 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6348 CancelRegion);
6349 break;
6350 case OMPD_target_data:
6351 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6352 EndLoc);
6353 break;
6354 case OMPD_target_enter_data:
6355 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6356 EndLoc, AStmt);
6357 break;
6358 case OMPD_target_exit_data:
6359 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6360 EndLoc, AStmt);
6361 break;
6362 case OMPD_taskloop:
6363 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6364 EndLoc, VarsWithInheritedDSA);
6365 break;
6366 case OMPD_taskloop_simd:
6367 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6368 EndLoc, VarsWithInheritedDSA);
6369 break;
6370 case OMPD_master_taskloop:
6372 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6373 break;
6374 case OMPD_masked_taskloop:
6376 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6377 break;
6378 case OMPD_master_taskloop_simd:
6380 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6381 break;
6382 case OMPD_masked_taskloop_simd:
6384 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6385 break;
6386 case OMPD_parallel_master_taskloop:
6388 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6389 break;
6390 case OMPD_parallel_masked_taskloop:
6392 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6393 break;
6394 case OMPD_parallel_master_taskloop_simd:
6396 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6397 break;
6398 case OMPD_parallel_masked_taskloop_simd:
6400 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6401 break;
6402 case OMPD_distribute:
6403 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6404 EndLoc, VarsWithInheritedDSA);
6405 break;
6406 case OMPD_target_update:
6407 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6408 EndLoc, AStmt);
6409 break;
6410 case OMPD_distribute_parallel_for:
6412 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6413 break;
6414 case OMPD_distribute_parallel_for_simd:
6416 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6417 break;
6418 case OMPD_distribute_simd:
6420 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6421 break;
6422 case OMPD_target_parallel_for_simd:
6424 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6425 break;
6426 case OMPD_target_simd:
6427 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6428 EndLoc, VarsWithInheritedDSA);
6429 break;
6430 case OMPD_teams_distribute:
6432 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6433 break;
6434 case OMPD_teams_distribute_simd:
6436 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6437 break;
6438 case OMPD_teams_distribute_parallel_for_simd:
6440 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6441 break;
6442 case OMPD_teams_distribute_parallel_for:
6444 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6445 break;
6446 case OMPD_target_teams:
6447 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6448 EndLoc);
6449 break;
6450 case OMPD_target_teams_distribute:
6452 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6453 break;
6454 case OMPD_target_teams_distribute_parallel_for:
6456 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6457 break;
6458 case OMPD_target_teams_distribute_parallel_for_simd:
6460 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6461 break;
6462 case OMPD_target_teams_distribute_simd:
6464 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6465 break;
6466 case OMPD_interop:
6467 assert(AStmt == nullptr &&
6468 "No associated statement allowed for 'omp interop' directive");
6469 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6470 break;
6471 case OMPD_dispatch:
6472 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6473 EndLoc);
6474 break;
6475 case OMPD_loop:
6476 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6477 EndLoc, VarsWithInheritedDSA);
6478 break;
6479 case OMPD_teams_loop:
6481 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6482 break;
6483 case OMPD_target_teams_loop:
6485 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6486 break;
6487 case OMPD_parallel_loop:
6489 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6490 break;
6491 case OMPD_target_parallel_loop:
6493 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6494 break;
6495 case OMPD_declare_target:
6496 case OMPD_end_declare_target:
6497 case OMPD_threadprivate:
6498 case OMPD_allocate:
6499 case OMPD_declare_reduction:
6500 case OMPD_declare_mapper:
6501 case OMPD_declare_simd:
6502 case OMPD_requires:
6503 case OMPD_declare_variant:
6504 case OMPD_begin_declare_variant:
6505 case OMPD_end_declare_variant:
6506 llvm_unreachable("OpenMP Directive is not allowed");
6507 case OMPD_unknown:
6508 default:
6509 llvm_unreachable("Unknown OpenMP directive");
6510 }
6511
6512 ErrorFound = Res.isInvalid() || ErrorFound;
6513
6514 // Check variables in the clauses if default(none) or
6515 // default(firstprivate) was specified.
6516 if (DSAStack->getDefaultDSA() == DSA_none ||
6517 DSAStack->getDefaultDSA() == DSA_private ||
6518 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6519 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6520 for (OMPClause *C : Clauses) {
6521 switch (C->getClauseKind()) {
6522 case OMPC_num_threads:
6523 case OMPC_dist_schedule:
6524 // Do not analyze if no parent teams directive.
6525 if (isOpenMPTeamsDirective(Kind))
6526 break;
6527 continue;
6528 case OMPC_if:
6529 if (isOpenMPTeamsDirective(Kind) &&
6530 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6531 break;
6532 if (isOpenMPParallelDirective(Kind) &&
6534 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6535 break;
6536 continue;
6537 case OMPC_schedule:
6538 case OMPC_detach:
6539 break;
6540 case OMPC_grainsize:
6541 case OMPC_num_tasks:
6542 case OMPC_final:
6543 case OMPC_priority:
6544 case OMPC_novariants:
6545 case OMPC_nocontext:
6546 // Do not analyze if no parent parallel directive.
6547 if (isOpenMPParallelDirective(Kind))
6548 break;
6549 continue;
6550 case OMPC_ordered:
6551 case OMPC_device:
6552 case OMPC_num_teams:
6553 case OMPC_thread_limit:
6554 case OMPC_hint:
6555 case OMPC_collapse:
6556 case OMPC_safelen:
6557 case OMPC_simdlen:
6558 case OMPC_sizes:
6559 case OMPC_default:
6560 case OMPC_proc_bind:
6561 case OMPC_private:
6562 case OMPC_firstprivate:
6563 case OMPC_lastprivate:
6564 case OMPC_shared:
6565 case OMPC_reduction:
6566 case OMPC_task_reduction:
6567 case OMPC_in_reduction:
6568 case OMPC_linear:
6569 case OMPC_aligned:
6570 case OMPC_copyin:
6571 case OMPC_copyprivate:
6572 case OMPC_nowait:
6573 case OMPC_untied:
6574 case OMPC_mergeable:
6575 case OMPC_allocate:
6576 case OMPC_read:
6577 case OMPC_write:
6578 case OMPC_update:
6579 case OMPC_capture:
6580 case OMPC_compare:
6581 case OMPC_seq_cst:
6582 case OMPC_acq_rel:
6583 case OMPC_acquire:
6584 case OMPC_release:
6585 case OMPC_relaxed:
6586 case OMPC_depend:
6587 case OMPC_threads:
6588 case OMPC_simd:
6589 case OMPC_map:
6590 case OMPC_nogroup:
6591 case OMPC_defaultmap:
6592 case OMPC_to:
6593 case OMPC_from:
6594 case OMPC_use_device_ptr:
6595 case OMPC_use_device_addr:
6596 case OMPC_is_device_ptr:
6597 case OMPC_has_device_addr:
6598 case OMPC_nontemporal:
6599 case OMPC_order:
6600 case OMPC_destroy:
6601 case OMPC_inclusive:
6602 case OMPC_exclusive:
6603 case OMPC_uses_allocators:
6604 case OMPC_affinity:
6605 case OMPC_bind:
6606 case OMPC_filter:
6607 continue;
6608 case OMPC_allocator:
6609 case OMPC_flush:
6610 case OMPC_depobj:
6611 case OMPC_threadprivate:
6612 case OMPC_uniform:
6613 case OMPC_unknown:
6614 case OMPC_unified_address:
6615 case OMPC_unified_shared_memory:
6616 case OMPC_reverse_offload:
6617 case OMPC_dynamic_allocators:
6618 case OMPC_atomic_default_mem_order:
6619 case OMPC_device_type:
6620 case OMPC_match:
6621 case OMPC_when:
6622 case OMPC_at:
6623 case OMPC_severity:
6624 case OMPC_message:
6625 default:
6626 llvm_unreachable("Unexpected clause");
6627 }
6628 for (Stmt *CC : C->children()) {
6629 if (CC)
6630 DSAChecker.Visit(CC);
6631 }
6632 }
6633 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6634 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6635 }
6636 for (const auto &P : VarsWithInheritedDSA) {
6637 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6638 continue;
6639 ErrorFound = true;
6640 if (DSAStack->getDefaultDSA() == DSA_none ||
6641 DSAStack->getDefaultDSA() == DSA_private ||
6642 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6643 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6644 << P.first << P.second->getSourceRange();
6645 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6646 } else if (getLangOpts().OpenMP >= 50) {
6647 Diag(P.second->getExprLoc(),
6648 diag::err_omp_defaultmap_no_attr_for_variable)
6649 << P.first << P.second->getSourceRange();
6650 Diag(DSAStack->getDefaultDSALocation(),
6651 diag::note_omp_defaultmap_attr_none);
6652 }
6653 }
6654
6655 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6656 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6657 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6658 AllowedNameModifiers.push_back(D);
6659 }
6660 if (!AllowedNameModifiers.empty())
6661 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6662 ErrorFound;
6663
6664 if (ErrorFound)
6665 return StmtError();
6666
6669 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6670 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6671 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6672 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6673 // Register target to DSA Stack.
6674 DSAStack->addTargetDirLocation(StartLoc);
6675 }
6676
6677 return Res;
6678}
6679
6681 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6682 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6683 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6684 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6685 assert(Aligneds.size() == Alignments.size());
6686 assert(Linears.size() == LinModifiers.size());
6687 assert(Linears.size() == Steps.size());
6688 if (!DG || DG.get().isNull())
6689 return DeclGroupPtrTy();
6690
6691 const int SimdId = 0;
6692 if (!DG.get().isSingleDecl()) {
6693 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6694 << SimdId;
6695 return DG;
6696 }
6697 Decl *ADecl = DG.get().getSingleDecl();
6698 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6699 ADecl = FTD->getTemplatedDecl();
6700
6701 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6702 if (!FD) {
6703 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6704 return DeclGroupPtrTy();
6705 }
6706
6707 // OpenMP [2.8.2, declare simd construct, Description]
6708 // The parameter of the simdlen clause must be a constant positive integer
6709 // expression.
6710 ExprResult SL;
6711 if (Simdlen)
6712 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6713 // OpenMP [2.8.2, declare simd construct, Description]
6714 // The special this pointer can be used as if was one of the arguments to the
6715 // function in any of the linear, aligned, or uniform clauses.
6716 // The uniform clause declares one or more arguments to have an invariant
6717 // value for all concurrent invocations of the function in the execution of a
6718 // single SIMD loop.
6719 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6720 const Expr *UniformedLinearThis = nullptr;
6721 for (const Expr *E : Uniforms) {
6722 E = E->IgnoreParenImpCasts();
6723 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6724 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6725 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6726 FD->getParamDecl(PVD->getFunctionScopeIndex())
6727 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6728 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6729 continue;
6730 }
6731 if (isa<CXXThisExpr>(E)) {
6732 UniformedLinearThis = E;
6733 continue;
6734 }
6735 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6736 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6737 }
6738 // OpenMP [2.8.2, declare simd construct, Description]
6739 // The aligned clause declares that the object to which each list item points
6740 // is aligned to the number of bytes expressed in the optional parameter of
6741 // the aligned clause.
6742 // The special this pointer can be used as if was one of the arguments to the
6743 // function in any of the linear, aligned, or uniform clauses.
6744 // The type of list items appearing in the aligned clause must be array,
6745 // pointer, reference to array, or reference to pointer.
6746 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6747 const Expr *AlignedThis = nullptr;
6748 for (const Expr *E : Aligneds) {
6749 E = E->IgnoreParenImpCasts();
6750 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6751 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6752 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6753 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6754 FD->getParamDecl(PVD->getFunctionScopeIndex())
6755 ->getCanonicalDecl() == CanonPVD) {
6756 // OpenMP [2.8.1, simd construct, Restrictions]
6757 // A list-item cannot appear in more than one aligned clause.
6758 if (AlignedArgs.count(CanonPVD) > 0) {
6759 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6760 << 1 << getOpenMPClauseName(OMPC_aligned)
6761 << E->getSourceRange();
6762 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6763 diag::note_omp_explicit_dsa)
6764 << getOpenMPClauseName(OMPC_aligned);
6765 continue;
6766 }
6767 AlignedArgs[CanonPVD] = E;
6768 QualType QTy = PVD->getType()
6769 .getNonReferenceType()
6770 .getUnqualifiedType()
6771 .getCanonicalType();
6772 const Type *Ty = QTy.getTypePtrOrNull();
6773 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6774 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6775 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6776 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6777 }
6778 continue;
6779 }
6780 }
6781 if (isa<CXXThisExpr>(E)) {
6782 if (AlignedThis) {
6783 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6784 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6785 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6786 << getOpenMPClauseName(OMPC_aligned);
6787 }
6788 AlignedThis = E;
6789 continue;
6790 }
6791 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6792 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6793 }
6794 // The optional parameter of the aligned clause, alignment, must be a constant
6795 // positive integer expression. If no optional parameter is specified,
6796 // implementation-defined default alignments for SIMD instructions on the
6797 // target platforms are assumed.
6799 for (Expr *E : Alignments) {
6800 ExprResult Align;
6801 if (E)
6802 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6803 NewAligns.push_back(Align.get());
6804 }
6805 // OpenMP [2.8.2, declare simd construct, Description]
6806 // The linear clause declares one or more list items to be private to a SIMD
6807 // lane and to have a linear relationship with respect to the iteration space
6808 // of a loop.
6809 // The special this pointer can be used as if was one of the arguments to the
6810 // function in any of the linear, aligned, or uniform clauses.
6811 // When a linear-step expression is specified in a linear clause it must be
6812 // either a constant integer expression or an integer-typed parameter that is
6813 // specified in a uniform clause on the directive.
6814 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6815 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6816 auto MI = LinModifiers.begin();
6817 for (const Expr *E : Linears) {
6818 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6819 ++MI;
6820 E = E->IgnoreParenImpCasts();
6821 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6822 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6823 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6824 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6825 FD->getParamDecl(PVD->getFunctionScopeIndex())
6826 ->getCanonicalDecl() == CanonPVD) {
6827 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6828 // A list-item cannot appear in more than one linear clause.
6829 if (LinearArgs.count(CanonPVD) > 0) {
6830 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6831 << getOpenMPClauseName(OMPC_linear)
6832 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6833 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6834 diag::note_omp_explicit_dsa)
6835 << getOpenMPClauseName(OMPC_linear);
6836 continue;
6837 }
6838 // Each argument can appear in at most one uniform or linear clause.
6839 if (UniformedArgs.count(CanonPVD) > 0) {
6840 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6841 << getOpenMPClauseName(OMPC_linear)
6842 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
6843 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6844 diag::note_omp_explicit_dsa)
6845 << getOpenMPClauseName(OMPC_uniform);
6846 continue;
6847 }
6848 LinearArgs[CanonPVD] = E;
6849 if (E->isValueDependent() || E->isTypeDependent() ||
6852 continue;
6853 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6854 PVD->getOriginalType(),
6855 /*IsDeclareSimd=*/true);
6856 continue;
6857 }
6858 }
6859 if (isa<CXXThisExpr>(E)) {
6860 if (UniformedLinearThis) {
6861 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6862 << getOpenMPClauseName(OMPC_linear)
6863 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6864 << E->getSourceRange();
6865 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6866 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6867 : OMPC_linear);
6868 continue;
6869 }
6870 UniformedLinearThis = E;
6871 if (E->isValueDependent() || E->isTypeDependent() ||
6873 continue;
6874 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6875 E->getType(), /*IsDeclareSimd=*/true);
6876 continue;
6877 }
6878 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6879 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6880 }
6881 Expr *Step = nullptr;
6882 Expr *NewStep = nullptr;
6883 SmallVector<Expr *, 4> NewSteps;
6884 for (Expr *E : Steps) {
6885 // Skip the same step expression, it was checked already.
6886 if (Step == E || !E) {
6887 NewSteps.push_back(E ? NewStep : nullptr);
6888 continue;
6889 }
6890 Step = E;
6891 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6892 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6893 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6894 if (UniformedArgs.count(CanonPVD) == 0) {
6895 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6896 << Step->getSourceRange();
6897 } else if (E->isValueDependent() || E->isTypeDependent() ||
6900 CanonPVD->getType()->hasIntegerRepresentation()) {
6901 NewSteps.push_back(Step);
6902 } else {
6903 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6904 << Step->getSourceRange();
6905 }
6906 continue;
6907 }
6908 NewStep = Step;
6909 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6910 !Step->isInstantiationDependent() &&
6912 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6913 .get();
6914 if (NewStep)
6915 NewStep = SemaRef
6917 NewStep, /*FIXME*/ Sema::AllowFold)
6918 .get();
6919 }
6920 NewSteps.push_back(NewStep);
6921 }
6922 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6923 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
6924 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
6925 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
6926 const_cast<Expr **>(Linears.data()), Linears.size(),
6927 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
6928 NewSteps.data(), NewSteps.size(), SR);
6929 ADecl->addAttr(NewAttr);
6930 return DG;
6931}
6932
6933static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6934 QualType NewType) {
6935 assert(NewType->isFunctionProtoType() &&
6936 "Expected function type with prototype.");
6937 assert(FD->getType()->isFunctionNoProtoType() &&
6938 "Expected function with type with no prototype.");
6939 assert(FDWithProto->getType()->isFunctionProtoType() &&
6940 "Expected function with prototype.");
6941 // Synthesize parameters with the same types.
6942 FD->setType(NewType);
6944 for (const ParmVarDecl *P : FDWithProto->parameters()) {
6945 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
6946 SourceLocation(), nullptr, P->getType(),
6947 /*TInfo=*/nullptr, SC_None, nullptr);
6948 Param->setScopeInfo(0, Params.size());
6949 Param->setImplicit();
6950 Params.push_back(Param);
6951 }
6952
6953 FD->setParams(Params);
6954}
6955
6957 if (D->isInvalidDecl())
6958 return;
6959 FunctionDecl *FD = nullptr;
6960 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
6961 FD = UTemplDecl->getTemplatedDecl();
6962 else
6963 FD = cast<FunctionDecl>(D);
6964 assert(FD && "Expected a function declaration!");
6965
6966 // If we are instantiating templates we do *not* apply scoped assumptions but
6967 // only global ones. We apply scoped assumption to the template definition
6968 // though.
6970 for (OMPAssumeAttr *AA : OMPAssumeScoped)
6971 FD->addAttr(AA);
6972 }
6973 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
6974 FD->addAttr(AA);
6975}
6976
6977SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
6978 : TI(&TI), NameSuffix(TI.getMangledName()) {}
6979
6981 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
6983 if (!D.getIdentifier())
6984 return;
6985
6986 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
6987
6988 // Template specialization is an extension, check if we do it.
6989 bool IsTemplated = !TemplateParamLists.empty();
6990 if (IsTemplated &&
6991 !DVScope.TI->isExtensionActive(
6992 llvm::omp::TraitProperty::implementation_extension_allow_templates))
6993 return;
6994
6995 const IdentifierInfo *BaseII = D.getIdentifier();
6996 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
6998 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
6999 /*ObjectType=*/QualType());
7000
7002 QualType FType = TInfo->getType();
7003
7004 bool IsConstexpr =
7005 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7006 bool IsConsteval =
7007 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7008
7009 for (auto *Candidate : Lookup) {
7010 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7011 FunctionDecl *UDecl = nullptr;
7012 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7013 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7014 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7015 UDecl = FTD->getTemplatedDecl();
7016 } else if (!IsTemplated)
7017 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7018 if (!UDecl)
7019 continue;
7020
7021 // Don't specialize constexpr/consteval functions with
7022 // non-constexpr/consteval functions.
7023 if (UDecl->isConstexpr() && !IsConstexpr)
7024 continue;
7025 if (UDecl->isConsteval() && !IsConsteval)
7026 continue;
7027
7028 QualType UDeclTy = UDecl->getType();
7029 if (!UDeclTy->isDependentType()) {
7031 FType, UDeclTy, /* OfBlockPointer */ false,
7032 /* Unqualified */ false, /* AllowCXX */ true);
7033 if (NewType.isNull())
7034 continue;
7035 }
7036
7037 // Found a base!
7038 Bases.push_back(UDecl);
7039 }
7040
7041 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7042 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7043 // If no base was found we create a declaration that we use as base.
7044 if (Bases.empty() && UseImplicitBase) {
7045 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7046 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7047 BaseD->setImplicit(true);
7048 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7049 Bases.push_back(BaseTemplD->getTemplatedDecl());
7050 else
7051 Bases.push_back(cast<FunctionDecl>(BaseD));
7052 }
7053
7054 std::string MangledName;
7055 MangledName += D.getIdentifier()->getName();
7056 MangledName += getOpenMPVariantManglingSeparatorStr();
7057 MangledName += DVScope.NameSuffix;
7058 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7059
7060 VariantII.setMangledOpenMPVariantName(true);
7061 D.SetIdentifier(&VariantII, D.getBeginLoc());
7062}
7063
7066 // Do not mark function as is used to prevent its emission if this is the
7067 // only place where it is used.
7070
7071 FunctionDecl *FD = nullptr;
7072 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7073 FD = UTemplDecl->getTemplatedDecl();
7074 else
7075 FD = cast<FunctionDecl>(D);
7076 auto *VariantFuncRef = DeclRefExpr::Create(
7078 /* RefersToEnclosingVariableOrCapture */ false,
7079 /* NameLoc */ FD->getLocation(), FD->getType(),
7081
7082 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7083 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7084 getASTContext(), VariantFuncRef, DVScope.TI,
7085 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7086 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7087 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7088 for (FunctionDecl *BaseFD : Bases)
7089 BaseFD->addAttr(OMPDeclareVariantA);
7090}
7091
7093 SourceLocation LParenLoc,
7094 MultiExprArg ArgExprs,
7095 SourceLocation RParenLoc,
7096 Expr *ExecConfig) {
7097 // The common case is a regular call we do not want to specialize at all. Try
7098 // to make that case fast by bailing early.
7099 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7100 if (!CE)
7101 return Call;
7102
7103 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7104 if (!CalleeFnDecl)
7105 return Call;
7106
7107 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7108 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7109 // checking for any calls inside an Order region
7111 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7112 }
7113
7114 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7115 return Call;
7116
7117 ASTContext &Context = getASTContext();
7118 std::function<void(StringRef)> DiagUnknownTrait = [this,
7119 CE](StringRef ISATrait) {
7120 // TODO Track the selector locations in a way that is accessible here to
7121 // improve the diagnostic location.
7122 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7123 << ISATrait;
7124 };
7125 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7127 DSAStack->getConstructTraits());
7128
7129 QualType CalleeFnType = CalleeFnDecl->getType();
7130
7133 while (CalleeFnDecl) {
7134 for (OMPDeclareVariantAttr *A :
7135 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7136 Expr *VariantRef = A->getVariantFuncRef();
7137
7138 VariantMatchInfo VMI;
7139 OMPTraitInfo &TI = A->getTraitInfo();
7140 TI.getAsVariantMatchInfo(Context, VMI);
7141 if (!isVariantApplicableInContext(VMI, OMPCtx,
7142 /* DeviceSetOnly */ false))
7143 continue;
7144
7145 VMIs.push_back(VMI);
7146 Exprs.push_back(VariantRef);
7147 }
7148
7149 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7150 }
7151
7152 ExprResult NewCall;
7153 do {
7154 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7155 if (BestIdx < 0)
7156 return Call;
7157 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7158 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7159
7160 {
7161 // Try to build a (member) call expression for the current best applicable
7162 // variant expression. We allow this to fail in which case we continue
7163 // with the next best variant expression. The fail case is part of the
7164 // implementation defined behavior in the OpenMP standard when it talks
7165 // about what differences in the function prototypes: "Any differences
7166 // that the specific OpenMP context requires in the prototype of the
7167 // variant from the base function prototype are implementation defined."
7168 // This wording is there to allow the specialized variant to have a
7169 // different type than the base function. This is intended and OK but if
7170 // we cannot create a call the difference is not in the "implementation
7171 // defined range" we allow.
7173
7174 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7175 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7176 BestExpr = MemberExpr::CreateImplicit(
7177 Context, MemberCall->getImplicitObjectArgument(),
7178 /* IsArrow */ false, SpecializedMethod, Context.BoundMemberTy,
7179 MemberCall->getValueKind(), MemberCall->getObjectKind());
7180 }
7181 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7182 RParenLoc, ExecConfig);
7183 if (NewCall.isUsable()) {
7184 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7185 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7187 CalleeFnType, NewCalleeFnDecl->getType(),
7188 /* OfBlockPointer */ false,
7189 /* Unqualified */ false, /* AllowCXX */ true);
7190 if (!NewType.isNull())
7191 break;
7192 // Don't use the call if the function type was not compatible.
7193 NewCall = nullptr;
7194 }
7195 }
7196 }
7197
7198 VMIs.erase(VMIs.begin() + BestIdx);
7199 Exprs.erase(Exprs.begin() + BestIdx);
7200 } while (!VMIs.empty());
7201
7202 if (!NewCall.isUsable())
7203 return Call;
7204 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7205}
7206
7207std::optional<std::pair<FunctionDecl *, Expr *>>
7209 Expr *VariantRef,
7210 OMPTraitInfo &TI,
7211 unsigned NumAppendArgs,
7212 SourceRange SR) {
7213 ASTContext &Context = getASTContext();
7214 if (!DG || DG.get().isNull())
7215 return std::nullopt;
7216
7217 const int VariantId = 1;
7218 // Must be applied only to single decl.
7219 if (!DG.get().isSingleDecl()) {
7220 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7221 << VariantId << SR;
7222 return std::nullopt;
7223 }
7224 Decl *ADecl = DG.get().getSingleDecl();
7225 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7226 ADecl = FTD->getTemplatedDecl();
7227
7228 // Decl must be a function.
7229 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7230 if (!FD) {
7231 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7232 << VariantId << SR;
7233 return std::nullopt;
7234 }
7235
7236 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7237 // The 'target' attribute needs to be separately checked because it does
7238 // not always signify a multiversion function declaration.
7239 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7240 };
7241 // OpenMP is not compatible with multiversion function attributes.
7242 if (HasMultiVersionAttributes(FD)) {
7243 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7244 << SR;
7245 return std::nullopt;
7246 }
7247
7248 // Allow #pragma omp declare variant only if the function is not used.
7249 if (FD->isUsed(false))
7250 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7251 << FD->getLocation();
7252
7253 // Check if the function was emitted already.
7254 const FunctionDecl *Definition;
7255 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7256 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7257 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7258 << FD->getLocation();
7259
7260 // The VariantRef must point to function.
7261 if (!VariantRef) {
7262 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7263 return std::nullopt;
7264 }
7265
7266 auto ShouldDelayChecks = [](Expr *&E, bool) {
7267 return E && (E->isTypeDependent() || E->isValueDependent() ||
7270 };
7271 // Do not check templates, wait until instantiation.
7272 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7273 TI.anyScoreOrCondition(ShouldDelayChecks))
7274 return std::make_pair(FD, VariantRef);
7275
7276 // Deal with non-constant score and user condition expressions.
7277 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7278 bool IsScore) -> bool {
7280 return false;
7281
7282 if (IsScore) {
7283 // We warn on non-constant scores and pretend they were not present.
7284 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7285 << E;
7286 E = nullptr;
7287 } else {
7288 // We could replace a non-constant user condition with "false" but we
7289 // will soon need to handle these anyway for the dynamic version of
7290 // OpenMP context selectors.
7291 Diag(E->getExprLoc(),
7292 diag::err_omp_declare_variant_user_condition_not_constant)
7293 << E;
7294 }
7295 return true;
7296 };
7297 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7298 return std::nullopt;
7299
7300 QualType AdjustedFnType = FD->getType();
7301 if (NumAppendArgs) {
7302 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7303 if (!PTy) {
7304 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7305 << SR;
7306 return std::nullopt;
7307 }
7308 // Adjust the function type to account for an extra omp_interop_t for each
7309 // specified in the append_args clause.
7310 const TypeDecl *TD = nullptr;
7311 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7314 NamedDecl *ND = Result.getFoundDecl();
7315 TD = dyn_cast_or_null<TypeDecl>(ND);
7316 }
7317 if (!TD) {
7318 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7319 return std::nullopt;
7320 }
7321 QualType InteropType = Context.getTypeDeclType(TD);
7322 if (PTy->isVariadic()) {
7323 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7324 return std::nullopt;
7325 }
7327 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7328 Params.insert(Params.end(), NumAppendArgs, InteropType);
7329 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7330 PTy->getExtProtoInfo());
7331 }
7332
7333 // Convert VariantRef expression to the type of the original function to
7334 // resolve possible conflicts.
7335 ExprResult VariantRefCast = VariantRef;
7336 if (getLangOpts().CPlusPlus) {
7337 QualType FnPtrType;
7338 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7339 if (Method && !Method->isStatic()) {
7340 const Type *ClassType =
7341 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7342 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7343 ExprResult ER;
7344 {
7345 // Build addr_of unary op to correctly handle type checks for member
7346 // functions.
7348 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7349 VariantRef);
7350 }
7351 if (!ER.isUsable()) {
7352 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7353 << VariantId << VariantRef->getSourceRange();
7354 return std::nullopt;
7355 }
7356 VariantRef = ER.get();
7357 } else {
7358 FnPtrType = Context.getPointerType(AdjustedFnType);
7359 }
7360 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7361 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7363 VariantRef, FnPtrType.getUnqualifiedType(),
7364 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7365 /*InOverloadResolution=*/false,
7366 /*CStyle=*/false,
7367 /*AllowObjCWritebackConversion=*/false);
7368 if (ICS.isFailure()) {
7369 Diag(VariantRef->getExprLoc(),
7370 diag::err_omp_declare_variant_incompat_types)
7371 << VariantRef->getType()
7372 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7373 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7374 return std::nullopt;
7375 }
7376 VariantRefCast = SemaRef.PerformImplicitConversion(
7377 VariantRef, FnPtrType.getUnqualifiedType(), Sema::AA_Converting);
7378 if (!VariantRefCast.isUsable())
7379 return std::nullopt;
7380 }
7381 // Drop previously built artificial addr_of unary op for member functions.
7382 if (Method && !Method->isStatic()) {
7383 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7384 if (auto *UO = dyn_cast<UnaryOperator>(
7385 PossibleAddrOfVariantRef->IgnoreImplicit()))
7386 VariantRefCast = UO->getSubExpr();
7387 }
7388 }
7389
7390 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7391 if (!ER.isUsable() ||
7393 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7394 << VariantId << VariantRef->getSourceRange();
7395 return std::nullopt;
7396 }
7397
7398 // The VariantRef must point to function.
7399 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7400 if (!DRE) {
7401 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7402 << VariantId << VariantRef->getSourceRange();
7403 return std::nullopt;
7404 }
7405 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7406 if (!NewFD) {
7407 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7408 << VariantId << VariantRef->getSourceRange();
7409 return std::nullopt;
7410 }
7411
7412 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7413 Diag(VariantRef->getExprLoc(),
7414 diag::err_omp_declare_variant_same_base_function)
7415 << VariantRef->getSourceRange();
7416 return std::nullopt;
7417 }
7418
7419 // Check if function types are compatible in C.
7420 if (!getLangOpts().CPlusPlus) {
7421 QualType NewType =
7422 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7423 if (NewType.isNull()) {
7424 Diag(VariantRef->getExprLoc(),
7425 diag::err_omp_declare_variant_incompat_types)
7426 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7427 << VariantRef->getSourceRange();
7428 return std::nullopt;
7429 }
7430 if (NewType->isFunctionProtoType()) {
7431 if (FD->getType()->isFunctionNoProtoType())
7432 setPrototype(SemaRef, FD, NewFD, NewType);
7433 else if (NewFD->getType()->isFunctionNoProtoType())
7434 setPrototype(SemaRef, NewFD, FD, NewType);
7435 }
7436 }
7437
7438 // Check if variant function is not marked with declare variant directive.
7439 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7440 Diag(VariantRef->getExprLoc(),
7441 diag::warn_omp_declare_variant_marked_as_declare_variant)
7442 << VariantRef->getSourceRange();
7443 SourceRange SR =
7444 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7445 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7446 return std::nullopt;
7447 }
7448
7449 enum DoesntSupport {
7450 VirtFuncs = 1,
7451 Constructors = 3,
7452 Destructors = 4,
7453 DeletedFuncs = 5,
7454 DefaultedFuncs = 6,
7455 ConstexprFuncs = 7,
7456 ConstevalFuncs = 8,
7457 };
7458 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7459 if (CXXFD->isVirtual()) {
7460 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7461 << VirtFuncs;
7462 return std::nullopt;
7463 }
7464
7465 if (isa<CXXConstructorDecl>(FD)) {
7466 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7467 << Constructors;
7468 return std::nullopt;
7469 }
7470
7471 if (isa<CXXDestructorDecl>(FD)) {
7472 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7473 << Destructors;
7474 return std::nullopt;
7475 }
7476 }
7477
7478 if (FD->isDeleted()) {
7479 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7480 << DeletedFuncs;
7481 return std::nullopt;
7482 }
7483
7484 if (FD->isDefaulted()) {
7485 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7486 << DefaultedFuncs;
7487 return std::nullopt;
7488 }
7489
7490 if (FD->isConstexpr()) {
7491 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7492 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7493 return std::nullopt;
7494 }
7495
7496 // Check general compatibility.
7502 VariantRef->getExprLoc(),
7503 PDiag(diag::err_omp_declare_variant_doesnt_support)),
7504 PartialDiagnosticAt(VariantRef->getExprLoc(),
7505 PDiag(diag::err_omp_declare_variant_diff)
7506 << FD->getLocation()),
7507 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7508 /*CLinkageMayDiffer=*/true))
7509 return std::nullopt;
7510 return std::make_pair(FD, cast<Expr>(DRE));
7511}
7512
7514 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7515 ArrayRef<Expr *> AdjustArgsNothing,
7516 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7517 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7518 SourceLocation AppendArgsLoc, SourceRange SR) {
7519
7520 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7521 // An adjust_args clause or append_args clause can only be specified if the
7522 // dispatch selector of the construct selector set appears in the match
7523 // clause.
7524
7525 SmallVector<Expr *, 8> AllAdjustArgs;
7526 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7527 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7528
7529 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7530 VariantMatchInfo VMI;
7532 if (!llvm::is_contained(
7533 VMI.ConstructTraits,
7534 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7535 if (!AllAdjustArgs.empty())
7536 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7537 << getOpenMPClauseName(OMPC_adjust_args);
7538 if (!AppendArgs.empty())
7539 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7540 << getOpenMPClauseName(OMPC_append_args);
7541 return;
7542 }
7543 }
7544
7545 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7546 // Each argument can only appear in a single adjust_args clause for each
7547 // declare variant directive.
7549
7550 for (Expr *E : AllAdjustArgs) {
7551 E = E->IgnoreParenImpCasts();
7552 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7553 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7554 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7555 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7556 FD->getParamDecl(PVD->getFunctionScopeIndex())
7557 ->getCanonicalDecl() == CanonPVD) {
7558 // It's a parameter of the function, check duplicates.
7559 if (!AdjustVars.insert(CanonPVD).second) {
7560 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7561 << PVD;
7562 return;
7563 }
7564 continue;
7565 }
7566 }
7567 }
7568 // Anything that is not a function parameter is an error.
7569 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7570 return;
7571 }
7572
7573 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7574 getASTContext(), VariantRef, &TI,
7575 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7576 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7577 AdjustArgsNeedDevicePtr.size(),
7578 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7579 FD->addAttr(NewAttr);
7580}
7581
7582static CapturedStmt *
7584 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7585 assert(CS && "Captured statement expected");
7586 // 1.2.2 OpenMP Language Terminology
7587 // Structured block - An executable statement with a single entry at the
7588 // top and a single exit at the bottom.
7589 // The point of exit cannot be a branch out of the structured block.
7590 // longjmp() and throw() must not violate the entry/exit criteria.
7591 CS->getCapturedDecl()->setNothrow();
7592
7593 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7594 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7595 CS = cast<CapturedStmt>(CS->getCapturedStmt());
7596 // 1.2.2 OpenMP Language Terminology
7597 // Structured block - An executable statement with a single entry at the
7598 // top and a single exit at the bottom.
7599 // The point of exit cannot be a branch out of the structured block.
7600 // longjmp() and throw() must not violate the entry/exit criteria.
7601 CS->getCapturedDecl()->setNothrow();
7602 }
7604 return CS;
7605}
7606
7609 Stmt *AStmt, SourceLocation StartLoc,
7610 SourceLocation EndLoc) {
7611 if (!AStmt)
7612 return StmtError();
7613
7614 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7615
7617 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7618 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7619}
7620
7621namespace {
7622/// Iteration space of a single for loop.
7623struct LoopIterationSpace final {
7624 /// True if the condition operator is the strict compare operator (<, > or
7625 /// !=).
7626 bool IsStrictCompare = false;
7627 /// Condition of the loop.
7628 Expr *PreCond = nullptr;
7629 /// This expression calculates the number of iterations in the loop.
7630 /// It is always possible to calculate it before starting the loop.
7631 Expr *NumIterations = nullptr;
7632 /// The loop counter variable.
7633 Expr *CounterVar = nullptr;
7634 /// Private loop counter variable.
7635 Expr *PrivateCounterVar = nullptr;
7636 /// This is initializer for the initial value of #CounterVar.
7637 Expr *CounterInit = nullptr;
7638 /// This is step for the #CounterVar used to generate its update:
7639 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7640 Expr *CounterStep = nullptr;
7641 /// Should step be subtracted?
7642 bool Subtract = false;
7643 /// Source range of the loop init.
7644 SourceRange InitSrcRange;
7645 /// Source range of the loop condition.
7646 SourceRange CondSrcRange;
7647 /// Source range of the loop increment.
7648 SourceRange IncSrcRange;
7649 /// Minimum value that can have the loop control variable. Used to support
7650 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7651 /// since only such variables can be used in non-loop invariant expressions.
7652 Expr *MinValue = nullptr;
7653 /// Maximum value that can have the loop control variable. Used to support
7654 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7655 /// since only such variables can be used in non-loop invariant expressions.
7656 Expr *MaxValue = nullptr;
7657 /// true, if the lower bound depends on the outer loop control var.
7658 bool IsNonRectangularLB = false;
7659 /// true, if the upper bound depends on the outer loop control var.
7660 bool IsNonRectangularUB = false;
7661 /// Index of the loop this loop depends on and forms non-rectangular loop
7662 /// nest.
7663 unsigned LoopDependentIdx = 0;
7664 /// Final condition for the non-rectangular loop nest support. It is used to
7665 /// check that the number of iterations for this particular counter must be
7666 /// finished.
7667 Expr *FinalCondition = nullptr;
7668};
7669
7670/// Helper class for checking canonical form of the OpenMP loops and
7671/// extracting iteration space of each loop in the loop nest, that will be used
7672/// for IR generation.
7673class OpenMPIterationSpaceChecker {
7674 /// Reference to Sema.
7675 Sema &SemaRef;
7676 /// Does the loop associated directive support non-rectangular loops?
7677 bool SupportsNonRectangular;
7678 /// Data-sharing stack.
7679 DSAStackTy &Stack;
7680 /// A location for diagnostics (when there is no some better location).
7681 SourceLocation DefaultLoc;
7682 /// A location for diagnostics (when increment is not compatible).
7683 SourceLocation ConditionLoc;
7684 /// A source location for referring to loop init later.
7685 SourceRange InitSrcRange;
7686 /// A source location for referring to condition later.
7687 SourceRange ConditionSrcRange;
7688 /// A source location for referring to increment later.
7689 SourceRange IncrementSrcRange;
7690 /// Loop variable.
7691 ValueDecl *LCDecl = nullptr;
7692 /// Reference to loop variable.
7693 Expr *LCRef = nullptr;
7694 /// Lower bound (initializer for the var).
7695 Expr *LB = nullptr;
7696 /// Upper bound.
7697 Expr *UB = nullptr;
7698 /// Loop step (increment).
7699 Expr *Step = nullptr;
7700 /// This flag is true when condition is one of:
7701 /// Var < UB
7702 /// Var <= UB
7703 /// UB > Var
7704 /// UB >= Var
7705 /// This will have no value when the condition is !=
7706 std::optional<bool> TestIsLessOp;
7707 /// This flag is true when condition is strict ( < or > ).
7708 bool TestIsStrictOp = false;
7709 /// This flag is true when step is subtracted on each iteration.
7710 bool SubtractStep = false;
7711 /// The outer loop counter this loop depends on (if any).
7712 const ValueDecl *DepDecl = nullptr;
7713 /// Contains number of loop (starts from 1) on which loop counter init
7714 /// expression of this loop depends on.
7715 std::optional<unsigned> InitDependOnLC;
7716 /// Contains number of loop (starts from 1) on which loop counter condition
7717 /// expression of this loop depends on.
7718 std::optional<unsigned> CondDependOnLC;
7719 /// Checks if the provide statement depends on the loop counter.
7720 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7721 bool IsInitializer);
7722 /// Original condition required for checking of the exit condition for
7723 /// non-rectangular loop.
7724 Expr *Condition = nullptr;
7725
7726public:
7727 OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7728 DSAStackTy &Stack, SourceLocation DefaultLoc)
7729 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7730 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7731 /// Check init-expr for canonical loop form and save loop counter
7732 /// variable - #Var and its initialization value - #LB.
7733 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7734 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7735 /// for less/greater and for strict/non-strict comparison.
7736 bool checkAndSetCond(Expr *S);
7737 /// Check incr-expr for canonical loop form and return true if it
7738 /// does not conform, otherwise save loop step (#Step).
7739 bool checkAndSetInc(Expr *S);
7740 /// Return the loop counter variable.
7741 ValueDecl *getLoopDecl() const { return LCDecl; }
7742 /// Return the reference expression to loop counter variable.
7743 Expr *getLoopDeclRefExpr() const { return LCRef; }
7744 /// Source range of the loop init.
7745 SourceRange getInitSrcRange() const { return InitSrcRange; }
7746 /// Source range of the loop condition.
7747 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7748 /// Source range of the loop increment.
7749 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7750 /// True if the step should be subtracted.
7751 bool shouldSubtractStep() const { return SubtractStep; }
7752 /// True, if the compare operator is strict (<, > or !=).
7753 bool isStrictTestOp() const { return TestIsStrictOp; }
7754 /// Build the expression to calculate the number of iterations.
7755 Expr *buildNumIterations(
7756 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7757 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7758 /// Build the precondition expression for the loops.
7759 Expr *
7760 buildPreCond(Scope *S, Expr *Cond,
7761 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7762 /// Build reference expression to the counter be used for codegen.
7763 DeclRefExpr *
7764 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7765 DSAStackTy &DSA) const;
7766 /// Build reference expression to the private counter be used for
7767 /// codegen.
7768 Expr *buildPrivateCounterVar() const;
7769 /// Build initialization of the counter be used for codegen.
7770 Expr *buildCounterInit() const;
7771 /// Build step of the counter be used for codegen.
7772 Expr *buildCounterStep() const;
7773 /// Build loop data with counter value for depend clauses in ordered
7774 /// directives.
7775 Expr *
7776 buildOrderedLoopData(Scope *S, Expr *Counter,
7777 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7778 SourceLocation Loc, Expr *Inc = nullptr,
7779 OverloadedOperatorKind OOK = OO_Amp);
7780 /// Builds the minimum value for the loop counter.
7781 std::pair<Expr *, Expr *> buildMinMaxValues(
7782 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7783 /// Builds final condition for the non-rectangular loops.
7784 Expr *buildFinalCondition(Scope *S) const;
7785 /// Return true if any expression is dependent.
7786 bool dependent() const;
7787 /// Returns true if the initializer forms non-rectangular loop.
7788 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7789 /// Returns true if the condition forms non-rectangular loop.
7790 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7791 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7792 unsigned getLoopDependentIdx() const {
7793 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7794 }
7795
7796private:
7797 /// Check the right-hand side of an assignment in the increment
7798 /// expression.
7799 bool checkAndSetIncRHS(Expr *RHS);
7800 /// Helper to set loop counter variable and its initializer.
7801 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7802 bool EmitDiags);
7803 /// Helper to set upper bound.
7804 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7806 /// Helper to set loop increment.
7807 bool setStep(Expr *NewStep, bool Subtract);
7808};
7809
7810bool OpenMPIterationSpaceChecker::dependent() const {
7811 if (!LCDecl) {
7812 assert(!LB && !UB && !Step);
7813 return false;
7814 }
7815 return LCDecl->getType()->isDependentType() ||
7816 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7817 (Step && Step->isValueDependent());
7818}
7819
7820bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7821 Expr *NewLCRefExpr,
7822 Expr *NewLB, bool EmitDiags) {
7823 // State consistency checking to ensure correct usage.
7824 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7825 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7826 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7827 return true;
7828 LCDecl = getCanonicalDecl(NewLCDecl);
7829 LCRef = NewLCRefExpr;
7830 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7831 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7832 if ((Ctor->isCopyOrMoveConstructor() ||
7833 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7834 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7835 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7836 LB = NewLB;
7837 if (EmitDiags)
7838 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7839 return false;
7840}
7841
7842bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7843 bool StrictOp, SourceRange SR,
7844 SourceLocation SL) {
7845 // State consistency checking to ensure correct usage.
7846 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7847 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7848 if (!NewUB || NewUB->containsErrors())
7849 return true;
7850 UB = NewUB;
7851 if (LessOp)
7852 TestIsLessOp = LessOp;
7853 TestIsStrictOp = StrictOp;
7854 ConditionSrcRange = SR;
7855 ConditionLoc = SL;
7856 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7857 return false;
7858}
7859
7860bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7861 // State consistency checking to ensure correct usage.
7862 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7863 if (!NewStep || NewStep->containsErrors())
7864 return true;
7865 if (!NewStep->isValueDependent()) {
7866 // Check that the step is integer expression.
7867 SourceLocation StepLoc = NewStep->getBeginLoc();
7869 StepLoc, getExprAsWritten(NewStep));
7870 if (Val.isInvalid())
7871 return true;
7872 NewStep = Val.get();
7873
7874 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7875 // If test-expr is of form var relational-op b and relational-op is < or
7876 // <= then incr-expr must cause var to increase on each iteration of the
7877 // loop. If test-expr is of form var relational-op b and relational-op is
7878 // > or >= then incr-expr must cause var to decrease on each iteration of
7879 // the loop.
7880 // If test-expr is of form b relational-op var and relational-op is < or
7881 // <= then incr-expr must cause var to decrease on each iteration of the
7882 // loop. If test-expr is of form b relational-op var and relational-op is
7883 // > or >= then incr-expr must cause var to increase on each iteration of
7884 // the loop.
7885 std::optional<llvm::APSInt> Result =
7886 NewStep->getIntegerConstantExpr(SemaRef.Context);
7887 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7888 bool IsConstNeg =
7889 Result && Result->isSigned() && (Subtract != Result->isNegative());
7890 bool IsConstPos =
7891 Result && Result->isSigned() && (Subtract == Result->isNegative());
7892 bool IsConstZero = Result && !Result->getBoolValue();
7893
7894 // != with increment is treated as <; != with decrement is treated as >
7895 if (!TestIsLessOp)
7896 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7897 if (UB && (IsConstZero ||
7898 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7899 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7900 SemaRef.Diag(NewStep->getExprLoc(),
7901 diag::err_omp_loop_incr_not_compatible)
7902 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7903 SemaRef.Diag(ConditionLoc,
7904 diag::note_omp_loop_cond_requires_compatible_incr)
7905 << *TestIsLessOp << ConditionSrcRange;
7906 return true;
7907 }
7908 if (*TestIsLessOp == Subtract) {
7909 NewStep =
7910 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
7911 .get();
7912 Subtract = !Subtract;
7913 }
7914 }
7915
7916 Step = NewStep;
7917 SubtractStep = Subtract;
7918 return false;
7919}
7920
7921namespace {
7922/// Checker for the non-rectangular loops. Checks if the initializer or
7923/// condition expression references loop counter variable.
7924class LoopCounterRefChecker final
7925 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
7926 Sema &SemaRef;
7927 DSAStackTy &Stack;
7928 const ValueDecl *CurLCDecl = nullptr;
7929 const ValueDecl *DepDecl = nullptr;
7930 const ValueDecl *PrevDepDecl = nullptr;
7931 bool IsInitializer = true;
7932 bool SupportsNonRectangular;
7933 unsigned BaseLoopId = 0;
7934 bool checkDecl(const Expr *E, const ValueDecl *VD) {
7935 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
7936 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
7937 << (IsInitializer ? 0 : 1);
7938 return false;
7939 }
7940 const auto &&Data = Stack.isLoopControlVariable(VD);
7941 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
7942 // The type of the loop iterator on which we depend may not have a random
7943 // access iterator type.
7944 if (Data.first && VD->getType()->isRecordType()) {
7945 SmallString<128> Name;
7946 llvm::raw_svector_ostream OS(Name);
7947 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
7948 /*Qualified=*/true);
7949 SemaRef.Diag(E->getExprLoc(),
7950 diag::err_omp_wrong_dependency_iterator_type)
7951 << OS.str();
7952 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
7953 return false;
7954 }
7955 if (Data.first && !SupportsNonRectangular) {
7956 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
7957 return false;
7958 }
7959 if (Data.first &&
7960 (DepDecl || (PrevDepDecl &&
7961 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
7962 if (!DepDecl && PrevDepDecl)
7963 DepDecl = PrevDepDecl;
7964 SmallString<128> Name;
7965 llvm::raw_svector_ostream OS(Name);
7966 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
7967 /*Qualified=*/true);
7968 SemaRef.Diag(E->getExprLoc(),
7969 diag::err_omp_invariant_or_linear_dependency)
7970 << OS.str();
7971 return false;
7972 }
7973 if (Data.first) {
7974 DepDecl = VD;
7975 BaseLoopId = Data.first;
7976 }
7977 return Data.first;
7978 }
7979
7980public:
7981 bool VisitDeclRefExpr(const DeclRefExpr *E) {
7982 const ValueDecl *VD = E->getDecl();
7983 if (isa<VarDecl>(VD))
7984 return checkDecl(E, VD);
7985 return false;
7986 }
7987 bool VisitMemberExpr(const MemberExpr *E) {
7988 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
7989 const ValueDecl *VD = E->getMemberDecl();
7990 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
7991 return checkDecl(E, VD);
7992 }
7993 return false;
7994 }
7995 bool VisitStmt(const Stmt *S) {
7996 bool Res = false;
7997 for (const Stmt *Child : S->children())
7998 Res = (Child && Visit(Child)) || Res;
7999 return Res;
8000 }
8001 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8002 const ValueDecl *CurLCDecl, bool IsInitializer,
8003 const ValueDecl *PrevDepDecl = nullptr,
8004 bool SupportsNonRectangular = true)
8005 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8006 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8007 SupportsNonRectangular(SupportsNonRectangular) {}
8008 unsigned getBaseLoopId() const {
8009 assert(CurLCDecl && "Expected loop dependency.");
8010 return BaseLoopId;
8011 }
8012 const ValueDecl *getDepDecl() const {
8013 assert(CurLCDecl && "Expected loop dependency.");
8014 return DepDecl;
8015 }
8016};
8017} // namespace
8018
8019std::optional<unsigned>
8020OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8021 bool IsInitializer) {
8022 // Check for the non-rectangular loops.
8023 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8024 DepDecl, SupportsNonRectangular);
8025 if (LoopStmtChecker.Visit(S)) {
8026 DepDecl = LoopStmtChecker.getDepDecl();
8027 return LoopStmtChecker.getBaseLoopId();
8028 }
8029 return std::nullopt;
8030}
8031
8032bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8033 // Check init-expr for canonical loop form and save loop counter
8034 // variable - #Var and its initialization value - #LB.
8035 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8036 // var = lb
8037 // integer-type var = lb
8038 // random-access-iterator-type var = lb
8039 // pointer-type var = lb
8040 //
8041 if (!S) {
8042 if (EmitDiags) {
8043 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8044 }
8045 return true;
8046 }
8047 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8048 if (!ExprTemp->cleanupsHaveSideEffects())
8049 S = ExprTemp->getSubExpr();
8050
8051 InitSrcRange = S->getSourceRange();
8052 if (Expr *E = dyn_cast<Expr>(S))
8053 S = E->IgnoreParens();
8054 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8055 if (BO->getOpcode() == BO_Assign) {
8056 Expr *LHS = BO->getLHS()->IgnoreParens();
8057 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8058 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8059 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8060 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8061 EmitDiags);
8062 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8063 }
8064 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8065 if (ME->isArrow() &&
8066 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8067 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8068 EmitDiags);
8069 }
8070 }
8071 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8072 if (DS->isSingleDecl()) {
8073 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8074 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8075 // Accept non-canonical init form here but emit ext. warning.
8076 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8077 SemaRef.Diag(S->getBeginLoc(),
8078 diag::ext_omp_loop_not_canonical_init)
8079 << S->getSourceRange();
8080 return setLCDeclAndLB(
8081 Var,
8082 buildDeclRefExpr(SemaRef, Var,
8083 Var->getType().getNonReferenceType(),
8084 DS->getBeginLoc()),
8085 Var->getInit(), EmitDiags);
8086 }
8087 }
8088 }
8089 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8090 if (CE->getOperator() == OO_Equal) {
8091 Expr *LHS = CE->getArg(0);
8092 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8093 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8094 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8095 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8096 EmitDiags);
8097 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8098 }
8099 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8100 if (ME->isArrow() &&
8101 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8102 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8103 EmitDiags);
8104 }
8105 }
8106 }
8107
8108 if (dependent() || SemaRef.CurContext->isDependentContext())
8109 return false;
8110 if (EmitDiags) {
8111 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8112 << S->getSourceRange();
8113 }
8114 return true;
8115}
8116
8117/// Ignore parenthesizes, implicit casts, copy constructor and return the
8118/// variable (which may be the loop variable) if possible.
8119static const ValueDecl *getInitLCDecl(const Expr *E) {
8120 if (!E)
8121 return nullptr;
8122 E = getExprAsWritten(E);
8123 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8124 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8125 if ((Ctor->isCopyOrMoveConstructor() ||
8126 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8127 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8128 E = CE->getArg(0)->IgnoreParenImpCasts();
8129 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8130 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8131 return getCanonicalDecl(VD);
8132 }
8133 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8134 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8135 return getCanonicalDecl(ME->getMemberDecl());
8136 return nullptr;
8137}
8138
8139bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8140 // Check test-expr for canonical form, save upper-bound UB, flags for
8141 // less/greater and for strict/non-strict comparison.
8142 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8143 // var relational-op b
8144 // b relational-op var
8145 //
8146 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8147 if (!S) {
8148 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8149 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8150 return true;
8151 }
8152 Condition = S;
8153 S = getExprAsWritten(S);
8154 SourceLocation CondLoc = S->getBeginLoc();
8155 auto &&CheckAndSetCond =
8156 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8157 const Expr *RHS, SourceRange SR,
8158 SourceLocation OpLoc) -> std::optional<bool> {
8159 if (BinaryOperator::isRelationalOp(Opcode)) {
8160 if (getInitLCDecl(LHS) == LCDecl)
8161 return setUB(const_cast<Expr *>(RHS),
8162 (Opcode == BO_LT || Opcode == BO_LE),
8163 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8164 if (getInitLCDecl(RHS) == LCDecl)
8165 return setUB(const_cast<Expr *>(LHS),
8166 (Opcode == BO_GT || Opcode == BO_GE),
8167 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8168 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8169 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8170 /*LessOp=*/std::nullopt,
8171 /*StrictOp=*/true, SR, OpLoc);
8172 }
8173 return std::nullopt;
8174 };
8175 std::optional<bool> Res;
8176 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8177 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8178 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8179 RBO->getOperatorLoc());
8180 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8181 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8182 BO->getSourceRange(), BO->getOperatorLoc());
8183 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8184 if (CE->getNumArgs() == 2) {
8185 Res = CheckAndSetCond(
8186 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8187 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8188 }
8189 }
8190 if (Res)
8191 return *Res;
8192 if (dependent() || SemaRef.CurContext->isDependentContext())
8193 return false;
8194 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8195 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8196 return true;
8197}
8198
8199bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8200 // RHS of canonical loop form increment can be:
8201 // var + incr
8202 // incr + var
8203 // var - incr
8204 //
8205 RHS = RHS->IgnoreParenImpCasts();
8206 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8207 if (BO->isAdditiveOp()) {
8208 bool IsAdd = BO->getOpcode() == BO_Add;
8209 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8210 return setStep(BO->getRHS(), !IsAdd);
8211 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8212 return setStep(BO->getLHS(), /*Subtract=*/false);
8213 }
8214 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8215 bool IsAdd = CE->getOperator() == OO_Plus;
8216 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8217 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8218 return setStep(CE->getArg(1), !IsAdd);
8219 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8220 return setStep(CE->getArg(0), /*Subtract=*/false);
8221 }
8222 }
8223 if (dependent() || SemaRef.CurContext->isDependentContext())
8224 return false;
8225 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8226 << RHS->getSourceRange() << LCDecl;
8227 return true;
8228}
8229
8230bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8231 // Check incr-expr for canonical loop form and return true if it
8232 // does not conform.
8233 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8234 // ++var
8235 // var++
8236 // --var
8237 // var--
8238 // var += incr
8239 // var -= incr
8240 // var = var + incr
8241 // var = incr + var
8242 // var = var - incr
8243 //
8244 if (!S) {
8245 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8246 return true;
8247 }
8248 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8249 if (!ExprTemp->cleanupsHaveSideEffects())
8250 S = ExprTemp->getSubExpr();
8251
8252 IncrementSrcRange = S->getSourceRange();
8253 S = S->IgnoreParens();
8254 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8255 if (UO->isIncrementDecrementOp() &&
8256 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8257 return setStep(SemaRef
8258 .ActOnIntegerConstant(UO->getBeginLoc(),
8259 (UO->isDecrementOp() ? -1 : 1))
8260 .get(),
8261 /*Subtract=*/false);
8262 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8263 switch (BO->getOpcode()) {
8264 case BO_AddAssign:
8265 case BO_SubAssign:
8266 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8267 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8268 break;
8269 case BO_Assign:
8270 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8271 return checkAndSetIncRHS(BO->getRHS());
8272 break;
8273 default:
8274 break;
8275 }
8276 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8277 switch (CE->getOperator()) {
8278 case OO_PlusPlus:
8279 case OO_MinusMinus:
8280 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8281 return setStep(SemaRef
8282 .ActOnIntegerConstant(
8283 CE->getBeginLoc(),
8284 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8285 .get(),
8286 /*Subtract=*/false);
8287 break;
8288 case OO_PlusEqual:
8289 case OO_MinusEqual:
8290 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8291 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8292 break;
8293 case OO_Equal:
8294 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8295 return checkAndSetIncRHS(CE->getArg(1));
8296 break;
8297 default:
8298 break;
8299 }
8300 }
8301 if (dependent() || SemaRef.CurContext->isDependentContext())
8302 return false;
8303 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8304 << S->getSourceRange() << LCDecl;
8305 return true;
8306}
8307
8308static ExprResult
8309tryBuildCapture(Sema &SemaRef, Expr *Capture,
8310 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8311 StringRef Name = ".capture_expr.") {
8312 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8313 return Capture;
8314 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8315 return SemaRef.PerformImplicitConversion(
8316 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8317 /*AllowExplicit=*/true);
8318 auto I = Captures.find(Capture);
8319 if (I != Captures.end())
8320 return buildCapture(SemaRef, Capture, I->second, Name);
8321 DeclRefExpr *Ref = nullptr;
8322 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8323 Captures[Capture] = Ref;
8324 return Res;
8325}
8326
8327/// Calculate number of iterations, transforming to unsigned, if number of
8328/// iterations may be larger than the original type.
8329static Expr *
8330calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8331 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8332 bool TestIsStrictOp, bool RoundToStep,
8333 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8334 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8335 if (!NewStep.isUsable())
8336 return nullptr;
8337 llvm::APSInt LRes, SRes;
8338 bool IsLowerConst = false, IsStepConst = false;
8339 if (std::optional<llvm::APSInt> Res =
8340 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8341 LRes = *Res;
8342 IsLowerConst = true;
8343 }
8344 if (std::optional<llvm::APSInt> Res =
8345 Step->getIntegerConstantExpr(SemaRef.Context)) {
8346 SRes = *Res;
8347 IsStepConst = true;
8348 }
8349 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8350 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8351 (TestIsStrictOp && LRes.isStrictlyPositive()));
8352 bool NeedToReorganize = false;
8353 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8354 if (!NoNeedToConvert && IsLowerConst &&
8355 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8356 NoNeedToConvert = true;
8357 if (RoundToStep) {
8358 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8359 ? LRes.getBitWidth()
8360 : SRes.getBitWidth();
8361 LRes = LRes.extend(BW + 1);
8362 LRes.setIsSigned(true);
8363 SRes = SRes.extend(BW + 1);
8364 SRes.setIsSigned(true);
8365 LRes -= SRes;
8366 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8367 LRes = LRes.trunc(BW);
8368 }
8369 if (TestIsStrictOp) {
8370 unsigned BW = LRes.getBitWidth();
8371 LRes = LRes.extend(BW + 1);
8372 LRes.setIsSigned(true);
8373 ++LRes;
8374 NoNeedToConvert =
8375 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8376 // truncate to the original bitwidth.
8377 LRes = LRes.trunc(BW);
8378 }
8379 NeedToReorganize = NoNeedToConvert;
8380 }
8381 llvm::APSInt URes;
8382 bool IsUpperConst = false;
8383 if (std::optional<llvm::APSInt> Res =
8384 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8385 URes = *Res;
8386 IsUpperConst = true;
8387 }
8388 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8389 (!RoundToStep || IsStepConst)) {
8390 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8391 : URes.getBitWidth();
8392 LRes = LRes.extend(BW + 1);
8393 LRes.setIsSigned(true);
8394 URes = URes.extend(BW + 1);
8395 URes.setIsSigned(true);
8396 URes -= LRes;
8397 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8398 NeedToReorganize = NoNeedToConvert;
8399 }
8400 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8401 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8402 // unsigned.
8403 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8404 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8405 QualType LowerTy = Lower->getType();
8406 QualType UpperTy = Upper->getType();
8407 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8408 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8409 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8410 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8412 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8413 Upper =
8414 SemaRef
8416 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8418 .get();
8419 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8420 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8421 }
8422 }
8423 if (!Lower || !Upper || NewStep.isInvalid())
8424 return nullptr;
8425
8426 ExprResult Diff;
8427 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8428 // 1]).
8429 if (NeedToReorganize) {
8430 Diff = Lower;
8431
8432 if (RoundToStep) {
8433 // Lower - Step
8434 Diff =
8435 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8436 if (!Diff.isUsable())
8437 return nullptr;
8438 }
8439
8440 // Lower - Step [+ 1]
8441 if (TestIsStrictOp)
8442 Diff = SemaRef.BuildBinOp(
8443 S, DefaultLoc, BO_Add, Diff.get(),
8444 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8445 if (!Diff.isUsable())
8446 return nullptr;
8447
8448 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8449 if (!Diff.isUsable())
8450 return nullptr;
8451
8452 // Upper - (Lower - Step [+ 1]).
8453 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8454 if (!Diff.isUsable())
8455 return nullptr;
8456 } else {
8457 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8458
8459 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8460 // BuildBinOp already emitted error, this one is to point user to upper
8461 // and lower bound, and to tell what is passed to 'operator-'.
8462 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8463 << Upper->getSourceRange() << Lower->getSourceRange();
8464 return nullptr;
8465 }
8466
8467 if (!Diff.isUsable())
8468 return nullptr;
8469
8470 // Upper - Lower [- 1]
8471 if (TestIsStrictOp)
8472 Diff = SemaRef.BuildBinOp(
8473 S, DefaultLoc, BO_Sub, Diff.get(),
8474 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8475 if (!Diff.isUsable())
8476 return nullptr;
8477
8478 if (RoundToStep) {
8479 // Upper - Lower [- 1] + Step
8480 Diff =
8481 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8482 if (!Diff.isUsable())
8483 return nullptr;
8484 }
8485 }
8486
8487 // Parentheses (for dumping/debugging purposes only).
8488 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8489 if (!Diff.isUsable())
8490 return nullptr;
8491
8492 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8493 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8494 if (!Diff.isUsable())
8495 return nullptr;
8496
8497 return Diff.get();
8498}
8499
8500/// Build the expression to calculate the number of iterations.
8501Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8502 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8503 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8504 QualType VarType = LCDecl->getType().getNonReferenceType();
8505 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8506 !SemaRef.getLangOpts().CPlusPlus)
8507 return nullptr;
8508 Expr *LBVal = LB;
8509 Expr *UBVal = UB;
8510 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8511 // max(LB(MinVal), LB(MaxVal)))
8512 if (InitDependOnLC) {
8513 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8514 if (!IS.MinValue || !IS.MaxValue)
8515 return nullptr;
8516 // OuterVar = Min
8517 ExprResult MinValue =
8518 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8519 if (!MinValue.isUsable())
8520 return nullptr;
8521
8522 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8523 IS.CounterVar, MinValue.get());
8524 if (!LBMinVal.isUsable())
8525 return nullptr;
8526 // OuterVar = Min, LBVal
8527 LBMinVal =
8528 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8529 if (!LBMinVal.isUsable())
8530 return nullptr;
8531 // (OuterVar = Min, LBVal)
8532 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8533 if (!LBMinVal.isUsable())
8534 return nullptr;
8535
8536 // OuterVar = Max
8537 ExprResult MaxValue =
8538 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8539 if (!MaxValue.isUsable())
8540 return nullptr;
8541
8542 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8543 IS.CounterVar, MaxValue.get());
8544 if (!LBMaxVal.isUsable())
8545 return nullptr;
8546 // OuterVar = Max, LBVal
8547 LBMaxVal =
8548 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8549 if (!LBMaxVal.isUsable())
8550 return nullptr;
8551 // (OuterVar = Max, LBVal)
8552 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8553 if (!LBMaxVal.isUsable())
8554 return nullptr;
8555
8556 Expr *LBMin =
8557 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8558 Expr *LBMax =
8559 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8560 if (!LBMin || !LBMax)
8561 return nullptr;
8562 // LB(MinVal) < LB(MaxVal)
8563 ExprResult MinLessMaxRes =
8564 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8565 if (!MinLessMaxRes.isUsable())
8566 return nullptr;
8567 Expr *MinLessMax =
8568 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8569 .get();
8570 if (!MinLessMax)
8571 return nullptr;
8572 if (*TestIsLessOp) {
8573 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8574 // LB(MaxVal))
8575 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8576 MinLessMax, LBMin, LBMax);
8577 if (!MinLB.isUsable())
8578 return nullptr;
8579 LBVal = MinLB.get();
8580 } else {
8581 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8582 // LB(MaxVal))
8583 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8584 MinLessMax, LBMax, LBMin);
8585 if (!MaxLB.isUsable())
8586 return nullptr;
8587 LBVal = MaxLB.get();
8588 }
8589 // OuterVar = LB
8590 LBMinVal =
8591 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8592 if (!LBMinVal.isUsable())
8593 return nullptr;
8594 LBVal = LBMinVal.get();
8595 }
8596 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8597 // min(UB(MinVal), UB(MaxVal))
8598 if (CondDependOnLC) {
8599 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8600 if (!IS.MinValue || !IS.MaxValue)
8601 return nullptr;
8602 // OuterVar = Min
8603 ExprResult MinValue =
8604 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8605 if (!MinValue.isUsable())
8606 return nullptr;
8607
8608 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8609 IS.CounterVar, MinValue.get());
8610 if (!UBMinVal.isUsable())
8611 return nullptr;
8612 // OuterVar = Min, UBVal
8613 UBMinVal =
8614 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8615 if (!UBMinVal.isUsable())
8616 return nullptr;
8617 // (OuterVar = Min, UBVal)
8618 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8619 if (!UBMinVal.isUsable())
8620 return nullptr;
8621
8622 // OuterVar = Max
8623 ExprResult MaxValue =
8624 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8625 if (!MaxValue.isUsable())
8626 return nullptr;
8627
8628 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8629 IS.CounterVar, MaxValue.get());
8630 if (!UBMaxVal.isUsable())
8631 return nullptr;
8632 // OuterVar = Max, UBVal
8633 UBMaxVal =
8634 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8635 if (!UBMaxVal.isUsable())
8636 return nullptr;
8637 // (OuterVar = Max, UBVal)
8638 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8639 if (!UBMaxVal.isUsable())
8640 return nullptr;
8641
8642 Expr *UBMin =
8643 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8644 Expr *UBMax =
8645 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8646 if (!UBMin || !UBMax)
8647 return nullptr;
8648 // UB(MinVal) > UB(MaxVal)
8649 ExprResult MinGreaterMaxRes =
8650 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8651 if (!MinGreaterMaxRes.isUsable())
8652 return nullptr;
8653 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8654 Captures, ".min_greater_max")
8655 .get();
8656 if (!MinGreaterMax)
8657 return nullptr;
8658 if (*TestIsLessOp) {
8659 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8660 // UB(MaxVal))
8661 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8662 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8663 if (!MaxUB.isUsable())
8664 return nullptr;
8665 UBVal = MaxUB.get();
8666 } else {
8667 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8668 // UB(MaxVal))
8669 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8670 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8671 if (!MinUB.isUsable())
8672 return nullptr;
8673 UBVal = MinUB.get();
8674 }
8675 }
8676 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8677 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8678 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8679 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8680 if (!Upper || !Lower)
8681 return nullptr;
8682
8683 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8684 Step, VarType, TestIsStrictOp,
8685 /*RoundToStep=*/true, Captures);
8686 if (!Diff.isUsable())
8687 return nullptr;
8688
8689 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8690 QualType Type = Diff.get()->getType();
8691 ASTContext &C = SemaRef.Context;
8692 bool UseVarType = VarType->hasIntegerRepresentation() &&
8693 C.getTypeSize(Type) > C.getTypeSize(VarType);
8694 if (!Type->isIntegerType() || UseVarType) {
8695 unsigned NewSize =
8696 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8697 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8699 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8700 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8701 Diff = SemaRef.PerformImplicitConversion(
8702 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8703 if (!Diff.isUsable())
8704 return nullptr;
8705 }
8706 }
8707 if (LimitedType) {
8708 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8709 if (NewSize != C.getTypeSize(Type)) {
8710 if (NewSize < C.getTypeSize(Type)) {
8711 assert(NewSize == 64 && "incorrect loop var size");
8712 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8713 << InitSrcRange << ConditionSrcRange;
8714 }
8715 QualType NewType = C.getIntTypeForBitwidth(
8717 C.getTypeSize(Type) < NewSize);
8718 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8719 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8720 Sema::AA_Converting, true);
8721 if (!Diff.isUsable())
8722 return nullptr;
8723 }
8724 }
8725 }
8726
8727 return Diff.get();
8728}
8729
8730std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8731 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8732 // Do not build for iterators, they cannot be used in non-rectangular loop
8733 // nests.
8734 if (LCDecl->getType()->isRecordType())
8735 return std::make_pair(nullptr, nullptr);
8736 // If we subtract, the min is in the condition, otherwise the min is in the
8737 // init value.
8738 Expr *MinExpr = nullptr;
8739 Expr *MaxExpr = nullptr;
8740 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8741 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8742 bool LBNonRect =
8743 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8744 bool UBNonRect =
8745 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8746 Expr *Lower =
8747 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8748 Expr *Upper =
8749 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8750 if (!Upper || !Lower)
8751 return std::make_pair(nullptr, nullptr);
8752
8753 if (*TestIsLessOp)
8754 MinExpr = Lower;
8755 else
8756 MaxExpr = Upper;
8757
8758 // Build minimum/maximum value based on number of iterations.
8759 QualType VarType = LCDecl->getType().getNonReferenceType();
8760
8761 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8762 Step, VarType, TestIsStrictOp,
8763 /*RoundToStep=*/false, Captures);
8764 if (!Diff.isUsable())
8765 return std::make_pair(nullptr, nullptr);
8766
8767 // ((Upper - Lower [- 1]) / Step) * Step
8768 // Parentheses (for dumping/debugging purposes only).
8769 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8770 if (!Diff.isUsable())
8771 return std::make_pair(nullptr, nullptr);
8772
8773 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8774 if (!NewStep.isUsable())
8775 return std::make_pair(nullptr, nullptr);
8776 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8777 if (!Diff.isUsable())
8778 return std::make_pair(nullptr, nullptr);
8779
8780 // Parentheses (for dumping/debugging purposes only).
8781 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8782 if (!Diff.isUsable())
8783 return std::make_pair(nullptr, nullptr);
8784
8785 // Convert to the ptrdiff_t, if original type is pointer.
8786 if (VarType->isAnyPointerType() &&
8787 !SemaRef.Context.hasSameType(
8788 Diff.get()->getType(),
8790 Diff = SemaRef.PerformImplicitConversion(
8791 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8792 Sema::AA_Converting, /*AllowExplicit=*/true);
8793 }
8794 if (!Diff.isUsable())
8795 return std::make_pair(nullptr, nullptr);
8796
8797 if (*TestIsLessOp) {
8798 // MinExpr = Lower;
8799 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8800 Diff = SemaRef.BuildBinOp(
8801 S, DefaultLoc, BO_Add,
8802 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8803 Diff.get());
8804 if (!Diff.isUsable())
8805 return std::make_pair(nullptr, nullptr);
8806 } else {
8807 // MaxExpr = Upper;
8808 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8809 Diff = SemaRef.BuildBinOp(
8810 S, DefaultLoc, BO_Sub,
8811 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8812 Diff.get());
8813 if (!Diff.isUsable())
8814 return std::make_pair(nullptr, nullptr);
8815 }
8816
8817 // Convert to the original type.
8818 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8819 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8821 /*AllowExplicit=*/true);
8822 if (!Diff.isUsable())
8823 return std::make_pair(nullptr, nullptr);
8824
8825 Sema::TentativeAnalysisScope Trap(SemaRef);
8826 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8827 if (!Diff.isUsable())
8828 return std::make_pair(nullptr, nullptr);
8829
8830 if (*TestIsLessOp)
8831 MaxExpr = Diff.get();
8832 else
8833 MinExpr = Diff.get();
8834
8835 return std::make_pair(MinExpr, MaxExpr);
8836}
8837
8838Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8839 if (InitDependOnLC || CondDependOnLC)
8840 return Condition;
8841 return nullptr;
8842}
8843
8844Expr *OpenMPIterationSpaceChecker::buildPreCond(
8845 Scope *S, Expr *Cond,
8846 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8847 // Do not build a precondition when the condition/initialization is dependent
8848 // to prevent pessimistic early loop exit.
8849 // TODO: this can be improved by calculating min/max values but not sure that
8850 // it will be very effective.
8851 if (CondDependOnLC || InitDependOnLC)
8852 return SemaRef
8854 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8855 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8856 /*AllowExplicit=*/true)
8857 .get();
8858
8859 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8860 Sema::TentativeAnalysisScope Trap(SemaRef);
8861
8862 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8863 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8864 if (!NewLB.isUsable() || !NewUB.isUsable())
8865 return nullptr;
8866
8867 ExprResult CondExpr =
8868 SemaRef.BuildBinOp(S, DefaultLoc,
8869 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8870 : (TestIsStrictOp ? BO_GT : BO_GE),
8871 NewLB.get(), NewUB.get());
8872 if (CondExpr.isUsable()) {
8873 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8874 SemaRef.Context.BoolTy))
8875 CondExpr = SemaRef.PerformImplicitConversion(
8876 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8877 /*AllowExplicit=*/true);
8878 }
8879
8880 // Otherwise use original loop condition and evaluate it in runtime.
8881 return CondExpr.isUsable() ? CondExpr.get() : Cond;
8882}
8883
8884/// Build reference expression to the counter be used for codegen.
8885DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8886 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8887 DSAStackTy &DSA) const {
8888 auto *VD = dyn_cast<VarDecl>(LCDecl);
8889 if (!VD) {
8890 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
8892 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
8893 const DSAStackTy::DSAVarData Data =
8894 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
8895 // If the loop control decl is explicitly marked as private, do not mark it
8896 // as captured again.
8897 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
8898 Captures.insert(std::make_pair(LCRef, Ref));
8899 return Ref;
8900 }
8901 return cast<DeclRefExpr>(LCRef);
8902}
8903
8904Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
8905 if (LCDecl && !LCDecl->isInvalidDecl()) {
8907 VarDecl *PrivateVar = buildVarDecl(
8908 SemaRef, DefaultLoc, Type, LCDecl->getName(),
8909 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
8910 isa<VarDecl>(LCDecl)
8911 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
8912 : nullptr);
8913 if (PrivateVar->isInvalidDecl())
8914 return nullptr;
8915 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
8916 }
8917 return nullptr;
8918}
8919
8920/// Build initialization of the counter to be used for codegen.
8921Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
8922
8923/// Build step of the counter be used for codegen.
8924Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
8925
8926Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
8927 Scope *S, Expr *Counter,
8928 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
8929 Expr *Inc, OverloadedOperatorKind OOK) {
8930 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
8931 if (!Cnt)
8932 return nullptr;
8933 if (Inc) {
8934 assert((OOK == OO_Plus || OOK == OO_Minus) &&
8935 "Expected only + or - operations for depend clauses.");
8936 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
8937 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
8938 if (!Cnt)
8939 return nullptr;
8940 }
8941 QualType VarType = LCDecl->getType().getNonReferenceType();
8942 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8943 !SemaRef.getLangOpts().CPlusPlus)
8944 return nullptr;
8945 // Upper - Lower
8946 Expr *Upper =
8947 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
8948 Expr *Lower =
8949 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
8950 if (!Upper || !Lower)
8951 return nullptr;
8952
8953 ExprResult Diff = calculateNumIters(
8954 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
8955 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
8956 if (!Diff.isUsable())
8957 return nullptr;
8958
8959 return Diff.get();
8960}
8961} // namespace
8962
8964 Stmt *Init) {
8965 assert(getLangOpts().OpenMP && "OpenMP is not active.");
8966 assert(Init && "Expected loop in canonical form.");
8967 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
8968 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
8969 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
8970 return;
8971
8972 DSAStack->loopStart();
8973 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
8974 *DSAStack, ForLoc);
8975 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
8976 if (ValueDecl *D = ISC.getLoopDecl()) {
8977 auto *VD = dyn_cast<VarDecl>(D);
8978 DeclRefExpr *PrivateRef = nullptr;
8979 if (!VD) {
8981 VD = Private;
8982 } else {
8983 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
8984 /*WithInit=*/false);
8985 VD = cast<VarDecl>(PrivateRef->getDecl());
8986 }
8987 }
8988 DSAStack->addLoopControlVariable(D, VD);
8989 const Decl *LD = DSAStack->getPossiblyLoopCounter();
8990 if (LD != D->getCanonicalDecl()) {
8991 DSAStack->resetPossibleLoopCounter();
8992 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
8994 SemaRef, const_cast<VarDecl *>(Var),
8995 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
8996 /*RefersToCapture=*/true));
8997 }
8998 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
8999 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9000 // associated for-loop of a simd construct with just one associated
9001 // for-loop may be listed in a linear clause with a constant-linear-step
9002 // that is the increment of the associated for-loop. The loop iteration
9003 // variable(s) in the associated for-loop(s) of a for or parallel for
9004 // construct may be listed in a private or lastprivate clause.
9005 DSAStackTy::DSAVarData DVar =
9006 DSAStack->getTopDSA(D, /*FromParent=*/false);
9007 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9008 // is declared in the loop and it is predetermined as a private.
9009 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9010 OpenMPClauseKind PredeterminedCKind =
9012 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9013 : OMPC_private;
9014 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9015 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9016 };
9017 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9018 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9019 (getLangOpts().OpenMP <= 45 ||
9020 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9022 IsOpenMPTaskloopDirective(DKind) ||
9024 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9025 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9026 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9027 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9028 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9029 << getOpenMPClauseName(PredeterminedCKind);
9030 if (DVar.RefExpr == nullptr)
9031 DVar.CKind = PredeterminedCKind;
9032 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9033 } else if (LoopDeclRefExpr) {
9034 // Make the loop iteration variable private (for worksharing
9035 // constructs), linear (for simd directives with the only one
9036 // associated loop) or lastprivate (for simd directives with several
9037 // collapsed or ordered loops).
9038 if (DVar.CKind == OMPC_unknown)
9039 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9040 }
9041 }
9042 }
9043 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9044}
9045
9046namespace {
9047// Utility for OpenMP doacross clause kind
9048class OMPDoacrossKind {
9049public:
9050 bool isSource(const OMPDoacrossClause *C) {
9051 return C->getDependenceType() == OMPC_DOACROSS_source ||
9052 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9053 }
9054 bool isSink(const OMPDoacrossClause *C) {
9055 return C->getDependenceType() == OMPC_DOACROSS_sink;
9056 }
9057 bool isSinkIter(const OMPDoacrossClause *C) {
9058 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9059 }
9060};
9061} // namespace
9062/// Called on a for stmt to check and extract its iteration space
9063/// for further processing (such as collapsing).
9065 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9066 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9067 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9068 Expr *OrderedLoopCountExpr,
9069 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9071 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9072 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9073 // OpenMP [2.9.1, Canonical Loop Form]
9074 // for (init-expr; test-expr; incr-expr) structured-block
9075 // for (range-decl: range-expr) structured-block
9076 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9077 S = CanonLoop->getLoopStmt();
9078 auto *For = dyn_cast_or_null<ForStmt>(S);
9079 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9080 // Ranged for is supported only in OpenMP 5.0.
9081 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9082 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9083 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9084 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9085 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9086 if (TotalNestedLoopCount > 1) {
9087 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9088 SemaRef.Diag(DSA.getConstructLoc(),
9089 diag::note_omp_collapse_ordered_expr)
9090 << 2 << CollapseLoopCountExpr->getSourceRange()
9091 << OrderedLoopCountExpr->getSourceRange();
9092 else if (CollapseLoopCountExpr)
9093 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9094 diag::note_omp_collapse_ordered_expr)
9095 << 0 << CollapseLoopCountExpr->getSourceRange();
9096 else
9097 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9098 diag::note_omp_collapse_ordered_expr)
9099 << 1 << OrderedLoopCountExpr->getSourceRange();
9100 }
9101 return true;
9102 }
9103 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9104 "No loop body.");
9105 // Postpone analysis in dependent contexts for ranged for loops.
9106 if (CXXFor && SemaRef.CurContext->isDependentContext())
9107 return false;
9108
9109 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9110 For ? For->getForLoc() : CXXFor->getForLoc());
9111
9112 // Check init.
9113 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9114 if (ISC.checkAndSetInit(Init))
9115 return true;
9116
9117 bool HasErrors = false;
9118
9119 // Check loop variable's type.
9120 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9121 // OpenMP [2.6, Canonical Loop Form]
9122 // Var is one of the following:
9123 // A variable of signed or unsigned integer type.
9124 // For C++, a variable of a random access iterator type.
9125 // For C, a variable of a pointer type.
9126 QualType VarType = LCDecl->getType().getNonReferenceType();
9127 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9128 !VarType->isPointerType() &&
9129 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9130 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9131 << SemaRef.getLangOpts().CPlusPlus;
9132 HasErrors = true;
9133 }
9134
9135 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9136 // a Construct
9137 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9138 // parallel for construct is (are) private.
9139 // The loop iteration variable in the associated for-loop of a simd
9140 // construct with just one associated for-loop is linear with a
9141 // constant-linear-step that is the increment of the associated for-loop.
9142 // Exclude loop var from the list of variables with implicitly defined data
9143 // sharing attributes.
9144 VarsWithImplicitDSA.erase(LCDecl);
9145
9146 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9147
9148 // Check test-expr.
9149 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9150
9151 // Check incr-expr.
9152 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9153 }
9154
9155 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9156 return HasErrors;
9157
9158 // Build the loop's iteration space representation.
9159 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9160 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9161 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9162 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9168 Captures);
9169 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9170 ISC.buildCounterVar(Captures, DSA);
9171 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9172 ISC.buildPrivateCounterVar();
9173 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9174 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9175 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9176 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9177 ISC.getConditionSrcRange();
9178 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9179 ISC.getIncrementSrcRange();
9180 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9181 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9182 ISC.isStrictTestOp();
9183 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9184 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9185 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9186 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9187 ISC.buildFinalCondition(DSA.getCurScope());
9188 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9189 ISC.doesInitDependOnLC();
9190 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9191 ISC.doesCondDependOnLC();
9192 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9193 ISC.getLoopDependentIdx();
9194
9195 HasErrors |=
9196 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9197 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9198 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9199 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9200 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9201 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9202 if (!HasErrors && DSA.isOrderedRegion()) {
9203 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9204 if (CurrentNestedLoopCount <
9205 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9206 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9207 CurrentNestedLoopCount,
9208 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9209 DSA.getOrderedRegionParam().second->setLoopCounter(
9210 CurrentNestedLoopCount,
9211 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9212 }
9213 }
9214 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9215 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9216 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9217 unsigned NumLoops =
9218 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9219 if (CurrentNestedLoopCount >= NumLoops) {
9220 // Erroneous case - clause has some problems.
9221 continue;
9222 }
9223 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9224 Pair.second.size() <= CurrentNestedLoopCount) {
9225 // Erroneous case - clause has some problems.
9226 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9227 continue;
9228 }
9229 OMPDoacrossKind ODK;
9230 if (DoacrossC && ODK.isSink(DoacrossC) &&
9231 Pair.second.size() <= CurrentNestedLoopCount) {
9232 // Erroneous case - clause has some problems.
9233 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9234 continue;
9235 }
9236 Expr *CntValue;
9237 SourceLocation DepLoc =
9238 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9239 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9240 (DoacrossC && ODK.isSource(DoacrossC)))
9241 CntValue = ISC.buildOrderedLoopData(
9242 DSA.getCurScope(),
9243 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9244 DepLoc);
9245 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9246 Expr *Cnt = SemaRef
9248 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9249 .get();
9250 if (!Cnt)
9251 continue;
9252 // build CounterVar - 1
9253 Expr *Inc =
9254 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9255 .get();
9256 CntValue = ISC.buildOrderedLoopData(
9257 DSA.getCurScope(),
9258 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9259 DepLoc, Inc, clang::OO_Minus);
9260 } else
9261 CntValue = ISC.buildOrderedLoopData(
9262 DSA.getCurScope(),
9263 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9264 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9265 Pair.second[CurrentNestedLoopCount].second);
9266 if (DependC)
9267 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9268 else
9269 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9270 }
9271 }
9272
9273 return HasErrors;
9274}
9275
9276/// Build 'VarRef = Start.
9277static ExprResult
9279 ExprResult Start, bool IsNonRectangularLB,
9280 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9281 // Build 'VarRef = Start.
9282 ExprResult NewStart = IsNonRectangularLB
9283 ? Start.get()
9284 : tryBuildCapture(SemaRef, Start.get(), Captures);
9285 if (!NewStart.isUsable())
9286 return ExprError();
9287 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9288 VarRef.get()->getType())) {
9289 NewStart = SemaRef.PerformImplicitConversion(
9290 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9291 /*AllowExplicit=*/true);
9292 if (!NewStart.isUsable())
9293 return ExprError();
9294 }
9295
9297 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9298 return Init;
9299}
9300
9301/// Build 'VarRef = Start + Iter * Step'.
9303 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9304 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9305 bool IsNonRectangularLB,
9306 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9307 // Add parentheses (for debugging purposes only).
9308 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9309 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9310 !Step.isUsable())
9311 return ExprError();
9312
9313 ExprResult NewStep = Step;
9314 if (Captures)
9315 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9316 if (NewStep.isInvalid())
9317 return ExprError();
9319 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9320 if (!Update.isUsable())
9321 return ExprError();
9322
9323 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9324 // 'VarRef = Start (+|-) Iter * Step'.
9325 if (!Start.isUsable())
9326 return ExprError();
9327 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9328 if (!NewStart.isUsable())
9329 return ExprError();
9330 if (Captures && !IsNonRectangularLB)
9331 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9332 if (NewStart.isInvalid())
9333 return ExprError();
9334
9335 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9336 ExprResult SavedUpdate = Update;
9337 ExprResult UpdateVal;
9338 if (VarRef.get()->getType()->isOverloadableType() ||
9339 NewStart.get()->getType()->isOverloadableType() ||
9340 Update.get()->getType()->isOverloadableType()) {
9341 Sema::TentativeAnalysisScope Trap(SemaRef);
9342
9343 Update =
9344 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9345 if (Update.isUsable()) {
9346 UpdateVal =
9347 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9348 VarRef.get(), SavedUpdate.get());
9349 if (UpdateVal.isUsable()) {
9350 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9351 UpdateVal.get());
9352 }
9353 }
9354 }
9355
9356 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9357 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9358 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9359 NewStart.get(), SavedUpdate.get());
9360 if (!Update.isUsable())
9361 return ExprError();
9362
9363 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9364 VarRef.get()->getType())) {
9366 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9367 if (!Update.isUsable())
9368 return ExprError();
9369 }
9370
9371 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9372 }
9373 return Update;
9374}
9375
9376/// Convert integer expression \a E to make it have at least \a Bits
9377/// bits.
9378static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9379 if (E == nullptr)
9380 return ExprError();
9381 ASTContext &C = SemaRef.Context;
9382 QualType OldType = E->getType();
9383 unsigned HasBits = C.getTypeSize(OldType);
9384 if (HasBits >= Bits)
9385 return ExprResult(E);
9386 // OK to convert to signed, because new type has more bits than old.
9387 QualType NewType = C.getIntTypeForBitwidth(Bits, /* Signed */ true);
9388 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9389 true);
9390}
9391
9392/// Check if the given expression \a E is a constant integer that fits
9393/// into \a Bits bits.
9394static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9395 if (E == nullptr)
9396 return false;
9397 if (std::optional<llvm::APSInt> Result =
9399 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9400 return false;
9401}
9402
9403/// Build preinits statement for the given declarations.
9405 MutableArrayRef<Decl *> PreInits) {
9406 if (!PreInits.empty()) {
9407 return new (Context) DeclStmt(
9408 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9410 }
9411 return nullptr;
9412}
9413
9414/// Append the \p Item or the content of a CompoundStmt to the list \p
9415/// TargetList.
9416///
9417/// A CompoundStmt is used as container in case multiple statements need to be
9418/// stored in lieu of using an explicit list. Flattening is necessary because
9419/// contained DeclStmts need to be visible after the execution of the list. Used
9420/// for OpenMP pre-init declarations/statements.
9422 Stmt *Item) {
9423 // nullptr represents an empty list.
9424 if (!Item)
9425 return;
9426
9427 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9428 llvm::append_range(TargetList, CS->body());
9429 else
9430 TargetList.push_back(Item);
9431}
9432
9433/// Build preinits statement for the given declarations.
9434static Stmt *
9436 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9437 if (!Captures.empty()) {
9438 SmallVector<Decl *, 16> PreInits;
9439 for (const auto &Pair : Captures)
9440 PreInits.push_back(Pair.second->getDecl());
9441 return buildPreInits(Context, PreInits);
9442 }
9443 return nullptr;
9444}
9445
9446/// Build pre-init statement for the given statements.
9447static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9448 if (PreInits.empty())
9449 return nullptr;
9450
9451 SmallVector<Stmt *> Stmts;
9452 for (Stmt *S : PreInits)
9453 appendFlattenedStmtList(Stmts, S);
9454 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9455}
9456
9457/// Build postupdate expression for the given list of postupdates expressions.
9458static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9459 Expr *PostUpdate = nullptr;
9460 if (!PostUpdates.empty()) {
9461 for (Expr *E : PostUpdates) {
9462 Expr *ConvE = S.BuildCStyleCastExpr(
9463 E->getExprLoc(),
9465 E->getExprLoc(), E)
9466 .get();
9467 PostUpdate = PostUpdate
9468 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9469 PostUpdate, ConvE)
9470 .get()
9471 : ConvE;
9472 }
9473 }
9474 return PostUpdate;
9475}
9476
9477/// Called on a for stmt to check itself and nested loops (if any).
9478/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9479/// number of collapsed loops otherwise.
9480static unsigned
9481checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9482 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9483 DSAStackTy &DSA,
9484 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9486 unsigned NestedLoopCount = 1;
9487 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9489
9490 if (CollapseLoopCountExpr) {
9491 // Found 'collapse' clause - calculate collapse number.
9493 if (!CollapseLoopCountExpr->isValueDependent() &&
9494 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9495 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9496 } else {
9497 Built.clear(/*Size=*/1);
9498 return 1;
9499 }
9500 }
9501 unsigned OrderedLoopCount = 1;
9502 if (OrderedLoopCountExpr) {
9503 // Found 'ordered' clause - calculate collapse number.
9504 Expr::EvalResult EVResult;
9505 if (!OrderedLoopCountExpr->isValueDependent() &&
9506 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9507 SemaRef.getASTContext())) {
9508 llvm::APSInt Result = EVResult.Val.getInt();
9509 if (Result.getLimitedValue() < NestedLoopCount) {
9510 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9511 diag::err_omp_wrong_ordered_loop_count)
9512 << OrderedLoopCountExpr->getSourceRange();
9513 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9514 diag::note_collapse_loop_count)
9515 << CollapseLoopCountExpr->getSourceRange();
9516 }
9517 OrderedLoopCount = Result.getLimitedValue();
9518 } else {
9519 Built.clear(/*Size=*/1);
9520 return 1;
9521 }
9522 }
9523 // This is helper routine for loop directives (e.g., 'for', 'simd',
9524 // 'for simd', etc.).
9525 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9526 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9527 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9530 SupportsNonPerfectlyNested, NumLoops,
9531 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9532 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9533 &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9535 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9536 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9537 VarsWithImplicitDSA, IterSpaces, Captures))
9538 return true;
9539 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9540 IterSpaces[Cnt].CounterVar) {
9541 // Handle initialization of captured loop iterator variables.
9542 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9543 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9544 Captures[DRE] = DRE;
9545 }
9546 }
9547 return false;
9548 },
9549 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9550 Stmt *DependentPreInits = Transform->getPreInits();
9551 if (!DependentPreInits)
9552 return;
9553
9554 // Search for pre-init declared variables that need to be captured
9555 // to be referenceable inside the directive.
9556 SmallVector<Stmt *> Constituents;
9557 appendFlattenedStmtList(Constituents, DependentPreInits);
9558 for (Stmt *S : Constituents) {
9559 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9560 for (Decl *C : DC->decls()) {
9561 auto *D = cast<VarDecl>(C);
9563 SemaRef, D, D->getType().getNonReferenceType(),
9564 Transform->getBeginLoc());
9565 Captures[Ref] = Ref;
9566 }
9567 }
9568 }
9569 }))
9570 return 0;
9571
9572 Built.clear(/* size */ NestedLoopCount);
9573
9574 if (SemaRef.CurContext->isDependentContext())
9575 return NestedLoopCount;
9576
9577 // An example of what is generated for the following code:
9578 //
9579 // #pragma omp simd collapse(2) ordered(2)
9580 // for (i = 0; i < NI; ++i)
9581 // for (k = 0; k < NK; ++k)
9582 // for (j = J0; j < NJ; j+=2) {
9583 // <loop body>
9584 // }
9585 //
9586 // We generate the code below.
9587 // Note: the loop body may be outlined in CodeGen.
9588 // Note: some counters may be C++ classes, operator- is used to find number of
9589 // iterations and operator+= to calculate counter value.
9590 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9591 // or i64 is currently supported).
9592 //
9593 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9594 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9595 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9596 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9597 // // similar updates for vars in clauses (e.g. 'linear')
9598 // <loop body (using local i and j)>
9599 // }
9600 // i = NI; // assign final values of counters
9601 // j = NJ;
9602 //
9603
9604 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9605 // the iteration counts of the collapsed for loops.
9606 // Precondition tests if there is at least one iteration (all conditions are
9607 // true).
9608 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9609 Expr *N0 = IterSpaces[0].NumIterations;
9610 ExprResult LastIteration32 =
9611 widenIterationCount(/*Bits=*/32,
9612 SemaRef
9613 .PerformImplicitConversion(
9614 N0->IgnoreImpCasts(), N0->getType(),
9615 Sema::AA_Converting, /*AllowExplicit=*/true)
9616 .get(),
9617 SemaRef);
9618 ExprResult LastIteration64 = widenIterationCount(
9619 /*Bits=*/64,
9620 SemaRef
9621 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9623 /*AllowExplicit=*/true)
9624 .get(),
9625 SemaRef);
9626
9627 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9628 return NestedLoopCount;
9629
9630 ASTContext &C = SemaRef.Context;
9631 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9632
9633 Scope *CurScope = DSA.getCurScope();
9634 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9635 if (PreCond.isUsable()) {
9636 PreCond =
9637 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9638 PreCond.get(), IterSpaces[Cnt].PreCond);
9639 }
9640 Expr *N = IterSpaces[Cnt].NumIterations;
9642 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9643 if (LastIteration32.isUsable())
9644 LastIteration32 = SemaRef.BuildBinOp(
9645 CurScope, Loc, BO_Mul, LastIteration32.get(),
9646 SemaRef
9649 /*AllowExplicit=*/true)
9650 .get());
9651 if (LastIteration64.isUsable())
9652 LastIteration64 = SemaRef.BuildBinOp(
9653 CurScope, Loc, BO_Mul, LastIteration64.get(),
9654 SemaRef
9657 /*AllowExplicit=*/true)
9658 .get());
9659 }
9660
9661 // Choose either the 32-bit or 64-bit version.
9662 ExprResult LastIteration = LastIteration64;
9663 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9664 (LastIteration32.isUsable() &&
9665 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9666 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9667 fitsInto(
9668 /*Bits=*/32,
9669 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9670 LastIteration64.get(), SemaRef))))
9671 LastIteration = LastIteration32;
9672 QualType VType = LastIteration.get()->getType();
9673 QualType RealVType = VType;
9674 QualType StrideVType = VType;
9675 if (isOpenMPTaskLoopDirective(DKind)) {
9676 VType =
9677 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9678 StrideVType =
9679 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9680 }
9681
9682 if (!LastIteration.isUsable())
9683 return 0;
9684
9685 // Save the number of iterations.
9686 ExprResult NumIterations = LastIteration;
9687 {
9688 LastIteration = SemaRef.BuildBinOp(
9689 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9690 LastIteration.get(),
9691 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9692 if (!LastIteration.isUsable())
9693 return 0;
9694 }
9695
9696 // Calculate the last iteration number beforehand instead of doing this on
9697 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9698 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9699 ExprResult CalcLastIteration;
9700 if (!IsConstant) {
9701 ExprResult SaveRef =
9702 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9703 LastIteration = SaveRef;
9704
9705 // Prepare SaveRef + 1.
9706 NumIterations = SemaRef.BuildBinOp(
9707 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9708 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9709 if (!NumIterations.isUsable())
9710 return 0;
9711 }
9712
9713 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9714
9715 // Build variables passed into runtime, necessary for worksharing directives.
9716 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9721 // Lower bound variable, initialized with zero.
9722 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9723 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9724 SemaRef.AddInitializerToDecl(LBDecl,
9725 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9726 /*DirectInit*/ false);
9727
9728 // Upper bound variable, initialized with last iteration number.
9729 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9730 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9731 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9732 /*DirectInit*/ false);
9733
9734 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9735 // This will be used to implement clause 'lastprivate'.
9736 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9737 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9738 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9739 SemaRef.AddInitializerToDecl(ILDecl,
9740 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9741 /*DirectInit*/ false);
9742
9743 // Stride variable returned by runtime (we initialize it to 1 by default).
9744 VarDecl *STDecl =
9745 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9746 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9747 SemaRef.AddInitializerToDecl(STDecl,
9748 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9749 /*DirectInit*/ false);
9750
9751 // Build expression: UB = min(UB, LastIteration)
9752 // It is necessary for CodeGen of directives with static scheduling.
9753 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9754 UB.get(), LastIteration.get());
9755 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9756 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9757 LastIteration.get(), UB.get());
9758 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9759 CondOp.get());
9760 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false);
9761
9762 // If we have a combined directive that combines 'distribute', 'for' or
9763 // 'simd' we need to be able to access the bounds of the schedule of the
9764 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9765 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9767 // Lower bound variable, initialized with zero.
9768 VarDecl *CombLBDecl =
9769 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9770 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9771 SemaRef.AddInitializerToDecl(
9772 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9773 /*DirectInit*/ false);
9774
9775 // Upper bound variable, initialized with last iteration number.
9776 VarDecl *CombUBDecl =
9777 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9778 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9779 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9780 /*DirectInit*/ false);
9781
9782 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9783 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9784 ExprResult CombCondOp =
9785 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9786 LastIteration.get(), CombUB.get());
9787 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9788 CombCondOp.get());
9789 CombEUB =
9790 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false);
9791
9792 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9793 // We expect to have at least 2 more parameters than the 'parallel'
9794 // directive does - the lower and upper bounds of the previous schedule.
9795 assert(CD->getNumParams() >= 4 &&
9796 "Unexpected number of parameters in loop combined directive");
9797
9798 // Set the proper type for the bounds given what we learned from the
9799 // enclosed loops.
9800 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9801 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9802
9803 // Previous lower and upper bounds are obtained from the region
9804 // parameters.
9805 PrevLB =
9806 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9807 PrevUB =
9808 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9809 }
9810 }
9811
9812 // Build the iteration variable and its initialization before loop.
9813 ExprResult IV;
9814 ExprResult Init, CombInit;
9815 {
9816 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9817 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9818 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9823 ? LB.get()
9824 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9825 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9826 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false);
9827
9829 Expr *CombRHS =
9834 ? CombLB.get()
9835 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9836 CombInit =
9837 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9838 CombInit =
9839 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false);
9840 }
9841 }
9842
9843 bool UseStrictCompare =
9844 RealVType->hasUnsignedIntegerRepresentation() &&
9845 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9846 return LIS.IsStrictCompare;
9847 });
9848 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9849 // unsigned IV)) for worksharing loops.
9850 SourceLocation CondLoc = AStmt->getBeginLoc();
9851 Expr *BoundUB = UB.get();
9852 if (UseStrictCompare) {
9853 BoundUB =
9854 SemaRef
9855 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
9856 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9857 .get();
9858 BoundUB =
9859 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue*/ false).get();
9860 }
9861 ExprResult Cond =
9866 ? SemaRef.BuildBinOp(CurScope, CondLoc,
9867 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
9868 BoundUB)
9869 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9870 NumIterations.get());
9871 ExprResult CombDistCond;
9873 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
9874 NumIterations.get());
9875 }
9876
9877 ExprResult CombCond;
9879 Expr *BoundCombUB = CombUB.get();
9880 if (UseStrictCompare) {
9881 BoundCombUB =
9882 SemaRef
9883 .BuildBinOp(
9884 CurScope, CondLoc, BO_Add, BoundCombUB,
9885 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
9886 .get();
9887 BoundCombUB =
9888 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue*/ false)
9889 .get();
9890 }
9891 CombCond =
9892 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
9893 IV.get(), BoundCombUB);
9894 }
9895 // Loop increment (IV = IV + 1)
9896 SourceLocation IncLoc = AStmt->getBeginLoc();
9897 ExprResult Inc =
9898 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
9899 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
9900 if (!Inc.isUsable())
9901 return 0;
9902 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
9903 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false);
9904 if (!Inc.isUsable())
9905 return 0;
9906
9907 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
9908 // Used for directives with static scheduling.
9909 // In combined construct, add combined version that use CombLB and CombUB
9910 // base variables for the update
9911 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
9916 // LB + ST
9917 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
9918 if (!NextLB.isUsable())
9919 return 0;
9920 // LB = LB + ST
9921 NextLB =
9922 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
9923 NextLB =
9924 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false);
9925 if (!NextLB.isUsable())
9926 return 0;
9927 // UB + ST
9928 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
9929 if (!NextUB.isUsable())
9930 return 0;
9931 // UB = UB + ST
9932 NextUB =
9933 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
9934 NextUB =
9935 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false);
9936 if (!NextUB.isUsable())
9937 return 0;
9939 CombNextLB =
9940 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
9941 if (!NextLB.isUsable())
9942 return 0;
9943 // LB = LB + ST
9944 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
9945 CombNextLB.get());
9946 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
9947 /*DiscardedValue*/ false);
9948 if (!CombNextLB.isUsable())
9949 return 0;
9950 // UB + ST
9951 CombNextUB =
9952 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
9953 if (!CombNextUB.isUsable())
9954 return 0;
9955 // UB = UB + ST
9956 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
9957 CombNextUB.get());
9958 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
9959 /*DiscardedValue*/ false);
9960 if (!CombNextUB.isUsable())
9961 return 0;
9962 }
9963 }
9964
9965 // Create increment expression for distribute loop when combined in a same
9966 // directive with for as IV = IV + ST; ensure upper bound expression based
9967 // on PrevUB instead of NumIterations - used to implement 'for' when found
9968 // in combination with 'distribute', like in 'distribute parallel for'
9969 SourceLocation DistIncLoc = AStmt->getBeginLoc();
9970 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
9972 DistCond = SemaRef.BuildBinOp(
9973 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
9974 assert(DistCond.isUsable() && "distribute cond expr was not built");
9975
9976 DistInc =
9977 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
9978 assert(DistInc.isUsable() && "distribute inc expr was not built");
9979 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
9980 DistInc.get());
9981 DistInc =
9982 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false);
9983 assert(DistInc.isUsable() && "distribute inc expr was not built");
9984
9985 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
9986 // construct
9987 ExprResult NewPrevUB = PrevUB;
9988 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
9989 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
9990 PrevUB.get()->getType())) {
9991 NewPrevUB = SemaRef.BuildCStyleCastExpr(
9992 DistEUBLoc,
9994 DistEUBLoc, NewPrevUB.get());
9995 if (!NewPrevUB.isUsable())
9996 return 0;
9997 }
9998 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
9999 UB.get(), NewPrevUB.get());
10000 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10001 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10002 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10003 CondOp.get());
10004 PrevEUB =
10005 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false);
10006
10007 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10008 // parallel for is in combination with a distribute directive with
10009 // schedule(static, 1)
10010 Expr *BoundPrevUB = PrevUB.get();
10011 if (UseStrictCompare) {
10012 BoundPrevUB =
10013 SemaRef
10014 .BuildBinOp(
10015 CurScope, CondLoc, BO_Add, BoundPrevUB,
10016 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10017 .get();
10018 BoundPrevUB =
10019 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue*/ false)
10020 .get();
10021 }
10022 ParForInDistCond =
10023 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10024 IV.get(), BoundPrevUB);
10025 }
10026
10027 // Build updates and final values of the loop counters.
10028 bool HasErrors = false;
10029 Built.Counters.resize(NestedLoopCount);
10030 Built.Inits.resize(NestedLoopCount);
10031 Built.Updates.resize(NestedLoopCount);
10032 Built.Finals.resize(NestedLoopCount);
10033 Built.DependentCounters.resize(NestedLoopCount);
10034 Built.DependentInits.resize(NestedLoopCount);
10035 Built.FinalsConditions.resize(NestedLoopCount);
10036 {
10037 // We implement the following algorithm for obtaining the
10038 // original loop iteration variable values based on the
10039 // value of the collapsed loop iteration variable IV.
10040 //
10041 // Let n+1 be the number of collapsed loops in the nest.
10042 // Iteration variables (I0, I1, .... In)
10043 // Iteration counts (N0, N1, ... Nn)
10044 //
10045 // Acc = IV;
10046 //
10047 // To compute Ik for loop k, 0 <= k <= n, generate:
10048 // Prod = N(k+1) * N(k+2) * ... * Nn;
10049 // Ik = Acc / Prod;
10050 // Acc -= Ik * Prod;
10051 //
10052 ExprResult Acc = IV;
10053 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10054 LoopIterationSpace &IS = IterSpaces[Cnt];
10055 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10057
10058 // Compute prod
10059 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10060 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10061 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10062 IterSpaces[K].NumIterations);
10063
10064 // Iter = Acc / Prod
10065 // If there is at least one more inner loop to avoid
10066 // multiplication by 1.
10067 if (Cnt + 1 < NestedLoopCount)
10068 Iter =
10069 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10070 else
10071 Iter = Acc;
10072 if (!Iter.isUsable()) {
10073 HasErrors = true;
10074 break;
10075 }
10076
10077 // Update Acc:
10078 // Acc -= Iter * Prod
10079 // Check if there is at least one more inner loop to avoid
10080 // multiplication by 1.
10081 if (Cnt + 1 < NestedLoopCount)
10082 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10083 Prod.get());
10084 else
10085 Prod = Iter;
10086 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10087
10088 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10089 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10090 DeclRefExpr *CounterVar = buildDeclRefExpr(
10091 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10092 /*RefersToCapture=*/true);
10094 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10095 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10096 if (!Init.isUsable()) {
10097 HasErrors = true;
10098 break;
10099 }
10101 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10102 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10103 if (!Update.isUsable()) {
10104 HasErrors = true;
10105 break;
10106 }
10107
10108 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10109 ExprResult Final =
10110 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10111 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10112 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10113 if (!Final.isUsable()) {
10114 HasErrors = true;
10115 break;
10116 }
10117
10118 if (!Update.isUsable() || !Final.isUsable()) {
10119 HasErrors = true;
10120 break;
10121 }
10122 // Save results
10123 Built.Counters[Cnt] = IS.CounterVar;
10124 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10125 Built.Inits[Cnt] = Init.get();
10126 Built.Updates[Cnt] = Update.get();
10127 Built.Finals[Cnt] = Final.get();
10128 Built.DependentCounters[Cnt] = nullptr;
10129 Built.DependentInits[Cnt] = nullptr;
10130 Built.FinalsConditions[Cnt] = nullptr;
10131 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10132 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10133 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10134 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10135 }
10136 }
10137 }
10138
10139 if (HasErrors)
10140 return 0;
10141
10142 // Save results
10143 Built.IterationVarRef = IV.get();
10144 Built.LastIteration = LastIteration.get();
10145 Built.NumIterations = NumIterations.get();
10146 Built.CalcLastIteration = SemaRef
10147 .ActOnFinishFullExpr(CalcLastIteration.get(),
10148 /*DiscardedValue=*/false)
10149 .get();
10150 Built.PreCond = PreCond.get();
10151 Built.PreInits = buildPreInits(C, Captures);
10152 Built.Cond = Cond.get();
10153 Built.Init = Init.get();
10154 Built.Inc = Inc.get();
10155 Built.LB = LB.get();
10156 Built.UB = UB.get();
10157 Built.IL = IL.get();
10158 Built.ST = ST.get();
10159 Built.EUB = EUB.get();
10160 Built.NLB = NextLB.get();
10161 Built.NUB = NextUB.get();
10162 Built.PrevLB = PrevLB.get();
10163 Built.PrevUB = PrevUB.get();
10164 Built.DistInc = DistInc.get();
10165 Built.PrevEUB = PrevEUB.get();
10166 Built.DistCombinedFields.LB = CombLB.get();
10167 Built.DistCombinedFields.UB = CombUB.get();
10168 Built.DistCombinedFields.EUB = CombEUB.get();
10169 Built.DistCombinedFields.Init = CombInit.get();
10170 Built.DistCombinedFields.Cond = CombCond.get();
10171 Built.DistCombinedFields.NLB = CombNextLB.get();
10172 Built.DistCombinedFields.NUB = CombNextUB.get();
10173 Built.DistCombinedFields.DistCond = CombDistCond.get();
10174 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10175
10176 return NestedLoopCount;
10177}
10178
10180 auto CollapseClauses =
10181 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10182 if (CollapseClauses.begin() != CollapseClauses.end())
10183 return (*CollapseClauses.begin())->getNumForLoops();
10184 return nullptr;
10185}
10186
10188 auto OrderedClauses =
10189 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10190 if (OrderedClauses.begin() != OrderedClauses.end())
10191 return (*OrderedClauses.begin())->getNumForLoops();
10192 return nullptr;
10193}
10194
10196 const ArrayRef<OMPClause *> Clauses) {
10197 const OMPSafelenClause *Safelen = nullptr;
10198 const OMPSimdlenClause *Simdlen = nullptr;
10199
10200 for (const OMPClause *Clause : Clauses) {
10201 if (Clause->getClauseKind() == OMPC_safelen)
10202 Safelen = cast<OMPSafelenClause>(Clause);
10203 else if (Clause->getClauseKind() == OMPC_simdlen)
10204 Simdlen = cast<OMPSimdlenClause>(Clause);
10205 if (Safelen && Simdlen)
10206 break;
10207 }
10208
10209 if (Simdlen && Safelen) {
10210 const Expr *SimdlenLength = Simdlen->getSimdlen();
10211 const Expr *SafelenLength = Safelen->getSafelen();
10212 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10213 SimdlenLength->isInstantiationDependent() ||
10214 SimdlenLength->containsUnexpandedParameterPack())
10215 return false;
10216 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10217 SafelenLength->isInstantiationDependent() ||
10218 SafelenLength->containsUnexpandedParameterPack())
10219 return false;
10220 Expr::EvalResult SimdlenResult, SafelenResult;
10221 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10222 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10223 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10224 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10225 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10226 // If both simdlen and safelen clauses are specified, the value of the
10227 // simdlen parameter must be less than or equal to the value of the safelen
10228 // parameter.
10229 if (SimdlenRes > SafelenRes) {
10230 S.Diag(SimdlenLength->getExprLoc(),
10231 diag::err_omp_wrong_simdlen_safelen_values)
10232 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10233 return true;
10234 }
10235 }
10236 return false;
10237}
10238
10240 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10241 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10242 if (!AStmt)
10243 return StmtError();
10244
10245 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10246
10247 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10249 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10250 // define the nested loops number.
10251 unsigned NestedLoopCount = checkOpenMPLoop(
10252 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10253 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10254 if (NestedLoopCount == 0)
10255 return StmtError();
10256
10257 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10258 return StmtError();
10259
10261 return StmtError();
10262
10263 auto *SimdDirective = OMPSimdDirective::Create(
10264 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10265 return SimdDirective;
10266}
10267
10269 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10270 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10271 if (!AStmt)
10272 return StmtError();
10273
10274 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10276 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10277 // define the nested loops number.
10278 unsigned NestedLoopCount = checkOpenMPLoop(
10279 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10280 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10281 if (NestedLoopCount == 0)
10282 return StmtError();
10283
10284 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10285 return StmtError();
10286
10287 auto *ForDirective = OMPForDirective::Create(
10288 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10289 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10290 return ForDirective;
10291}
10292
10294 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10295 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10296 if (!AStmt)
10297 return StmtError();
10298
10299 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10300
10301 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10303 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10304 // define the nested loops number.
10305 unsigned NestedLoopCount =
10306 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10307 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10308 VarsWithImplicitDSA, B);
10309 if (NestedLoopCount == 0)
10310 return StmtError();
10311
10312 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10313 return StmtError();
10314
10316 return StmtError();
10317
10318 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10319 NestedLoopCount, Clauses, AStmt, B);
10320}
10321
10323 Stmt *AStmt, DSAStackTy *Stack) {
10324 if (!AStmt)
10325 return true;
10326
10327 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10328 auto BaseStmt = AStmt;
10329 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10330 BaseStmt = CS->getCapturedStmt();
10331 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10332 auto S = C->children();
10333 if (S.begin() == S.end())
10334 return true;
10335 // All associated statements must be '#pragma omp section' except for
10336 // the first one.
10337 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10338 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10339 if (SectionStmt)
10340 SemaRef.Diag(SectionStmt->getBeginLoc(),
10341 diag::err_omp_sections_substmt_not_section)
10342 << getOpenMPDirectiveName(DKind);
10343 return true;
10344 }
10345 cast<OMPSectionDirective>(SectionStmt)
10346 ->setHasCancel(Stack->isCancelRegion());
10347 }
10348 } else {
10349 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10350 << getOpenMPDirectiveName(DKind);
10351 return true;
10352 }
10353 return false;
10354}
10355
10358 Stmt *AStmt, SourceLocation StartLoc,
10359 SourceLocation EndLoc) {
10360 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10361 return StmtError();
10362
10364
10366 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10367 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10368}
10369
10371 SourceLocation StartLoc,
10372 SourceLocation EndLoc) {
10373 if (!AStmt)
10374 return StmtError();
10375
10377 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10378
10379 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10380 DSAStack->isCancelRegion());
10381}
10382
10385 if (auto *CE = dyn_cast<CallExpr>(E))
10386 if (CE->getDirectCallee())
10387 return E;
10388 return nullptr;
10389}
10390
10393 Stmt *AStmt, SourceLocation StartLoc,
10394 SourceLocation EndLoc) {
10395 if (!AStmt)
10396 return StmtError();
10397
10398 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10399
10400 // 5.1 OpenMP
10401 // expression-stmt : an expression statement with one of the following forms:
10402 // expression = target-call ( [expression-list] );
10403 // target-call ( [expression-list] );
10404
10405 SourceLocation TargetCallLoc;
10406
10408 Expr *TargetCall = nullptr;
10409
10410 auto *E = dyn_cast<Expr>(S);
10411 if (!E) {
10412 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10413 return StmtError();
10414 }
10415
10417
10418 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10419 if (BO->getOpcode() == BO_Assign)
10420 TargetCall = getDirectCallExpr(BO->getRHS());
10421 } else {
10422 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10423 if (COCE->getOperator() == OO_Equal)
10424 TargetCall = getDirectCallExpr(COCE->getArg(1));
10425 if (!TargetCall)
10426 TargetCall = getDirectCallExpr(E);
10427 }
10428 if (!TargetCall) {
10429 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10430 return StmtError();
10431 }
10432 TargetCallLoc = TargetCall->getExprLoc();
10433 }
10434
10436
10437 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10438 Clauses, AStmt, TargetCallLoc);
10439}
10440
10443 DSAStackTy *Stack) {
10444 bool ErrorFound = false;
10445 for (OMPClause *C : Clauses) {
10446 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10447 for (Expr *RefExpr : LPC->varlists()) {
10448 SourceLocation ELoc;
10449 SourceRange ERange;
10450 Expr *SimpleRefExpr = RefExpr;
10451 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10452 if (ValueDecl *D = Res.first) {
10453 auto &&Info = Stack->isLoopControlVariable(D);
10454 if (!Info.first) {
10455 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10456 << getOpenMPDirectiveName(K);
10457 ErrorFound = true;
10458 }
10459 }
10460 }
10461 }
10462 }
10463 return ErrorFound;
10464}
10465
10467 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10468 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10469 if (!AStmt)
10470 return StmtError();
10471
10472 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10473 // A list item may not appear in a lastprivate clause unless it is the
10474 // loop iteration variable of a loop that is associated with the construct.
10475 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10476 return StmtError();
10477
10478 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10479
10481 // In presence of clause 'collapse', it will define the nested loops number.
10482 unsigned NestedLoopCount = checkOpenMPLoop(
10483 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10484 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10485 if (NestedLoopCount == 0)
10486 return StmtError();
10487
10488 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10489 "omp loop exprs were not built");
10490
10491 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10492 NestedLoopCount, Clauses, AStmt, B);
10493}
10494
10496 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10497 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10498 if (!AStmt)
10499 return StmtError();
10500
10501 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10502 // A list item may not appear in a lastprivate clause unless it is the
10503 // loop iteration variable of a loop that is associated with the construct.
10504 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10505 return StmtError();
10506
10507 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10508
10510 // In presence of clause 'collapse', it will define the nested loops number.
10511 unsigned NestedLoopCount =
10512 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10513 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10514 VarsWithImplicitDSA, B);
10515 if (NestedLoopCount == 0)
10516 return StmtError();
10517
10518 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10519 "omp loop exprs were not built");
10520
10521 DSAStack->setParentTeamsRegionLoc(StartLoc);
10522
10524 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10525}
10526
10528 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10529 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10530 if (!AStmt)
10531 return StmtError();
10532
10533 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10534 // A list item may not appear in a lastprivate clause unless it is the
10535 // loop iteration variable of a loop that is associated with the construct.
10536 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10537 DSAStack))
10538 return StmtError();
10539
10540 CapturedStmt *CS =
10541 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10542
10544 // In presence of clause 'collapse', it will define the nested loops number.
10545 unsigned NestedLoopCount =
10546 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10547 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10548 VarsWithImplicitDSA, B);
10549 if (NestedLoopCount == 0)
10550 return StmtError();
10551
10552 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10553 "omp loop exprs were not built");
10554
10556 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10558}
10559
10561 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10562 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10563 if (!AStmt)
10564 return StmtError();
10565
10566 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10567 // A list item may not appear in a lastprivate clause unless it is the
10568 // loop iteration variable of a loop that is associated with the construct.
10569 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10570 DSAStack))
10571 return StmtError();
10572
10573 CapturedStmt *CS =
10574 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10575
10577 // In presence of clause 'collapse', it will define the nested loops number.
10578 unsigned NestedLoopCount =
10579 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10580 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10581 VarsWithImplicitDSA, B);
10582 if (NestedLoopCount == 0)
10583 return StmtError();
10584
10585 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10586 "omp loop exprs were not built");
10587
10589 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10590}
10591
10593 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10594 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10595 if (!AStmt)
10596 return StmtError();
10597
10598 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10599 // A list item may not appear in a lastprivate clause unless it is the
10600 // loop iteration variable of a loop that is associated with the construct.
10601 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10602 DSAStack))
10603 return StmtError();
10604
10605 CapturedStmt *CS =
10606 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
10607
10609 // In presence of clause 'collapse', it will define the nested loops number.
10610 unsigned NestedLoopCount =
10611 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10612 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10613 VarsWithImplicitDSA, B);
10614 if (NestedLoopCount == 0)
10615 return StmtError();
10616
10617 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10618 "omp loop exprs were not built");
10619
10621 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10622}
10623
10625 Stmt *AStmt,
10626 SourceLocation StartLoc,
10627 SourceLocation EndLoc) {
10628 if (!AStmt)
10629 return StmtError();
10630
10631 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10632
10634
10635 // OpenMP [2.7.3, single Construct, Restrictions]
10636 // The copyprivate clause must not be used with the nowait clause.
10637 const OMPClause *Nowait = nullptr;
10638 const OMPClause *Copyprivate = nullptr;
10639 for (const OMPClause *Clause : Clauses) {
10640 if (Clause->getClauseKind() == OMPC_nowait)
10641 Nowait = Clause;
10642 else if (Clause->getClauseKind() == OMPC_copyprivate)
10643 Copyprivate = Clause;
10644 if (Copyprivate && Nowait) {
10645 Diag(Copyprivate->getBeginLoc(),
10646 diag::err_omp_single_copyprivate_with_nowait);
10647 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10648 return StmtError();
10649 }
10650 }
10651
10652 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10653 AStmt);
10654}
10655
10657 SourceLocation StartLoc,
10658 SourceLocation EndLoc) {
10659 if (!AStmt)
10660 return StmtError();
10661
10663
10664 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
10665}
10666
10668 Stmt *AStmt,
10669 SourceLocation StartLoc,
10670 SourceLocation EndLoc) {
10671 if (!AStmt)
10672 return StmtError();
10673
10675
10676 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10677 AStmt);
10678}
10679
10681 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10682 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10683 if (!AStmt)
10684 return StmtError();
10685
10686 bool ErrorFound = false;
10687 llvm::APSInt Hint;
10688 SourceLocation HintLoc;
10689 bool DependentHint = false;
10690 for (const OMPClause *C : Clauses) {
10691 if (C->getClauseKind() == OMPC_hint) {
10692 if (!DirName.getName()) {
10693 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10694 ErrorFound = true;
10695 }
10696 Expr *E = cast<OMPHintClause>(C)->getHint();
10697 if (E->isTypeDependent() || E->isValueDependent() ||
10699 DependentHint = true;
10700 } else {
10702 HintLoc = C->getBeginLoc();
10703 }
10704 }
10705 }
10706 if (ErrorFound)
10707 return StmtError();
10708 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10709 if (Pair.first && DirName.getName() && !DependentHint) {
10710 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10711 Diag(StartLoc, diag::err_omp_critical_with_hint);
10712 if (HintLoc.isValid())
10713 Diag(HintLoc, diag::note_omp_critical_hint_here)
10714 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10715 else
10716 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10717 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10718 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10719 << 1
10720 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10721 /*Radix=*/10, /*Signed=*/false);
10722 } else {
10723 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10724 }
10725 }
10726 }
10727
10729
10730 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
10731 EndLoc, Clauses, AStmt);
10732 if (!Pair.first && DirName.getName() && !DependentHint)
10733 DSAStack->addCriticalWithHint(Dir, Hint);
10734 return Dir;
10735}
10736
10738 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10739 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10740 if (!AStmt)
10741 return StmtError();
10742
10743 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10744
10746 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10747 // define the nested loops number.
10748 unsigned NestedLoopCount =
10749 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10750 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10751 VarsWithImplicitDSA, B);
10752 if (NestedLoopCount == 0)
10753 return StmtError();
10754
10755 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10756 return StmtError();
10757
10759 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10760 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10761}
10762
10764 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10765 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10766 if (!AStmt)
10767 return StmtError();
10768
10769 CapturedStmt *CS =
10770 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10771
10773 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10774 // define the nested loops number.
10775 unsigned NestedLoopCount =
10776 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10777 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10778 VarsWithImplicitDSA, B);
10779 if (NestedLoopCount == 0)
10780 return StmtError();
10781
10782 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10783 return StmtError();
10784
10786 return StmtError();
10787
10789 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10790}
10791
10793 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10794 SourceLocation EndLoc) {
10795 if (!AStmt)
10796 return StmtError();
10797
10798 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
10799
10801 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10802 DSAStack->getTaskgroupReductionRef());
10803}
10804
10806 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10807 SourceLocation EndLoc) {
10808 if (!AStmt)
10809 return StmtError();
10810
10811 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
10812
10814 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10815 DSAStack->getTaskgroupReductionRef());
10816}
10817
10819 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10820 SourceLocation EndLoc) {
10821 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
10822 return StmtError();
10823
10825
10827 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10828 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10829}
10830
10831/// Find and diagnose mutually exclusive clause kinds.
10833 Sema &S, ArrayRef<OMPClause *> Clauses,
10834 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
10835 const OMPClause *PrevClause = nullptr;
10836 bool ErrorFound = false;
10837 for (const OMPClause *C : Clauses) {
10838 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
10839 if (!PrevClause) {
10840 PrevClause = C;
10841 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
10842 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10843 << getOpenMPClauseName(C->getClauseKind())
10844 << getOpenMPClauseName(PrevClause->getClauseKind());
10845 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
10846 << getOpenMPClauseName(PrevClause->getClauseKind());
10847 ErrorFound = true;
10848 }
10849 }
10850 }
10851 return ErrorFound;
10852}
10853
10855 Stmt *AStmt,
10856 SourceLocation StartLoc,
10857 SourceLocation EndLoc) {
10858 if (!AStmt)
10859 return StmtError();
10860
10861 // OpenMP 5.0, 2.10.1 task Construct
10862 // If a detach clause appears on the directive, then a mergeable clause cannot
10863 // appear on the same directive.
10865 {OMPC_detach, OMPC_mergeable}))
10866 return StmtError();
10867
10868 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
10869
10870 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10871 AStmt, DSAStack->isCancelRegion());
10872}
10873
10875 SourceLocation EndLoc) {
10876 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
10877}
10878
10880 SourceLocation EndLoc) {
10881 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
10882}
10883
10885 SourceLocation StartLoc,
10886 SourceLocation EndLoc,
10887 bool InExContext) {
10888 const OMPAtClause *AtC =
10889 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
10890
10891 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
10892 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
10893 return StmtError();
10894 }
10895
10896 const OMPSeverityClause *SeverityC =
10897 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
10898 const OMPMessageClause *MessageC =
10899 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
10900 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
10901
10902 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
10903 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
10904 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
10905 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
10906 else
10907 Diag(StartLoc, diag::err_diagnose_if_succeeded)
10908 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
10909 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
10910 return StmtError();
10911 }
10912 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
10913}
10914
10917 SourceLocation StartLoc,
10918 SourceLocation EndLoc) {
10919 const OMPNowaitClause *NowaitC =
10920 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
10921 bool HasDependC =
10922 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
10923 .empty();
10924 if (NowaitC && !HasDependC) {
10925 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
10926 return StmtError();
10927 }
10928
10929 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
10930 Clauses);
10931}
10932
10935 Stmt *AStmt, SourceLocation StartLoc,
10936 SourceLocation EndLoc) {
10937 if (!AStmt)
10938 return StmtError();
10939
10940 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10941
10943
10944 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
10945 Clauses, AStmt,
10946 DSAStack->getTaskgroupReductionRef());
10947}
10948
10950 SourceLocation StartLoc,
10951 SourceLocation EndLoc) {
10952 OMPFlushClause *FC = nullptr;
10953 OMPClause *OrderClause = nullptr;
10954 for (OMPClause *C : Clauses) {
10955 if (C->getClauseKind() == OMPC_flush)
10956 FC = cast<OMPFlushClause>(C);
10957 else
10958 OrderClause = C;
10959 }
10960 OpenMPClauseKind MemOrderKind = OMPC_unknown;
10961 SourceLocation MemOrderLoc;
10962 for (const OMPClause *C : Clauses) {
10963 if (C->getClauseKind() == OMPC_acq_rel ||
10964 C->getClauseKind() == OMPC_acquire ||
10965 C->getClauseKind() == OMPC_release) {
10966 if (MemOrderKind != OMPC_unknown) {
10967 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
10968 << getOpenMPDirectiveName(OMPD_flush) << 1
10969 << SourceRange(C->getBeginLoc(), C->getEndLoc());
10970 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
10971 << getOpenMPClauseName(MemOrderKind);
10972 } else {
10973 MemOrderKind = C->getClauseKind();
10974 MemOrderLoc = C->getBeginLoc();
10975 }
10976 }
10977 }
10978 if (FC && OrderClause) {
10979 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
10980 << getOpenMPClauseName(OrderClause->getClauseKind());
10981 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
10982 << getOpenMPClauseName(OrderClause->getClauseKind());
10983 return StmtError();
10984 }
10985 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
10986}
10987
10989 SourceLocation StartLoc,
10990 SourceLocation EndLoc) {
10991 if (Clauses.empty()) {
10992 Diag(StartLoc, diag::err_omp_depobj_expected);
10993 return StmtError();
10994 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
10995 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
10996 return StmtError();
10997 }
10998 // Only depobj expression and another single clause is allowed.
10999 if (Clauses.size() > 2) {
11000 Diag(Clauses[2]->getBeginLoc(),
11001 diag::err_omp_depobj_single_clause_expected);
11002 return StmtError();
11003 } else if (Clauses.size() < 1) {
11004 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11005 return StmtError();
11006 }
11007 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11008}
11009
11011 SourceLocation StartLoc,
11012 SourceLocation EndLoc) {
11013 // Check that exactly one clause is specified.
11014 if (Clauses.size() != 1) {
11015 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11016 diag::err_omp_scan_single_clause_expected);
11017 return StmtError();
11018 }
11019 // Check that scan directive is used in the scope of the OpenMP loop body.
11020 if (Scope *S = DSAStack->getCurScope()) {
11021 Scope *ParentS = S->getParent();
11022 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11023 !ParentS->getBreakParent()->isOpenMPLoopScope())
11024 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11025 << getOpenMPDirectiveName(OMPD_scan) << 5);
11026 }
11027 // Check that only one instance of scan directives is used in the same outer
11028 // region.
11029 if (DSAStack->doesParentHasScanDirective()) {
11030 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11031 Diag(DSAStack->getParentScanDirectiveLoc(),
11032 diag::note_omp_previous_directive)
11033 << "scan";
11034 return StmtError();
11035 }
11036 DSAStack->setParentHasScanDirective(StartLoc);
11037 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11038}
11039
11042 Stmt *AStmt, SourceLocation StartLoc,
11043 SourceLocation EndLoc) {
11044 const OMPClause *DependFound = nullptr;
11045 const OMPClause *DependSourceClause = nullptr;
11046 const OMPClause *DependSinkClause = nullptr;
11047 const OMPClause *DoacrossFound = nullptr;
11048 const OMPClause *DoacrossSourceClause = nullptr;
11049 const OMPClause *DoacrossSinkClause = nullptr;
11050 bool ErrorFound = false;
11051 const OMPThreadsClause *TC = nullptr;
11052 const OMPSIMDClause *SC = nullptr;
11053 for (const OMPClause *C : Clauses) {
11054 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11055 auto DC = dyn_cast<OMPDependClause>(C);
11056 if (DC || DOC) {
11057 DependFound = DC ? C : nullptr;
11058 DoacrossFound = DOC ? C : nullptr;
11059 OMPDoacrossKind ODK;
11060 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11061 (DOC && (ODK.isSource(DOC)))) {
11062 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11063 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11064 << getOpenMPDirectiveName(OMPD_ordered)
11065 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11066 ErrorFound = true;
11067 } else {
11068 if (DC)
11069 DependSourceClause = C;
11070 else
11071 DoacrossSourceClause = C;
11072 }
11073 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11074 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11075 << (DC ? "depend" : "doacross") << 0;
11076 ErrorFound = true;
11077 }
11078 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11079 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11080 if (DependSourceClause || DoacrossSourceClause) {
11081 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11082 << (DC ? "depend" : "doacross") << 1;
11083 ErrorFound = true;
11084 }
11085 if (DC)
11086 DependSinkClause = C;
11087 else
11088 DoacrossSinkClause = C;
11089 }
11090 } else if (C->getClauseKind() == OMPC_threads) {
11091 TC = cast<OMPThreadsClause>(C);
11092 } else if (C->getClauseKind() == OMPC_simd) {
11093 SC = cast<OMPSIMDClause>(C);
11094 }
11095 }
11096 if (!ErrorFound && !SC &&
11097 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11098 // OpenMP [2.8.1,simd Construct, Restrictions]
11099 // An ordered construct with the simd clause is the only OpenMP construct
11100 // that can appear in the simd region.
11101 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11102 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11103 ErrorFound = true;
11104 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11106 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11107 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11108 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11109 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11110 ErrorFound = true;
11111 } else if ((DependFound || DoacrossFound) &&
11112 !DSAStack->getParentOrderedRegionParam().first) {
11114 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11115 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11116 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11117 ErrorFound = true;
11118 } else if (TC || Clauses.empty()) {
11119 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11120 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11121 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11122 << (TC != nullptr);
11123 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11124 ErrorFound = true;
11125 }
11126 }
11127 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11128 return StmtError();
11129
11130 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11131 // During execution of an iteration of a worksharing-loop or a loop nest
11132 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11133 // must not execute more than one ordered region corresponding to an ordered
11134 // construct without a depend clause.
11135 if (!DependFound && !DoacrossFound) {
11136 if (DSAStack->doesParentHasOrderedDirective()) {
11137 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11138 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11139 diag::note_omp_previous_directive)
11140 << "ordered";
11141 return StmtError();
11142 }
11143 DSAStack->setParentHasOrderedDirective(StartLoc);
11144 }
11145
11146 if (AStmt) {
11147 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11148
11150 }
11151
11152 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11153 AStmt);
11154}
11155
11156namespace {
11157/// Helper class for checking expression in 'omp atomic [update]'
11158/// construct.
11159class OpenMPAtomicUpdateChecker {
11160 /// Error results for atomic update expressions.
11161 enum ExprAnalysisErrorCode {
11162 /// A statement is not an expression statement.
11163 NotAnExpression,
11164 /// Expression is not builtin binary or unary operation.
11165 NotABinaryOrUnaryExpression,
11166 /// Unary operation is not post-/pre- increment/decrement operation.
11167 NotAnUnaryIncDecExpression,
11168 /// An expression is not of scalar type.
11169 NotAScalarType,
11170 /// A binary operation is not an assignment operation.
11171 NotAnAssignmentOp,
11172 /// RHS part of the binary operation is not a binary expression.
11173 NotABinaryExpression,
11174 /// RHS part is not additive/multiplicative/shift/bitwise binary
11175 /// expression.
11176 NotABinaryOperator,
11177 /// RHS binary operation does not have reference to the updated LHS
11178 /// part.
11179 NotAnUpdateExpression,
11180 /// An expression contains semantical error not related to
11181 /// 'omp atomic [update]'
11182 NotAValidExpression,
11183 /// No errors is found.
11184 NoError
11185 };
11186 /// Reference to Sema.
11187 Sema &SemaRef;
11188 /// A location for note diagnostics (when error is found).
11189 SourceLocation NoteLoc;
11190 /// 'x' lvalue part of the source atomic expression.
11191 Expr *X;
11192 /// 'expr' rvalue part of the source atomic expression.
11193 Expr *E;
11194 /// Helper expression of the form
11195 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11196 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11197 Expr *UpdateExpr;
11198 /// Is 'x' a LHS in a RHS part of full update expression. It is
11199 /// important for non-associative operations.
11200 bool IsXLHSInRHSPart;
11202 SourceLocation OpLoc;
11203 /// true if the source expression is a postfix unary operation, false
11204 /// if it is a prefix unary operation.
11205 bool IsPostfixUpdate;
11206
11207public:
11208 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11209 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11210 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11211 /// Check specified statement that it is suitable for 'atomic update'
11212 /// constructs and extract 'x', 'expr' and Operation from the original
11213 /// expression. If DiagId and NoteId == 0, then only check is performed
11214 /// without error notification.
11215 /// \param DiagId Diagnostic which should be emitted if error is found.
11216 /// \param NoteId Diagnostic note for the main error message.
11217 /// \return true if statement is not an update expression, false otherwise.
11218 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11219 /// Return the 'x' lvalue part of the source atomic expression.
11220 Expr *getX() const { return X; }
11221 /// Return the 'expr' rvalue part of the source atomic expression.
11222 Expr *getExpr() const { return E; }
11223 /// Return the update expression used in calculation of the updated
11224 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11225 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11226 Expr *getUpdateExpr() const { return UpdateExpr; }
11227 /// Return true if 'x' is LHS in RHS part of full update expression,
11228 /// false otherwise.
11229 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11230
11231 /// true if the source expression is a postfix unary operation, false
11232 /// if it is a prefix unary operation.
11233 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11234
11235private:
11236 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11237 unsigned NoteId = 0);
11238};
11239
11240bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11241 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11242 ExprAnalysisErrorCode ErrorFound = NoError;
11243 SourceLocation ErrorLoc, NoteLoc;
11244 SourceRange ErrorRange, NoteRange;
11245 // Allowed constructs are:
11246 // x = x binop expr;
11247 // x = expr binop x;
11248 if (AtomicBinOp->getOpcode() == BO_Assign) {
11249 X = AtomicBinOp->getLHS();
11250 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11251 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11252 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11253 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11254 AtomicInnerBinOp->isBitwiseOp()) {
11255 Op = AtomicInnerBinOp->getOpcode();
11256 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11257 Expr *LHS = AtomicInnerBinOp->getLHS();
11258 Expr *RHS = AtomicInnerBinOp->getRHS();
11259 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11260 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11261 /*Canonical=*/true);
11262 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11263 /*Canonical=*/true);
11264 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11265 /*Canonical=*/true);
11266 if (XId == LHSId) {
11267 E = RHS;
11268 IsXLHSInRHSPart = true;
11269 } else if (XId == RHSId) {
11270 E = LHS;
11271 IsXLHSInRHSPart = false;
11272 } else {
11273 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11274 ErrorRange = AtomicInnerBinOp->getSourceRange();
11275 NoteLoc = X->getExprLoc();
11276 NoteRange = X->getSourceRange();
11277 ErrorFound = NotAnUpdateExpression;
11278 }
11279 } else {
11280 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11281 ErrorRange = AtomicInnerBinOp->getSourceRange();
11282 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11283 NoteRange = SourceRange(NoteLoc, NoteLoc);
11284 ErrorFound = NotABinaryOperator;
11285 }
11286 } else {
11287 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11288 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11289 ErrorFound = NotABinaryExpression;
11290 }
11291 } else {
11292 ErrorLoc = AtomicBinOp->getExprLoc();
11293 ErrorRange = AtomicBinOp->getSourceRange();
11294 NoteLoc = AtomicBinOp->getOperatorLoc();
11295 NoteRange = SourceRange(NoteLoc, NoteLoc);
11296 ErrorFound = NotAnAssignmentOp;
11297 }
11298 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11299 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11300 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11301 return true;
11302 }
11303 if (SemaRef.CurContext->isDependentContext())
11304 E = X = UpdateExpr = nullptr;
11305 return ErrorFound != NoError;
11306}
11307
11308bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11309 unsigned NoteId) {
11310 ExprAnalysisErrorCode ErrorFound = NoError;
11311 SourceLocation ErrorLoc, NoteLoc;
11312 SourceRange ErrorRange, NoteRange;
11313 // Allowed constructs are:
11314 // x++;
11315 // x--;
11316 // ++x;
11317 // --x;
11318 // x binop= expr;
11319 // x = x binop expr;
11320 // x = expr binop x;
11321 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11322 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11323 if (AtomicBody->getType()->isScalarType() ||
11324 AtomicBody->isInstantiationDependent()) {
11325 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11326 AtomicBody->IgnoreParenImpCasts())) {
11327 // Check for Compound Assignment Operation
11329 AtomicCompAssignOp->getOpcode());
11330 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11331 E = AtomicCompAssignOp->getRHS();
11332 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11333 IsXLHSInRHSPart = true;
11334 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11335 AtomicBody->IgnoreParenImpCasts())) {
11336 // Check for Binary Operation
11337 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11338 return true;
11339 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11340 AtomicBody->IgnoreParenImpCasts())) {
11341 // Check for Unary Operation
11342 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11343 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11344 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11345 OpLoc = AtomicUnaryOp->getOperatorLoc();
11346 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11347 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11348 IsXLHSInRHSPart = true;
11349 } else {
11350 ErrorFound = NotAnUnaryIncDecExpression;
11351 ErrorLoc = AtomicUnaryOp->getExprLoc();
11352 ErrorRange = AtomicUnaryOp->getSourceRange();
11353 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11354 NoteRange = SourceRange(NoteLoc, NoteLoc);
11355 }
11356 } else if (!AtomicBody->isInstantiationDependent()) {
11357 ErrorFound = NotABinaryOrUnaryExpression;
11358 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11359 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11360 } else if (AtomicBody->containsErrors()) {
11361 ErrorFound = NotAValidExpression;
11362 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11363 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11364 }
11365 } else {
11366 ErrorFound = NotAScalarType;
11367 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11368 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11369 }
11370 } else {
11371 ErrorFound = NotAnExpression;
11372 NoteLoc = ErrorLoc = S->getBeginLoc();
11373 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11374 }
11375 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11376 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11377 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11378 return true;
11379 }
11380 if (SemaRef.CurContext->isDependentContext())
11381 E = X = UpdateExpr = nullptr;
11382 if (ErrorFound == NoError && E && X) {
11383 // Build an update expression of form 'OpaqueValueExpr(x) binop
11384 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11385 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11386 auto *OVEX = new (SemaRef.getASTContext())
11387 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11388 auto *OVEExpr = new (SemaRef.getASTContext())
11391 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11392 IsXLHSInRHSPart ? OVEExpr : OVEX);
11393 if (Update.isInvalid())
11394 return true;
11395 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11397 if (Update.isInvalid())
11398 return true;
11399 UpdateExpr = Update.get();
11400 }
11401 return ErrorFound != NoError;
11402}
11403
11404/// Get the node id of the fixed point of an expression \a S.
11405llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11406 llvm::FoldingSetNodeID Id;
11407 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11408 return Id;
11409}
11410
11411/// Check if two expressions are same.
11412bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11413 const Expr *RHS) {
11414 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11415}
11416
11417class OpenMPAtomicCompareChecker {
11418public:
11419 /// All kinds of errors that can occur in `atomic compare`
11420 enum ErrorTy {
11421 /// Empty compound statement.
11422 NoStmt = 0,
11423 /// More than one statement in a compound statement.
11424 MoreThanOneStmt,
11425 /// Not an assignment binary operator.
11426 NotAnAssignment,
11427 /// Not a conditional operator.
11428 NotCondOp,
11429 /// Wrong false expr. According to the spec, 'x' should be at the false
11430 /// expression of a conditional expression.
11431 WrongFalseExpr,
11432 /// The condition of a conditional expression is not a binary operator.
11433 NotABinaryOp,
11434 /// Invalid binary operator (not <, >, or ==).
11435 InvalidBinaryOp,
11436 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11437 InvalidComparison,
11438 /// X is not a lvalue.
11439 XNotLValue,
11440 /// Not a scalar.
11441 NotScalar,
11442 /// Not an integer.
11443 NotInteger,
11444 /// 'else' statement is not expected.
11445 UnexpectedElse,
11446 /// Not an equality operator.
11447 NotEQ,
11448 /// Invalid assignment (not v == x).
11449 InvalidAssignment,
11450 /// Not if statement
11451 NotIfStmt,
11452 /// More than two statements in a compound statement.
11453 MoreThanTwoStmts,
11454 /// Not a compound statement.
11455 NotCompoundStmt,
11456 /// No else statement.
11457 NoElse,
11458 /// Not 'if (r)'.
11459 InvalidCondition,
11460 /// No error.
11461 NoError,
11462 };
11463
11464 struct ErrorInfoTy {
11465 ErrorTy Error;
11466 SourceLocation ErrorLoc;
11467 SourceRange ErrorRange;
11468 SourceLocation NoteLoc;
11469 SourceRange NoteRange;
11470 };
11471
11472 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11473
11474 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11475 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11476
11477 Expr *getX() const { return X; }
11478 Expr *getE() const { return E; }
11479 Expr *getD() const { return D; }
11480 Expr *getCond() const { return C; }
11481 bool isXBinopExpr() const { return IsXBinopExpr; }
11482
11483protected:
11484 /// Reference to ASTContext
11485 ASTContext &ContextRef;
11486 /// 'x' lvalue part of the source atomic expression.
11487 Expr *X = nullptr;
11488 /// 'expr' or 'e' rvalue part of the source atomic expression.
11489 Expr *E = nullptr;
11490 /// 'd' rvalue part of the source atomic expression.
11491 Expr *D = nullptr;
11492 /// 'cond' part of the source atomic expression. It is in one of the following
11493 /// forms:
11494 /// expr ordop x
11495 /// x ordop expr
11496 /// x == e
11497 /// e == x
11498 Expr *C = nullptr;
11499 /// True if the cond expr is in the form of 'x ordop expr'.
11500 bool IsXBinopExpr = true;
11501
11502 /// Check if it is a valid conditional update statement (cond-update-stmt).
11503 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11504
11505 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11506 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11507
11508 /// Check if all captured values have right type.
11509 bool checkType(ErrorInfoTy &ErrorInfo) const;
11510
11511 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11512 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11514 return true;
11515
11516 if (ShouldBeLValue && !E->isLValue()) {
11517 ErrorInfo.Error = ErrorTy::XNotLValue;
11518 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11519 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11520 return false;
11521 }
11522
11523 QualType QTy = E->getType();
11524 if (!QTy->isScalarType()) {
11525 ErrorInfo.Error = ErrorTy::NotScalar;
11526 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11527 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11528 return false;
11529 }
11530 if (ShouldBeInteger && !QTy->isIntegerType()) {
11531 ErrorInfo.Error = ErrorTy::NotInteger;
11532 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11533 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11534 return false;
11535 }
11536
11537 return true;
11538 }
11539};
11540
11541bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11542 ErrorInfoTy &ErrorInfo) {
11543 auto *Then = S->getThen();
11544 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11545 if (CS->body_empty()) {
11546 ErrorInfo.Error = ErrorTy::NoStmt;
11547 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11548 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11549 return false;
11550 }
11551 if (CS->size() > 1) {
11552 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11553 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11554 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11555 return false;
11556 }
11557 Then = CS->body_front();
11558 }
11559
11560 auto *BO = dyn_cast<BinaryOperator>(Then);
11561 if (!BO) {
11562 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11565 return false;
11566 }
11567 if (BO->getOpcode() != BO_Assign) {
11568 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11569 ErrorInfo.ErrorLoc = BO->getExprLoc();
11570 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11571 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11572 return false;
11573 }
11574
11575 X = BO->getLHS();
11576
11577 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11578 if (!Cond) {
11579 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11580 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11581 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11582 return false;
11583 }
11584
11585 switch (Cond->getOpcode()) {
11586 case BO_EQ: {
11587 C = Cond;
11588 D = BO->getRHS();
11589 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11590 E = Cond->getRHS();
11591 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11592 E = Cond->getLHS();
11593 } else {
11594 ErrorInfo.Error = ErrorTy::InvalidComparison;
11595 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11596 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11597 return false;
11598 }
11599 break;
11600 }
11601 case BO_LT:
11602 case BO_GT: {
11603 E = BO->getRHS();
11604 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11605 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11606 C = Cond;
11607 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11608 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11609 C = Cond;
11610 IsXBinopExpr = false;
11611 } else {
11612 ErrorInfo.Error = ErrorTy::InvalidComparison;
11613 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11614 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11615 return false;
11616 }
11617 break;
11618 }
11619 default:
11620 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11621 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11622 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11623 return false;
11624 }
11625
11626 if (S->getElse()) {
11627 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11628 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11629 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11630 return false;
11631 }
11632
11633 return true;
11634}
11635
11636bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11637 ErrorInfoTy &ErrorInfo) {
11638 auto *BO = dyn_cast<BinaryOperator>(S);
11639 if (!BO) {
11640 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11641 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11642 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11643 return false;
11644 }
11645 if (BO->getOpcode() != BO_Assign) {
11646 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11647 ErrorInfo.ErrorLoc = BO->getExprLoc();
11648 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11649 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11650 return false;
11651 }
11652
11653 X = BO->getLHS();
11654
11655 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11656 if (!CO) {
11657 ErrorInfo.Error = ErrorTy::NotCondOp;
11658 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11659 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11660 return false;
11661 }
11662
11663 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11664 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11665 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11666 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11667 CO->getFalseExpr()->getSourceRange();
11668 return false;
11669 }
11670
11671 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11672 if (!Cond) {
11673 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11674 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11675 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11676 CO->getCond()->getSourceRange();
11677 return false;
11678 }
11679
11680 switch (Cond->getOpcode()) {
11681 case BO_EQ: {
11682 C = Cond;
11683 D = CO->getTrueExpr();
11684 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11685 E = Cond->getRHS();
11686 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11687 E = Cond->getLHS();
11688 } else {
11689 ErrorInfo.Error = ErrorTy::InvalidComparison;
11690 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11691 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11692 return false;
11693 }
11694 break;
11695 }
11696 case BO_LT:
11697 case BO_GT: {
11698 E = CO->getTrueExpr();
11699 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11700 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11701 C = Cond;
11702 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11703 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11704 C = Cond;
11705 IsXBinopExpr = false;
11706 } else {
11707 ErrorInfo.Error = ErrorTy::InvalidComparison;
11708 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11709 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11710 return false;
11711 }
11712 break;
11713 }
11714 default:
11715 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11716 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11717 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11718 return false;
11719 }
11720
11721 return true;
11722}
11723
11724bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11725 // 'x' and 'e' cannot be nullptr
11726 assert(X && E && "X and E cannot be nullptr");
11727
11728 if (!CheckValue(X, ErrorInfo, true))
11729 return false;
11730
11731 if (!CheckValue(E, ErrorInfo, false))
11732 return false;
11733
11734 if (D && !CheckValue(D, ErrorInfo, false))
11735 return false;
11736
11737 return true;
11738}
11739
11740bool OpenMPAtomicCompareChecker::checkStmt(
11741 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11742 auto *CS = dyn_cast<CompoundStmt>(S);
11743 if (CS) {
11744 if (CS->body_empty()) {
11745 ErrorInfo.Error = ErrorTy::NoStmt;
11746 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11747 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11748 return false;
11749 }
11750
11751 if (CS->size() != 1) {
11752 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11753 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11754 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11755 return false;
11756 }
11757 S = CS->body_front();
11758 }
11759
11760 auto Res = false;
11761
11762 if (auto *IS = dyn_cast<IfStmt>(S)) {
11763 // Check if the statement is in one of the following forms
11764 // (cond-update-stmt):
11765 // if (expr ordop x) { x = expr; }
11766 // if (x ordop expr) { x = expr; }
11767 // if (x == e) { x = d; }
11768 Res = checkCondUpdateStmt(IS, ErrorInfo);
11769 } else {
11770 // Check if the statement is in one of the following forms (cond-expr-stmt):
11771 // x = expr ordop x ? expr : x;
11772 // x = x ordop expr ? expr : x;
11773 // x = x == e ? d : x;
11774 Res = checkCondExprStmt(S, ErrorInfo);
11775 }
11776
11777 if (!Res)
11778 return false;
11779
11780 return checkType(ErrorInfo);
11781}
11782
11783class OpenMPAtomicCompareCaptureChecker final
11784 : public OpenMPAtomicCompareChecker {
11785public:
11786 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11787
11788 Expr *getV() const { return V; }
11789 Expr *getR() const { return R; }
11790 bool isFailOnly() const { return IsFailOnly; }
11791 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11792
11793 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11794 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11795
11796private:
11797 bool checkType(ErrorInfoTy &ErrorInfo);
11798
11799 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11800 // form of 'conditional-update-capture-atomic' structured block on the v5.2
11801 // spec p.p. 82:
11802 // (1) { v = x; cond-update-stmt }
11803 // (2) { cond-update-stmt v = x; }
11804 // (3) if(x == e) { x = d; } else { v = x; }
11805 // (4) { r = x == e; if(r) { x = d; } }
11806 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11807
11808 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11809 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11810
11811 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11812 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11813 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
11814
11815 /// 'v' lvalue part of the source atomic expression.
11816 Expr *V = nullptr;
11817 /// 'r' lvalue part of the source atomic expression.
11818 Expr *R = nullptr;
11819 /// If 'v' is only updated when the comparison fails.
11820 bool IsFailOnly = false;
11821 /// If original value of 'x' must be stored in 'v', not an updated one.
11822 bool IsPostfixUpdate = false;
11823};
11824
11825bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11826 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11827 return false;
11828
11829 if (V && !CheckValue(V, ErrorInfo, true))
11830 return false;
11831
11832 if (R && !CheckValue(R, ErrorInfo, true, true))
11833 return false;
11834
11835 return true;
11836}
11837
11838bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
11839 ErrorInfoTy &ErrorInfo) {
11840 IsFailOnly = true;
11841
11842 auto *Then = S->getThen();
11843 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11844 if (CS->body_empty()) {
11845 ErrorInfo.Error = ErrorTy::NoStmt;
11846 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11847 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11848 return false;
11849 }
11850 if (CS->size() > 1) {
11851 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11852 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11853 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11854 return false;
11855 }
11856 Then = CS->body_front();
11857 }
11858
11859 auto *BO = dyn_cast<BinaryOperator>(Then);
11860 if (!BO) {
11861 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11862 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11863 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11864 return false;
11865 }
11866 if (BO->getOpcode() != BO_Assign) {
11867 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11868 ErrorInfo.ErrorLoc = BO->getExprLoc();
11869 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11870 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11871 return false;
11872 }
11873
11874 X = BO->getLHS();
11875 D = BO->getRHS();
11876
11877 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11878 if (!Cond) {
11879 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11880 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11881 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11882 return false;
11883 }
11884 if (Cond->getOpcode() != BO_EQ) {
11885 ErrorInfo.Error = ErrorTy::NotEQ;
11886 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11887 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11888 return false;
11889 }
11890
11891 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11892 E = Cond->getRHS();
11893 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11894 E = Cond->getLHS();
11895 } else {
11896 ErrorInfo.Error = ErrorTy::InvalidComparison;
11897 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11898 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11899 return false;
11900 }
11901
11902 C = Cond;
11903
11904 if (!S->getElse()) {
11905 ErrorInfo.Error = ErrorTy::NoElse;
11906 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11907 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11908 return false;
11909 }
11910
11911 auto *Else = S->getElse();
11912 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
11913 if (CS->body_empty()) {
11914 ErrorInfo.Error = ErrorTy::NoStmt;
11915 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11916 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11917 return false;
11918 }
11919 if (CS->size() > 1) {
11920 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11921 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11922 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11923 return false;
11924 }
11925 Else = CS->body_front();
11926 }
11927
11928 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
11929 if (!ElseBO) {
11930 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11931 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
11932 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
11933 return false;
11934 }
11935 if (ElseBO->getOpcode() != BO_Assign) {
11936 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11937 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
11938 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
11939 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
11940 return false;
11941 }
11942
11943 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
11944 ErrorInfo.Error = ErrorTy::InvalidAssignment;
11945 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
11946 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11947 ElseBO->getRHS()->getSourceRange();
11948 return false;
11949 }
11950
11951 V = ElseBO->getLHS();
11952
11953 return checkType(ErrorInfo);
11954}
11955
11956bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
11957 ErrorInfoTy &ErrorInfo) {
11958 // We don't check here as they should be already done before call this
11959 // function.
11960 auto *CS = cast<CompoundStmt>(S);
11961 assert(CS->size() == 2 && "CompoundStmt size is not expected");
11962 auto *S1 = cast<BinaryOperator>(CS->body_front());
11963 auto *S2 = cast<IfStmt>(CS->body_back());
11964 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
11965
11966 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
11967 ErrorInfo.Error = ErrorTy::InvalidCondition;
11968 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
11969 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
11970 return false;
11971 }
11972
11973 R = S1->getLHS();
11974
11975 auto *Then = S2->getThen();
11976 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
11977 if (ThenCS->body_empty()) {
11978 ErrorInfo.Error = ErrorTy::NoStmt;
11979 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
11980 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
11981 return false;
11982 }
11983 if (ThenCS->size() > 1) {
11984 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11985 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
11986 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
11987 return false;
11988 }
11989 Then = ThenCS->body_front();
11990 }
11991
11992 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
11993 if (!ThenBO) {
11994 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11995 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
11996 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
11997 return false;
11998 }
11999 if (ThenBO->getOpcode() != BO_Assign) {
12000 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12001 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12002 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12003 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12004 return false;
12005 }
12006
12007 X = ThenBO->getLHS();
12008 D = ThenBO->getRHS();
12009
12010 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12011 if (BO->getOpcode() != BO_EQ) {
12012 ErrorInfo.Error = ErrorTy::NotEQ;
12013 ErrorInfo.ErrorLoc = BO->getExprLoc();
12014 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12015 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12016 return false;
12017 }
12018
12019 C = BO;
12020
12021 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12022 E = BO->getRHS();
12023 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12024 E = BO->getLHS();
12025 } else {
12026 ErrorInfo.Error = ErrorTy::InvalidComparison;
12027 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12028 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12029 return false;
12030 }
12031
12032 if (S2->getElse()) {
12033 IsFailOnly = true;
12034
12035 auto *Else = S2->getElse();
12036 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12037 if (ElseCS->body_empty()) {
12038 ErrorInfo.Error = ErrorTy::NoStmt;
12039 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12040 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12041 return false;
12042 }
12043 if (ElseCS->size() > 1) {
12044 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12045 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12046 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12047 return false;
12048 }
12049 Else = ElseCS->body_front();
12050 }
12051
12052 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12053 if (!ElseBO) {
12054 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12055 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12056 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12057 return false;
12058 }
12059 if (ElseBO->getOpcode() != BO_Assign) {
12060 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12061 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12062 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12063 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12064 return false;
12065 }
12066 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12067 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12068 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12069 ErrorInfo.NoteLoc = X->getExprLoc();
12070 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12071 ErrorInfo.NoteRange = X->getSourceRange();
12072 return false;
12073 }
12074
12075 V = ElseBO->getLHS();
12076 }
12077
12078 return checkType(ErrorInfo);
12079}
12080
12081bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12082 ErrorInfoTy &ErrorInfo) {
12083 // if(x == e) { x = d; } else { v = x; }
12084 if (auto *IS = dyn_cast<IfStmt>(S))
12085 return checkForm3(IS, ErrorInfo);
12086
12087 auto *CS = dyn_cast<CompoundStmt>(S);
12088 if (!CS) {
12089 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12090 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12092 return false;
12093 }
12094 if (CS->body_empty()) {
12095 ErrorInfo.Error = ErrorTy::NoStmt;
12096 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12097 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12098 return false;
12099 }
12100
12101 // { if(x == e) { x = d; } else { v = x; } }
12102 if (CS->size() == 1) {
12103 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12104 if (!IS) {
12105 ErrorInfo.Error = ErrorTy::NotIfStmt;
12106 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12107 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12108 CS->body_front()->getSourceRange();
12109 return false;
12110 }
12111
12112 return checkForm3(IS, ErrorInfo);
12113 } else if (CS->size() == 2) {
12114 auto *S1 = CS->body_front();
12115 auto *S2 = CS->body_back();
12116
12117 Stmt *UpdateStmt = nullptr;
12118 Stmt *CondUpdateStmt = nullptr;
12119 Stmt *CondExprStmt = nullptr;
12120
12121 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12122 // It could be one of the following cases:
12123 // { v = x; cond-update-stmt }
12124 // { v = x; cond-expr-stmt }
12125 // { cond-expr-stmt; v = x; }
12126 // form 45
12127 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12128 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12129 // check if form 45
12130 if (isa<IfStmt>(S2))
12131 return checkForm45(CS, ErrorInfo);
12132 // { cond-expr-stmt; v = x; }
12133 CondExprStmt = S1;
12134 UpdateStmt = S2;
12135 } else {
12136 IsPostfixUpdate = true;
12137 UpdateStmt = S1;
12138 if (isa<IfStmt>(S2)) {
12139 // { v = x; cond-update-stmt }
12140 CondUpdateStmt = S2;
12141 } else {
12142 // { v = x; cond-expr-stmt }
12143 CondExprStmt = S2;
12144 }
12145 }
12146 } else {
12147 // { cond-update-stmt v = x; }
12148 UpdateStmt = S2;
12149 CondUpdateStmt = S1;
12150 }
12151
12152 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12153 auto *IS = dyn_cast<IfStmt>(CUS);
12154 if (!IS) {
12155 ErrorInfo.Error = ErrorTy::NotIfStmt;
12156 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12157 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12158 return false;
12159 }
12160
12161 return checkCondUpdateStmt(IS, ErrorInfo);
12162 };
12163
12164 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12165 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12166 auto *BO = dyn_cast<BinaryOperator>(US);
12167 if (!BO) {
12168 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12169 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12170 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12171 return false;
12172 }
12173 if (BO->getOpcode() != BO_Assign) {
12174 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12175 ErrorInfo.ErrorLoc = BO->getExprLoc();
12176 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12177 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12178 return false;
12179 }
12180 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12181 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12182 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12183 ErrorInfo.NoteLoc = this->X->getExprLoc();
12184 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12185 ErrorInfo.NoteRange = this->X->getSourceRange();
12186 return false;
12187 }
12188
12189 this->V = BO->getLHS();
12190
12191 return true;
12192 };
12193
12194 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12195 return false;
12196 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12197 return false;
12198 if (!CheckUpdateStmt(UpdateStmt))
12199 return false;
12200 } else {
12201 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12202 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12203 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12204 return false;
12205 }
12206
12207 return checkType(ErrorInfo);
12208}
12209} // namespace
12210
12212 Stmt *AStmt,
12213 SourceLocation StartLoc,
12214 SourceLocation EndLoc) {
12215 ASTContext &Context = getASTContext();
12216 // Register location of the first atomic directive.
12217 DSAStack->addAtomicDirectiveLoc(StartLoc);
12218 if (!AStmt)
12219 return StmtError();
12220
12221 // 1.2.2 OpenMP Language Terminology
12222 // Structured block - An executable statement with a single entry at the
12223 // top and a single exit at the bottom.
12224 // The point of exit cannot be a branch out of the structured block.
12225 // longjmp() and throw() must not violate the entry/exit criteria.
12226 OpenMPClauseKind AtomicKind = OMPC_unknown;
12227 SourceLocation AtomicKindLoc;
12228 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12229 SourceLocation MemOrderLoc;
12230 bool MutexClauseEncountered = false;
12231 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12232 for (const OMPClause *C : Clauses) {
12233 switch (C->getClauseKind()) {
12234 case OMPC_read:
12235 case OMPC_write:
12236 case OMPC_update:
12237 MutexClauseEncountered = true;
12238 [[fallthrough]];
12239 case OMPC_capture:
12240 case OMPC_compare: {
12241 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12242 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12243 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12244 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12245 << getOpenMPClauseName(AtomicKind);
12246 } else {
12247 AtomicKind = C->getClauseKind();
12248 AtomicKindLoc = C->getBeginLoc();
12249 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12250 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12251 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12252 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12253 << getOpenMPClauseName(AtomicKind);
12254 }
12255 }
12256 break;
12257 }
12258 case OMPC_weak:
12259 case OMPC_fail: {
12260 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12261 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12262 << getOpenMPClauseName(C->getClauseKind())
12263 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12264 return StmtError();
12265 }
12266 break;
12267 }
12268 case OMPC_seq_cst:
12269 case OMPC_acq_rel:
12270 case OMPC_acquire:
12271 case OMPC_release:
12272 case OMPC_relaxed: {
12273 if (MemOrderKind != OMPC_unknown) {
12274 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12275 << getOpenMPDirectiveName(OMPD_atomic) << 0
12276 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12277 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12278 << getOpenMPClauseName(MemOrderKind);
12279 } else {
12280 MemOrderKind = C->getClauseKind();
12281 MemOrderLoc = C->getBeginLoc();
12282 }
12283 break;
12284 }
12285 // The following clauses are allowed, but we don't need to do anything here.
12286 case OMPC_hint:
12287 break;
12288 default:
12289 llvm_unreachable("unknown clause is encountered");
12290 }
12291 }
12292 bool IsCompareCapture = false;
12293 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12294 EncounteredAtomicKinds.contains(OMPC_capture)) {
12295 IsCompareCapture = true;
12296 AtomicKind = OMPC_compare;
12297 }
12298 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12299 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12300 // release.
12301 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12302 // acquire.
12303 // If atomic-clause is update or not present then memory-order-clause must not
12304 // be acq_rel or acquire.
12305 if ((AtomicKind == OMPC_read &&
12306 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12307 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12308 AtomicKind == OMPC_unknown) &&
12309 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12310 SourceLocation Loc = AtomicKindLoc;
12311 if (AtomicKind == OMPC_unknown)
12312 Loc = StartLoc;
12313 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12314 << getOpenMPClauseName(AtomicKind)
12315 << (AtomicKind == OMPC_unknown ? 1 : 0)
12316 << getOpenMPClauseName(MemOrderKind);
12317 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12318 << getOpenMPClauseName(MemOrderKind);
12319 }
12320
12321 Stmt *Body = AStmt;
12322 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12323 Body = EWC->getSubExpr();
12324
12325 Expr *X = nullptr;
12326 Expr *V = nullptr;
12327 Expr *E = nullptr;
12328 Expr *UE = nullptr;
12329 Expr *D = nullptr;
12330 Expr *CE = nullptr;
12331 Expr *R = nullptr;
12332 bool IsXLHSInRHSPart = false;
12333 bool IsPostfixUpdate = false;
12334 bool IsFailOnly = false;
12335 // OpenMP [2.12.6, atomic Construct]
12336 // In the next expressions:
12337 // * x and v (as applicable) are both l-value expressions with scalar type.
12338 // * During the execution of an atomic region, multiple syntactic
12339 // occurrences of x must designate the same storage location.
12340 // * Neither of v and expr (as applicable) may access the storage location
12341 // designated by x.
12342 // * Neither of x and expr (as applicable) may access the storage location
12343 // designated by v.
12344 // * expr is an expression with scalar type.
12345 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12346 // * binop, binop=, ++, and -- are not overloaded operators.
12347 // * The expression x binop expr must be numerically equivalent to x binop
12348 // (expr). This requirement is satisfied if the operators in expr have
12349 // precedence greater than binop, or by using parentheses around expr or
12350 // subexpressions of expr.
12351 // * The expression expr binop x must be numerically equivalent to (expr)
12352 // binop x. This requirement is satisfied if the operators in expr have
12353 // precedence equal to or greater than binop, or by using parentheses around
12354 // expr or subexpressions of expr.
12355 // * For forms that allow multiple occurrences of x, the number of times
12356 // that x is evaluated is unspecified.
12357 if (AtomicKind == OMPC_read) {
12358 enum {
12359 NotAnExpression,
12360 NotAnAssignmentOp,
12361 NotAScalarType,
12362 NotAnLValue,
12363 NoError
12364 } ErrorFound = NoError;
12365 SourceLocation ErrorLoc, NoteLoc;
12366 SourceRange ErrorRange, NoteRange;
12367 // If clause is read:
12368 // v = x;
12369 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12370 const auto *AtomicBinOp =
12371 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12372 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12373 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12374 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12375 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12376 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12377 if (!X->isLValue() || !V->isLValue()) {
12378 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12379 ErrorFound = NotAnLValue;
12380 ErrorLoc = AtomicBinOp->getExprLoc();
12381 ErrorRange = AtomicBinOp->getSourceRange();
12382 NoteLoc = NotLValueExpr->getExprLoc();
12383 NoteRange = NotLValueExpr->getSourceRange();
12384 }
12385 } else if (!X->isInstantiationDependent() ||
12386 !V->isInstantiationDependent()) {
12387 const Expr *NotScalarExpr =
12388 (X->isInstantiationDependent() || X->getType()->isScalarType())
12389 ? V
12390 : X;
12391 ErrorFound = NotAScalarType;
12392 ErrorLoc = AtomicBinOp->getExprLoc();
12393 ErrorRange = AtomicBinOp->getSourceRange();
12394 NoteLoc = NotScalarExpr->getExprLoc();
12395 NoteRange = NotScalarExpr->getSourceRange();
12396 }
12397 } else if (!AtomicBody->isInstantiationDependent()) {
12398 ErrorFound = NotAnAssignmentOp;
12399 ErrorLoc = AtomicBody->getExprLoc();
12400 ErrorRange = AtomicBody->getSourceRange();
12401 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12402 : AtomicBody->getExprLoc();
12403 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12404 : AtomicBody->getSourceRange();
12405 }
12406 } else {
12407 ErrorFound = NotAnExpression;
12408 NoteLoc = ErrorLoc = Body->getBeginLoc();
12409 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12410 }
12411 if (ErrorFound != NoError) {
12412 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12413 << ErrorRange;
12414 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12415 << ErrorFound << NoteRange;
12416 return StmtError();
12417 }
12419 V = X = nullptr;
12420 } else if (AtomicKind == OMPC_write) {
12421 enum {
12422 NotAnExpression,
12423 NotAnAssignmentOp,
12424 NotAScalarType,
12425 NotAnLValue,
12426 NoError
12427 } ErrorFound = NoError;
12428 SourceLocation ErrorLoc, NoteLoc;
12429 SourceRange ErrorRange, NoteRange;
12430 // If clause is write:
12431 // x = expr;
12432 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12433 const auto *AtomicBinOp =
12434 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12435 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12436 X = AtomicBinOp->getLHS();
12437 E = AtomicBinOp->getRHS();
12438 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12440 if (!X->isLValue()) {
12441 ErrorFound = NotAnLValue;
12442 ErrorLoc = AtomicBinOp->getExprLoc();
12443 ErrorRange = AtomicBinOp->getSourceRange();
12444 NoteLoc = X->getExprLoc();
12445 NoteRange = X->getSourceRange();
12446 }
12447 } else if (!X->isInstantiationDependent() ||
12449 const Expr *NotScalarExpr =
12450 (X->isInstantiationDependent() || X->getType()->isScalarType())
12451 ? E
12452 : X;
12453 ErrorFound = NotAScalarType;
12454 ErrorLoc = AtomicBinOp->getExprLoc();
12455 ErrorRange = AtomicBinOp->getSourceRange();
12456 NoteLoc = NotScalarExpr->getExprLoc();
12457 NoteRange = NotScalarExpr->getSourceRange();
12458 }
12459 } else if (!AtomicBody->isInstantiationDependent()) {
12460 ErrorFound = NotAnAssignmentOp;
12461 ErrorLoc = AtomicBody->getExprLoc();
12462 ErrorRange = AtomicBody->getSourceRange();
12463 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12464 : AtomicBody->getExprLoc();
12465 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12466 : AtomicBody->getSourceRange();
12467 }
12468 } else {
12469 ErrorFound = NotAnExpression;
12470 NoteLoc = ErrorLoc = Body->getBeginLoc();
12471 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12472 }
12473 if (ErrorFound != NoError) {
12474 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12475 << ErrorRange;
12476 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12477 << ErrorFound << NoteRange;
12478 return StmtError();
12479 }
12481 E = X = nullptr;
12482 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12483 // If clause is update:
12484 // x++;
12485 // x--;
12486 // ++x;
12487 // --x;
12488 // x binop= expr;
12489 // x = x binop expr;
12490 // x = expr binop x;
12491 OpenMPAtomicUpdateChecker Checker(SemaRef);
12492 if (Checker.checkStatement(
12493 Body,
12494 (AtomicKind == OMPC_update)
12495 ? diag::err_omp_atomic_update_not_expression_statement
12496 : diag::err_omp_atomic_not_expression_statement,
12497 diag::note_omp_atomic_update))
12498 return StmtError();
12500 E = Checker.getExpr();
12501 X = Checker.getX();
12502 UE = Checker.getUpdateExpr();
12503 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12504 }
12505 } else if (AtomicKind == OMPC_capture) {
12506 enum {
12507 NotAnAssignmentOp,
12508 NotACompoundStatement,
12509 NotTwoSubstatements,
12510 NotASpecificExpression,
12511 NoError
12512 } ErrorFound = NoError;
12513 SourceLocation ErrorLoc, NoteLoc;
12514 SourceRange ErrorRange, NoteRange;
12515 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12516 // If clause is a capture:
12517 // v = x++;
12518 // v = x--;
12519 // v = ++x;
12520 // v = --x;
12521 // v = x binop= expr;
12522 // v = x = x binop expr;
12523 // v = x = expr binop x;
12524 const auto *AtomicBinOp =
12525 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12526 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12527 V = AtomicBinOp->getLHS();
12528 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12529 OpenMPAtomicUpdateChecker Checker(SemaRef);
12530 if (Checker.checkStatement(
12531 Body, diag::err_omp_atomic_capture_not_expression_statement,
12532 diag::note_omp_atomic_update))
12533 return StmtError();
12534 E = Checker.getExpr();
12535 X = Checker.getX();
12536 UE = Checker.getUpdateExpr();
12537 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12538 IsPostfixUpdate = Checker.isPostfixUpdate();
12539 } else if (!AtomicBody->isInstantiationDependent()) {
12540 ErrorLoc = AtomicBody->getExprLoc();
12541 ErrorRange = AtomicBody->getSourceRange();
12542 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12543 : AtomicBody->getExprLoc();
12544 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12545 : AtomicBody->getSourceRange();
12546 ErrorFound = NotAnAssignmentOp;
12547 }
12548 if (ErrorFound != NoError) {
12549 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12550 << ErrorRange;
12551 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12552 return StmtError();
12553 }
12555 UE = V = E = X = nullptr;
12556 } else {
12557 // If clause is a capture:
12558 // { v = x; x = expr; }
12559 // { v = x; x++; }
12560 // { v = x; x--; }
12561 // { v = x; ++x; }
12562 // { v = x; --x; }
12563 // { v = x; x binop= expr; }
12564 // { v = x; x = x binop expr; }
12565 // { v = x; x = expr binop x; }
12566 // { x++; v = x; }
12567 // { x--; v = x; }
12568 // { ++x; v = x; }
12569 // { --x; v = x; }
12570 // { x binop= expr; v = x; }
12571 // { x = x binop expr; v = x; }
12572 // { x = expr binop x; v = x; }
12573 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12574 // Check that this is { expr1; expr2; }
12575 if (CS->size() == 2) {
12576 Stmt *First = CS->body_front();
12577 Stmt *Second = CS->body_back();
12578 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12579 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12580 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12581 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12582 // Need to find what subexpression is 'v' and what is 'x'.
12583 OpenMPAtomicUpdateChecker Checker(SemaRef);
12584 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12585 BinaryOperator *BinOp = nullptr;
12586 if (IsUpdateExprFound) {
12587 BinOp = dyn_cast<BinaryOperator>(First);
12588 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12589 }
12590 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12591 // { v = x; x++; }
12592 // { v = x; x--; }
12593 // { v = x; ++x; }
12594 // { v = x; --x; }
12595 // { v = x; x binop= expr; }
12596 // { v = x; x = x binop expr; }
12597 // { v = x; x = expr binop x; }
12598 // Check that the first expression has form v = x.
12599 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12600 llvm::FoldingSetNodeID XId, PossibleXId;
12601 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12602 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12603 IsUpdateExprFound = XId == PossibleXId;
12604 if (IsUpdateExprFound) {
12605 V = BinOp->getLHS();
12606 X = Checker.getX();
12607 E = Checker.getExpr();
12608 UE = Checker.getUpdateExpr();
12609 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12610 IsPostfixUpdate = true;
12611 }
12612 }
12613 if (!IsUpdateExprFound) {
12614 IsUpdateExprFound = !Checker.checkStatement(First);
12615 BinOp = nullptr;
12616 if (IsUpdateExprFound) {
12617 BinOp = dyn_cast<BinaryOperator>(Second);
12618 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12619 }
12620 if (IsUpdateExprFound &&
12622 // { x++; v = x; }
12623 // { x--; v = x; }
12624 // { ++x; v = x; }
12625 // { --x; v = x; }
12626 // { x binop= expr; v = x; }
12627 // { x = x binop expr; v = x; }
12628 // { x = expr binop x; v = x; }
12629 // Check that the second 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 = false;
12642 }
12643 }
12644 }
12645 if (!IsUpdateExprFound) {
12646 // { v = x; x = expr; }
12647 auto *FirstExpr = dyn_cast<Expr>(First);
12648 auto *SecondExpr = dyn_cast<Expr>(Second);
12649 if (!FirstExpr || !SecondExpr ||
12650 !(FirstExpr->isInstantiationDependent() ||
12651 SecondExpr->isInstantiationDependent())) {
12652 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12653 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12654 ErrorFound = NotAnAssignmentOp;
12655 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12656 : First->getBeginLoc();
12657 NoteRange = ErrorRange = FirstBinOp
12658 ? FirstBinOp->getSourceRange()
12659 : SourceRange(ErrorLoc, ErrorLoc);
12660 } else {
12661 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12662 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12663 ErrorFound = NotAnAssignmentOp;
12664 NoteLoc = ErrorLoc = SecondBinOp
12665 ? SecondBinOp->getOperatorLoc()
12666 : Second->getBeginLoc();
12667 NoteRange = ErrorRange =
12668 SecondBinOp ? SecondBinOp->getSourceRange()
12669 : SourceRange(ErrorLoc, ErrorLoc);
12670 } else {
12671 Expr *PossibleXRHSInFirst =
12672 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12673 Expr *PossibleXLHSInSecond =
12674 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12675 llvm::FoldingSetNodeID X1Id, X2Id;
12676 PossibleXRHSInFirst->Profile(X1Id, Context,
12677 /*Canonical=*/true);
12678 PossibleXLHSInSecond->Profile(X2Id, Context,
12679 /*Canonical=*/true);
12680 IsUpdateExprFound = X1Id == X2Id;
12681 if (IsUpdateExprFound) {
12682 V = FirstBinOp->getLHS();
12683 X = SecondBinOp->getLHS();
12684 E = SecondBinOp->getRHS();
12685 UE = nullptr;
12686 IsXLHSInRHSPart = false;
12687 IsPostfixUpdate = true;
12688 } else {
12689 ErrorFound = NotASpecificExpression;
12690 ErrorLoc = FirstBinOp->getExprLoc();
12691 ErrorRange = FirstBinOp->getSourceRange();
12692 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12693 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12694 }
12695 }
12696 }
12697 }
12698 }
12699 } else {
12700 NoteLoc = ErrorLoc = Body->getBeginLoc();
12701 NoteRange = ErrorRange =
12702 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12703 ErrorFound = NotTwoSubstatements;
12704 }
12705 } else {
12706 NoteLoc = ErrorLoc = Body->getBeginLoc();
12707 NoteRange = ErrorRange =
12708 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12709 ErrorFound = NotACompoundStatement;
12710 }
12711 }
12712 if (ErrorFound != NoError) {
12713 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12714 << ErrorRange;
12715 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12716 return StmtError();
12717 }
12719 UE = V = E = X = nullptr;
12720 } else if (AtomicKind == OMPC_compare) {
12721 if (IsCompareCapture) {
12722 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12723 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12724 if (!Checker.checkStmt(Body, ErrorInfo)) {
12725 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12726 << ErrorInfo.ErrorRange;
12727 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12728 << ErrorInfo.Error << ErrorInfo.NoteRange;
12729 return StmtError();
12730 }
12731 X = Checker.getX();
12732 E = Checker.getE();
12733 D = Checker.getD();
12734 CE = Checker.getCond();
12735 V = Checker.getV();
12736 R = Checker.getR();
12737 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12738 IsXLHSInRHSPart = Checker.isXBinopExpr();
12739 IsFailOnly = Checker.isFailOnly();
12740 IsPostfixUpdate = Checker.isPostfixUpdate();
12741 } else {
12742 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12743 OpenMPAtomicCompareChecker Checker(SemaRef);
12744 if (!Checker.checkStmt(Body, ErrorInfo)) {
12745 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12746 << ErrorInfo.ErrorRange;
12747 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12748 << ErrorInfo.Error << ErrorInfo.NoteRange;
12749 return StmtError();
12750 }
12751 X = Checker.getX();
12752 E = Checker.getE();
12753 D = Checker.getD();
12754 CE = Checker.getCond();
12755 // The weak clause may only appear if the resulting atomic operation is
12756 // an atomic conditional update for which the comparison tests for
12757 // equality. It was not possible to do this check in
12758 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12759 // could not be performed (Clauses are not available).
12760 auto *It = find_if(Clauses, [](OMPClause *C) {
12761 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12762 });
12763 if (It != Clauses.end()) {
12764 auto *Cond = dyn_cast<BinaryOperator>(CE);
12765 if (Cond->getOpcode() != BO_EQ) {
12766 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12767 ErrorInfo.ErrorLoc = Cond->getExprLoc();
12768 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12769 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12770
12771 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12772 << ErrorInfo.ErrorRange;
12773 return StmtError();
12774 }
12775 }
12776 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12777 IsXLHSInRHSPart = Checker.isXBinopExpr();
12778 }
12779 }
12780
12782
12784 Context, StartLoc, EndLoc, Clauses, AStmt,
12785 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12786}
12787
12789 Stmt *AStmt,
12790 SourceLocation StartLoc,
12791 SourceLocation EndLoc) {
12792 if (!AStmt)
12793 return StmtError();
12794
12795 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
12796
12797 // OpenMP [2.16, Nesting of Regions]
12798 // If specified, a teams construct must be contained within a target
12799 // construct. That target construct must contain no statements or directives
12800 // outside of the teams construct.
12801 if (DSAStack->hasInnerTeamsRegion()) {
12802 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12803 bool OMPTeamsFound = true;
12804 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12805 auto I = CS->body_begin();
12806 while (I != CS->body_end()) {
12807 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12808 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12809 if (!IsTeams || I != CS->body_begin()) {
12810 OMPTeamsFound = false;
12811 if (IsTeams && I != CS->body_begin()) {
12812 // This is the two teams case. Since the InnerTeamsRegionLoc will
12813 // point to this second one reset the iterator to the other teams.
12814 --I;
12815 }
12816 break;
12817 }
12818 ++I;
12819 }
12820 assert(I != CS->body_end() && "Not found statement");
12821 S = *I;
12822 } else {
12823 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12824 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12825 }
12826 if (!OMPTeamsFound) {
12827 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12828 Diag(DSAStack->getInnerTeamsRegionLoc(),
12829 diag::note_omp_nested_teams_construct_here);
12830 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12831 << isa<OMPExecutableDirective>(S);
12832 return StmtError();
12833 }
12834 }
12835
12836 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12837 AStmt);
12838}
12839
12841 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12842 SourceLocation EndLoc) {
12843 if (!AStmt)
12844 return StmtError();
12845
12846 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
12847
12849 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12850 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12851}
12852
12854 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12855 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12856 if (!AStmt)
12857 return StmtError();
12858
12859 CapturedStmt *CS =
12860 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
12861
12863 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12864 // define the nested loops number.
12865 unsigned NestedLoopCount =
12866 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
12867 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
12868 VarsWithImplicitDSA, B);
12869 if (NestedLoopCount == 0)
12870 return StmtError();
12871
12872 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
12873 return StmtError();
12874
12876 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12877 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12878}
12879
12880/// Check for existence of a map clause in the list of clauses.
12882 const OpenMPClauseKind K) {
12883 return llvm::any_of(
12884 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
12885}
12886
12887template <typename... Params>
12889 const Params... ClauseTypes) {
12890 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
12891}
12892
12893/// Check if the variables in the mapping clause are externally visible.
12895 for (const OMPClause *C : Clauses) {
12896 if (auto *TC = dyn_cast<OMPToClause>(C))
12897 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
12898 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12899 (VD->isExternallyVisible() &&
12900 VD->getVisibility() != HiddenVisibility);
12901 });
12902 else if (auto *FC = dyn_cast<OMPFromClause>(C))
12903 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
12904 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
12905 (VD->isExternallyVisible() &&
12906 VD->getVisibility() != HiddenVisibility);
12907 });
12908 }
12909
12910 return true;
12911}
12912
12915 Stmt *AStmt, SourceLocation StartLoc,
12916 SourceLocation EndLoc) {
12917 if (!AStmt)
12918 return StmtError();
12919
12920 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12921
12922 // OpenMP [2.12.2, target data Construct, Restrictions]
12923 // At least one map, use_device_addr or use_device_ptr clause must appear on
12924 // the directive.
12925 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
12926 (getLangOpts().OpenMP < 50 ||
12927 !hasClauses(Clauses, OMPC_use_device_addr))) {
12928 StringRef Expected;
12929 if (getLangOpts().OpenMP < 50)
12930 Expected = "'map' or 'use_device_ptr'";
12931 else
12932 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
12933 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12934 << Expected << getOpenMPDirectiveName(OMPD_target_data);
12935 return StmtError();
12936 }
12937
12939
12940 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
12941 Clauses, AStmt);
12942}
12943
12945 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
12946 SourceLocation EndLoc, Stmt *AStmt) {
12947 if (!AStmt)
12948 return StmtError();
12949
12950 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
12951
12952 // OpenMP [2.10.2, Restrictions, p. 99]
12953 // At least one map clause must appear on the directive.
12954 if (!hasClauses(Clauses, OMPC_map)) {
12955 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12956 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
12957 return StmtError();
12958 }
12959
12960 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
12961 Clauses, AStmt);
12962}
12963
12965 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
12966 SourceLocation EndLoc, Stmt *AStmt) {
12967 if (!AStmt)
12968 return StmtError();
12969
12970 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
12971
12972 // OpenMP [2.10.3, Restrictions, p. 102]
12973 // At least one map clause must appear on the directive.
12974 if (!hasClauses(Clauses, OMPC_map)) {
12975 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
12976 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
12977 return StmtError();
12978 }
12979
12980 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
12981 Clauses, AStmt);
12982}
12983
12985 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
12986 SourceLocation EndLoc, Stmt *AStmt) {
12987 if (!AStmt)
12988 return StmtError();
12989
12990 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
12991
12992 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
12993 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
12994 return StmtError();
12995 }
12996
12997 if (!isClauseMappable(Clauses)) {
12998 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
12999 return StmtError();
13000 }
13001
13002 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13003 Clauses, AStmt);
13004}
13005
13007 Stmt *AStmt,
13008 SourceLocation StartLoc,
13009 SourceLocation EndLoc) {
13010 if (!AStmt)
13011 return StmtError();
13012
13013 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13014 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13015 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13016
13017 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13018
13019 DSAStack->setParentTeamsRegionLoc(StartLoc);
13020
13021 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13022 AStmt);
13023}
13024
13026 SourceLocation StartLoc, SourceLocation EndLoc,
13027 OpenMPDirectiveKind CancelRegion) {
13028 if (DSAStack->isParentNowaitRegion()) {
13029 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13030 return StmtError();
13031 }
13032 if (DSAStack->isParentOrderedRegion()) {
13033 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13034 return StmtError();
13035 }
13037 EndLoc, CancelRegion);
13038}
13039
13041 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13042 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13043 if (DSAStack->isParentNowaitRegion()) {
13044 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13045 return StmtError();
13046 }
13047 if (DSAStack->isParentOrderedRegion()) {
13048 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13049 return StmtError();
13050 }
13051 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13052 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13053 CancelRegion);
13054}
13055
13057 ArrayRef<OMPClause *> Clauses) {
13058 const OMPClause *ReductionClause = nullptr;
13059 const OMPClause *NogroupClause = nullptr;
13060 for (const OMPClause *C : Clauses) {
13061 if (C->getClauseKind() == OMPC_reduction) {
13062 ReductionClause = C;
13063 if (NogroupClause)
13064 break;
13065 continue;
13066 }
13067 if (C->getClauseKind() == OMPC_nogroup) {
13068 NogroupClause = C;
13069 if (ReductionClause)
13070 break;
13071 continue;
13072 }
13073 }
13074 if (ReductionClause && NogroupClause) {
13075 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13076 << SourceRange(NogroupClause->getBeginLoc(),
13077 NogroupClause->getEndLoc());
13078 return true;
13079 }
13080 return false;
13081}
13082
13084 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13085 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13086 if (!AStmt)
13087 return StmtError();
13088
13089 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13091 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13092 // define the nested loops number.
13093 unsigned NestedLoopCount =
13094 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13095 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13096 *DSAStack, VarsWithImplicitDSA, B);
13097 if (NestedLoopCount == 0)
13098 return StmtError();
13099
13100 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13101 "omp for loop exprs were not built");
13102
13103 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13104 // The grainsize clause and num_tasks clause are mutually exclusive and may
13105 // not appear on the same taskloop directive.
13107 {OMPC_grainsize, OMPC_num_tasks}))
13108 return StmtError();
13109 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13110 // If a reduction clause is present on the taskloop directive, the nogroup
13111 // clause must not be specified.
13113 return StmtError();
13114
13116 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13117 NestedLoopCount, Clauses, AStmt, B,
13118 DSAStack->isCancelRegion());
13119}
13120
13122 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13123 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13124 if (!AStmt)
13125 return StmtError();
13126
13127 CapturedStmt *CS =
13128 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13129
13130 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13132 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13133 // define the nested loops number.
13134 unsigned NestedLoopCount =
13135 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13136 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13137 VarsWithImplicitDSA, B);
13138 if (NestedLoopCount == 0)
13139 return StmtError();
13140
13141 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13142 return StmtError();
13143
13144 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13145 // The grainsize clause and num_tasks clause are mutually exclusive and may
13146 // not appear on the same taskloop directive.
13148 {OMPC_grainsize, OMPC_num_tasks}))
13149 return StmtError();
13150 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13151 // If a reduction clause is present on the taskloop directive, the nogroup
13152 // clause must not be specified.
13154 return StmtError();
13156 return StmtError();
13157
13158 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13159 NestedLoopCount, Clauses, AStmt, B);
13160}
13161
13163 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13164 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13165 if (!AStmt)
13166 return StmtError();
13167
13168 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13170 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13171 // define the nested loops number.
13172 unsigned NestedLoopCount =
13173 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13174 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13175 *DSAStack, VarsWithImplicitDSA, B);
13176 if (NestedLoopCount == 0)
13177 return StmtError();
13178
13179 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13180 "omp for loop exprs were not built");
13181
13182 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13183 // The grainsize clause and num_tasks clause are mutually exclusive and may
13184 // not appear on the same taskloop directive.
13186 {OMPC_grainsize, OMPC_num_tasks}))
13187 return StmtError();
13188 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13189 // If a reduction clause is present on the taskloop directive, the nogroup
13190 // clause must not be specified.
13192 return StmtError();
13193
13195 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13196 NestedLoopCount, Clauses, AStmt, B,
13197 DSAStack->isCancelRegion());
13198}
13199
13201 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13202 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13203 if (!AStmt)
13204 return StmtError();
13205
13206 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13208 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13209 // define the nested loops number.
13210 unsigned NestedLoopCount =
13211 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13212 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13213 *DSAStack, VarsWithImplicitDSA, B);
13214 if (NestedLoopCount == 0)
13215 return StmtError();
13216
13217 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13218 "omp for loop exprs were not built");
13219
13220 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13221 // The grainsize clause and num_tasks clause are mutually exclusive and may
13222 // not appear on the same taskloop directive.
13224 {OMPC_grainsize, OMPC_num_tasks}))
13225 return StmtError();
13226 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13227 // If a reduction clause is present on the taskloop directive, the nogroup
13228 // clause must not be specified.
13230 return StmtError();
13231
13233 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13234 NestedLoopCount, Clauses, AStmt, B,
13235 DSAStack->isCancelRegion());
13236}
13237
13239 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13240 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13241 if (!AStmt)
13242 return StmtError();
13243
13244 CapturedStmt *CS =
13245 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13246
13247 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13249 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13250 // define the nested loops number.
13251 unsigned NestedLoopCount =
13252 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13253 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13254 VarsWithImplicitDSA, B);
13255 if (NestedLoopCount == 0)
13256 return StmtError();
13257
13258 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13259 return StmtError();
13260
13261 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13262 // The grainsize clause and num_tasks clause are mutually exclusive and may
13263 // not appear on the same taskloop directive.
13265 {OMPC_grainsize, OMPC_num_tasks}))
13266 return StmtError();
13267 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13268 // If a reduction clause is present on the taskloop directive, the nogroup
13269 // clause must not be specified.
13271 return StmtError();
13273 return StmtError();
13274
13276 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13277}
13278
13280 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13281 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13282 if (!AStmt)
13283 return StmtError();
13284
13285 CapturedStmt *CS =
13286 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13287
13288 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13290 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13291 // define the nested loops number.
13292 unsigned NestedLoopCount =
13293 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13294 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13295 VarsWithImplicitDSA, B);
13296 if (NestedLoopCount == 0)
13297 return StmtError();
13298
13299 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13300 return StmtError();
13301
13302 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13303 // The grainsize clause and num_tasks clause are mutually exclusive and may
13304 // not appear on the same taskloop directive.
13306 {OMPC_grainsize, OMPC_num_tasks}))
13307 return StmtError();
13308 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13309 // If a reduction clause is present on the taskloop directive, the nogroup
13310 // clause must not be specified.
13312 return StmtError();
13314 return StmtError();
13315
13317 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13318}
13319
13321 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13322 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13323 if (!AStmt)
13324 return StmtError();
13325
13326 CapturedStmt *CS =
13327 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13328
13330 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13331 // define the nested loops number.
13332 unsigned NestedLoopCount = checkOpenMPLoop(
13333 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13334 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13335 VarsWithImplicitDSA, B);
13336 if (NestedLoopCount == 0)
13337 return StmtError();
13338
13339 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13340 "omp for loop exprs were not built");
13341
13342 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13343 // The grainsize clause and num_tasks clause are mutually exclusive and may
13344 // not appear on the same taskloop directive.
13346 {OMPC_grainsize, OMPC_num_tasks}))
13347 return StmtError();
13348 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13349 // If a reduction clause is present on the taskloop directive, the nogroup
13350 // clause must not be specified.
13352 return StmtError();
13353
13355 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13356 DSAStack->isCancelRegion());
13357}
13358
13360 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13361 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13362 if (!AStmt)
13363 return StmtError();
13364
13365 CapturedStmt *CS =
13366 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13367
13369 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13370 // define the nested loops number.
13371 unsigned NestedLoopCount = checkOpenMPLoop(
13372 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13373 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13374 VarsWithImplicitDSA, B);
13375 if (NestedLoopCount == 0)
13376 return StmtError();
13377
13378 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13379 "omp for loop exprs were not built");
13380
13381 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13382 // The grainsize clause and num_tasks clause are mutually exclusive and may
13383 // not appear on the same taskloop directive.
13385 {OMPC_grainsize, OMPC_num_tasks}))
13386 return StmtError();
13387 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13388 // If a reduction clause is present on the taskloop directive, the nogroup
13389 // clause must not be specified.
13391 return StmtError();
13392
13394 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13395 DSAStack->isCancelRegion());
13396}
13397
13399 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13400 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13401 if (!AStmt)
13402 return StmtError();
13403
13405 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13406
13408 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13409 // define the nested loops number.
13410 unsigned NestedLoopCount = checkOpenMPLoop(
13411 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13412 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13413 VarsWithImplicitDSA, B);
13414 if (NestedLoopCount == 0)
13415 return StmtError();
13416
13417 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13418 return StmtError();
13419
13420 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13421 // The grainsize clause and num_tasks clause are mutually exclusive and may
13422 // not appear on the same taskloop directive.
13424 {OMPC_grainsize, OMPC_num_tasks}))
13425 return StmtError();
13426 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13427 // If a reduction clause is present on the taskloop directive, the nogroup
13428 // clause must not be specified.
13430 return StmtError();
13432 return StmtError();
13433
13435 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13436}
13437
13439 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13440 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13441 if (!AStmt)
13442 return StmtError();
13443
13445 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13446
13448 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13449 // define the nested loops number.
13450 unsigned NestedLoopCount = checkOpenMPLoop(
13451 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13452 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13453 VarsWithImplicitDSA, B);
13454 if (NestedLoopCount == 0)
13455 return StmtError();
13456
13457 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13458 return StmtError();
13459
13460 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13461 // The grainsize clause and num_tasks clause are mutually exclusive and may
13462 // not appear on the same taskloop directive.
13464 {OMPC_grainsize, OMPC_num_tasks}))
13465 return StmtError();
13466 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13467 // If a reduction clause is present on the taskloop directive, the nogroup
13468 // clause must not be specified.
13470 return StmtError();
13472 return StmtError();
13473
13475 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13476}
13477
13479 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13480 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13481 if (!AStmt)
13482 return StmtError();
13483
13484 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13486 // In presence of clause 'collapse' with number of loops, it will
13487 // define the nested loops number.
13488 unsigned NestedLoopCount =
13489 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13490 nullptr /*ordered not a clause on distribute*/, AStmt,
13491 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13492 if (NestedLoopCount == 0)
13493 return StmtError();
13494
13495 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13496 "omp for loop exprs were not built");
13497
13499 auto *DistributeDirective = OMPDistributeDirective::Create(
13500 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13501 return DistributeDirective;
13502}
13503
13505 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13506 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13507 if (!AStmt)
13508 return StmtError();
13509
13510 CapturedStmt *CS =
13511 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
13512
13514 // In presence of clause 'collapse' with number of loops, it will
13515 // define the nested loops number.
13516 unsigned NestedLoopCount = checkOpenMPLoop(
13517 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13518 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13519 VarsWithImplicitDSA, B);
13520 if (NestedLoopCount == 0)
13521 return StmtError();
13522
13523 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13524 "omp for loop exprs were not built");
13525
13527 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13528 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13529}
13530
13532 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13533 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13534 if (!AStmt)
13535 return StmtError();
13536
13538 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13539
13541 // In presence of clause 'collapse' with number of loops, it will
13542 // define the nested loops number.
13543 unsigned NestedLoopCount = checkOpenMPLoop(
13544 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13545 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13546 VarsWithImplicitDSA, B);
13547 if (NestedLoopCount == 0)
13548 return StmtError();
13549
13550 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13551 return StmtError();
13552
13554 return StmtError();
13555
13557 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
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_simd, AStmt);
13568
13570 // In presence of clause 'collapse' with number of loops, it will
13571 // define the nested loops number.
13572 unsigned NestedLoopCount =
13573 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13574 nullptr /*ordered not a clause on distribute*/, CS,
13575 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13576 if (NestedLoopCount == 0)
13577 return StmtError();
13578
13579 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13580 return StmtError();
13581
13583 return StmtError();
13584
13585 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13586 NestedLoopCount, Clauses, AStmt, B);
13587}
13588
13590 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13591 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13592 if (!AStmt)
13593 return StmtError();
13594
13595 CapturedStmt *CS =
13596 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13597
13599 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13600 // define the nested loops number.
13601 unsigned NestedLoopCount = checkOpenMPLoop(
13602 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13603 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13604 VarsWithImplicitDSA, B);
13605 if (NestedLoopCount == 0)
13606 return StmtError();
13607
13608 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13609 return StmtError();
13610
13612 return StmtError();
13613
13615 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13616}
13617
13619 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13620 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13621 if (!AStmt)
13622 return StmtError();
13623
13624 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13625
13627 // In presence of clause 'collapse' with number of loops, it will define the
13628 // nested loops number.
13629 unsigned NestedLoopCount =
13630 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13631 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13632 VarsWithImplicitDSA, B);
13633 if (NestedLoopCount == 0)
13634 return StmtError();
13635
13636 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13637 return StmtError();
13638
13640 return StmtError();
13641
13642 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13643 NestedLoopCount, Clauses, AStmt, B);
13644}
13645
13647 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13648 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13649 if (!AStmt)
13650 return StmtError();
13651
13652 CapturedStmt *CS =
13653 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13654
13656 // In presence of clause 'collapse' with number of loops, it will
13657 // define the nested loops number.
13658 unsigned NestedLoopCount =
13659 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13660 nullptr /*ordered not a clause on distribute*/, CS,
13661 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13662 if (NestedLoopCount == 0)
13663 return StmtError();
13664
13665 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13666 "omp teams distribute loop exprs were not built");
13667
13668 DSAStack->setParentTeamsRegionLoc(StartLoc);
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 =
13681 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13682
13684 // In presence of clause 'collapse' with number of loops, it will
13685 // define the nested loops number.
13686 unsigned NestedLoopCount = checkOpenMPLoop(
13687 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13688 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13689 VarsWithImplicitDSA, B);
13690 if (NestedLoopCount == 0)
13691 return StmtError();
13692
13693 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13694 return StmtError();
13695
13697 return StmtError();
13698
13699 DSAStack->setParentTeamsRegionLoc(StartLoc);
13700
13702 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13703}
13704
13706 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13707 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13708 if (!AStmt)
13709 return StmtError();
13710
13712 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13713
13715 // In presence of clause 'collapse' with number of loops, it will
13716 // define the nested loops number.
13717 unsigned NestedLoopCount = checkOpenMPLoop(
13718 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13719 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13720 VarsWithImplicitDSA, B);
13721 if (NestedLoopCount == 0)
13722 return StmtError();
13723
13724 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13725 return StmtError();
13726
13728 return StmtError();
13729
13730 DSAStack->setParentTeamsRegionLoc(StartLoc);
13731
13733 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13734}
13735
13737 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13738 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13739 if (!AStmt)
13740 return StmtError();
13741
13743 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13744
13746 // In presence of clause 'collapse' with number of loops, it will
13747 // define the nested loops number.
13748 unsigned NestedLoopCount = checkOpenMPLoop(
13749 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13750 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13751 VarsWithImplicitDSA, B);
13752
13753 if (NestedLoopCount == 0)
13754 return StmtError();
13755
13756 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13757 "omp for loop exprs were not built");
13758
13759 DSAStack->setParentTeamsRegionLoc(StartLoc);
13760
13762 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13763 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13764}
13765
13767 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13768 SourceLocation EndLoc) {
13769 if (!AStmt)
13770 return StmtError();
13771
13772 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
13773
13774 const OMPClause *BareClause = nullptr;
13775 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
13776 hasClauses(Clauses, OMPC_thread_limit);
13777 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
13778 BareClause = C;
13779 return C->getClauseKind() == OMPC_ompx_bare;
13780 });
13781
13782 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13783 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
13784 return StmtError();
13785 }
13786
13787 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
13788 Clauses, AStmt);
13789}
13790
13792 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13793 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13794 if (!AStmt)
13795 return StmtError();
13796
13797 CapturedStmt *CS =
13798 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
13799
13801 // In presence of clause 'collapse' with number of loops, it will
13802 // define the nested loops number.
13803 unsigned NestedLoopCount = checkOpenMPLoop(
13804 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
13805 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13806 VarsWithImplicitDSA, B);
13807 if (NestedLoopCount == 0)
13808 return StmtError();
13809
13810 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13811 "omp target teams distribute loop exprs were not built");
13812
13814 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13815}
13816
13818 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13819 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13820 if (!AStmt)
13821 return StmtError();
13822
13824 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
13825
13827 // In presence of clause 'collapse' with number of loops, it will
13828 // define the nested loops number.
13829 unsigned NestedLoopCount = checkOpenMPLoop(
13830 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13831 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13832 VarsWithImplicitDSA, B);
13833 if (NestedLoopCount == 0)
13834 return StmtError();
13835
13836 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13837 return StmtError();
13838
13840 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13841 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13842}
13843
13845 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13846 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13847 if (!AStmt)
13848 return StmtError();
13849
13851 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
13852
13854 // In presence of clause 'collapse' with number of loops, it will
13855 // define the nested loops number.
13856 unsigned NestedLoopCount =
13857 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
13858 getCollapseNumberExpr(Clauses),
13859 nullptr /*ordered not a clause on distribute*/, CS,
13860 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13861 if (NestedLoopCount == 0)
13862 return StmtError();
13863
13864 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13865 return StmtError();
13866
13868 return StmtError();
13869
13871 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13872}
13873
13875 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13876 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13877 if (!AStmt)
13878 return StmtError();
13879
13881 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
13882
13884 // In presence of clause 'collapse' with number of loops, it will
13885 // define the nested loops number.
13886 unsigned NestedLoopCount = checkOpenMPLoop(
13887 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13888 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13889 VarsWithImplicitDSA, B);
13890 if (NestedLoopCount == 0)
13891 return StmtError();
13892
13893 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13894 return StmtError();
13895
13897 return StmtError();
13898
13900 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13901}
13902
13903bool SemaOpenMP::checkTransformableLoopNest(
13904 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
13906 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
13907 OriginalInits.emplace_back();
13909 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
13910 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
13911 Stmt *CurStmt) {
13912 VarsWithInheritedDSAType TmpDSA;
13913 unsigned SingleNumLoops =
13914 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
13915 TmpDSA, LoopHelpers[Cnt]);
13916 if (SingleNumLoops == 0)
13917 return true;
13918 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
13919 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
13920 OriginalInits.back().push_back(For->getInit());
13921 Body = For->getBody();
13922 } else {
13923 assert(isa<CXXForRangeStmt>(CurStmt) &&
13924 "Expected canonical for or range-based for loops.");
13925 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
13926 OriginalInits.back().push_back(CXXFor->getBeginStmt());
13927 Body = CXXFor->getBody();
13928 }
13929 OriginalInits.emplace_back();
13930 return false;
13931 },
13932 [&OriginalInits](OMPLoopBasedDirective *Transform) {
13933 Stmt *DependentPreInits;
13934 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
13935 DependentPreInits = Dir->getPreInits();
13936 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
13937 DependentPreInits = Dir->getPreInits();
13938 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
13939 DependentPreInits = Dir->getPreInits();
13940 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
13941 DependentPreInits = Dir->getPreInits();
13942 else
13943 llvm_unreachable("Unhandled loop transformation");
13944
13945 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
13946 });
13947 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
13948 OriginalInits.pop_back();
13949 return Result;
13950}
13951
13952/// Add preinit statements that need to be propageted from the selected loop.
13953static void addLoopPreInits(ASTContext &Context,
13955 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
13956 SmallVectorImpl<Stmt *> &PreInits) {
13957
13958 // For range-based for-statements, ensure that their syntactic sugar is
13959 // executed by adding them as pre-init statements.
13960 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
13961 Stmt *RangeInit = CXXRangeFor->getInit();
13962 if (RangeInit)
13963 PreInits.push_back(RangeInit);
13964
13965 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
13966 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
13967 RangeStmt->getBeginLoc(),
13968 RangeStmt->getEndLoc()));
13969
13970 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
13971 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
13972 RangeEnd->getBeginLoc(),
13973 RangeEnd->getEndLoc()));
13974 }
13975
13976 llvm::append_range(PreInits, OriginalInit);
13977
13978 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
13979 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
13980 PreInits.push_back(new (Context) DeclStmt(
13981 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
13982 }
13983
13984 // Gather declarations for the data members used as counters.
13985 for (Expr *CounterRef : LoopHelper.Counters) {
13986 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
13987 if (isa<OMPCapturedExprDecl>(CounterDecl))
13988 PreInits.push_back(new (Context) DeclStmt(
13989 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
13990 }
13991}
13992
13993/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
13994/// loop of a construct.
13995static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
13996 size_t NumLoops = LoopStmts.size();
13998 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
13999 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14000 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14001 LoopStmts[Cnt] = CurStmt;
14002 return false;
14003 });
14004 assert(!is_contained(LoopStmts, nullptr) &&
14005 "Expecting a loop statement for each affected loop");
14006}
14007
14009 Stmt *AStmt,
14010 SourceLocation StartLoc,
14011 SourceLocation EndLoc) {
14012 ASTContext &Context = getASTContext();
14013 Scope *CurScope = SemaRef.getCurScope();
14014
14015 const auto *SizesClause =
14016 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14017 if (!SizesClause ||
14018 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14019 return StmtError();
14020 unsigned NumLoops = SizesClause->getNumSizes();
14021
14022 // Empty statement should only be possible if there already was an error.
14023 if (!AStmt)
14024 return StmtError();
14025
14026 // Verify and diagnose loop nest.
14028 Stmt *Body = nullptr;
14029 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14030 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14031 OriginalInits))
14032 return StmtError();
14033
14034 // Delay tiling to when template is completely instantiated.
14036 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14037 NumLoops, AStmt, nullptr, nullptr);
14038
14039 assert(LoopHelpers.size() == NumLoops &&
14040 "Expecting loop iteration space dimensionality to match number of "
14041 "affected loops");
14042 assert(OriginalInits.size() == NumLoops &&
14043 "Expecting loop iteration space dimensionality to match number of "
14044 "affected loops");
14045
14046 // Collect all affected loop statements.
14047 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14048 collectLoopStmts(AStmt, LoopStmts);
14049
14050 SmallVector<Stmt *, 4> PreInits;
14051 CaptureVars CopyTransformer(SemaRef);
14052
14053 // Create iteration variables for the generated loops.
14054 SmallVector<VarDecl *, 4> FloorIndVars;
14055 SmallVector<VarDecl *, 4> TileIndVars;
14056 FloorIndVars.resize(NumLoops);
14057 TileIndVars.resize(NumLoops);
14058 for (unsigned I = 0; I < NumLoops; ++I) {
14059 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14060
14061 assert(LoopHelper.Counters.size() == 1 &&
14062 "Expect single-dimensional loop iteration space");
14063 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14064 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14065 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14066 QualType CntTy = IterVarRef->getType();
14067
14068 // Iteration variable for the floor (i.e. outer) loop.
14069 {
14070 std::string FloorCntName =
14071 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14072 VarDecl *FloorCntDecl =
14073 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14074 FloorIndVars[I] = FloorCntDecl;
14075 }
14076
14077 // Iteration variable for the tile (i.e. inner) loop.
14078 {
14079 std::string TileCntName =
14080 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14081
14082 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14083 // used by the expressions to derive the original iteration variable's
14084 // value from the logical iteration number.
14085 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14086 TileCntDecl->setDeclName(
14087 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14088 TileIndVars[I] = TileCntDecl;
14089 }
14090
14091 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14092 PreInits);
14093 }
14094
14095 // Once the original iteration values are set, append the innermost body.
14096 Stmt *Inner = Body;
14097
14098 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14099 SizesClause, CurScope](int I) -> Expr * {
14100 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14101 if (isa<ConstantExpr>(DimTileSizeExpr))
14102 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14103
14104 // When the tile size is not a constant but a variable, it is possible to
14105 // pass non-positive numbers. For instance:
14106 // \code{c}
14107 // int a = 0;
14108 // #pragma omp tile sizes(a)
14109 // for (int i = 0; i < 42; ++i)
14110 // body(i);
14111 // \endcode
14112 // Although there is no meaningful interpretation of the tile size, the body
14113 // should still be executed 42 times to avoid surprises. To preserve the
14114 // invariant that every loop iteration is executed exactly once and not
14115 // cause an infinite loop, apply a minimum tile size of one.
14116 // Build expr:
14117 // \code{c}
14118 // (TS <= 0) ? 1 : TS
14119 // \endcode
14120 QualType DimTy = DimTileSizeExpr->getType();
14121 uint64_t DimWidth = Context.getTypeSize(DimTy);
14123 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14124 IntegerLiteral *One =
14125 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14127 CurScope, {}, BO_LE,
14128 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14129 Expr *MinOne = new (Context) ConditionalOperator(
14130 Cond, {}, One, {},
14131 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14133 return MinOne;
14134 };
14135
14136 // Create tile loops from the inside to the outside.
14137 for (int I = NumLoops - 1; I >= 0; --I) {
14138 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14139 Expr *NumIterations = LoopHelper.NumIterations;
14140 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14141 QualType IVTy = NumIterations->getType();
14142 Stmt *LoopStmt = LoopStmts[I];
14143
14144 // Commonly used variables. One of the constraints of an AST is that every
14145 // node object must appear at most once, hence we define lamdas that create
14146 // a new AST node at every use.
14147 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14148 OrigCntVar]() {
14149 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14150 OrigCntVar->getExprLoc());
14151 };
14152 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14153 OrigCntVar]() {
14154 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14155 OrigCntVar->getExprLoc());
14156 };
14157
14158 // For init-statement: auto .tile.iv = .floor.iv
14160 TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(),
14161 /*DirectInit=*/false);
14162 Decl *CounterDecl = TileIndVars[I];
14163 StmtResult InitStmt = new (Context)
14164 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14165 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14166 if (!InitStmt.isUsable())
14167 return StmtError();
14168
14169 // For cond-expression:
14170 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14171 ExprResult EndOfTile =
14172 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14173 MakeFloorIVRef(), MakeDimTileSize(I));
14174 if (!EndOfTile.isUsable())
14175 return StmtError();
14176 ExprResult IsPartialTile =
14177 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14178 NumIterations, EndOfTile.get());
14179 if (!IsPartialTile.isUsable())
14180 return StmtError();
14181 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14182 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14183 IsPartialTile.get(), NumIterations, EndOfTile.get());
14184 if (!MinTileAndIterSpace.isUsable())
14185 return StmtError();
14186 ExprResult CondExpr =
14187 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14188 MakeTileIVRef(), MinTileAndIterSpace.get());
14189 if (!CondExpr.isUsable())
14190 return StmtError();
14191
14192 // For incr-statement: ++.tile.iv
14193 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14194 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14195 if (!IncrStmt.isUsable())
14196 return StmtError();
14197
14198 // Statements to set the original iteration variable's value from the
14199 // logical iteration number.
14200 // Generated for loop is:
14201 // \code
14202 // Original_for_init;
14203 // for (auto .tile.iv = .floor.iv;
14204 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14205 // ++.tile.iv) {
14206 // Original_Body;
14207 // Original_counter_update;
14208 // }
14209 // \endcode
14210 // FIXME: If the innermost body is an loop itself, inserting these
14211 // statements stops it being recognized as a perfectly nested loop (e.g.
14212 // for applying tiling again). If this is the case, sink the expressions
14213 // further into the inner loop.
14214 SmallVector<Stmt *, 4> BodyParts;
14215 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14216 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14217 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14218 BodyParts.push_back(Inner);
14219 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14220 Inner->getBeginLoc(), Inner->getEndLoc());
14221 Inner = new (Context)
14222 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14223 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14224 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14225 }
14226
14227 // Create floor loops from the inside to the outside.
14228 for (int I = NumLoops - 1; I >= 0; --I) {
14229 auto &LoopHelper = LoopHelpers[I];
14230 Expr *NumIterations = LoopHelper.NumIterations;
14231 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14232 QualType IVTy = NumIterations->getType();
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 MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14238 OrigCntVar]() {
14239 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14240 OrigCntVar->getExprLoc());
14241 };
14242
14243 // For init-statement: auto .floor.iv = 0
14245 FloorIndVars[I],
14246 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14247 /*DirectInit=*/false);
14248 Decl *CounterDecl = FloorIndVars[I];
14249 StmtResult InitStmt = new (Context)
14250 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14251 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14252 if (!InitStmt.isUsable())
14253 return StmtError();
14254
14255 // For cond-expression: .floor.iv < NumIterations
14256 ExprResult CondExpr =
14257 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14258 MakeFloorIVRef(), NumIterations);
14259 if (!CondExpr.isUsable())
14260 return StmtError();
14261
14262 // For incr-statement: .floor.iv += DimTileSize
14263 ExprResult IncrStmt =
14264 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14265 MakeFloorIVRef(), MakeDimTileSize(I));
14266 if (!IncrStmt.isUsable())
14267 return StmtError();
14268
14269 Inner = new (Context)
14270 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14271 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14272 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14273 }
14274
14275 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14276 AStmt, Inner,
14277 buildPreInits(Context, PreInits));
14278}
14279
14281 Stmt *AStmt,
14282 SourceLocation StartLoc,
14283 SourceLocation EndLoc) {
14284 ASTContext &Context = getASTContext();
14285 Scope *CurScope = SemaRef.getCurScope();
14286 // Empty statement should only be possible if there already was an error.
14287 if (!AStmt)
14288 return StmtError();
14289
14291 {OMPC_partial, OMPC_full}))
14292 return StmtError();
14293
14294 const OMPFullClause *FullClause =
14295 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14296 const OMPPartialClause *PartialClause =
14297 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14298 assert(!(FullClause && PartialClause) &&
14299 "mutual exclusivity must have been checked before");
14300
14301 constexpr unsigned NumLoops = 1;
14302 Stmt *Body = nullptr;
14304 NumLoops);
14305 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14306 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14307 Body, OriginalInits))
14308 return StmtError();
14309
14310 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14311
14312 // Delay unrolling to when template is completely instantiated.
14314 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14315 NumGeneratedLoops, nullptr, nullptr);
14316
14317 assert(LoopHelpers.size() == NumLoops &&
14318 "Expecting a single-dimensional loop iteration space");
14319 assert(OriginalInits.size() == NumLoops &&
14320 "Expecting a single-dimensional loop iteration space");
14321 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14322
14323 if (FullClause) {
14325 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14326 /*SuppressExprDiags=*/true)
14327 .isUsable()) {
14328 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14329 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14330 << "#pragma omp unroll full";
14331 return StmtError();
14332 }
14333 }
14334
14335 // The generated loop may only be passed to other loop-associated directive
14336 // when a partial clause is specified. Without the requirement it is
14337 // sufficient to generate loop unroll metadata at code-generation.
14338 if (NumGeneratedLoops == 0)
14339 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14340 NumGeneratedLoops, nullptr, nullptr);
14341
14342 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14343 // associated with another loop directive.
14344 //
14345 // The canonical loop analysis return by checkTransformableLoopNest assumes
14346 // the following structure to be the same loop without transformations or
14347 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14348 // LoopHelper.Counters;
14349 // for (; IV < LoopHelper.NumIterations; ++IV) {
14350 // LoopHelper.Updates;
14351 // Body;
14352 // }
14353 // \endcode
14354 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14355 // and referenced by LoopHelper.IterationVarRef.
14356 //
14357 // The unrolling directive transforms this into the following loop:
14358 // \code
14359 // OriginalInits; \
14360 // LoopHelper.PreInits; > NewPreInits
14361 // LoopHelper.Counters; /
14362 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14363 // #pragma clang loop unroll_count(Factor)
14364 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14365 // {
14366 // LoopHelper.Updates;
14367 // Body;
14368 // }
14369 // }
14370 // \endcode
14371 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14372 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14373 // references it. If the partially unrolled loop is associated with another
14374 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14375 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14376 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14377 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14378 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14379 // property of the OMPLoopBasedDirective instead of statements in
14380 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14381 // of a canonical loop nest where these PreInits are emitted before the
14382 // outermost directive.
14383
14384 // Find the loop statement.
14385 Stmt *LoopStmt = nullptr;
14386 collectLoopStmts(AStmt, {LoopStmt});
14387
14388 // Determine the PreInit declarations.
14389 SmallVector<Stmt *, 4> PreInits;
14390 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14391
14392 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14393 QualType IVTy = IterationVarRef->getType();
14394 assert(LoopHelper.Counters.size() == 1 &&
14395 "Expecting a single-dimensional loop iteration space");
14396 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14397
14398 // Determine the unroll factor.
14399 uint64_t Factor;
14400 SourceLocation FactorLoc;
14401 if (Expr *FactorVal = PartialClause->getFactor()) {
14402 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14403 FactorLoc = FactorVal->getExprLoc();
14404 } else {
14405 // TODO: Use a better profitability model.
14406 Factor = 2;
14407 }
14408 assert(Factor > 0 && "Expected positive unroll factor");
14409 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14411 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14412 IVTy, FactorLoc);
14413 };
14414
14415 // Iteration variable SourceLocations.
14416 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14417 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14418 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14419
14420 // Internal variable names.
14421 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14422 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14423 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14424 std::string InnerTripCountName =
14425 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
14426
14427 // Create the iteration variable for the unrolled loop.
14428 VarDecl *OuterIVDecl =
14429 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
14430 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14431 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
14432 };
14433
14434 // Iteration variable for the inner loop: Reuse the iteration variable created
14435 // by checkOpenMPLoop.
14436 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14437 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
14438 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14439 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
14440 };
14441
14442 // Make a copy of the NumIterations expression for each use: By the AST
14443 // constraints, every expression object in a DeclContext must be unique.
14444 CaptureVars CopyTransformer(SemaRef);
14445 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14446 return AssertSuccess(
14447 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14448 };
14449
14450 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
14451 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
14452 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
14453 /*DirectInit=*/false);
14454 StmtResult InnerInit = new (Context)
14455 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14456 if (!InnerInit.isUsable())
14457 return StmtError();
14458
14459 // Inner For cond-expression:
14460 // \code
14461 // .unroll_inner.iv < .unrolled.iv + Factor &&
14462 // .unroll_inner.iv < NumIterations
14463 // \endcode
14464 // This conjunction of two conditions allows ScalarEvolution to derive the
14465 // maximum trip count of the inner loop.
14466 ExprResult EndOfTile =
14467 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14468 MakeOuterRef(), MakeFactorExpr());
14469 if (!EndOfTile.isUsable())
14470 return StmtError();
14471 ExprResult InnerCond1 =
14472 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14473 MakeInnerRef(), EndOfTile.get());
14474 if (!InnerCond1.isUsable())
14475 return StmtError();
14476 ExprResult InnerCond2 =
14477 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14478 MakeInnerRef(), MakeNumIterations());
14479 if (!InnerCond2.isUsable())
14480 return StmtError();
14481 ExprResult InnerCond =
14482 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
14483 InnerCond1.get(), InnerCond2.get());
14484 if (!InnerCond.isUsable())
14485 return StmtError();
14486
14487 // Inner For incr-statement: ++.unroll_inner.iv
14488 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
14489 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
14490 if (!InnerIncr.isUsable())
14491 return StmtError();
14492
14493 // Inner For statement.
14494 SmallVector<Stmt *> InnerBodyStmts;
14495 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14496 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14497 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14498 InnerBodyStmts.push_back(Body);
14499 CompoundStmt *InnerBody =
14501 Body->getBeginLoc(), Body->getEndLoc());
14502 ForStmt *InnerFor = new (Context)
14503 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
14504 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
14505 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14506
14507 // Unroll metadata for the inner loop.
14508 // This needs to take into account the remainder portion of the unrolled loop,
14509 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
14510 // supports multiple loop exits. Instead, unroll using a factor equivalent to
14511 // the maximum trip count, which will also generate a remainder loop. Just
14512 // `unroll(enable)` (which could have been useful if the user has not
14513 // specified a concrete factor; even though the outer loop cannot be
14514 // influenced anymore, would avoid more code bloat than necessary) will refuse
14515 // the loop because "Won't unroll; remainder loop could not be generated when
14516 // assuming runtime trip count". Even if it did work, it must not choose a
14517 // larger unroll factor than the maximum loop length, or it would always just
14518 // execute the remainder loop.
14519 LoopHintAttr *UnrollHintAttr =
14520 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14521 LoopHintAttr::Numeric, MakeFactorExpr());
14522 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
14523 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
14524
14525 // Outer For init-statement: auto .unrolled.iv = 0
14527 OuterIVDecl,
14528 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14529 /*DirectInit=*/false);
14530 StmtResult OuterInit = new (Context)
14531 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14532 if (!OuterInit.isUsable())
14533 return StmtError();
14534
14535 // Outer For cond-expression: .unrolled.iv < NumIterations
14536 ExprResult OuterConde =
14537 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14538 MakeOuterRef(), MakeNumIterations());
14539 if (!OuterConde.isUsable())
14540 return StmtError();
14541
14542 // Outer For incr-statement: .unrolled.iv += Factor
14543 ExprResult OuterIncr =
14544 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14545 MakeOuterRef(), MakeFactorExpr());
14546 if (!OuterIncr.isUsable())
14547 return StmtError();
14548
14549 // Outer For statement.
14550 ForStmt *OuterFor = new (Context)
14551 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
14552 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
14553 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14554
14555 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14556 NumGeneratedLoops, OuterFor,
14557 buildPreInits(Context, PreInits));
14558}
14559
14561 SourceLocation StartLoc,
14562 SourceLocation EndLoc) {
14563 ASTContext &Context = getASTContext();
14564 Scope *CurScope = SemaRef.getCurScope();
14565
14566 // Empty statement should only be possible if there already was an error.
14567 if (!AStmt)
14568 return StmtError();
14569
14570 constexpr unsigned NumLoops = 1;
14571 Stmt *Body = nullptr;
14573 NumLoops);
14574 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14575 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14576 Body, OriginalInits))
14577 return StmtError();
14578
14579 // Delay applying the transformation to when template is completely
14580 // instantiated.
14582 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14583 nullptr, nullptr);
14584
14585 assert(LoopHelpers.size() == NumLoops &&
14586 "Expecting a single-dimensional loop iteration space");
14587 assert(OriginalInits.size() == NumLoops &&
14588 "Expecting a single-dimensional loop iteration space");
14589 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14590
14591 // Find the loop statement.
14592 Stmt *LoopStmt = nullptr;
14593 collectLoopStmts(AStmt, {LoopStmt});
14594
14595 // Determine the PreInit declarations.
14596 SmallVector<Stmt *> PreInits;
14597 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14598
14599 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14600 QualType IVTy = IterationVarRef->getType();
14601 uint64_t IVWidth = Context.getTypeSize(IVTy);
14602 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14603
14604 // Iteration variable SourceLocations.
14605 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14606 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14607 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14608
14609 // Locations pointing to the transformation.
14610 SourceLocation TransformLoc = StartLoc;
14611 SourceLocation TransformLocBegin = StartLoc;
14612 SourceLocation TransformLocEnd = EndLoc;
14613
14614 // Internal variable names.
14615 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14616 SmallString<64> ForwardIVName(".forward.iv.");
14617 ForwardIVName += OrigVarName;
14618 SmallString<64> ReversedIVName(".reversed.iv.");
14619 ReversedIVName += OrigVarName;
14620
14621 // LoopHelper.Updates will read the logical iteration number from
14622 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
14623 // that logical iteration from it, then assign it to the user loop counter
14624 // variable. We cannot directly use LoopHelper.IterationVarRef as the
14625 // induction variable of the generated loop because it may cause an underflow:
14626 // \code{.c}
14627 // for (unsigned i = 0; i < n; ++i)
14628 // body(i);
14629 // \endcode
14630 //
14631 // Naive reversal:
14632 // \code{.c}
14633 // for (unsigned i = n-1; i >= 0; --i)
14634 // body(i);
14635 // \endcode
14636 //
14637 // Instead, we introduce a new iteration variable representing the logical
14638 // iteration counter of the original loop, convert it to the logical iteration
14639 // number of the reversed loop, then let LoopHelper.Updates compute the user's
14640 // loop iteration variable from it.
14641 // \code{.cpp}
14642 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
14643 // auto .reversed.iv = n - .forward.iv - 1;
14644 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
14645 // body(i); // Body
14646 // }
14647 // \endcode
14648
14649 // Subexpressions with more than one use. One of the constraints of an AST is
14650 // that every node object must appear at most once, hence we define a lambda
14651 // that creates a new AST node at every use.
14652 CaptureVars CopyTransformer(SemaRef);
14653 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14654 return AssertSuccess(
14655 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14656 };
14657
14658 // Create the iteration variable for the forward loop (from 0 to n-1).
14659 VarDecl *ForwardIVDecl =
14660 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
14661 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
14662 OrigVarLoc]() {
14663 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
14664 };
14665
14666 // Iteration variable for the reversed induction variable (from n-1 downto 0):
14667 // Reuse the iteration variable created by checkOpenMPLoop.
14668 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14669 ReversedIVDecl->setDeclName(
14670 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
14671
14672 // For init-statement:
14673 // \code{.cpp}
14674 // auto .forward.iv = 0;
14675 // \endcode
14676 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
14677 ForwardIVDecl->getType(), OrigVarLoc);
14678 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
14679 StmtResult Init = new (Context)
14680 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14681 if (!Init.isUsable())
14682 return StmtError();
14683
14684 // Forward iv cond-expression:
14685 // \code{.cpp}
14686 // .forward.iv < MakeNumIterations()
14687 // \endcode
14688 ExprResult Cond =
14689 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14690 MakeForwardRef(), MakeNumIterations());
14691 if (!Cond.isUsable())
14692 return StmtError();
14693
14694 // Forward incr-statement:
14695 // \code{.c}
14696 // ++.forward.iv
14697 // \endcode
14698 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
14699 UO_PreInc, MakeForwardRef());
14700 if (!Incr.isUsable())
14701 return StmtError();
14702
14703 // Reverse the forward-iv:
14704 // \code{.cpp}
14705 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
14706 // \endcode
14707 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
14708 TransformLoc);
14709 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
14710 MakeNumIterations(), One);
14711 if (!Minus.isUsable())
14712 return StmtError();
14713 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
14714 MakeForwardRef());
14715 if (!Minus.isUsable())
14716 return StmtError();
14717 StmtResult InitReversed = new (Context) DeclStmt(
14718 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14719 if (!InitReversed.isUsable())
14720 return StmtError();
14721 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
14722 /*DirectInit=*/false);
14723
14724 // The new loop body.
14725 SmallVector<Stmt *, 4> BodyStmts;
14726 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
14727 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14728 BodyStmts.push_back(InitReversed.get());
14729 llvm::append_range(BodyStmts, LoopHelper.Updates);
14730 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14731 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14732 BodyStmts.push_back(Body);
14733 auto *ReversedBody =
14734 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
14735 Body->getBeginLoc(), Body->getEndLoc());
14736
14737 // Finally create the reversed For-statement.
14738 auto *ReversedFor = new (Context)
14739 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
14740 ReversedBody, LoopHelper.Init->getBeginLoc(),
14741 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14742 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14743 ReversedFor,
14744 buildPreInits(Context, PreInits));
14745}
14746
14748 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14749 SourceLocation EndLoc) {
14750 ASTContext &Context = getASTContext();
14751 DeclContext *CurContext = SemaRef.CurContext;
14752 Scope *CurScope = SemaRef.getCurScope();
14753
14754 // Empty statement should only be possible if there already was an error.
14755 if (!AStmt)
14756 return StmtError();
14757
14758 // interchange without permutation clause swaps two loops.
14759 constexpr size_t NumLoops = 2;
14760
14761 // Verify and diagnose loop nest.
14763 Stmt *Body = nullptr;
14764 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
14765 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14766 LoopHelpers, Body, OriginalInits))
14767 return StmtError();
14768
14769 // Delay interchange to when template is completely instantiated.
14770 if (CurContext->isDependentContext())
14771 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14772 NumLoops, AStmt, nullptr, nullptr);
14773
14774 assert(LoopHelpers.size() == NumLoops &&
14775 "Expecting loop iteration space dimensionaly to match number of "
14776 "affected loops");
14777 assert(OriginalInits.size() == NumLoops &&
14778 "Expecting loop iteration space dimensionaly to match number of "
14779 "affected loops");
14780
14781 // Decode the permutation clause.
14782 constexpr uint64_t Permutation[] = {1, 0};
14783
14784 // Find the affected loops.
14785 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14786 collectLoopStmts(AStmt, LoopStmts);
14787
14788 // Collect pre-init statements on the order before the permuation.
14789 SmallVector<Stmt *> PreInits;
14790 for (auto I : llvm::seq<int>(NumLoops)) {
14791 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14792
14793 assert(LoopHelper.Counters.size() == 1 &&
14794 "Single-dimensional loop iteration space expected");
14795 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14796
14797 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14798 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14799 PreInits);
14800 }
14801
14802 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
14803 CaptureVars CopyTransformer(SemaRef);
14804
14805 // Create the permuted loops from the inside to the outside of the
14806 // interchanged loop nest. Body of the innermost new loop is the original
14807 // innermost body.
14808 Stmt *Inner = Body;
14809 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
14810 // Get the original loop that belongs to this new position.
14811 uint64_t SourceIdx = Permutation[TargetIdx];
14812 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
14813 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
14814 assert(SourceHelper.Counters.size() == 1 &&
14815 "Single-dimensional loop iteration space expected");
14816 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
14817
14818 // Normalized loop counter variable: From 0 to n-1, always an integer type.
14819 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
14820 QualType IVTy = IterVarRef->getType();
14821 assert(IVTy->isIntegerType() &&
14822 "Expected the logical iteration counter to be an integer");
14823
14824 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14825 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
14826
14827 // Make a copy of the NumIterations expression for each use: By the AST
14828 // constraints, every expression object in a DeclContext must be unique.
14829 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
14830 return AssertSuccess(
14831 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
14832 };
14833
14834 // Iteration variable for the permuted loop. Reuse the one from
14835 // checkOpenMPLoop which will also be used to update the original loop
14836 // variable.
14837 SmallString<64> PermutedCntName(".permuted_");
14838 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
14839 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14840 PermutedCntDecl->setDeclName(
14841 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
14842 PermutedIndVars[TargetIdx] = PermutedCntDecl;
14843 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
14844 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
14845 };
14846
14847 // For init-statement:
14848 // \code
14849 // auto .permuted_{target}.iv = 0
14850 // \endcode
14851 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
14852 if (!Zero.isUsable())
14853 return StmtError();
14854 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
14855 /*DirectInit=*/false);
14856 StmtResult InitStmt = new (Context)
14857 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
14858 OrigCntVar->getEndLoc());
14859 if (!InitStmt.isUsable())
14860 return StmtError();
14861
14862 // For cond-expression:
14863 // \code
14864 // .permuted_{target}.iv < MakeNumIterations()
14865 // \endcode
14866 ExprResult CondExpr =
14867 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
14868 MakePermutedRef(), MakeNumIterations());
14869 if (!CondExpr.isUsable())
14870 return StmtError();
14871
14872 // For incr-statement:
14873 // \code
14874 // ++.tile.iv
14875 // \endcode
14876 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14877 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
14878 if (!IncrStmt.isUsable())
14879 return StmtError();
14880
14881 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
14882 SourceHelper.Updates.end());
14883 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
14884 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14885 BodyParts.push_back(Inner);
14886 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14887 Inner->getBeginLoc(), Inner->getEndLoc());
14888 Inner = new (Context) ForStmt(
14889 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
14890 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
14891 SourceHelper.Inc->getEndLoc());
14892 }
14893
14894 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14895 NumLoops, AStmt, Inner,
14896 buildPreInits(Context, PreInits));
14897}
14898
14900 Expr *Expr,
14901 SourceLocation StartLoc,
14902 SourceLocation LParenLoc,
14903 SourceLocation EndLoc) {
14904 OMPClause *Res = nullptr;
14905 switch (Kind) {
14906 case OMPC_final:
14907 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
14908 break;
14909 case OMPC_num_threads:
14910 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
14911 break;
14912 case OMPC_safelen:
14913 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
14914 break;
14915 case OMPC_simdlen:
14916 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
14917 break;
14918 case OMPC_allocator:
14919 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
14920 break;
14921 case OMPC_collapse:
14922 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
14923 break;
14924 case OMPC_ordered:
14925 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
14926 break;
14927 case OMPC_num_teams:
14928 Res = ActOnOpenMPNumTeamsClause(Expr, StartLoc, LParenLoc, EndLoc);
14929 break;
14930 case OMPC_thread_limit:
14931 Res = ActOnOpenMPThreadLimitClause(Expr, StartLoc, LParenLoc, EndLoc);
14932 break;
14933 case OMPC_priority:
14934 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
14935 break;
14936 case OMPC_hint:
14937 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
14938 break;
14939 case OMPC_depobj:
14940 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
14941 break;
14942 case OMPC_detach:
14943 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
14944 break;
14945 case OMPC_novariants:
14946 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
14947 break;
14948 case OMPC_nocontext:
14949 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
14950 break;
14951 case OMPC_filter:
14952 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
14953 break;
14954 case OMPC_partial:
14955 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
14956 break;
14957 case OMPC_message:
14958 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
14959 break;
14960 case OMPC_align:
14961 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
14962 break;
14963 case OMPC_ompx_dyn_cgroup_mem:
14964 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
14965 break;
14966 case OMPC_grainsize:
14967 case OMPC_num_tasks:
14968 case OMPC_device:
14969 case OMPC_if:
14970 case OMPC_default:
14971 case OMPC_proc_bind:
14972 case OMPC_schedule:
14973 case OMPC_private:
14974 case OMPC_firstprivate:
14975 case OMPC_lastprivate:
14976 case OMPC_shared:
14977 case OMPC_reduction:
14978 case OMPC_task_reduction:
14979 case OMPC_in_reduction:
14980 case OMPC_linear:
14981 case OMPC_aligned:
14982 case OMPC_copyin:
14983 case OMPC_copyprivate:
14984 case OMPC_nowait:
14985 case OMPC_untied:
14986 case OMPC_mergeable:
14987 case OMPC_threadprivate:
14988 case OMPC_sizes:
14989 case OMPC_allocate:
14990 case OMPC_flush:
14991 case OMPC_read:
14992 case OMPC_write:
14993 case OMPC_update:
14994 case OMPC_capture:
14995 case OMPC_compare:
14996 case OMPC_seq_cst:
14997 case OMPC_acq_rel:
14998 case OMPC_acquire:
14999 case OMPC_release:
15000 case OMPC_relaxed:
15001 case OMPC_depend:
15002 case OMPC_threads:
15003 case OMPC_simd:
15004 case OMPC_map:
15005 case OMPC_nogroup:
15006 case OMPC_dist_schedule:
15007 case OMPC_defaultmap:
15008 case OMPC_unknown:
15009 case OMPC_uniform:
15010 case OMPC_to:
15011 case OMPC_from:
15012 case OMPC_use_device_ptr:
15013 case OMPC_use_device_addr:
15014 case OMPC_is_device_ptr:
15015 case OMPC_unified_address:
15016 case OMPC_unified_shared_memory:
15017 case OMPC_reverse_offload:
15018 case OMPC_dynamic_allocators:
15019 case OMPC_atomic_default_mem_order:
15020 case OMPC_device_type:
15021 case OMPC_match:
15022 case OMPC_nontemporal:
15023 case OMPC_order:
15024 case OMPC_at:
15025 case OMPC_severity:
15026 case OMPC_destroy:
15027 case OMPC_inclusive:
15028 case OMPC_exclusive:
15029 case OMPC_uses_allocators:
15030 case OMPC_affinity:
15031 case OMPC_when:
15032 case OMPC_bind:
15033 default:
15034 llvm_unreachable("Clause is not allowed.");
15035 }
15036 return Res;
15037}
15038
15039// An OpenMP directive such as 'target parallel' has two captured regions:
15040// for the 'target' and 'parallel' respectively. This function returns
15041// the region in which to capture expressions associated with a clause.
15042// A return value of OMPD_unknown signifies that the expression should not
15043// be captured.
15045 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15046 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15047 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15048 "Invalid directive with CKind-clause");
15049
15050 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15051 if (NameModifier != OMPD_unknown &&
15052 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15053 return OMPD_unknown;
15054
15055 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15056
15057 // [5.2:341:24-30]
15058 // If the clauses have expressions on them, such as for various clauses where
15059 // the argument of the clause is an expression, or lower-bound, length, or
15060 // stride expressions inside array sections (or subscript and stride
15061 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15062 // expressions, the expressions are evaluated immediately before the construct
15063 // to which the clause has been split or duplicated per the above rules
15064 // (therefore inside of the outer leaf constructs). However, the expressions
15065 // inside the num_teams and thread_limit clauses are always evaluated before
15066 // the outermost leaf construct.
15067
15068 // Process special cases first.
15069 switch (CKind) {
15070 case OMPC_if:
15071 switch (DKind) {
15072 case OMPD_teams_loop:
15073 case OMPD_target_teams_loop:
15074 // For [target] teams loop, assume capture region is 'teams' so it's
15075 // available for codegen later to use if/when necessary.
15076 return OMPD_teams;
15077 case OMPD_target_update:
15078 case OMPD_target_enter_data:
15079 case OMPD_target_exit_data:
15080 return OMPD_task;
15081 default:
15082 break;
15083 }
15084 break;
15085 case OMPC_num_teams:
15086 case OMPC_thread_limit:
15087 case OMPC_ompx_dyn_cgroup_mem:
15088 if (Leafs[0] == OMPD_target)
15089 return OMPD_target;
15090 break;
15091 case OMPC_device:
15092 if (Leafs[0] == OMPD_target ||
15093 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15094 OMPD_target_enter_data, OMPD_target_exit_data},
15095 DKind))
15096 return OMPD_task;
15097 break;
15098 case OMPC_novariants:
15099 case OMPC_nocontext:
15100 if (DKind == OMPD_dispatch)
15101 return OMPD_task;
15102 break;
15103 case OMPC_when:
15104 if (DKind == OMPD_metadirective)
15105 return OMPD_metadirective;
15106 break;
15107 case OMPC_filter:
15108 return OMPD_unknown;
15109 default:
15110 break;
15111 }
15112
15113 // If none of the special cases above applied, and DKind is a capturing
15114 // directive, find the innermost enclosing leaf construct that allows the
15115 // clause, and returns the corresponding capture region.
15116
15117 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15118 // Find the index in "Leafs" of the last leaf that allows the given
15119 // clause. The search will only include indexes [0, EndIdx).
15120 // EndIdx may be set to the index of the NameModifier, if present.
15121 int InnermostIdx = [&]() {
15122 for (int I = EndIdx - 1; I >= 0; --I) {
15123 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15124 return I;
15125 }
15126 return -1;
15127 }();
15128
15129 // Find the nearest enclosing capture region.
15131 for (int I = InnermostIdx - 1; I >= 0; --I) {
15132 if (!isOpenMPCapturingDirective(Leafs[I]))
15133 continue;
15134 Regions.clear();
15135 getOpenMPCaptureRegions(Regions, Leafs[I]);
15136 if (Regions[0] != OMPD_unknown)
15137 return Regions.back();
15138 }
15139 return OMPD_unknown;
15140 };
15141
15142 if (isOpenMPCapturingDirective(DKind)) {
15143 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15144 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15145 if (Leafs[I] == Dir)
15146 return I + 1;
15147 }
15148 return 0;
15149 };
15150
15151 int End = NameModifier == OMPD_unknown ? Leafs.size()
15152 : GetLeafIndex(NameModifier);
15153 return GetEnclosingRegion(End, CKind);
15154 }
15155
15156 return OMPD_unknown;
15157}
15158
15160 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15161 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15162 SourceLocation ColonLoc, SourceLocation EndLoc) {
15163 Expr *ValExpr = Condition;
15164 Stmt *HelperValStmt = nullptr;
15165 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15166 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15167 !Condition->isInstantiationDependent() &&
15168 !Condition->containsUnexpandedParameterPack()) {
15170 if (Val.isInvalid())
15171 return nullptr;
15172
15173 ValExpr = Val.get();
15174
15175 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15176 CaptureRegion = getOpenMPCaptureRegionForClause(
15177 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15178 if (CaptureRegion != OMPD_unknown &&
15180 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15181 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15182 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15183 HelperValStmt = buildPreInits(getASTContext(), Captures);
15184 }
15185 }
15186
15187 return new (getASTContext())
15188 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15189 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15190}
15191
15193 SourceLocation StartLoc,
15194 SourceLocation LParenLoc,
15195 SourceLocation EndLoc) {
15196 Expr *ValExpr = Condition;
15197 Stmt *HelperValStmt = nullptr;
15198 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15199 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15200 !Condition->isInstantiationDependent() &&
15201 !Condition->containsUnexpandedParameterPack()) {
15203 if (Val.isInvalid())
15204 return nullptr;
15205
15206 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
15207
15208 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15209 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15210 getLangOpts().OpenMP);
15211 if (CaptureRegion != OMPD_unknown &&
15213 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15214 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15215 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15216 HelperValStmt = buildPreInits(getASTContext(), Captures);
15217 }
15218 }
15219
15220 return new (getASTContext()) OMPFinalClause(
15221 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15222}
15223
15226 Expr *Op) {
15227 if (!Op)
15228 return ExprError();
15229
15230 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15231 public:
15232 IntConvertDiagnoser()
15233 : ICEConvertDiagnoser(/*AllowScopedEnumerations*/ false, false, true) {}
15234 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15235 QualType T) override {
15236 return S.Diag(Loc, diag::err_omp_not_integral) << T;
15237 }
15238 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15239 QualType T) override {
15240 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15241 }
15242 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15243 QualType T,
15244 QualType ConvTy) override {
15245 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15246 }
15247 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15248 QualType ConvTy) override {
15249 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15250 << ConvTy->isEnumeralType() << ConvTy;
15251 }
15252 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15253 QualType T) override {
15254 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15255 }
15256 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15257 QualType ConvTy) override {
15258 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15259 << ConvTy->isEnumeralType() << ConvTy;
15260 }
15261 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15262 QualType) override {
15263 llvm_unreachable("conversion functions are permitted");
15264 }
15265 } ConvertDiagnoser;
15266 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
15267}
15268
15269static bool
15271 bool StrictlyPositive, bool BuildCapture = false,
15272 OpenMPDirectiveKind DKind = OMPD_unknown,
15273 OpenMPDirectiveKind *CaptureRegion = nullptr,
15274 Stmt **HelperValStmt = nullptr) {
15275 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15276 !ValExpr->isInstantiationDependent()) {
15277 SourceLocation Loc = ValExpr->getExprLoc();
15280 if (Value.isInvalid())
15281 return false;
15282
15283 ValExpr = Value.get();
15284 // The expression must evaluate to a non-negative integer value.
15285 if (std::optional<llvm::APSInt> Result =
15286 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
15287 if (Result->isSigned() &&
15288 !((!StrictlyPositive && Result->isNonNegative()) ||
15289 (StrictlyPositive && Result->isStrictlyPositive()))) {
15290 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15291 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15292 << ValExpr->getSourceRange();
15293 return false;
15294 }
15295 }
15296 if (!BuildCapture)
15297 return true;
15298 *CaptureRegion =
15299 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15300 if (*CaptureRegion != OMPD_unknown &&
15301 !SemaRef.CurContext->isDependentContext()) {
15302 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15303 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15304 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15305 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
15306 }
15307 }
15308 return true;
15309}
15310
15312 SourceLocation StartLoc,
15313 SourceLocation LParenLoc,
15314 SourceLocation EndLoc) {
15315 Expr *ValExpr = NumThreads;
15316 Stmt *HelperValStmt = nullptr;
15317
15318 // OpenMP [2.5, Restrictions]
15319 // The num_threads expression must evaluate to a positive integer value.
15320 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15321 /*StrictlyPositive=*/true))
15322 return nullptr;
15323
15324 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15326 DKind, OMPC_num_threads, getLangOpts().OpenMP);
15327 if (CaptureRegion != OMPD_unknown &&
15329 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15330 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15331 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15332 HelperValStmt = buildPreInits(getASTContext(), Captures);
15333 }
15334
15335 return new (getASTContext()) OMPNumThreadsClause(
15336 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15337}
15338
15340 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15341 bool SuppressExprDiags) {
15342 if (!E)
15343 return ExprError();
15344 if (E->isValueDependent() || E->isTypeDependent() ||
15346 return E;
15347
15348 llvm::APSInt Result;
15349 ExprResult ICE;
15350 if (SuppressExprDiags) {
15351 // Use a custom diagnoser that suppresses 'note' diagnostics about the
15352 // expression.
15353 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15354 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15356 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15357 llvm_unreachable("Diagnostic suppressed");
15358 }
15359 } Diagnoser;
15362 } else {
15364 /*FIXME*/ Sema::AllowFold);
15365 }
15366 if (ICE.isInvalid())
15367 return ExprError();
15368
15369 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
15370 (!StrictlyPositive && !Result.isNonNegative())) {
15371 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
15372 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15373 << E->getSourceRange();
15374 return ExprError();
15375 }
15376 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
15377 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
15378 << E->getSourceRange();
15379 return ExprError();
15380 }
15381 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
15382 DSAStack->setAssociatedLoops(Result.getExtValue());
15383 else if (CKind == OMPC_ordered)
15384 DSAStack->setAssociatedLoops(Result.getExtValue());
15385 return ICE;
15386}
15387
15389 SourceLocation StartLoc,
15390 SourceLocation LParenLoc,
15391 SourceLocation EndLoc) {
15392 // OpenMP [2.8.1, simd construct, Description]
15393 // The parameter of the safelen clause must be a constant
15394 // positive integer expression.
15395 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
15396 if (Safelen.isInvalid())
15397 return nullptr;
15398 return new (getASTContext())
15399 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
15400}
15401
15403 SourceLocation StartLoc,
15404 SourceLocation LParenLoc,
15405 SourceLocation EndLoc) {
15406 // OpenMP [2.8.1, simd construct, Description]
15407 // The parameter of the simdlen clause must be a constant
15408 // positive integer expression.
15409 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
15410 if (Simdlen.isInvalid())
15411 return nullptr;
15412 return new (getASTContext())
15413 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
15414}
15415
15416/// Tries to find omp_allocator_handle_t type.
15418 DSAStackTy *Stack) {
15419 if (!Stack->getOMPAllocatorHandleT().isNull())
15420 return true;
15421
15422 // Set the allocator handle type.
15423 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
15424 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
15425 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
15426 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15427 << "omp_allocator_handle_t";
15428 return false;
15429 }
15430 QualType AllocatorHandleEnumTy = PT.get();
15431 AllocatorHandleEnumTy.addConst();
15432 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15433
15434 // Fill the predefined allocator map.
15435 bool ErrorFound = false;
15436 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15437 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
15438 StringRef Allocator =
15439 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15440 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
15441 auto *VD = dyn_cast_or_null<ValueDecl>(
15442 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
15443 if (!VD) {
15444 ErrorFound = true;
15445 break;
15446 }
15447 QualType AllocatorType =
15449 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
15450 if (!Res.isUsable()) {
15451 ErrorFound = true;
15452 break;
15453 }
15454 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
15456 /* AllowExplicit */ true);
15457 if (!Res.isUsable()) {
15458 ErrorFound = true;
15459 break;
15460 }
15461 Stack->setAllocator(AllocatorKind, Res.get());
15462 }
15463 if (ErrorFound) {
15464 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15465 << "omp_allocator_handle_t";
15466 return false;
15467 }
15468
15469 return true;
15470}
15471
15473 SourceLocation StartLoc,
15474 SourceLocation LParenLoc,
15475 SourceLocation EndLoc) {
15476 // OpenMP [2.11.3, allocate Directive, Description]
15477 // allocator is an expression of omp_allocator_handle_t type.
15479 return nullptr;
15480
15482 if (Allocator.isInvalid())
15483 return nullptr;
15485 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
15487 /*AllowExplicit=*/true);
15488 if (Allocator.isInvalid())
15489 return nullptr;
15490 return new (getASTContext())
15491 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
15492}
15493
15495 SourceLocation StartLoc,
15496 SourceLocation LParenLoc,
15497 SourceLocation EndLoc) {
15498 // OpenMP [2.7.1, loop construct, Description]
15499 // OpenMP [2.8.1, simd construct, Description]
15500 // OpenMP [2.9.6, distribute construct, Description]
15501 // The parameter of the collapse clause must be a constant
15502 // positive integer expression.
15503 ExprResult NumForLoopsResult =
15504 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
15505 if (NumForLoopsResult.isInvalid())
15506 return nullptr;
15507 return new (getASTContext())
15508 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
15509}
15510
15512 SourceLocation EndLoc,
15513 SourceLocation LParenLoc,
15514 Expr *NumForLoops) {
15515 // OpenMP [2.7.1, loop construct, Description]
15516 // OpenMP [2.8.1, simd construct, Description]
15517 // OpenMP [2.9.6, distribute construct, Description]
15518 // The parameter of the ordered clause must be a constant
15519 // positive integer expression if any.
15520 if (NumForLoops && LParenLoc.isValid()) {
15521 ExprResult NumForLoopsResult =
15522 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
15523 if (NumForLoopsResult.isInvalid())
15524 return nullptr;
15525 NumForLoops = NumForLoopsResult.get();
15526 } else {
15527 NumForLoops = nullptr;
15528 }
15529 auto *Clause =
15531 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
15532 StartLoc, LParenLoc, EndLoc);
15533 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
15534 return Clause;
15535}
15536
15538 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
15539 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15540 OMPClause *Res = nullptr;
15541 switch (Kind) {
15542 case OMPC_default:
15543 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
15544 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15545 break;
15546 case OMPC_proc_bind:
15547 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
15548 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15549 break;
15550 case OMPC_atomic_default_mem_order:
15552 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
15553 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15554 break;
15555 case OMPC_fail:
15556 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
15557 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15558 break;
15559 case OMPC_update:
15560 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
15561 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15562 break;
15563 case OMPC_bind:
15564 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
15565 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15566 break;
15567 case OMPC_at:
15568 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
15569 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15570 break;
15571 case OMPC_severity:
15573 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
15574 LParenLoc, EndLoc);
15575 break;
15576 case OMPC_if:
15577 case OMPC_final:
15578 case OMPC_num_threads:
15579 case OMPC_safelen:
15580 case OMPC_simdlen:
15581 case OMPC_sizes:
15582 case OMPC_allocator:
15583 case OMPC_collapse:
15584 case OMPC_schedule:
15585 case OMPC_private:
15586 case OMPC_firstprivate:
15587 case OMPC_lastprivate:
15588 case OMPC_shared:
15589 case OMPC_reduction:
15590 case OMPC_task_reduction:
15591 case OMPC_in_reduction:
15592 case OMPC_linear:
15593 case OMPC_aligned:
15594 case OMPC_copyin:
15595 case OMPC_copyprivate:
15596 case OMPC_ordered:
15597 case OMPC_nowait:
15598 case OMPC_untied:
15599 case OMPC_mergeable:
15600 case OMPC_threadprivate:
15601 case OMPC_allocate:
15602 case OMPC_flush:
15603 case OMPC_depobj:
15604 case OMPC_read:
15605 case OMPC_write:
15606 case OMPC_capture:
15607 case OMPC_compare:
15608 case OMPC_seq_cst:
15609 case OMPC_acq_rel:
15610 case OMPC_acquire:
15611 case OMPC_release:
15612 case OMPC_relaxed:
15613 case OMPC_depend:
15614 case OMPC_device:
15615 case OMPC_threads:
15616 case OMPC_simd:
15617 case OMPC_map:
15618 case OMPC_num_teams:
15619 case OMPC_thread_limit:
15620 case OMPC_priority:
15621 case OMPC_grainsize:
15622 case OMPC_nogroup:
15623 case OMPC_num_tasks:
15624 case OMPC_hint:
15625 case OMPC_dist_schedule:
15626 case OMPC_defaultmap:
15627 case OMPC_unknown:
15628 case OMPC_uniform:
15629 case OMPC_to:
15630 case OMPC_from:
15631 case OMPC_use_device_ptr:
15632 case OMPC_use_device_addr:
15633 case OMPC_is_device_ptr:
15634 case OMPC_has_device_addr:
15635 case OMPC_unified_address:
15636 case OMPC_unified_shared_memory:
15637 case OMPC_reverse_offload:
15638 case OMPC_dynamic_allocators:
15639 case OMPC_device_type:
15640 case OMPC_match:
15641 case OMPC_nontemporal:
15642 case OMPC_destroy:
15643 case OMPC_novariants:
15644 case OMPC_nocontext:
15645 case OMPC_detach:
15646 case OMPC_inclusive:
15647 case OMPC_exclusive:
15648 case OMPC_uses_allocators:
15649 case OMPC_affinity:
15650 case OMPC_when:
15651 case OMPC_message:
15652 default:
15653 llvm_unreachable("Clause is not allowed.");
15654 }
15655 return Res;
15656}
15657
15658static std::string
15660 ArrayRef<unsigned> Exclude = std::nullopt) {
15661 SmallString<256> Buffer;
15662 llvm::raw_svector_ostream Out(Buffer);
15663 unsigned Skipped = Exclude.size();
15664 for (unsigned I = First; I < Last; ++I) {
15665 if (llvm::is_contained(Exclude, I)) {
15666 --Skipped;
15667 continue;
15668 }
15669 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15670 if (I + Skipped + 2 == Last)
15671 Out << " or ";
15672 else if (I + Skipped + 1 != Last)
15673 Out << ", ";
15674 }
15675 return std::string(Out.str());
15676}
15677
15679 SourceLocation KindKwLoc,
15680 SourceLocation StartLoc,
15681 SourceLocation LParenLoc,
15682 SourceLocation EndLoc) {
15683 if (Kind == OMP_DEFAULT_unknown) {
15684 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15685 << getListOfPossibleValues(OMPC_default, /*First=*/0,
15686 /*Last=*/unsigned(OMP_DEFAULT_unknown))
15687 << getOpenMPClauseName(OMPC_default);
15688 return nullptr;
15689 }
15690
15691 switch (Kind) {
15692 case OMP_DEFAULT_none:
15693 DSAStack->setDefaultDSANone(KindKwLoc);
15694 break;
15695 case OMP_DEFAULT_shared:
15696 DSAStack->setDefaultDSAShared(KindKwLoc);
15697 break;
15698 case OMP_DEFAULT_firstprivate:
15699 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15700 break;
15701 case OMP_DEFAULT_private:
15702 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15703 break;
15704 default:
15705 llvm_unreachable("DSA unexpected in OpenMP default clause");
15706 }
15707
15708 return new (getASTContext())
15709 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15710}
15711
15713 SourceLocation KindKwLoc,
15714 SourceLocation StartLoc,
15715 SourceLocation LParenLoc,
15716 SourceLocation EndLoc) {
15717 if (Kind == OMP_PROC_BIND_unknown) {
15718 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15719 << getListOfPossibleValues(OMPC_proc_bind,
15720 /*First=*/unsigned(OMP_PROC_BIND_master),
15721 /*Last=*/
15722 unsigned(getLangOpts().OpenMP > 50
15723 ? OMP_PROC_BIND_primary
15724 : OMP_PROC_BIND_spread) +
15725 1)
15726 << getOpenMPClauseName(OMPC_proc_bind);
15727 return nullptr;
15728 }
15729 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
15730 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15731 << getListOfPossibleValues(OMPC_proc_bind,
15732 /*First=*/unsigned(OMP_PROC_BIND_master),
15733 /*Last=*/
15734 unsigned(OMP_PROC_BIND_spread) + 1)
15735 << getOpenMPClauseName(OMPC_proc_bind);
15736 return new (getASTContext())
15737 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15738}
15739
15742 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15744 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15746 OMPC_atomic_default_mem_order, /*First=*/0,
15748 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15749 return nullptr;
15750 }
15752 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15753}
15754
15756 SourceLocation KindKwLoc,
15757 SourceLocation StartLoc,
15758 SourceLocation LParenLoc,
15759 SourceLocation EndLoc) {
15760 if (Kind == OMPC_AT_unknown) {
15761 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15762 << getListOfPossibleValues(OMPC_at, /*First=*/0,
15763 /*Last=*/OMPC_AT_unknown)
15764 << getOpenMPClauseName(OMPC_at);
15765 return nullptr;
15766 }
15767 return new (getASTContext())
15768 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15769}
15770
15772 SourceLocation KindKwLoc,
15773 SourceLocation StartLoc,
15774 SourceLocation LParenLoc,
15775 SourceLocation EndLoc) {
15776 if (Kind == OMPC_SEVERITY_unknown) {
15777 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15778 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
15779 /*Last=*/OMPC_SEVERITY_unknown)
15780 << getOpenMPClauseName(OMPC_severity);
15781 return nullptr;
15782 }
15783 return new (getASTContext())
15784 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15785}
15786
15788 SourceLocation StartLoc,
15789 SourceLocation LParenLoc,
15790 SourceLocation EndLoc) {
15791 assert(ME && "NULL expr in Message clause");
15792 if (!isa<StringLiteral>(ME)) {
15793 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
15794 << getOpenMPClauseName(OMPC_message);
15795 return nullptr;
15796 }
15797 return new (getASTContext())
15798 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
15799}
15800
15803 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
15804 SourceLocation KindLoc, SourceLocation EndLoc) {
15805 if (Kind != OMPC_ORDER_concurrent ||
15806 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
15807 // Kind should be concurrent,
15808 // Modifiers introduced in OpenMP 5.1
15809 static_assert(OMPC_ORDER_unknown > 0,
15810 "OMPC_ORDER_unknown not greater than 0");
15811
15812 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
15813 << getListOfPossibleValues(OMPC_order,
15814 /*First=*/0,
15815 /*Last=*/OMPC_ORDER_unknown)
15816 << getOpenMPClauseName(OMPC_order);
15817 return nullptr;
15818 }
15819 if (getLangOpts().OpenMP >= 51) {
15820 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
15821 Diag(MLoc, diag::err_omp_unexpected_clause_value)
15822 << getListOfPossibleValues(OMPC_order,
15823 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
15824 /*Last=*/OMPC_ORDER_MODIFIER_last)
15825 << getOpenMPClauseName(OMPC_order);
15826 } else {
15827 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
15828 if (DSAStack->getCurScope()) {
15829 // mark the current scope with 'order' flag
15830 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
15831 DSAStack->getCurScope()->setFlags(existingFlags |
15833 }
15834 }
15835 }
15836 return new (getASTContext()) OMPOrderClause(
15837 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
15838}
15839
15841 SourceLocation KindKwLoc,
15842 SourceLocation StartLoc,
15843 SourceLocation LParenLoc,
15844 SourceLocation EndLoc) {
15845 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
15846 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
15847 SmallVector<unsigned> Except = {
15848 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
15849 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
15850 if (getLangOpts().OpenMP < 51)
15851 Except.push_back(OMPC_DEPEND_inoutset);
15852 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15853 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
15854 /*Last=*/OMPC_DEPEND_unknown, Except)
15855 << getOpenMPClauseName(OMPC_update);
15856 return nullptr;
15857 }
15858 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
15859 KindKwLoc, Kind, EndLoc);
15860}
15861
15863 SourceLocation StartLoc,
15864 SourceLocation LParenLoc,
15865 SourceLocation EndLoc) {
15866 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
15867
15868 for (Expr *&SizeExpr : SanitizedSizeExprs) {
15869 // Skip if already sanitized, e.g. during a partial template instantiation.
15870 if (!SizeExpr)
15871 continue;
15872
15873 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
15874 /*StrictlyPositive=*/true);
15875
15876 // isNonNegativeIntegerValue returns true for non-integral types (but still
15877 // emits error diagnostic), so check for the expected type explicitly.
15878 QualType SizeTy = SizeExpr->getType();
15879 if (!SizeTy->isIntegerType())
15880 IsValid = false;
15881
15882 // Handling in templates is tricky. There are four possibilities to
15883 // consider:
15884 //
15885 // 1a. The expression is valid and we are in a instantiated template or not
15886 // in a template:
15887 // Pass valid expression to be further analysed later in Sema.
15888 // 1b. The expression is valid and we are in a template (including partial
15889 // instantiation):
15890 // isNonNegativeIntegerValue skipped any checks so there is no
15891 // guarantee it will be correct after instantiation.
15892 // ActOnOpenMPSizesClause will be called again at instantiation when
15893 // it is not in a dependent context anymore. This may cause warnings
15894 // to be emitted multiple times.
15895 // 2a. The expression is invalid and we are in an instantiated template or
15896 // not in a template:
15897 // Invalidate the expression with a clearly wrong value (nullptr) so
15898 // later in Sema we do not have to do the same validity analysis again
15899 // or crash from unexpected data. Error diagnostics have already been
15900 // emitted.
15901 // 2b. The expression is invalid and we are in a template (including partial
15902 // instantiation):
15903 // Pass the invalid expression as-is, template instantiation may
15904 // replace unexpected types/values with valid ones. The directives
15905 // with this clause must not try to use these expressions in dependent
15906 // contexts, but delay analysis until full instantiation.
15907 if (!SizeExpr->isInstantiationDependent() && !IsValid)
15908 SizeExpr = nullptr;
15909 }
15910
15911 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
15912 SanitizedSizeExprs);
15913}
15914
15916 SourceLocation EndLoc) {
15917 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
15918}
15919
15921 SourceLocation StartLoc,
15922 SourceLocation LParenLoc,
15923 SourceLocation EndLoc) {
15924 if (FactorExpr) {
15925 // If an argument is specified, it must be a constant (or an unevaluated
15926 // template expression).
15928 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
15929 if (FactorResult.isInvalid())
15930 return nullptr;
15931 FactorExpr = FactorResult.get();
15932 }
15933
15934 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
15935 FactorExpr);
15936}
15937
15939 SourceLocation LParenLoc,
15940 SourceLocation EndLoc) {
15941 ExprResult AlignVal;
15942 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
15943 if (AlignVal.isInvalid())
15944 return nullptr;
15945 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
15946 LParenLoc, EndLoc);
15947}
15948
15951 SourceLocation StartLoc, SourceLocation LParenLoc,
15952 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
15953 SourceLocation EndLoc) {
15954 OMPClause *Res = nullptr;
15955 switch (Kind) {
15956 case OMPC_schedule:
15957 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
15958 assert(Argument.size() == NumberOfElements &&
15959 ArgumentLoc.size() == NumberOfElements);
15961 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
15962 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
15963 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
15964 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
15965 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
15966 break;
15967 case OMPC_if:
15968 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
15969 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
15970 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
15971 DelimLoc, EndLoc);
15972 break;
15973 case OMPC_dist_schedule:
15975 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
15976 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
15977 break;
15978 case OMPC_defaultmap:
15979 enum { Modifier, DefaultmapKind };
15981 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
15982 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
15983 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
15984 EndLoc);
15985 break;
15986 case OMPC_order:
15987 enum { OrderModifier, OrderKind };
15989 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
15990 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
15991 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
15992 break;
15993 case OMPC_device:
15994 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
15996 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
15997 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
15998 break;
15999 case OMPC_grainsize:
16000 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16001 "Modifier for grainsize clause and its location are expected.");
16003 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16004 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16005 break;
16006 case OMPC_num_tasks:
16007 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16008 "Modifier for num_tasks clause and its location are expected.");
16010 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16011 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16012 break;
16013 case OMPC_final:
16014 case OMPC_num_threads:
16015 case OMPC_safelen:
16016 case OMPC_simdlen:
16017 case OMPC_sizes:
16018 case OMPC_allocator:
16019 case OMPC_collapse:
16020 case OMPC_default:
16021 case OMPC_proc_bind:
16022 case OMPC_private:
16023 case OMPC_firstprivate:
16024 case OMPC_lastprivate:
16025 case OMPC_shared:
16026 case OMPC_reduction:
16027 case OMPC_task_reduction:
16028 case OMPC_in_reduction:
16029 case OMPC_linear:
16030 case OMPC_aligned:
16031 case OMPC_copyin:
16032 case OMPC_copyprivate:
16033 case OMPC_ordered:
16034 case OMPC_nowait:
16035 case OMPC_untied:
16036 case OMPC_mergeable:
16037 case OMPC_threadprivate:
16038 case OMPC_allocate:
16039 case OMPC_flush:
16040 case OMPC_depobj:
16041 case OMPC_read:
16042 case OMPC_write:
16043 case OMPC_update:
16044 case OMPC_capture:
16045 case OMPC_compare:
16046 case OMPC_seq_cst:
16047 case OMPC_acq_rel:
16048 case OMPC_acquire:
16049 case OMPC_release:
16050 case OMPC_relaxed:
16051 case OMPC_depend:
16052 case OMPC_threads:
16053 case OMPC_simd:
16054 case OMPC_map:
16055 case OMPC_num_teams:
16056 case OMPC_thread_limit:
16057 case OMPC_priority:
16058 case OMPC_nogroup:
16059 case OMPC_hint:
16060 case OMPC_unknown:
16061 case OMPC_uniform:
16062 case OMPC_to:
16063 case OMPC_from:
16064 case OMPC_use_device_ptr:
16065 case OMPC_use_device_addr:
16066 case OMPC_is_device_ptr:
16067 case OMPC_has_device_addr:
16068 case OMPC_unified_address:
16069 case OMPC_unified_shared_memory:
16070 case OMPC_reverse_offload:
16071 case OMPC_dynamic_allocators:
16072 case OMPC_atomic_default_mem_order:
16073 case OMPC_device_type:
16074 case OMPC_match:
16075 case OMPC_nontemporal:
16076 case OMPC_at:
16077 case OMPC_severity:
16078 case OMPC_message:
16079 case OMPC_destroy:
16080 case OMPC_novariants:
16081 case OMPC_nocontext:
16082 case OMPC_detach:
16083 case OMPC_inclusive:
16084 case OMPC_exclusive:
16085 case OMPC_uses_allocators:
16086 case OMPC_affinity:
16087 case OMPC_when:
16088 case OMPC_bind:
16089 default:
16090 llvm_unreachable("Clause is not allowed.");
16091 }
16092 return Res;
16093}
16094
16097 SourceLocation M1Loc, SourceLocation M2Loc) {
16098 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16099 SmallVector<unsigned, 2> Excluded;
16101 Excluded.push_back(M2);
16102 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16103 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16104 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16105 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16106 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16107 << getListOfPossibleValues(OMPC_schedule,
16108 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16110 Excluded)
16111 << getOpenMPClauseName(OMPC_schedule);
16112 return true;
16113 }
16114 return false;
16115}
16116
16119 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16120 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16121 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16122 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16123 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16124 return nullptr;
16125 // OpenMP, 2.7.1, Loop Construct, Restrictions
16126 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16127 // but not both.
16128 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16129 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16130 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16131 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16132 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16133 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16134 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16135 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16136 return nullptr;
16137 }
16138 if (Kind == OMPC_SCHEDULE_unknown) {
16139 std::string Values;
16140 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16141 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16142 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16144 Exclude);
16145 } else {
16146 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16147 /*Last=*/OMPC_SCHEDULE_unknown);
16148 }
16149 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16150 << Values << getOpenMPClauseName(OMPC_schedule);
16151 return nullptr;
16152 }
16153 // OpenMP, 2.7.1, Loop Construct, Restrictions
16154 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16155 // schedule(guided).
16156 // OpenMP 5.0 does not have this restriction.
16157 if (getLangOpts().OpenMP < 50 &&
16158 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16159 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16160 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16161 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16162 diag::err_omp_schedule_nonmonotonic_static);
16163 return nullptr;
16164 }
16165 Expr *ValExpr = ChunkSize;
16166 Stmt *HelperValStmt = nullptr;
16167 if (ChunkSize) {
16168 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16169 !ChunkSize->isInstantiationDependent() &&
16170 !ChunkSize->containsUnexpandedParameterPack()) {
16171 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16172 ExprResult Val =
16173 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16174 if (Val.isInvalid())
16175 return nullptr;
16176
16177 ValExpr = Val.get();
16178
16179 // OpenMP [2.7.1, Restrictions]
16180 // chunk_size must be a loop invariant integer expression with a positive
16181 // value.
16182 if (std::optional<llvm::APSInt> Result =
16184 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16185 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16186 << "schedule" << 1 << ChunkSize->getSourceRange();
16187 return nullptr;
16188 }
16190 DSAStack->getCurrentDirective(), OMPC_schedule,
16191 getLangOpts().OpenMP) != OMPD_unknown &&
16193 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16194 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16195 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16196 HelperValStmt = buildPreInits(getASTContext(), Captures);
16197 }
16198 }
16199 }
16200
16201 return new (getASTContext())
16202 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16203 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16204}
16205
16207 SourceLocation StartLoc,
16208 SourceLocation EndLoc) {
16209 OMPClause *Res = nullptr;
16210 switch (Kind) {
16211 case OMPC_ordered:
16212 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16213 break;
16214 case OMPC_nowait:
16215 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16216 break;
16217 case OMPC_untied:
16218 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16219 break;
16220 case OMPC_mergeable:
16221 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16222 break;
16223 case OMPC_read:
16224 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16225 break;
16226 case OMPC_write:
16227 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16228 break;
16229 case OMPC_update:
16230 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16231 break;
16232 case OMPC_capture:
16233 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16234 break;
16235 case OMPC_compare:
16236 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16237 break;
16238 case OMPC_fail:
16239 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16240 break;
16241 case OMPC_seq_cst:
16242 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16243 break;
16244 case OMPC_acq_rel:
16245 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16246 break;
16247 case OMPC_acquire:
16248 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16249 break;
16250 case OMPC_release:
16251 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16252 break;
16253 case OMPC_relaxed:
16254 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16255 break;
16256 case OMPC_weak:
16257 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16258 break;
16259 case OMPC_threads:
16260 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16261 break;
16262 case OMPC_simd:
16263 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16264 break;
16265 case OMPC_nogroup:
16266 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16267 break;
16268 case OMPC_unified_address:
16269 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16270 break;
16271 case OMPC_unified_shared_memory:
16272 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16273 break;
16274 case OMPC_reverse_offload:
16275 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16276 break;
16277 case OMPC_dynamic_allocators:
16278 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16279 break;
16280 case OMPC_destroy:
16281 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16282 /*LParenLoc=*/SourceLocation(),
16283 /*VarLoc=*/SourceLocation(), EndLoc);
16284 break;
16285 case OMPC_full:
16286 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16287 break;
16288 case OMPC_partial:
16289 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16290 break;
16291 case OMPC_ompx_bare:
16292 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16293 break;
16294 case OMPC_if:
16295 case OMPC_final:
16296 case OMPC_num_threads:
16297 case OMPC_safelen:
16298 case OMPC_simdlen:
16299 case OMPC_sizes:
16300 case OMPC_allocator:
16301 case OMPC_collapse:
16302 case OMPC_schedule:
16303 case OMPC_private:
16304 case OMPC_firstprivate:
16305 case OMPC_lastprivate:
16306 case OMPC_shared:
16307 case OMPC_reduction:
16308 case OMPC_task_reduction:
16309 case OMPC_in_reduction:
16310 case OMPC_linear:
16311 case OMPC_aligned:
16312 case OMPC_copyin:
16313 case OMPC_copyprivate:
16314 case OMPC_default:
16315 case OMPC_proc_bind:
16316 case OMPC_threadprivate:
16317 case OMPC_allocate:
16318 case OMPC_flush:
16319 case OMPC_depobj:
16320 case OMPC_depend:
16321 case OMPC_device:
16322 case OMPC_map:
16323 case OMPC_num_teams:
16324 case OMPC_thread_limit:
16325 case OMPC_priority:
16326 case OMPC_grainsize:
16327 case OMPC_num_tasks:
16328 case OMPC_hint:
16329 case OMPC_dist_schedule:
16330 case OMPC_defaultmap:
16331 case OMPC_unknown:
16332 case OMPC_uniform:
16333 case OMPC_to:
16334 case OMPC_from:
16335 case OMPC_use_device_ptr:
16336 case OMPC_use_device_addr:
16337 case OMPC_is_device_ptr:
16338 case OMPC_has_device_addr:
16339 case OMPC_atomic_default_mem_order:
16340 case OMPC_device_type:
16341 case OMPC_match:
16342 case OMPC_nontemporal:
16343 case OMPC_order:
16344 case OMPC_at:
16345 case OMPC_severity:
16346 case OMPC_message:
16347 case OMPC_novariants:
16348 case OMPC_nocontext:
16349 case OMPC_detach:
16350 case OMPC_inclusive:
16351 case OMPC_exclusive:
16352 case OMPC_uses_allocators:
16353 case OMPC_affinity:
16354 case OMPC_when:
16355 case OMPC_ompx_dyn_cgroup_mem:
16356 default:
16357 llvm_unreachable("Clause is not allowed.");
16358 }
16359 return Res;
16360}
16361
16363 SourceLocation EndLoc) {
16364 DSAStack->setNowaitRegion();
16365 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
16366}
16367
16369 SourceLocation EndLoc) {
16370 DSAStack->setUntiedRegion();
16371 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
16372}
16373
16375 SourceLocation EndLoc) {
16376 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
16377}
16378
16380 SourceLocation EndLoc) {
16381 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
16382}
16383
16385 SourceLocation EndLoc) {
16386 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
16387}
16388
16390 SourceLocation EndLoc) {
16391 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
16392}
16393
16395 SourceLocation EndLoc) {
16396 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
16397}
16398
16400 SourceLocation EndLoc) {
16401 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
16402}
16403
16405 SourceLocation EndLoc) {
16406 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
16407}
16408
16410 SourceLocation KindLoc,
16411 SourceLocation StartLoc,
16412 SourceLocation LParenLoc,
16413 SourceLocation EndLoc) {
16414
16416 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16417 return nullptr;
16418 }
16419 return new (getASTContext())
16420 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
16421}
16422
16424 SourceLocation EndLoc) {
16425 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
16426}
16427
16429 SourceLocation EndLoc) {
16430 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
16431}
16432
16434 SourceLocation EndLoc) {
16435 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
16436}
16437
16439 SourceLocation EndLoc) {
16440 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
16441}
16442
16444 SourceLocation EndLoc) {
16445 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
16446}
16447
16449 SourceLocation EndLoc) {
16450 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
16451}
16452
16454 SourceLocation EndLoc) {
16455 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
16456}
16457
16459 SourceLocation EndLoc) {
16460 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
16461}
16462
16464 SourceLocation EndLoc) {
16465 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
16466}
16467
16469 SourceLocation EndLoc) {
16470 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
16471}
16472
16473OMPClause *
16475 SourceLocation EndLoc) {
16476 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16477}
16478
16480 SourceLocation EndLoc) {
16481 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
16482}
16483
16484OMPClause *
16486 SourceLocation EndLoc) {
16487 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
16488}
16489
16492 SourceLocation StartLoc,
16493 SourceLocation EndLoc) {
16494
16495 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16496 // At least one action-clause must appear on a directive.
16497 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16498 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
16499 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16500 << Expected << getOpenMPDirectiveName(OMPD_interop);
16501 return StmtError();
16502 }
16503
16504 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16505 // A depend clause can only appear on the directive if a targetsync
16506 // interop-type is present or the interop-var was initialized with
16507 // the targetsync interop-type.
16508
16509 // If there is any 'init' clause diagnose if there is no 'init' clause with
16510 // interop-type of 'targetsync'. Cases involving other directives cannot be
16511 // diagnosed.
16512 const OMPDependClause *DependClause = nullptr;
16513 bool HasInitClause = false;
16514 bool IsTargetSync = false;
16515 for (const OMPClause *C : Clauses) {
16516 if (IsTargetSync)
16517 break;
16518 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
16519 HasInitClause = true;
16520 if (InitClause->getIsTargetSync())
16521 IsTargetSync = true;
16522 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
16523 DependClause = DC;
16524 }
16525 }
16526 if (DependClause && HasInitClause && !IsTargetSync) {
16527 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16528 return StmtError();
16529 }
16530
16531 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16532 // Each interop-var may be specified for at most one action-clause of each
16533 // interop construct.
16535 for (OMPClause *C : Clauses) {
16536 OpenMPClauseKind ClauseKind = C->getClauseKind();
16537 std::pair<ValueDecl *, bool> DeclResult;
16538 SourceLocation ELoc;
16539 SourceRange ERange;
16540
16541 if (ClauseKind == OMPC_init) {
16542 auto *E = cast<OMPInitClause>(C)->getInteropVar();
16543 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16544 } else if (ClauseKind == OMPC_use) {
16545 auto *E = cast<OMPUseClause>(C)->getInteropVar();
16546 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16547 } else if (ClauseKind == OMPC_destroy) {
16548 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
16549 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16550 }
16551
16552 if (DeclResult.first) {
16553 if (!InteropVars.insert(DeclResult.first).second) {
16554 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16555 << DeclResult.first;
16556 return StmtError();
16557 }
16558 }
16559 }
16560
16561 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
16562 Clauses);
16563}
16564
16565static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
16566 SourceLocation VarLoc,
16567 OpenMPClauseKind Kind) {
16568 SourceLocation ELoc;
16569 SourceRange ERange;
16570 Expr *RefExpr = InteropVarExpr;
16571 auto Res =
16572 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
16573 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
16574
16575 if (Res.second) {
16576 // It will be analyzed later.
16577 return true;
16578 }
16579
16580 if (!Res.first)
16581 return false;
16582
16583 // Interop variable should be of type omp_interop_t.
16584 bool HasError = false;
16585 QualType InteropType;
16586 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
16587 VarLoc, Sema::LookupOrdinaryName);
16588 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
16589 NamedDecl *ND = Result.getFoundDecl();
16590 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
16591 InteropType = QualType(TD->getTypeForDecl(), 0);
16592 } else {
16593 HasError = true;
16594 }
16595 } else {
16596 HasError = true;
16597 }
16598
16599 if (HasError) {
16600 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
16601 << "omp_interop_t";
16602 return false;
16603 }
16604
16605 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
16606 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
16607 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16608 return false;
16609 }
16610
16611 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16612 // The interop-var passed to init or destroy must be non-const.
16613 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16614 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
16615 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
16616 << /*non-const*/ 1;
16617 return false;
16618 }
16619 return true;
16620}
16621
16623 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
16624 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
16625
16626 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
16627 return nullptr;
16628
16629 // Check prefer_type values. These foreign-runtime-id values are either
16630 // string literals or constant integral expressions.
16631 for (const Expr *E : InteropInfo.PreferTypes) {
16632 if (E->isValueDependent() || E->isTypeDependent() ||
16634 continue;
16636 continue;
16637 if (isa<StringLiteral>(E))
16638 continue;
16639 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
16640 return nullptr;
16641 }
16642
16643 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
16644 StartLoc, LParenLoc, VarLoc, EndLoc);
16645}
16646
16648 SourceLocation StartLoc,
16649 SourceLocation LParenLoc,
16650 SourceLocation VarLoc,
16651 SourceLocation EndLoc) {
16652
16653 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
16654 return nullptr;
16655
16656 return new (getASTContext())
16657 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16658}
16659
16661 SourceLocation StartLoc,
16662 SourceLocation LParenLoc,
16663 SourceLocation VarLoc,
16664 SourceLocation EndLoc) {
16665 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
16666 DSAStack->getCurrentDirective() == OMPD_depobj) {
16667 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16668 << getOpenMPClauseName(OMPC_destroy)
16669 << getOpenMPDirectiveName(OMPD_depobj);
16670 return nullptr;
16671 }
16672 if (InteropVar &&
16673 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
16674 return nullptr;
16675
16676 return new (getASTContext())
16677 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16678}
16679
16681 SourceLocation StartLoc,
16682 SourceLocation LParenLoc,
16683 SourceLocation EndLoc) {
16684 Expr *ValExpr = Condition;
16685 Stmt *HelperValStmt = nullptr;
16686 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16687 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16688 !Condition->isInstantiationDependent() &&
16689 !Condition->containsUnexpandedParameterPack()) {
16691 if (Val.isInvalid())
16692 return nullptr;
16693
16694 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16695
16696 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16697 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
16698 getLangOpts().OpenMP);
16699 if (CaptureRegion != OMPD_unknown &&
16701 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16702 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16703 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16704 HelperValStmt = buildPreInits(getASTContext(), Captures);
16705 }
16706 }
16707
16708 return new (getASTContext()) OMPNovariantsClause(
16709 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16710}
16711
16713 SourceLocation StartLoc,
16714 SourceLocation LParenLoc,
16715 SourceLocation EndLoc) {
16716 Expr *ValExpr = Condition;
16717 Stmt *HelperValStmt = nullptr;
16718 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16719 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16720 !Condition->isInstantiationDependent() &&
16721 !Condition->containsUnexpandedParameterPack()) {
16723 if (Val.isInvalid())
16724 return nullptr;
16725
16726 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16727
16728 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16729 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
16730 getLangOpts().OpenMP);
16731 if (CaptureRegion != OMPD_unknown &&
16733 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16734 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16735 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16736 HelperValStmt = buildPreInits(getASTContext(), Captures);
16737 }
16738 }
16739
16740 return new (getASTContext()) OMPNocontextClause(
16741 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16742}
16743
16745 SourceLocation StartLoc,
16746 SourceLocation LParenLoc,
16747 SourceLocation EndLoc) {
16748 Expr *ValExpr = ThreadID;
16749 Stmt *HelperValStmt = nullptr;
16750
16751 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16752 OpenMPDirectiveKind CaptureRegion =
16753 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
16754 if (CaptureRegion != OMPD_unknown &&
16756 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16757 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16758 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16759 HelperValStmt = buildPreInits(getASTContext(), Captures);
16760 }
16761
16762 return new (getASTContext()) OMPFilterClause(
16763 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16764}
16765
16767 ArrayRef<Expr *> VarList,
16768 const OMPVarListLocTy &Locs,
16770 SourceLocation StartLoc = Locs.StartLoc;
16771 SourceLocation LParenLoc = Locs.LParenLoc;
16772 SourceLocation EndLoc = Locs.EndLoc;
16773 OMPClause *Res = nullptr;
16774 int ExtraModifier = Data.ExtraModifier;
16775 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
16776 SourceLocation ColonLoc = Data.ColonLoc;
16777 switch (Kind) {
16778 case OMPC_private:
16779 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16780 break;
16781 case OMPC_firstprivate:
16782 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16783 break;
16784 case OMPC_lastprivate:
16785 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
16786 "Unexpected lastprivate modifier.");
16788 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
16789 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
16790 break;
16791 case OMPC_shared:
16792 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
16793 break;
16794 case OMPC_reduction:
16795 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
16796 "Unexpected lastprivate modifier.");
16798 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
16799 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
16800 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16801 break;
16802 case OMPC_task_reduction:
16804 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16805 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16806 break;
16807 case OMPC_in_reduction:
16809 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
16810 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
16811 break;
16812 case OMPC_linear:
16813 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
16814 "Unexpected linear modifier.");
16816 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
16817 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
16818 ColonLoc, Data.StepModifierLoc, EndLoc);
16819 break;
16820 case OMPC_aligned:
16821 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
16822 LParenLoc, ColonLoc, EndLoc);
16823 break;
16824 case OMPC_copyin:
16825 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
16826 break;
16827 case OMPC_copyprivate:
16828 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16829 break;
16830 case OMPC_flush:
16831 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
16832 break;
16833 case OMPC_depend:
16834 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
16835 "Unexpected depend modifier.");
16837 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
16838 ColonLoc, Data.OmpAllMemoryLoc},
16839 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
16840 break;
16841 case OMPC_map:
16842 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
16843 "Unexpected map modifier.");
16845 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
16846 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
16847 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
16848 ExtraModifierLoc, ColonLoc, VarList, Locs);
16849 break;
16850 case OMPC_to:
16851 Res =
16852 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
16853 Data.ReductionOrMapperIdScopeSpec,
16854 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
16855 break;
16856 case OMPC_from:
16857 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
16858 Data.ReductionOrMapperIdScopeSpec,
16859 Data.ReductionOrMapperId, ColonLoc, VarList,
16860 Locs);
16861 break;
16862 case OMPC_use_device_ptr:
16863 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
16864 break;
16865 case OMPC_use_device_addr:
16866 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
16867 break;
16868 case OMPC_is_device_ptr:
16869 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
16870 break;
16871 case OMPC_has_device_addr:
16872 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
16873 break;
16874 case OMPC_allocate:
16875 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
16876 LParenLoc, ColonLoc, EndLoc);
16877 break;
16878 case OMPC_nontemporal:
16879 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
16880 break;
16881 case OMPC_inclusive:
16882 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
16883 break;
16884 case OMPC_exclusive:
16885 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
16886 break;
16887 case OMPC_affinity:
16888 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
16889 Data.DepModOrTailExpr, VarList);
16890 break;
16891 case OMPC_doacross:
16893 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
16894 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
16895 break;
16896 case OMPC_if:
16897 case OMPC_depobj:
16898 case OMPC_final:
16899 case OMPC_num_threads:
16900 case OMPC_safelen:
16901 case OMPC_simdlen:
16902 case OMPC_sizes:
16903 case OMPC_allocator:
16904 case OMPC_collapse:
16905 case OMPC_default:
16906 case OMPC_proc_bind:
16907 case OMPC_schedule:
16908 case OMPC_ordered:
16909 case OMPC_nowait:
16910 case OMPC_untied:
16911 case OMPC_mergeable:
16912 case OMPC_threadprivate:
16913 case OMPC_read:
16914 case OMPC_write:
16915 case OMPC_update:
16916 case OMPC_capture:
16917 case OMPC_compare:
16918 case OMPC_seq_cst:
16919 case OMPC_acq_rel:
16920 case OMPC_acquire:
16921 case OMPC_release:
16922 case OMPC_relaxed:
16923 case OMPC_device:
16924 case OMPC_threads:
16925 case OMPC_simd:
16926 case OMPC_num_teams:
16927 case OMPC_thread_limit:
16928 case OMPC_priority:
16929 case OMPC_grainsize:
16930 case OMPC_nogroup:
16931 case OMPC_num_tasks:
16932 case OMPC_hint:
16933 case OMPC_dist_schedule:
16934 case OMPC_defaultmap:
16935 case OMPC_unknown:
16936 case OMPC_uniform:
16937 case OMPC_unified_address:
16938 case OMPC_unified_shared_memory:
16939 case OMPC_reverse_offload:
16940 case OMPC_dynamic_allocators:
16941 case OMPC_atomic_default_mem_order:
16942 case OMPC_device_type:
16943 case OMPC_match:
16944 case OMPC_order:
16945 case OMPC_at:
16946 case OMPC_severity:
16947 case OMPC_message:
16948 case OMPC_destroy:
16949 case OMPC_novariants:
16950 case OMPC_nocontext:
16951 case OMPC_detach:
16952 case OMPC_uses_allocators:
16953 case OMPC_when:
16954 case OMPC_bind:
16955 default:
16956 llvm_unreachable("Clause is not allowed.");
16957 }
16958 return Res;
16959}
16960
16962 ExprObjectKind OK,
16965 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
16966 if (!Res.isUsable())
16967 return ExprError();
16968 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
16969 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
16970 if (!Res.isUsable())
16971 return ExprError();
16972 }
16973 if (VK != VK_LValue && Res.get()->isGLValue()) {
16974 Res = SemaRef.DefaultLvalueConversion(Res.get());
16975 if (!Res.isUsable())
16976 return ExprError();
16977 }
16978 return Res;
16979}
16980
16982 SourceLocation StartLoc,
16983 SourceLocation LParenLoc,
16984 SourceLocation EndLoc) {
16986 SmallVector<Expr *, 8> PrivateCopies;
16987 bool IsImplicitClause =
16988 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
16989 for (Expr *RefExpr : VarList) {
16990 assert(RefExpr && "NULL expr in OpenMP private clause.");
16991 SourceLocation ELoc;
16992 SourceRange ERange;
16993 Expr *SimpleRefExpr = RefExpr;
16994 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
16995 if (Res.second) {
16996 // It will be analyzed later.
16997 Vars.push_back(RefExpr);
16998 PrivateCopies.push_back(nullptr);
16999 }
17000 ValueDecl *D = Res.first;
17001 if (!D)
17002 continue;
17003
17004 QualType Type = D->getType();
17005 auto *VD = dyn_cast<VarDecl>(D);
17006
17007 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17008 // A variable that appears in a private clause must not have an incomplete
17009 // type or a reference type.
17011 diag::err_omp_private_incomplete_type))
17012 continue;
17013 Type = Type.getNonReferenceType();
17014
17015 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17016 // A variable that is privatized must not have a const-qualified type
17017 // unless it is of class type with a mutable member. This restriction does
17018 // not apply to the firstprivate clause.
17019 //
17020 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17021 // A variable that appears in a private clause must not have a
17022 // const-qualified type unless it is of class type with a mutable member.
17023 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17024 continue;
17025
17026 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17027 // in a Construct]
17028 // Variables with the predetermined data-sharing attributes may not be
17029 // listed in data-sharing attributes clauses, except for the cases
17030 // listed below. For these exceptions only, listing a predetermined
17031 // variable in a data-sharing attribute clause is allowed and overrides
17032 // the variable's predetermined data-sharing attributes.
17033 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17034 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17035 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17036 << getOpenMPClauseName(OMPC_private);
17038 continue;
17039 }
17040
17041 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17042 // Variably modified types are not supported for tasks.
17044 isOpenMPTaskingDirective(CurrDir)) {
17045 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17046 << getOpenMPClauseName(OMPC_private) << Type
17047 << getOpenMPDirectiveName(CurrDir);
17048 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17050 Diag(D->getLocation(),
17051 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17052 << D;
17053 continue;
17054 }
17055
17056 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17057 // A list item cannot appear in both a map clause and a data-sharing
17058 // attribute clause on the same construct
17059 //
17060 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17061 // A list item cannot appear in both a map clause and a data-sharing
17062 // attribute clause on the same construct unless the construct is a
17063 // combined construct.
17064 if ((getLangOpts().OpenMP <= 45 &&
17066 CurrDir == OMPD_target) {
17067 OpenMPClauseKind ConflictKind;
17068 if (DSAStack->checkMappableExprComponentListsForDecl(
17069 VD, /*CurrentRegionOnly=*/true,
17071 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17072 ConflictKind = WhereFoundClauseKind;
17073 return true;
17074 })) {
17075 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17076 << getOpenMPClauseName(OMPC_private)
17077 << getOpenMPClauseName(ConflictKind)
17078 << getOpenMPDirectiveName(CurrDir);
17080 continue;
17081 }
17082 }
17083
17084 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17085 // A variable of class type (or array thereof) that appears in a private
17086 // clause requires an accessible, unambiguous default constructor for the
17087 // class type.
17088 // Generate helper private variable and initialize it with the default
17089 // value. The address of the original variable is replaced by the address of
17090 // the new private variable in CodeGen. This new variable is not added to
17091 // IdResolver, so the code in the OpenMP region uses original variable for
17092 // proper diagnostics.
17093 Type = Type.getUnqualifiedType();
17094 VarDecl *VDPrivate =
17095 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17096 D->hasAttrs() ? &D->getAttrs() : nullptr,
17097 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17099 if (VDPrivate->isInvalidDecl())
17100 continue;
17101 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17102 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17103
17104 DeclRefExpr *Ref = nullptr;
17105 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17106 auto *FD = dyn_cast<FieldDecl>(D);
17107 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17108 if (VD)
17110 RefExpr->getExprLoc());
17111 else
17112 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17113 }
17114 if (!IsImplicitClause)
17115 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17116 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17117 ? RefExpr->IgnoreParens()
17118 : Ref);
17119 PrivateCopies.push_back(VDPrivateRefExpr);
17120 }
17121
17122 if (Vars.empty())
17123 return nullptr;
17124
17125 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17126 Vars, PrivateCopies);
17127}
17128
17130 SourceLocation StartLoc,
17131 SourceLocation LParenLoc,
17132 SourceLocation EndLoc) {
17134 SmallVector<Expr *, 8> PrivateCopies;
17136 SmallVector<Decl *, 4> ExprCaptures;
17137 bool IsImplicitClause =
17138 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17139 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17140
17141 for (Expr *RefExpr : VarList) {
17142 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17143 SourceLocation ELoc;
17144 SourceRange ERange;
17145 Expr *SimpleRefExpr = RefExpr;
17146 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17147 if (Res.second) {
17148 // It will be analyzed later.
17149 Vars.push_back(RefExpr);
17150 PrivateCopies.push_back(nullptr);
17151 Inits.push_back(nullptr);
17152 }
17153 ValueDecl *D = Res.first;
17154 if (!D)
17155 continue;
17156
17157 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17158 QualType Type = D->getType();
17159 auto *VD = dyn_cast<VarDecl>(D);
17160
17161 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17162 // A variable that appears in a private clause must not have an incomplete
17163 // type or a reference type.
17165 diag::err_omp_firstprivate_incomplete_type))
17166 continue;
17167 Type = Type.getNonReferenceType();
17168
17169 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17170 // A variable of class type (or array thereof) that appears in a private
17171 // clause requires an accessible, unambiguous copy constructor for the
17172 // class type.
17173 QualType ElemType =
17175
17176 // If an implicit firstprivate variable found it was checked already.
17177 DSAStackTy::DSAVarData TopDVar;
17178 if (!IsImplicitClause) {
17179 DSAStackTy::DSAVarData DVar =
17180 DSAStack->getTopDSA(D, /*FromParent=*/false);
17181 TopDVar = DVar;
17182 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17183 bool IsConstant = ElemType.isConstant(getASTContext());
17184 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17185 // A list item that specifies a given variable may not appear in more
17186 // than one clause on the same directive, except that a variable may be
17187 // specified in both firstprivate and lastprivate clauses.
17188 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17189 // A list item may appear in a firstprivate or lastprivate clause but not
17190 // both.
17191 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17192 (isOpenMPDistributeDirective(CurrDir) ||
17193 DVar.CKind != OMPC_lastprivate) &&
17194 DVar.RefExpr) {
17195 Diag(ELoc, diag::err_omp_wrong_dsa)
17196 << getOpenMPClauseName(DVar.CKind)
17197 << getOpenMPClauseName(OMPC_firstprivate);
17199 continue;
17200 }
17201
17202 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17203 // in a Construct]
17204 // Variables with the predetermined data-sharing attributes may not be
17205 // listed in data-sharing attributes clauses, except for the cases
17206 // listed below. For these exceptions only, listing a predetermined
17207 // variable in a data-sharing attribute clause is allowed and overrides
17208 // the variable's predetermined data-sharing attributes.
17209 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17210 // in a Construct, C/C++, p.2]
17211 // Variables with const-qualified type having no mutable member may be
17212 // listed in a firstprivate clause, even if they are static data members.
17213 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17214 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17215 Diag(ELoc, diag::err_omp_wrong_dsa)
17216 << getOpenMPClauseName(DVar.CKind)
17217 << getOpenMPClauseName(OMPC_firstprivate);
17219 continue;
17220 }
17221
17222 // OpenMP [2.9.3.4, Restrictions, p.2]
17223 // A list item that is private within a parallel region must not appear
17224 // in a firstprivate clause on a worksharing construct if any of the
17225 // worksharing regions arising from the worksharing construct ever bind
17226 // to any of the parallel regions arising from the parallel construct.
17227 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17228 // A list item that is private within a teams region must not appear in a
17229 // firstprivate clause on a distribute construct if any of the distribute
17230 // regions arising from the distribute construct ever bind to any of the
17231 // teams regions arising from the teams construct.
17232 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17233 // A list item that appears in a reduction clause of a teams construct
17234 // must not appear in a firstprivate clause on a distribute construct if
17235 // any of the distribute regions arising from the distribute construct
17236 // ever bind to any of the teams regions arising from the teams construct.
17237 if ((isOpenMPWorksharingDirective(CurrDir) ||
17238 isOpenMPDistributeDirective(CurrDir)) &&
17239 !isOpenMPParallelDirective(CurrDir) &&
17240 !isOpenMPTeamsDirective(CurrDir)) {
17241 DVar = DSAStack->getImplicitDSA(D, true);
17242 if (DVar.CKind != OMPC_shared &&
17243 (isOpenMPParallelDirective(DVar.DKind) ||
17244 isOpenMPTeamsDirective(DVar.DKind) ||
17245 DVar.DKind == OMPD_unknown)) {
17246 Diag(ELoc, diag::err_omp_required_access)
17247 << getOpenMPClauseName(OMPC_firstprivate)
17248 << getOpenMPClauseName(OMPC_shared);
17250 continue;
17251 }
17252 }
17253 // OpenMP [2.9.3.4, Restrictions, p.3]
17254 // A list item that appears in a reduction clause of a parallel construct
17255 // must not appear in a firstprivate clause on a worksharing or task
17256 // construct if any of the worksharing or task regions arising from the
17257 // worksharing or task construct ever bind to any of the parallel regions
17258 // arising from the parallel construct.
17259 // OpenMP [2.9.3.4, Restrictions, p.4]
17260 // A list item that appears in a reduction clause in worksharing
17261 // construct must not appear in a firstprivate clause in a task construct
17262 // encountered during execution of any of the worksharing regions arising
17263 // from the worksharing construct.
17264 if (isOpenMPTaskingDirective(CurrDir)) {
17265 DVar = DSAStack->hasInnermostDSA(
17266 D,
17267 [](OpenMPClauseKind C, bool AppliedToPointee) {
17268 return C == OMPC_reduction && !AppliedToPointee;
17269 },
17270 [](OpenMPDirectiveKind K) {
17271 return isOpenMPParallelDirective(K) ||
17274 },
17275 /*FromParent=*/true);
17276 if (DVar.CKind == OMPC_reduction &&
17277 (isOpenMPParallelDirective(DVar.DKind) ||
17278 isOpenMPWorksharingDirective(DVar.DKind) ||
17279 isOpenMPTeamsDirective(DVar.DKind))) {
17280 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17281 << getOpenMPDirectiveName(DVar.DKind);
17283 continue;
17284 }
17285 }
17286
17287 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17288 // A list item cannot appear in both a map clause and a data-sharing
17289 // attribute clause on the same construct
17290 //
17291 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17292 // A list item cannot appear in both a map clause and a data-sharing
17293 // attribute clause on the same construct unless the construct is a
17294 // combined construct.
17295 if ((getLangOpts().OpenMP <= 45 &&
17297 CurrDir == OMPD_target) {
17298 OpenMPClauseKind ConflictKind;
17299 if (DSAStack->checkMappableExprComponentListsForDecl(
17300 VD, /*CurrentRegionOnly=*/true,
17301 [&ConflictKind](
17303 OpenMPClauseKind WhereFoundClauseKind) {
17304 ConflictKind = WhereFoundClauseKind;
17305 return true;
17306 })) {
17307 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17308 << getOpenMPClauseName(OMPC_firstprivate)
17309 << getOpenMPClauseName(ConflictKind)
17310 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17312 continue;
17313 }
17314 }
17315 }
17316
17317 // Variably modified types are not supported for tasks.
17319 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
17320 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17321 << getOpenMPClauseName(OMPC_firstprivate) << Type
17322 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17323 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17325 Diag(D->getLocation(),
17326 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17327 << D;
17328 continue;
17329 }
17330
17331 Type = Type.getUnqualifiedType();
17332 VarDecl *VDPrivate =
17333 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17334 D->hasAttrs() ? &D->getAttrs() : nullptr,
17335 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17336 // Generate helper private variable and initialize it with the value of the
17337 // original variable. The address of the original variable is replaced by
17338 // the address of the new private variable in the CodeGen. This new variable
17339 // is not added to IdResolver, so the code in the OpenMP region uses
17340 // original variable for proper diagnostics and variable capturing.
17341 Expr *VDInitRefExpr = nullptr;
17342 // For arrays generate initializer for single element and replace it by the
17343 // original array element in CodeGen.
17344 if (Type->isArrayType()) {
17345 VarDecl *VDInit =
17346 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
17347 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
17348 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
17349 ElemType = ElemType.getUnqualifiedType();
17350 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
17351 ElemType, ".firstprivate.temp");
17352 InitializedEntity Entity =
17355
17356 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
17357 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
17358 if (Result.isInvalid())
17359 VDPrivate->setInvalidDecl();
17360 else
17361 VDPrivate->setInit(Result.getAs<Expr>());
17362 // Remove temp variable declaration.
17363 getASTContext().Deallocate(VDInitTemp);
17364 } else {
17365 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
17366 ".firstprivate.temp");
17367 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
17368 RefExpr->getExprLoc());
17370 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
17371 /*DirectInit=*/false);
17372 }
17373 if (VDPrivate->isInvalidDecl()) {
17374 if (IsImplicitClause) {
17375 Diag(RefExpr->getExprLoc(),
17376 diag::note_omp_task_predetermined_firstprivate_here);
17377 }
17378 continue;
17379 }
17380 SemaRef.CurContext->addDecl(VDPrivate);
17381 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17382 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
17383 RefExpr->getExprLoc());
17384 DeclRefExpr *Ref = nullptr;
17385 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17386 if (TopDVar.CKind == OMPC_lastprivate) {
17387 Ref = TopDVar.PrivateCopy;
17388 } else {
17389 auto *FD = dyn_cast<FieldDecl>(D);
17390 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17391 if (VD)
17392 Ref =
17394 RefExpr->getExprLoc());
17395 else
17396 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17397 if (VD || !isOpenMPCapturedDecl(D))
17398 ExprCaptures.push_back(Ref->getDecl());
17399 }
17400 }
17401 if (!IsImplicitClause)
17402 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17403 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17404 ? RefExpr->IgnoreParens()
17405 : Ref);
17406 PrivateCopies.push_back(VDPrivateRefExpr);
17407 Inits.push_back(VDInitRefExpr);
17408 }
17409
17410 if (Vars.empty())
17411 return nullptr;
17412
17414 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17415 buildPreInits(getASTContext(), ExprCaptures));
17416}
17417
17420 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
17421 SourceLocation LParenLoc, SourceLocation EndLoc) {
17422 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
17423 assert(ColonLoc.isValid() && "Colon location must be valid.");
17424 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17425 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
17426 /*Last=*/OMPC_LASTPRIVATE_unknown)
17427 << getOpenMPClauseName(OMPC_lastprivate);
17428 return nullptr;
17429 }
17430
17432 SmallVector<Expr *, 8> SrcExprs;
17433 SmallVector<Expr *, 8> DstExprs;
17434 SmallVector<Expr *, 8> AssignmentOps;
17435 SmallVector<Decl *, 4> ExprCaptures;
17436 SmallVector<Expr *, 4> ExprPostUpdates;
17437 for (Expr *RefExpr : VarList) {
17438 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17439 SourceLocation ELoc;
17440 SourceRange ERange;
17441 Expr *SimpleRefExpr = RefExpr;
17442 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17443 if (Res.second) {
17444 // It will be analyzed later.
17445 Vars.push_back(RefExpr);
17446 SrcExprs.push_back(nullptr);
17447 DstExprs.push_back(nullptr);
17448 AssignmentOps.push_back(nullptr);
17449 }
17450 ValueDecl *D = Res.first;
17451 if (!D)
17452 continue;
17453
17454 QualType Type = D->getType();
17455 auto *VD = dyn_cast<VarDecl>(D);
17456
17457 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
17458 // A variable that appears in a lastprivate clause must not have an
17459 // incomplete type or a reference type.
17461 diag::err_omp_lastprivate_incomplete_type))
17462 continue;
17463 Type = Type.getNonReferenceType();
17464
17465 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17466 // A variable that is privatized must not have a const-qualified type
17467 // unless it is of class type with a mutable member. This restriction does
17468 // not apply to the firstprivate clause.
17469 //
17470 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
17471 // A variable that appears in a lastprivate clause must not have a
17472 // const-qualified type unless it is of class type with a mutable member.
17473 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
17474 continue;
17475
17476 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
17477 // A list item that appears in a lastprivate clause with the conditional
17478 // modifier must be a scalar variable.
17479 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
17480 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17481 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17483 Diag(D->getLocation(),
17484 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17485 << D;
17486 continue;
17487 }
17488
17489 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17490 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
17491 // in a Construct]
17492 // Variables with the predetermined data-sharing attributes may not be
17493 // listed in data-sharing attributes clauses, except for the cases
17494 // listed below.
17495 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17496 // A list item may appear in a firstprivate or lastprivate clause but not
17497 // both.
17498 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17499 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17500 (isOpenMPDistributeDirective(CurrDir) ||
17501 DVar.CKind != OMPC_firstprivate) &&
17502 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
17503 Diag(ELoc, diag::err_omp_wrong_dsa)
17504 << getOpenMPClauseName(DVar.CKind)
17505 << getOpenMPClauseName(OMPC_lastprivate);
17507 continue;
17508 }
17509
17510 // OpenMP [2.14.3.5, Restrictions, p.2]
17511 // A list item that is private within a parallel region, or that appears in
17512 // the reduction clause of a parallel construct, must not appear in a
17513 // lastprivate clause on a worksharing construct if any of the corresponding
17514 // worksharing regions ever binds to any of the corresponding parallel
17515 // regions.
17516 DSAStackTy::DSAVarData TopDVar = DVar;
17517 if (isOpenMPWorksharingDirective(CurrDir) &&
17518 !isOpenMPParallelDirective(CurrDir) &&
17519 !isOpenMPTeamsDirective(CurrDir)) {
17520 DVar = DSAStack->getImplicitDSA(D, true);
17521 if (DVar.CKind != OMPC_shared) {
17522 Diag(ELoc, diag::err_omp_required_access)
17523 << getOpenMPClauseName(OMPC_lastprivate)
17524 << getOpenMPClauseName(OMPC_shared);
17526 continue;
17527 }
17528 }
17529
17530 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
17531 // A variable of class type (or array thereof) that appears in a
17532 // lastprivate clause requires an accessible, unambiguous default
17533 // constructor for the class type, unless the list item is also specified
17534 // in a firstprivate clause.
17535 // A variable of class type (or array thereof) that appears in a
17536 // lastprivate clause requires an accessible, unambiguous copy assignment
17537 // operator for the class type.
17539 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
17540 Type.getUnqualifiedType(), ".lastprivate.src",
17541 D->hasAttrs() ? &D->getAttrs() : nullptr);
17542 DeclRefExpr *PseudoSrcExpr =
17543 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
17544 VarDecl *DstVD =
17545 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
17546 D->hasAttrs() ? &D->getAttrs() : nullptr);
17547 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
17548 // For arrays generate assignment operation for single element and replace
17549 // it by the original array element in CodeGen.
17550 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
17551 PseudoDstExpr, PseudoSrcExpr);
17552 if (AssignmentOp.isInvalid())
17553 continue;
17554 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
17555 /*DiscardedValue*/ false);
17556 if (AssignmentOp.isInvalid())
17557 continue;
17558
17559 DeclRefExpr *Ref = nullptr;
17560 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17561 if (TopDVar.CKind == OMPC_firstprivate) {
17562 Ref = TopDVar.PrivateCopy;
17563 } else {
17564 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17565 if (!isOpenMPCapturedDecl(D))
17566 ExprCaptures.push_back(Ref->getDecl());
17567 }
17568 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17570 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
17572 if (!RefRes.isUsable())
17573 continue;
17574 ExprResult PostUpdateRes =
17575 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
17576 SimpleRefExpr, RefRes.get());
17577 if (!PostUpdateRes.isUsable())
17578 continue;
17579 ExprPostUpdates.push_back(
17580 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
17581 }
17582 }
17583 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17584 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17585 ? RefExpr->IgnoreParens()
17586 : Ref);
17587 SrcExprs.push_back(PseudoSrcExpr);
17588 DstExprs.push_back(PseudoDstExpr);
17589 AssignmentOps.push_back(AssignmentOp.get());
17590 }
17591
17592 if (Vars.empty())
17593 return nullptr;
17594
17596 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17597 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17598 buildPreInits(getASTContext(), ExprCaptures),
17599 buildPostUpdate(SemaRef, ExprPostUpdates));
17600}
17601
17603 SourceLocation StartLoc,
17604 SourceLocation LParenLoc,
17605 SourceLocation EndLoc) {
17607 for (Expr *RefExpr : VarList) {
17608 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17609 SourceLocation ELoc;
17610 SourceRange ERange;
17611 Expr *SimpleRefExpr = RefExpr;
17612 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17613 if (Res.second) {
17614 // It will be analyzed later.
17615 Vars.push_back(RefExpr);
17616 }
17617 ValueDecl *D = Res.first;
17618 if (!D)
17619 continue;
17620
17621 auto *VD = dyn_cast<VarDecl>(D);
17622 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17623 // in a Construct]
17624 // Variables with the predetermined data-sharing attributes may not be
17625 // listed in data-sharing attributes clauses, except for the cases
17626 // listed below. For these exceptions only, listing a predetermined
17627 // variable in a data-sharing attribute clause is allowed and overrides
17628 // the variable's predetermined data-sharing attributes.
17629 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17630 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17631 DVar.RefExpr) {
17632 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17633 << getOpenMPClauseName(OMPC_shared);
17635 continue;
17636 }
17637
17638 DeclRefExpr *Ref = nullptr;
17639 if (!VD && isOpenMPCapturedDecl(D) &&
17641 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17642 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17643 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
17644 ? RefExpr->IgnoreParens()
17645 : Ref);
17646 }
17647
17648 if (Vars.empty())
17649 return nullptr;
17650
17651 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17652 Vars);
17653}
17654
17655namespace {
17656class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
17657 DSAStackTy *Stack;
17658
17659public:
17660 bool VisitDeclRefExpr(DeclRefExpr *E) {
17661 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
17662 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
17663 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17664 return false;
17665 if (DVar.CKind != OMPC_unknown)
17666 return true;
17667 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17668 VD,
17669 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
17670 return isOpenMPPrivate(C) && !AppliedToPointee;
17671 },
17672 [](OpenMPDirectiveKind) { return true; },
17673 /*FromParent=*/true);
17674 return DVarPrivate.CKind != OMPC_unknown;
17675 }
17676 return false;
17677 }
17678 bool VisitStmt(Stmt *S) {
17679 for (Stmt *Child : S->children()) {
17680 if (Child && Visit(Child))
17681 return true;
17682 }
17683 return false;
17684 }
17685 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17686};
17687} // namespace
17688
17689namespace {
17690// Transform MemberExpression for specified FieldDecl of current class to
17691// DeclRefExpr to specified OMPCapturedExprDecl.
17692class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
17693 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
17694 ValueDecl *Field = nullptr;
17695 DeclRefExpr *CapturedExpr = nullptr;
17696
17697public:
17698 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
17699 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
17700
17701 ExprResult TransformMemberExpr(MemberExpr *E) {
17702 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
17703 E->getMemberDecl() == Field) {
17704 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
17705 return CapturedExpr;
17706 }
17707 return BaseTransform::TransformMemberExpr(E);
17708 }
17709 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
17710};
17711} // namespace
17712
17713template <typename T, typename U>
17715 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
17716 for (U &Set : Lookups) {
17717 for (auto *D : Set) {
17718 if (T Res = Gen(cast<ValueDecl>(D)))
17719 return Res;
17720 }
17721 }
17722 return T();
17723}
17724
17726 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
17727
17728 for (auto *RD : D->redecls()) {
17729 // Don't bother with extra checks if we already know this one isn't visible.
17730 if (RD == D)
17731 continue;
17732
17733 auto ND = cast<NamedDecl>(RD);
17734 if (LookupResult::isVisible(SemaRef, ND))
17735 return ND;
17736 }
17737
17738 return nullptr;
17739}
17740
17741static void
17745 // Find all of the associated namespaces and classes based on the
17746 // arguments we have.
17747 Sema::AssociatedNamespaceSet AssociatedNamespaces;
17748 Sema::AssociatedClassSet AssociatedClasses;
17749 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
17750 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
17751 AssociatedClasses);
17752
17753 // C++ [basic.lookup.argdep]p3:
17754 // Let X be the lookup set produced by unqualified lookup (3.4.1)
17755 // and let Y be the lookup set produced by argument dependent
17756 // lookup (defined as follows). If X contains [...] then Y is
17757 // empty. Otherwise Y is the set of declarations found in the
17758 // namespaces associated with the argument types as described
17759 // below. The set of declarations found by the lookup of the name
17760 // is the union of X and Y.
17761 //
17762 // Here, we compute Y and add its members to the overloaded
17763 // candidate set.
17764 for (auto *NS : AssociatedNamespaces) {
17765 // When considering an associated namespace, the lookup is the
17766 // same as the lookup performed when the associated namespace is
17767 // used as a qualifier (3.4.3.2) except that:
17768 //
17769 // -- Any using-directives in the associated namespace are
17770 // ignored.
17771 //
17772 // -- Any namespace-scope friend functions declared in
17773 // associated classes are visible within their respective
17774 // namespaces even if they are not visible during an ordinary
17775 // lookup (11.4).
17776 DeclContext::lookup_result R = NS->lookup(Id.getName());
17777 for (auto *D : R) {
17778 auto *Underlying = D;
17779 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
17780 Underlying = USD->getTargetDecl();
17781
17782 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
17783 !isa<OMPDeclareMapperDecl>(Underlying))
17784 continue;
17785
17786 if (!SemaRef.isVisible(D)) {
17787 D = findAcceptableDecl(SemaRef, D);
17788 if (!D)
17789 continue;
17790 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
17791 Underlying = USD->getTargetDecl();
17792 }
17793 Lookups.emplace_back();
17794 Lookups.back().addDecl(Underlying);
17795 }
17796 }
17797}
17798
17799static ExprResult
17801 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
17802 const DeclarationNameInfo &ReductionId, QualType Ty,
17803 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
17804 if (ReductionIdScopeSpec.isInvalid())
17805 return ExprError();
17806 SmallVector<UnresolvedSet<8>, 4> Lookups;
17807 if (S) {
17808 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
17809 Lookup.suppressDiagnostics();
17810 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
17811 /*ObjectType=*/QualType())) {
17812 NamedDecl *D = Lookup.getRepresentativeDecl();
17813 do {
17814 S = S->getParent();
17815 } while (S && !S->isDeclScope(D));
17816 if (S)
17817 S = S->getParent();
17818 Lookups.emplace_back();
17819 Lookups.back().append(Lookup.begin(), Lookup.end());
17820 Lookup.clear();
17821 }
17822 } else if (auto *ULE =
17823 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
17824 Lookups.push_back(UnresolvedSet<8>());
17825 Decl *PrevD = nullptr;
17826 for (NamedDecl *D : ULE->decls()) {
17827 if (D == PrevD)
17828 Lookups.push_back(UnresolvedSet<8>());
17829 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
17830 Lookups.back().addDecl(DRD);
17831 PrevD = D;
17832 }
17833 }
17834 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
17837 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
17838 return !D->isInvalidDecl() &&
17839 (D->getType()->isDependentType() ||
17840 D->getType()->isInstantiationDependentType() ||
17841 D->getType()->containsUnexpandedParameterPack());
17842 })) {
17843 UnresolvedSet<8> ResSet;
17844 for (const UnresolvedSet<8> &Set : Lookups) {
17845 if (Set.empty())
17846 continue;
17847 ResSet.append(Set.begin(), Set.end());
17848 // The last item marks the end of all declarations at the specified scope.
17849 ResSet.addDecl(Set[Set.size() - 1]);
17850 }
17852 SemaRef.Context, /*NamingClass=*/nullptr,
17853 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
17854 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false);
17855 }
17856 // Lookup inside the classes.
17857 // C++ [over.match.oper]p3:
17858 // For a unary operator @ with an operand of a type whose
17859 // cv-unqualified version is T1, and for a binary operator @ with
17860 // a left operand of a type whose cv-unqualified version is T1 and
17861 // a right operand of a type whose cv-unqualified version is T2,
17862 // three sets of candidate functions, designated member
17863 // candidates, non-member candidates and built-in candidates, are
17864 // constructed as follows:
17865 // -- If T1 is a complete class type or a class currently being
17866 // defined, the set of member candidates is the result of the
17867 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
17868 // the set of member candidates is empty.
17869 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
17870 Lookup.suppressDiagnostics();
17871 if (const auto *TyRec = Ty->getAs<RecordType>()) {
17872 // Complete the type if it can be completed.
17873 // If the type is neither complete nor being defined, bail out now.
17874 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
17875 TyRec->getDecl()->getDefinition()) {
17876 Lookup.clear();
17877 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
17878 if (Lookup.empty()) {
17879 Lookups.emplace_back();
17880 Lookups.back().append(Lookup.begin(), Lookup.end());
17881 }
17882 }
17883 }
17884 // Perform ADL.
17885 if (SemaRef.getLangOpts().CPlusPlus)
17886 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
17887 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
17888 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
17889 if (!D->isInvalidDecl() &&
17890 SemaRef.Context.hasSameType(D->getType(), Ty))
17891 return D;
17892 return nullptr;
17893 }))
17894 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
17895 VK_LValue, Loc);
17896 if (SemaRef.getLangOpts().CPlusPlus) {
17897 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
17898 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
17899 if (!D->isInvalidDecl() &&
17900 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
17901 !Ty.isMoreQualifiedThan(D->getType()))
17902 return D;
17903 return nullptr;
17904 })) {
17905 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
17906 /*DetectVirtual=*/false);
17907 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
17908 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
17909 VD->getType().getUnqualifiedType()))) {
17910 if (SemaRef.CheckBaseClassAccess(
17911 Loc, VD->getType(), Ty, Paths.front(),
17912 /*DiagID=*/0) != Sema::AR_inaccessible) {
17913 SemaRef.BuildBasePathArray(Paths, BasePath);
17914 return SemaRef.BuildDeclRefExpr(
17916 }
17917 }
17918 }
17919 }
17920 }
17921 if (ReductionIdScopeSpec.isSet()) {
17922 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
17923 << Ty << Range;
17924 return ExprError();
17925 }
17926 return ExprEmpty();
17927}
17928
17929namespace {
17930/// Data for the reduction-based clauses.
17931struct ReductionData {
17932 /// List of original reduction items.
17934 /// List of private copies of the reduction items.
17935 SmallVector<Expr *, 8> Privates;
17936 /// LHS expressions for the reduction_op expressions.
17938 /// RHS expressions for the reduction_op expressions.
17940 /// Reduction operation expression.
17941 SmallVector<Expr *, 8> ReductionOps;
17942 /// inscan copy operation expressions.
17943 SmallVector<Expr *, 8> InscanCopyOps;
17944 /// inscan copy temp array expressions for prefix sums.
17945 SmallVector<Expr *, 8> InscanCopyArrayTemps;
17946 /// inscan copy temp array element expressions for prefix sums.
17947 SmallVector<Expr *, 8> InscanCopyArrayElems;
17948 /// Taskgroup descriptors for the corresponding reduction items in
17949 /// in_reduction clauses.
17950 SmallVector<Expr *, 8> TaskgroupDescriptors;
17951 /// List of captures for clause.
17952 SmallVector<Decl *, 4> ExprCaptures;
17953 /// List of postupdate expressions.
17954 SmallVector<Expr *, 4> ExprPostUpdates;
17955 /// Reduction modifier.
17956 unsigned RedModifier = 0;
17957 ReductionData() = delete;
17958 /// Reserves required memory for the reduction data.
17959 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
17960 Vars.reserve(Size);
17961 Privates.reserve(Size);
17962 LHSs.reserve(Size);
17963 RHSs.reserve(Size);
17964 ReductionOps.reserve(Size);
17965 if (RedModifier == OMPC_REDUCTION_inscan) {
17966 InscanCopyOps.reserve(Size);
17967 InscanCopyArrayTemps.reserve(Size);
17968 InscanCopyArrayElems.reserve(Size);
17969 }
17970 TaskgroupDescriptors.reserve(Size);
17971 ExprCaptures.reserve(Size);
17972 ExprPostUpdates.reserve(Size);
17973 }
17974 /// Stores reduction item and reduction operation only (required for dependent
17975 /// reduction item).
17976 void push(Expr *Item, Expr *ReductionOp) {
17977 Vars.emplace_back(Item);
17978 Privates.emplace_back(nullptr);
17979 LHSs.emplace_back(nullptr);
17980 RHSs.emplace_back(nullptr);
17981 ReductionOps.emplace_back(ReductionOp);
17982 TaskgroupDescriptors.emplace_back(nullptr);
17983 if (RedModifier == OMPC_REDUCTION_inscan) {
17984 InscanCopyOps.push_back(nullptr);
17985 InscanCopyArrayTemps.push_back(nullptr);
17986 InscanCopyArrayElems.push_back(nullptr);
17987 }
17988 }
17989 /// Stores reduction data.
17990 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
17991 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
17992 Expr *CopyArrayElem) {
17993 Vars.emplace_back(Item);
17994 Privates.emplace_back(Private);
17995 LHSs.emplace_back(LHS);
17996 RHSs.emplace_back(RHS);
17997 ReductionOps.emplace_back(ReductionOp);
17998 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
17999 if (RedModifier == OMPC_REDUCTION_inscan) {
18000 InscanCopyOps.push_back(CopyOp);
18001 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18002 InscanCopyArrayElems.push_back(CopyArrayElem);
18003 } else {
18004 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18005 CopyArrayElem == nullptr &&
18006 "Copy operation must be used for inscan reductions only.");
18007 }
18008 }
18009};
18010} // namespace
18011
18013 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18014 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18015 const Expr *Length = OASE->getLength();
18016 if (Length == nullptr) {
18017 // For array sections of the form [1:] or [:], we would need to analyze
18018 // the lower bound...
18019 if (OASE->getColonLocFirst().isValid())
18020 return false;
18021
18022 // This is an array subscript which has implicit length 1!
18023 SingleElement = true;
18024 ArraySizes.push_back(llvm::APSInt::get(1));
18025 } else {
18027 if (!Length->EvaluateAsInt(Result, Context))
18028 return false;
18029
18030 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18031 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18032 ArraySizes.push_back(ConstantLengthValue);
18033 }
18034
18035 // Get the base of this array section and walk up from there.
18036 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18037
18038 // We require length = 1 for all array sections except the right-most to
18039 // guarantee that the memory region is contiguous and has no holes in it.
18040 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18041 Length = TempOASE->getLength();
18042 if (Length == nullptr) {
18043 // For array sections of the form [1:] or [:], we would need to analyze
18044 // the lower bound...
18045 if (OASE->getColonLocFirst().isValid())
18046 return false;
18047
18048 // This is an array subscript which has implicit length 1!
18049 ArraySizes.push_back(llvm::APSInt::get(1));
18050 } else {
18052 if (!Length->EvaluateAsInt(Result, Context))
18053 return false;
18054
18055 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18056 if (ConstantLengthValue.getSExtValue() != 1)
18057 return false;
18058
18059 ArraySizes.push_back(ConstantLengthValue);
18060 }
18061 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18062 }
18063
18064 // If we have a single element, we don't need to add the implicit lengths.
18065 if (!SingleElement) {
18066 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18067 // Has implicit length 1!
18068 ArraySizes.push_back(llvm::APSInt::get(1));
18069 Base = TempASE->getBase()->IgnoreParenImpCasts();
18070 }
18071 }
18072
18073 // This array section can be privatized as a single value or as a constant
18074 // sized array.
18075 return true;
18076}
18077
18078static BinaryOperatorKind
18080 if (BOK == BO_Add)
18081 return BO_AddAssign;
18082 if (BOK == BO_Mul)
18083 return BO_MulAssign;
18084 if (BOK == BO_And)
18085 return BO_AndAssign;
18086 if (BOK == BO_Or)
18087 return BO_OrAssign;
18088 if (BOK == BO_Xor)
18089 return BO_XorAssign;
18090 return BOK;
18091}
18092
18094 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18095 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18096 SourceLocation ColonLoc, SourceLocation EndLoc,
18097 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18098 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18099 DeclarationName DN = ReductionId.getName();
18101 BinaryOperatorKind BOK = BO_Comma;
18102
18103 ASTContext &Context = S.Context;
18104 // OpenMP [2.14.3.6, reduction clause]
18105 // C
18106 // reduction-identifier is either an identifier or one of the following
18107 // operators: +, -, *, &, |, ^, && and ||
18108 // C++
18109 // reduction-identifier is either an id-expression or one of the following
18110 // operators: +, -, *, &, |, ^, && and ||
18111 switch (OOK) {
18112 case OO_Plus:
18113 BOK = BO_Add;
18114 break;
18115 case OO_Minus:
18116 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18117 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18118 // reduction identifier.
18119 if (S.LangOpts.OpenMP > 52)
18120 BOK = BO_Comma;
18121 else
18122 BOK = BO_Add;
18123 break;
18124 case OO_Star:
18125 BOK = BO_Mul;
18126 break;
18127 case OO_Amp:
18128 BOK = BO_And;
18129 break;
18130 case OO_Pipe:
18131 BOK = BO_Or;
18132 break;
18133 case OO_Caret:
18134 BOK = BO_Xor;
18135 break;
18136 case OO_AmpAmp:
18137 BOK = BO_LAnd;
18138 break;
18139 case OO_PipePipe:
18140 BOK = BO_LOr;
18141 break;
18142 case OO_New:
18143 case OO_Delete:
18144 case OO_Array_New:
18145 case OO_Array_Delete:
18146 case OO_Slash:
18147 case OO_Percent:
18148 case OO_Tilde:
18149 case OO_Exclaim:
18150 case OO_Equal:
18151 case OO_Less:
18152 case OO_Greater:
18153 case OO_LessEqual:
18154 case OO_GreaterEqual:
18155 case OO_PlusEqual:
18156 case OO_MinusEqual:
18157 case OO_StarEqual:
18158 case OO_SlashEqual:
18159 case OO_PercentEqual:
18160 case OO_CaretEqual:
18161 case OO_AmpEqual:
18162 case OO_PipeEqual:
18163 case OO_LessLess:
18164 case OO_GreaterGreater:
18165 case OO_LessLessEqual:
18166 case OO_GreaterGreaterEqual:
18167 case OO_EqualEqual:
18168 case OO_ExclaimEqual:
18169 case OO_Spaceship:
18170 case OO_PlusPlus:
18171 case OO_MinusMinus:
18172 case OO_Comma:
18173 case OO_ArrowStar:
18174 case OO_Arrow:
18175 case OO_Call:
18176 case OO_Subscript:
18177 case OO_Conditional:
18178 case OO_Coawait:
18180 llvm_unreachable("Unexpected reduction identifier");
18181 case OO_None:
18182 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18183 if (II->isStr("max"))
18184 BOK = BO_GT;
18185 else if (II->isStr("min"))
18186 BOK = BO_LT;
18187 }
18188 break;
18189 }
18190
18191 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18192 // A reduction clause with the minus (-) operator was deprecated
18193 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18194 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18195
18196 SourceRange ReductionIdRange;
18197 if (ReductionIdScopeSpec.isValid())
18198 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18199 else
18200 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18201 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18202
18203 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18204 bool FirstIter = true;
18205 for (Expr *RefExpr : VarList) {
18206 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18207 // OpenMP [2.1, C/C++]
18208 // A list item is a variable or array section, subject to the restrictions
18209 // specified in Section 2.4 on page 42 and in each of the sections
18210 // describing clauses and directives for which a list appears.
18211 // OpenMP [2.14.3.3, Restrictions, p.1]
18212 // A variable that is part of another variable (as an array or
18213 // structure element) cannot appear in a private clause.
18214 if (!FirstIter && IR != ER)
18215 ++IR;
18216 FirstIter = false;
18217 SourceLocation ELoc;
18218 SourceRange ERange;
18219 Expr *SimpleRefExpr = RefExpr;
18220 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18221 /*AllowArraySection=*/true);
18222 if (Res.second) {
18223 // Try to find 'declare reduction' corresponding construct before using
18224 // builtin/overloaded operators.
18225 QualType Type = Context.DependentTy;
18226 CXXCastPath BasePath;
18227 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18228 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18229 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18230 Expr *ReductionOp = nullptr;
18231 if (S.CurContext->isDependentContext() &&
18232 (DeclareReductionRef.isUnset() ||
18233 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18234 ReductionOp = DeclareReductionRef.get();
18235 // It will be analyzed later.
18236 RD.push(RefExpr, ReductionOp);
18237 }
18238 ValueDecl *D = Res.first;
18239 if (!D)
18240 continue;
18241
18242 Expr *TaskgroupDescriptor = nullptr;
18243 QualType Type;
18244 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18245 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18246 if (ASE) {
18247 Type = ASE->getType().getNonReferenceType();
18248 } else if (OASE) {
18249 QualType BaseType =
18251 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18252 Type = ATy->getElementType();
18253 else
18254 Type = BaseType->getPointeeType();
18255 Type = Type.getNonReferenceType();
18256 } else {
18257 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
18258 }
18259 auto *VD = dyn_cast<VarDecl>(D);
18260
18261 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18262 // A variable that appears in a private clause must not have an incomplete
18263 // type or a reference type.
18264 if (S.RequireCompleteType(ELoc, D->getType(),
18265 diag::err_omp_reduction_incomplete_type))
18266 continue;
18267 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18268 // A list item that appears in a reduction clause must not be
18269 // const-qualified.
18270 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18271 /*AcceptIfMutable*/ false, ASE || OASE))
18272 continue;
18273
18274 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18275 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18276 // If a list-item is a reference type then it must bind to the same object
18277 // for all threads of the team.
18278 if (!ASE && !OASE) {
18279 if (VD) {
18280 VarDecl *VDDef = VD->getDefinition();
18281 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18282 DSARefChecker Check(Stack);
18283 if (Check.Visit(VDDef->getInit())) {
18284 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18285 << getOpenMPClauseName(ClauseKind) << ERange;
18286 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18287 continue;
18288 }
18289 }
18290 }
18291
18292 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18293 // in a Construct]
18294 // Variables with the predetermined data-sharing attributes may not be
18295 // listed in data-sharing attributes clauses, except for the cases
18296 // listed below. For these exceptions only, listing a predetermined
18297 // variable in a data-sharing attribute clause is allowed and overrides
18298 // the variable's predetermined data-sharing attributes.
18299 // OpenMP [2.14.3.6, Restrictions, p.3]
18300 // Any number of reduction clauses can be specified on the directive,
18301 // but a list item can appear only once in the reduction clauses for that
18302 // directive.
18303 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18304 if (DVar.CKind == OMPC_reduction) {
18305 S.Diag(ELoc, diag::err_omp_once_referenced)
18306 << getOpenMPClauseName(ClauseKind);
18307 if (DVar.RefExpr)
18308 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18309 continue;
18310 }
18311 if (DVar.CKind != OMPC_unknown) {
18312 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18313 << getOpenMPClauseName(DVar.CKind)
18314 << getOpenMPClauseName(OMPC_reduction);
18315 reportOriginalDsa(S, Stack, D, DVar);
18316 continue;
18317 }
18318
18319 // OpenMP [2.14.3.6, Restrictions, p.1]
18320 // A list item that appears in a reduction clause of a worksharing
18321 // construct must be shared in the parallel regions to which any of the
18322 // worksharing regions arising from the worksharing construct bind.
18323 if (isOpenMPWorksharingDirective(CurrDir) &&
18324 !isOpenMPParallelDirective(CurrDir) &&
18325 !isOpenMPTeamsDirective(CurrDir)) {
18326 DVar = Stack->getImplicitDSA(D, true);
18327 if (DVar.CKind != OMPC_shared) {
18328 S.Diag(ELoc, diag::err_omp_required_access)
18329 << getOpenMPClauseName(OMPC_reduction)
18330 << getOpenMPClauseName(OMPC_shared);
18331 reportOriginalDsa(S, Stack, D, DVar);
18332 continue;
18333 }
18334 }
18335 } else {
18336 // Threadprivates cannot be shared between threads, so dignose if the base
18337 // is a threadprivate variable.
18338 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18339 if (DVar.CKind == OMPC_threadprivate) {
18340 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18341 << getOpenMPClauseName(DVar.CKind)
18342 << getOpenMPClauseName(OMPC_reduction);
18343 reportOriginalDsa(S, Stack, D, DVar);
18344 continue;
18345 }
18346 }
18347
18348 // Try to find 'declare reduction' corresponding construct before using
18349 // builtin/overloaded operators.
18350 CXXCastPath BasePath;
18351 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18352 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18353 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18354 if (DeclareReductionRef.isInvalid())
18355 continue;
18356 if (S.CurContext->isDependentContext() &&
18357 (DeclareReductionRef.isUnset() ||
18358 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
18359 RD.push(RefExpr, DeclareReductionRef.get());
18360 continue;
18361 }
18362 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
18363 // Not allowed reduction identifier is found.
18364 if (S.LangOpts.OpenMP > 52)
18365 S.Diag(ReductionId.getBeginLoc(),
18366 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18367 << Type << ReductionIdRange;
18368 else
18369 S.Diag(ReductionId.getBeginLoc(),
18370 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18371 << Type << ReductionIdRange;
18372 continue;
18373 }
18374
18375 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18376 // The type of a list item that appears in a reduction clause must be valid
18377 // for the reduction-identifier. For a max or min reduction in C, the type
18378 // of the list item must be an allowed arithmetic data type: char, int,
18379 // float, double, or _Bool, possibly modified with long, short, signed, or
18380 // unsigned. For a max or min reduction in C++, the type of the list item
18381 // must be an allowed arithmetic data type: char, wchar_t, int, float,
18382 // double, or bool, possibly modified with long, short, signed, or unsigned.
18383 if (DeclareReductionRef.isUnset()) {
18384 if ((BOK == BO_GT || BOK == BO_LT) &&
18385 !(Type->isScalarType() ||
18386 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
18387 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18388 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
18389 if (!ASE && !OASE) {
18390 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18392 S.Diag(D->getLocation(),
18393 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18394 << D;
18395 }
18396 continue;
18397 }
18398 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18399 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
18400 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18401 << getOpenMPClauseName(ClauseKind);
18402 if (!ASE && !OASE) {
18403 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18405 S.Diag(D->getLocation(),
18406 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18407 << D;
18408 }
18409 continue;
18410 }
18411 }
18412
18413 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
18414 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
18415 D->hasAttrs() ? &D->getAttrs() : nullptr);
18416 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
18417 D->hasAttrs() ? &D->getAttrs() : nullptr);
18418 QualType PrivateTy = Type;
18419
18420 // Try if we can determine constant lengths for all array sections and avoid
18421 // the VLA.
18422 bool ConstantLengthOASE = false;
18423 if (OASE) {
18424 bool SingleElement;
18426 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
18427 Context, OASE, SingleElement, ArraySizes);
18428
18429 // If we don't have a single element, we must emit a constant array type.
18430 if (ConstantLengthOASE && !SingleElement) {
18431 for (llvm::APSInt &Size : ArraySizes)
18432 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
18434 /*IndexTypeQuals=*/0);
18435 }
18436 }
18437
18438 if ((OASE && !ConstantLengthOASE) ||
18439 (!OASE && !ASE &&
18440 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18441 if (!Context.getTargetInfo().isVLASupported()) {
18442 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
18443 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18444 S.Diag(ELoc, diag::note_vla_unsupported);
18445 continue;
18446 } else {
18447 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18448 S.targetDiag(ELoc, diag::note_vla_unsupported);
18449 }
18450 }
18451 // For arrays/array sections only:
18452 // Create pseudo array type for private copy. The size for this array will
18453 // be generated during codegen.
18454 // For array subscripts or single variables Private Ty is the same as Type
18455 // (type of the variable or single array element).
18456 PrivateTy = Context.getVariableArrayType(
18457 Type,
18458 new (Context)
18459 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
18460 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
18461 } else if (!ASE && !OASE &&
18462 Context.getAsArrayType(D->getType().getNonReferenceType())) {
18463 PrivateTy = D->getType().getNonReferenceType();
18464 }
18465 // Private copy.
18466 VarDecl *PrivateVD =
18467 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18468 D->hasAttrs() ? &D->getAttrs() : nullptr,
18469 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18470 // Add initializer for private variable.
18471 Expr *Init = nullptr;
18472 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
18473 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
18474 if (DeclareReductionRef.isUsable()) {
18475 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
18476 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18477 if (DRD->getInitializer()) {
18478 Init = DRDRef;
18479 RHSVD->setInit(DRDRef);
18481 }
18482 } else {
18483 switch (BOK) {
18484 case BO_Add:
18485 case BO_Xor:
18486 case BO_Or:
18487 case BO_LOr:
18488 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
18490 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
18491 break;
18492 case BO_Mul:
18493 case BO_LAnd:
18494 if (Type->isScalarType() || Type->isAnyComplexType()) {
18495 // '*' and '&&' reduction ops - initializer is '1'.
18496 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
18497 }
18498 break;
18499 case BO_And: {
18500 // '&' reduction op - initializer is '~0'.
18501 QualType OrigType = Type;
18502 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
18503 Type = ComplexTy->getElementType();
18504 if (Type->isRealFloatingType()) {
18505 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18506 Context.getFloatTypeSemantics(Type));
18507 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18508 Type, ELoc);
18509 } else if (Type->isScalarType()) {
18510 uint64_t Size = Context.getTypeSize(Type);
18511 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
18512 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18513 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18514 }
18515 if (Init && OrigType->isAnyComplexType()) {
18516 // Init = 0xFFFF + 0xFFFFi;
18517 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
18518 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
18519 }
18520 Type = OrigType;
18521 break;
18522 }
18523 case BO_LT:
18524 case BO_GT: {
18525 // 'min' reduction op - initializer is 'Largest representable number in
18526 // the reduction list item type'.
18527 // 'max' reduction op - initializer is 'Least representable number in
18528 // the reduction list item type'.
18529 if (Type->isIntegerType() || Type->isPointerType()) {
18530 bool IsSigned = Type->hasSignedIntegerRepresentation();
18531 uint64_t Size = Context.getTypeSize(Type);
18532 QualType IntTy =
18533 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
18534 llvm::APInt InitValue =
18535 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18536 : llvm::APInt::getMinValue(Size)
18537 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18538 : llvm::APInt::getMaxValue(Size);
18539 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18540 if (Type->isPointerType()) {
18541 // Cast to pointer type.
18543 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
18544 if (CastExpr.isInvalid())
18545 continue;
18546 Init = CastExpr.get();
18547 }
18548 } else if (Type->isRealFloatingType()) {
18549 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18550 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
18551 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18552 Type, ELoc);
18553 }
18554 break;
18555 }
18556 case BO_PtrMemD:
18557 case BO_PtrMemI:
18558 case BO_MulAssign:
18559 case BO_Div:
18560 case BO_Rem:
18561 case BO_Sub:
18562 case BO_Shl:
18563 case BO_Shr:
18564 case BO_LE:
18565 case BO_GE:
18566 case BO_EQ:
18567 case BO_NE:
18568 case BO_Cmp:
18569 case BO_AndAssign:
18570 case BO_XorAssign:
18571 case BO_OrAssign:
18572 case BO_Assign:
18573 case BO_AddAssign:
18574 case BO_SubAssign:
18575 case BO_DivAssign:
18576 case BO_RemAssign:
18577 case BO_ShlAssign:
18578 case BO_ShrAssign:
18579 case BO_Comma:
18580 llvm_unreachable("Unexpected reduction operation");
18581 }
18582 }
18583 if (Init && DeclareReductionRef.isUnset()) {
18584 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
18585 // Store initializer for single element in private copy. Will be used
18586 // during codegen.
18587 PrivateVD->setInit(RHSVD->getInit());
18588 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18589 } else if (!Init) {
18590 S.ActOnUninitializedDecl(RHSVD);
18591 // Store initializer for single element in private copy. Will be used
18592 // during codegen.
18593 PrivateVD->setInit(RHSVD->getInit());
18594 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18595 }
18596 if (RHSVD->isInvalidDecl())
18597 continue;
18598 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
18599 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18600 << Type << ReductionIdRange;
18601 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18603 S.Diag(D->getLocation(),
18604 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18605 << D;
18606 continue;
18607 }
18608 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
18609 ExprResult ReductionOp;
18610 if (DeclareReductionRef.isUsable()) {
18611 QualType RedTy = DeclareReductionRef.get()->getType();
18612 QualType PtrRedTy = Context.getPointerType(RedTy);
18613 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
18614 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
18615 if (!BasePath.empty()) {
18616 LHS = S.DefaultLvalueConversion(LHS.get());
18617 RHS = S.DefaultLvalueConversion(RHS.get());
18619 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
18620 LHS.get()->getValueKind(), FPOptionsOverride());
18622 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
18623 RHS.get()->getValueKind(), FPOptionsOverride());
18624 }
18626 QualType Params[] = {PtrRedTy, PtrRedTy};
18627 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
18628 auto *OVE = new (Context) OpaqueValueExpr(
18629 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
18630 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
18631 Expr *Args[] = {LHS.get(), RHS.get()};
18632 ReductionOp =
18633 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
18635 } else {
18637 if (Type->isRecordType() && CombBOK != BOK) {
18639 ReductionOp =
18640 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18641 CombBOK, LHSDRE, RHSDRE);
18642 }
18643 if (!ReductionOp.isUsable()) {
18644 ReductionOp =
18645 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
18646 LHSDRE, RHSDRE);
18647 if (ReductionOp.isUsable()) {
18648 if (BOK != BO_LT && BOK != BO_GT) {
18649 ReductionOp =
18650 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18651 BO_Assign, LHSDRE, ReductionOp.get());
18652 } else {
18653 auto *ConditionalOp = new (Context)
18654 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
18655 RHSDRE, Type, VK_LValue, OK_Ordinary);
18656 ReductionOp =
18657 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18658 BO_Assign, LHSDRE, ConditionalOp);
18659 }
18660 }
18661 }
18662 if (ReductionOp.isUsable())
18663 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
18664 /*DiscardedValue*/ false);
18665 if (!ReductionOp.isUsable())
18666 continue;
18667 }
18668
18669 // Add copy operations for inscan reductions.
18670 // LHS = RHS;
18671 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18672 if (ClauseKind == OMPC_reduction &&
18673 RD.RedModifier == OMPC_REDUCTION_inscan) {
18674 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
18675 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18676 RHS.get());
18677 if (!CopyOpRes.isUsable())
18678 continue;
18679 CopyOpRes =
18680 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
18681 if (!CopyOpRes.isUsable())
18682 continue;
18683 // For simd directive and simd-based directives in simd mode no need to
18684 // construct temp array, need just a single temp element.
18685 if (Stack->getCurrentDirective() == OMPD_simd ||
18686 (S.getLangOpts().OpenMPSimd &&
18687 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
18688 VarDecl *TempArrayVD =
18689 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18690 D->hasAttrs() ? &D->getAttrs() : nullptr);
18691 // Add a constructor to the temp decl.
18692 S.ActOnUninitializedDecl(TempArrayVD);
18693 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
18694 } else {
18695 // Build temp array for prefix sum.
18696 auto *Dim = new (S.Context)
18699 PrivateTy, Dim, ArraySizeModifier::Normal,
18700 /*IndexTypeQuals=*/0, {ELoc, ELoc});
18701 VarDecl *TempArrayVD =
18702 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
18703 D->hasAttrs() ? &D->getAttrs() : nullptr);
18704 // Add a constructor to the temp decl.
18705 S.ActOnUninitializedDecl(TempArrayVD);
18706 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
18707 TempArrayElem =
18708 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
18709 auto *Idx = new (S.Context)
18711 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
18712 ELoc, Idx, ELoc);
18713 }
18714 }
18715
18716 // OpenMP [2.15.4.6, Restrictions, p.2]
18717 // A list item that appears in an in_reduction clause of a task construct
18718 // must appear in a task_reduction clause of a construct associated with a
18719 // taskgroup region that includes the participating task in its taskgroup
18720 // set. The construct associated with the innermost region that meets this
18721 // condition must specify the same reduction-identifier as the in_reduction
18722 // clause.
18723 if (ClauseKind == OMPC_in_reduction) {
18724 SourceRange ParentSR;
18725 BinaryOperatorKind ParentBOK;
18726 const Expr *ParentReductionOp = nullptr;
18727 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
18728 DSAStackTy::DSAVarData ParentBOKDSA =
18729 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
18730 ParentBOKTD);
18731 DSAStackTy::DSAVarData ParentReductionOpDSA =
18732 Stack->getTopMostTaskgroupReductionData(
18733 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
18734 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
18735 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
18736 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
18737 (DeclareReductionRef.isUsable() && IsParentBOK) ||
18738 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
18739 bool EmitError = true;
18740 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
18741 llvm::FoldingSetNodeID RedId, ParentRedId;
18742 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
18743 DeclareReductionRef.get()->Profile(RedId, Context,
18744 /*Canonical=*/true);
18745 EmitError = RedId != ParentRedId;
18746 }
18747 if (EmitError) {
18748 S.Diag(ReductionId.getBeginLoc(),
18749 diag::err_omp_reduction_identifier_mismatch)
18750 << ReductionIdRange << RefExpr->getSourceRange();
18751 S.Diag(ParentSR.getBegin(),
18752 diag::note_omp_previous_reduction_identifier)
18753 << ParentSR
18754 << (IsParentBOK ? ParentBOKDSA.RefExpr
18755 : ParentReductionOpDSA.RefExpr)
18756 ->getSourceRange();
18757 continue;
18758 }
18759 }
18760 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
18761 }
18762
18763 DeclRefExpr *Ref = nullptr;
18764 Expr *VarsExpr = RefExpr->IgnoreParens();
18765 if (!VD && !S.CurContext->isDependentContext()) {
18766 if (ASE || OASE) {
18767 TransformExprToCaptures RebuildToCapture(S, D);
18768 VarsExpr =
18769 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
18770 Ref = RebuildToCapture.getCapturedExpr();
18771 } else {
18772 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
18773 }
18774 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
18775 RD.ExprCaptures.emplace_back(Ref->getDecl());
18776 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
18777 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
18778 if (!RefRes.isUsable())
18779 continue;
18780 ExprResult PostUpdateRes =
18781 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18782 RefRes.get());
18783 if (!PostUpdateRes.isUsable())
18784 continue;
18785 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
18786 Stack->getCurrentDirective() == OMPD_taskgroup) {
18787 S.Diag(RefExpr->getExprLoc(),
18788 diag::err_omp_reduction_non_addressable_expression)
18789 << RefExpr->getSourceRange();
18790 continue;
18791 }
18792 RD.ExprPostUpdates.emplace_back(
18793 S.IgnoredValueConversions(PostUpdateRes.get()).get());
18794 }
18795 }
18796 }
18797 // All reduction items are still marked as reduction (to do not increase
18798 // code base size).
18799 unsigned Modifier = RD.RedModifier;
18800 // Consider task_reductions as reductions with task modifier. Required for
18801 // correct analysis of in_reduction clauses.
18802 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
18803 Modifier = OMPC_REDUCTION_task;
18804 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
18805 ASE || OASE);
18806 if (Modifier == OMPC_REDUCTION_task &&
18807 (CurrDir == OMPD_taskgroup ||
18808 ((isOpenMPParallelDirective(CurrDir) ||
18809 isOpenMPWorksharingDirective(CurrDir)) &&
18810 !isOpenMPSimdDirective(CurrDir)))) {
18811 if (DeclareReductionRef.isUsable())
18812 Stack->addTaskgroupReductionData(D, ReductionIdRange,
18813 DeclareReductionRef.get());
18814 else
18815 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
18816 }
18817 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
18818 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
18819 TempArrayElem.get());
18820 }
18821 return RD.Vars.empty();
18822}
18823
18826 SourceLocation StartLoc, SourceLocation LParenLoc,
18827 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
18828 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18829 ArrayRef<Expr *> UnresolvedReductions) {
18830 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
18831 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
18832 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
18833 /*Last=*/OMPC_REDUCTION_unknown)
18834 << getOpenMPClauseName(OMPC_reduction);
18835 return nullptr;
18836 }
18837 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
18838 // A reduction clause with the inscan reduction-modifier may only appear on a
18839 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
18840 // construct, a parallel worksharing-loop construct or a parallel
18841 // worksharing-loop SIMD construct.
18842 if (Modifier == OMPC_REDUCTION_inscan &&
18843 (DSAStack->getCurrentDirective() != OMPD_for &&
18844 DSAStack->getCurrentDirective() != OMPD_for_simd &&
18845 DSAStack->getCurrentDirective() != OMPD_simd &&
18846 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
18847 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
18848 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
18849 return nullptr;
18850 }
18851
18852 ReductionData RD(VarList.size(), Modifier);
18853 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
18854 StartLoc, LParenLoc, ColonLoc, EndLoc,
18855 ReductionIdScopeSpec, ReductionId,
18856 UnresolvedReductions, RD))
18857 return nullptr;
18858
18860 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
18861 Modifier, RD.Vars,
18862 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
18863 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
18864 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
18865 buildPreInits(getASTContext(), RD.ExprCaptures),
18866 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
18867}
18868
18870 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18871 SourceLocation ColonLoc, SourceLocation EndLoc,
18872 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18873 ArrayRef<Expr *> UnresolvedReductions) {
18874 ReductionData RD(VarList.size());
18875 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
18876 VarList, StartLoc, LParenLoc, ColonLoc,
18877 EndLoc, ReductionIdScopeSpec, ReductionId,
18878 UnresolvedReductions, RD))
18879 return nullptr;
18880
18882 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
18883 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
18884 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
18885 buildPreInits(getASTContext(), RD.ExprCaptures),
18886 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
18887}
18888
18890 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18891 SourceLocation ColonLoc, SourceLocation EndLoc,
18892 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18893 ArrayRef<Expr *> UnresolvedReductions) {
18894 ReductionData RD(VarList.size());
18895 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
18896 StartLoc, LParenLoc, ColonLoc, EndLoc,
18897 ReductionIdScopeSpec, ReductionId,
18898 UnresolvedReductions, RD))
18899 return nullptr;
18900
18902 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
18903 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
18904 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
18905 buildPreInits(getASTContext(), RD.ExprCaptures),
18906 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
18907}
18908
18910 SourceLocation LinLoc) {
18911 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
18912 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
18913 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
18914 << getLangOpts().CPlusPlus;
18915 return true;
18916 }
18917 return false;
18918}
18919
18921 OpenMPLinearClauseKind LinKind,
18922 QualType Type, bool IsDeclareSimd) {
18923 const auto *VD = dyn_cast_or_null<VarDecl>(D);
18924 // A variable must not have an incomplete type or a reference type.
18926 diag::err_omp_linear_incomplete_type))
18927 return true;
18928 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
18929 !Type->isReferenceType()) {
18930 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
18931 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
18932 return true;
18933 }
18934 Type = Type.getNonReferenceType();
18935
18936 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
18937 // A variable that is privatized must not have a const-qualified type
18938 // unless it is of class type with a mutable member. This restriction does
18939 // not apply to the firstprivate clause, nor to the linear clause on
18940 // declarative directives (like declare simd).
18941 if (!IsDeclareSimd &&
18942 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
18943 return true;
18944
18945 // A list item must be of integral or pointer type.
18946 Type = Type.getUnqualifiedType().getCanonicalType();
18947 const auto *Ty = Type.getTypePtrOrNull();
18948 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
18949 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
18950 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
18951 if (D) {
18952 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
18954 Diag(D->getLocation(),
18955 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18956 << D;
18957 }
18958 return true;
18959 }
18960 return false;
18961}
18962
18964 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
18965 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
18966 SourceLocation LinLoc, SourceLocation ColonLoc,
18967 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
18969 SmallVector<Expr *, 8> Privates;
18971 SmallVector<Decl *, 4> ExprCaptures;
18972 SmallVector<Expr *, 4> ExprPostUpdates;
18973 // OpenMP 5.2 [Section 5.4.6, linear clause]
18974 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
18975 // 'ref'
18976 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
18977 getLangOpts().OpenMP >= 52)
18978 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
18979 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
18980 LinKind = OMPC_LINEAR_val;
18981 for (Expr *RefExpr : VarList) {
18982 assert(RefExpr && "NULL expr in OpenMP linear clause.");
18983 SourceLocation ELoc;
18984 SourceRange ERange;
18985 Expr *SimpleRefExpr = RefExpr;
18986 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
18987 if (Res.second) {
18988 // It will be analyzed later.
18989 Vars.push_back(RefExpr);
18990 Privates.push_back(nullptr);
18991 Inits.push_back(nullptr);
18992 }
18993 ValueDecl *D = Res.first;
18994 if (!D)
18995 continue;
18996
18997 QualType Type = D->getType();
18998 auto *VD = dyn_cast<VarDecl>(D);
18999
19000 // OpenMP [2.14.3.7, linear clause]
19001 // A list-item cannot appear in more than one linear clause.
19002 // A list-item that appears in a linear clause cannot appear in any
19003 // other data-sharing attribute clause.
19004 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19005 if (DVar.RefExpr) {
19006 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19007 << getOpenMPClauseName(OMPC_linear);
19009 continue;
19010 }
19011
19012 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19013 continue;
19014 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19015
19016 // Build private copy of original var.
19017 VarDecl *Private =
19018 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19019 D->hasAttrs() ? &D->getAttrs() : nullptr,
19020 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19021 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19022 // Build var to save initial value.
19023 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19024 Expr *InitExpr;
19025 DeclRefExpr *Ref = nullptr;
19026 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19027 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19028 if (!isOpenMPCapturedDecl(D)) {
19029 ExprCaptures.push_back(Ref->getDecl());
19030 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19032 if (!RefRes.isUsable())
19033 continue;
19034 ExprResult PostUpdateRes =
19035 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19036 SimpleRefExpr, RefRes.get());
19037 if (!PostUpdateRes.isUsable())
19038 continue;
19039 ExprPostUpdates.push_back(
19040 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19041 }
19042 }
19043 }
19044 if (LinKind == OMPC_LINEAR_uval)
19045 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19046 else
19047 InitExpr = VD ? SimpleRefExpr : Ref;
19050 /*DirectInit=*/false);
19051 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19052
19053 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19054 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19055 ? RefExpr->IgnoreParens()
19056 : Ref);
19057 Privates.push_back(PrivateRef);
19058 Inits.push_back(InitRef);
19059 }
19060
19061 if (Vars.empty())
19062 return nullptr;
19063
19064 Expr *StepExpr = Step;
19065 Expr *CalcStepExpr = nullptr;
19066 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19067 !Step->isInstantiationDependent() &&
19069 SourceLocation StepLoc = Step->getBeginLoc();
19071 if (Val.isInvalid())
19072 return nullptr;
19073 StepExpr = Val.get();
19074
19075 // Build var to save the step value.
19076 VarDecl *SaveVar =
19077 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19078 ExprResult SaveRef =
19079 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19080 ExprResult CalcStep = SemaRef.BuildBinOp(
19081 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19082 CalcStep =
19083 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false);
19084
19085 // Warn about zero linear step (it would be probably better specified as
19086 // making corresponding variables 'const').
19087 if (std::optional<llvm::APSInt> Result =
19089 if (!Result->isNegative() && !Result->isStrictlyPositive())
19090 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19091 << Vars[0] << (Vars.size() > 1);
19092 } else if (CalcStep.isUsable()) {
19093 // Calculate the step beforehand instead of doing this on each iteration.
19094 // (This is not used if the number of iterations may be kfold-ed).
19095 CalcStepExpr = CalcStep.get();
19096 }
19097 }
19098
19099 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19100 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19101 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19102 buildPreInits(getASTContext(), ExprCaptures),
19103 buildPostUpdate(SemaRef, ExprPostUpdates));
19104}
19105
19107 Expr *NumIterations, Sema &SemaRef,
19108 Scope *S, DSAStackTy *Stack) {
19109 // Walk the vars and build update/final expressions for the CodeGen.
19110 SmallVector<Expr *, 8> Updates;
19112 SmallVector<Expr *, 8> UsedExprs;
19113 Expr *Step = Clause.getStep();
19114 Expr *CalcStep = Clause.getCalcStep();
19115 // OpenMP [2.14.3.7, linear clause]
19116 // If linear-step is not specified it is assumed to be 1.
19117 if (!Step)
19118 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19119 else if (CalcStep)
19120 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19121 bool HasErrors = false;
19122 auto CurInit = Clause.inits().begin();
19123 auto CurPrivate = Clause.privates().begin();
19124 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19125 for (Expr *RefExpr : Clause.varlists()) {
19126 SourceLocation ELoc;
19127 SourceRange ERange;
19128 Expr *SimpleRefExpr = RefExpr;
19129 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19130 ValueDecl *D = Res.first;
19131 if (Res.second || !D) {
19132 Updates.push_back(nullptr);
19133 Finals.push_back(nullptr);
19134 HasErrors = true;
19135 continue;
19136 }
19137 auto &&Info = Stack->isLoopControlVariable(D);
19138 // OpenMP [2.15.11, distribute simd Construct]
19139 // A list item may not appear in a linear clause, unless it is the loop
19140 // iteration variable.
19141 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19142 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19143 SemaRef.Diag(ELoc,
19144 diag::err_omp_linear_distribute_var_non_loop_iteration);
19145 Updates.push_back(nullptr);
19146 Finals.push_back(nullptr);
19147 HasErrors = true;
19148 continue;
19149 }
19150 Expr *InitExpr = *CurInit;
19151
19152 // Build privatized reference to the current linear var.
19153 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19154 Expr *CapturedRef;
19155 if (LinKind == OMPC_LINEAR_uval)
19156 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19157 else
19158 CapturedRef =
19159 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19160 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19161 /*RefersToCapture=*/true);
19162
19163 // Build update: Var = InitExpr + IV * Step
19165 if (!Info.first)
19167 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19168 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19169 else
19170 Update = *CurPrivate;
19171 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19172 /*DiscardedValue*/ false);
19173
19174 // Build final: Var = PrivCopy;
19175 ExprResult Final;
19176 if (!Info.first)
19177 Final = SemaRef.BuildBinOp(
19178 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19179 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19180 else
19181 Final = *CurPrivate;
19182 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19183 /*DiscardedValue*/ false);
19184
19185 if (!Update.isUsable() || !Final.isUsable()) {
19186 Updates.push_back(nullptr);
19187 Finals.push_back(nullptr);
19188 UsedExprs.push_back(nullptr);
19189 HasErrors = true;
19190 } else {
19191 Updates.push_back(Update.get());
19192 Finals.push_back(Final.get());
19193 if (!Info.first)
19194 UsedExprs.push_back(SimpleRefExpr);
19195 }
19196 ++CurInit;
19197 ++CurPrivate;
19198 }
19199 if (Expr *S = Clause.getStep())
19200 UsedExprs.push_back(S);
19201 // Fill the remaining part with the nullptr.
19202 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19203 Clause.setUpdates(Updates);
19204 Clause.setFinals(Finals);
19205 Clause.setUsedExprs(UsedExprs);
19206 return HasErrors;
19207}
19208
19210 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19211 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19213 for (Expr *RefExpr : VarList) {
19214 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19215 SourceLocation ELoc;
19216 SourceRange ERange;
19217 Expr *SimpleRefExpr = RefExpr;
19218 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19219 if (Res.second) {
19220 // It will be analyzed later.
19221 Vars.push_back(RefExpr);
19222 }
19223 ValueDecl *D = Res.first;
19224 if (!D)
19225 continue;
19226
19227 QualType QType = D->getType();
19228 auto *VD = dyn_cast<VarDecl>(D);
19229
19230 // OpenMP [2.8.1, simd construct, Restrictions]
19231 // The type of list items appearing in the aligned clause must be
19232 // array, pointer, reference to array, or reference to pointer.
19234 const Type *Ty = QType.getTypePtrOrNull();
19235 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19236 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19237 << QType << getLangOpts().CPlusPlus << ERange;
19238 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19240 Diag(D->getLocation(),
19241 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19242 << D;
19243 continue;
19244 }
19245
19246 // OpenMP [2.8.1, simd construct, Restrictions]
19247 // A list-item cannot appear in more than one aligned clause.
19248 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19249 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19250 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19251 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19252 << getOpenMPClauseName(OMPC_aligned);
19253 continue;
19254 }
19255
19256 DeclRefExpr *Ref = nullptr;
19257 if (!VD && isOpenMPCapturedDecl(D))
19258 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19259 Vars.push_back(SemaRef
19260 .DefaultFunctionArrayConversion(
19261 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19262 .get());
19263 }
19264
19265 // OpenMP [2.8.1, simd construct, Description]
19266 // The parameter of the aligned clause, alignment, must be a constant
19267 // positive integer expression.
19268 // If no optional parameter is specified, implementation-defined default
19269 // alignments for SIMD instructions on the target platforms are assumed.
19270 if (Alignment != nullptr) {
19271 ExprResult AlignResult =
19272 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19273 if (AlignResult.isInvalid())
19274 return nullptr;
19275 Alignment = AlignResult.get();
19276 }
19277 if (Vars.empty())
19278 return nullptr;
19279
19280 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
19281 ColonLoc, EndLoc, Vars, Alignment);
19282}
19283
19285 SourceLocation StartLoc,
19286 SourceLocation LParenLoc,
19287 SourceLocation EndLoc) {
19289 SmallVector<Expr *, 8> SrcExprs;
19290 SmallVector<Expr *, 8> DstExprs;
19291 SmallVector<Expr *, 8> AssignmentOps;
19292 for (Expr *RefExpr : VarList) {
19293 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19294 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19295 // It will be analyzed later.
19296 Vars.push_back(RefExpr);
19297 SrcExprs.push_back(nullptr);
19298 DstExprs.push_back(nullptr);
19299 AssignmentOps.push_back(nullptr);
19300 continue;
19301 }
19302
19303 SourceLocation ELoc = RefExpr->getExprLoc();
19304 // OpenMP [2.1, C/C++]
19305 // A list item is a variable name.
19306 // OpenMP [2.14.4.1, Restrictions, p.1]
19307 // A list item that appears in a copyin clause must be threadprivate.
19308 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19309 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19310 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19311 << 0 << RefExpr->getSourceRange();
19312 continue;
19313 }
19314
19315 Decl *D = DE->getDecl();
19316 auto *VD = cast<VarDecl>(D);
19317
19318 QualType Type = VD->getType();
19320 // It will be analyzed later.
19321 Vars.push_back(DE);
19322 SrcExprs.push_back(nullptr);
19323 DstExprs.push_back(nullptr);
19324 AssignmentOps.push_back(nullptr);
19325 continue;
19326 }
19327
19328 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19329 // A list item that appears in a copyin clause must be threadprivate.
19330 if (!DSAStack->isThreadPrivate(VD)) {
19331 Diag(ELoc, diag::err_omp_required_access)
19332 << getOpenMPClauseName(OMPC_copyin)
19333 << getOpenMPDirectiveName(OMPD_threadprivate);
19334 continue;
19335 }
19336
19337 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19338 // A variable of class type (or array thereof) that appears in a
19339 // copyin clause requires an accessible, unambiguous copy assignment
19340 // operator for the class type.
19341 QualType ElemType =
19343 VarDecl *SrcVD =
19344 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
19345 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19346 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
19347 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
19348 VarDecl *DstVD =
19349 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
19350 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19351 DeclRefExpr *PseudoDstExpr =
19352 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
19353 // For arrays generate assignment operation for single element and replace
19354 // it by the original array element in CodeGen.
19355 ExprResult AssignmentOp =
19356 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
19357 PseudoDstExpr, PseudoSrcExpr);
19358 if (AssignmentOp.isInvalid())
19359 continue;
19360 AssignmentOp =
19361 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
19362 /*DiscardedValue*/ false);
19363 if (AssignmentOp.isInvalid())
19364 continue;
19365
19366 DSAStack->addDSA(VD, DE, OMPC_copyin);
19367 Vars.push_back(DE);
19368 SrcExprs.push_back(PseudoSrcExpr);
19369 DstExprs.push_back(PseudoDstExpr);
19370 AssignmentOps.push_back(AssignmentOp.get());
19371 }
19372
19373 if (Vars.empty())
19374 return nullptr;
19375
19376 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19377 Vars, SrcExprs, DstExprs, AssignmentOps);
19378}
19379
19381 SourceLocation StartLoc,
19382 SourceLocation LParenLoc,
19383 SourceLocation EndLoc) {
19385 SmallVector<Expr *, 8> SrcExprs;
19386 SmallVector<Expr *, 8> DstExprs;
19387 SmallVector<Expr *, 8> AssignmentOps;
19388 for (Expr *RefExpr : VarList) {
19389 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19390 SourceLocation ELoc;
19391 SourceRange ERange;
19392 Expr *SimpleRefExpr = RefExpr;
19393 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19394 if (Res.second) {
19395 // It will be analyzed later.
19396 Vars.push_back(RefExpr);
19397 SrcExprs.push_back(nullptr);
19398 DstExprs.push_back(nullptr);
19399 AssignmentOps.push_back(nullptr);
19400 }
19401 ValueDecl *D = Res.first;
19402 if (!D)
19403 continue;
19404
19405 QualType Type = D->getType();
19406 auto *VD = dyn_cast<VarDecl>(D);
19407
19408 // OpenMP [2.14.4.2, Restrictions, p.2]
19409 // A list item that appears in a copyprivate clause may not appear in a
19410 // private or firstprivate clause on the single construct.
19411 if (!VD || !DSAStack->isThreadPrivate(VD)) {
19412 DSAStackTy::DSAVarData DVar =
19413 DSAStack->getTopDSA(D, /*FromParent=*/false);
19414 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19415 DVar.RefExpr) {
19416 Diag(ELoc, diag::err_omp_wrong_dsa)
19417 << getOpenMPClauseName(DVar.CKind)
19418 << getOpenMPClauseName(OMPC_copyprivate);
19420 continue;
19421 }
19422
19423 // OpenMP [2.11.4.2, Restrictions, p.1]
19424 // All list items that appear in a copyprivate clause must be either
19425 // threadprivate or private in the enclosing context.
19426 if (DVar.CKind == OMPC_unknown) {
19427 DVar = DSAStack->getImplicitDSA(D, false);
19428 if (DVar.CKind == OMPC_shared) {
19429 Diag(ELoc, diag::err_omp_required_access)
19430 << getOpenMPClauseName(OMPC_copyprivate)
19431 << "threadprivate or private in the enclosing context";
19433 continue;
19434 }
19435 }
19436 }
19437
19438 // Variably modified types are not supported.
19440 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19441 << getOpenMPClauseName(OMPC_copyprivate) << Type
19442 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
19443 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19445 Diag(D->getLocation(),
19446 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19447 << D;
19448 continue;
19449 }
19450
19451 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19452 // A variable of class type (or array thereof) that appears in a
19453 // copyin clause requires an accessible, unambiguous copy assignment
19454 // operator for the class type.
19456 .getBaseElementType(Type.getNonReferenceType())
19458 VarDecl *SrcVD =
19459 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
19460 D->hasAttrs() ? &D->getAttrs() : nullptr);
19461 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
19462 VarDecl *DstVD =
19463 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
19464 D->hasAttrs() ? &D->getAttrs() : nullptr);
19465 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19466 ExprResult AssignmentOp = SemaRef.BuildBinOp(
19467 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19468 if (AssignmentOp.isInvalid())
19469 continue;
19470 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19471 /*DiscardedValue*/ false);
19472 if (AssignmentOp.isInvalid())
19473 continue;
19474
19475 // No need to mark vars as copyprivate, they are already threadprivate or
19476 // implicitly private.
19477 assert(VD || isOpenMPCapturedDecl(D));
19478 Vars.push_back(
19479 VD ? RefExpr->IgnoreParens()
19480 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
19481 SrcExprs.push_back(PseudoSrcExpr);
19482 DstExprs.push_back(PseudoDstExpr);
19483 AssignmentOps.push_back(AssignmentOp.get());
19484 }
19485
19486 if (Vars.empty())
19487 return nullptr;
19488
19489 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
19490 EndLoc, Vars, SrcExprs, DstExprs,
19491 AssignmentOps);
19492}
19493
19495 SourceLocation StartLoc,
19496 SourceLocation LParenLoc,
19497 SourceLocation EndLoc) {
19498 if (VarList.empty())
19499 return nullptr;
19500
19501 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19502 VarList);
19503}
19504
19505/// Tries to find omp_depend_t. type.
19506static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
19507 bool Diagnose = true) {
19508 QualType OMPDependT = Stack->getOMPDependT();
19509 if (!OMPDependT.isNull())
19510 return true;
19511 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
19512 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
19513 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
19514 if (Diagnose)
19515 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
19516 return false;
19517 }
19518 Stack->setOMPDependT(PT.get());
19519 return true;
19520}
19521
19523 SourceLocation StartLoc,
19524 SourceLocation LParenLoc,
19525 SourceLocation EndLoc) {
19526 if (!Depobj)
19527 return nullptr;
19528
19529 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
19530
19531 // OpenMP 5.0, 2.17.10.1 depobj Construct
19532 // depobj is an lvalue expression of type omp_depend_t.
19533 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
19534 !Depobj->isInstantiationDependent() &&
19536 (OMPDependTFound && !getASTContext().typesAreCompatible(
19537 DSAStack->getOMPDependT(), Depobj->getType(),
19538 /*CompareUnqualified=*/true))) {
19539 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19540 << 0 << Depobj->getType() << Depobj->getSourceRange();
19541 }
19542
19543 if (!Depobj->isLValue()) {
19544 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19545 << 1 << Depobj->getSourceRange();
19546 }
19547
19548 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19549 Depobj);
19550}
19551
19552namespace {
19553// Utility struct that gathers the related info for doacross clause.
19554struct DoacrossDataInfoTy {
19555 // The list of expressions.
19557 // The OperatorOffset for doacross loop.
19559 // The depended loop count.
19560 llvm::APSInt TotalDepCount;
19561};
19562} // namespace
19563static DoacrossDataInfoTy
19565 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
19566 SourceLocation EndLoc) {
19567
19570 llvm::APSInt DepCounter(/*BitWidth=*/32);
19571 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19572
19573 if (const Expr *OrderedCountExpr =
19574 Stack->getParentOrderedRegionParam().first) {
19575 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
19576 TotalDepCount.setIsUnsigned(/*Val=*/true);
19577 }
19578
19579 for (Expr *RefExpr : VarList) {
19580 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
19581 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19582 // It will be analyzed later.
19583 Vars.push_back(RefExpr);
19584 continue;
19585 }
19586
19587 SourceLocation ELoc = RefExpr->getExprLoc();
19588 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19589 if (!IsSource) {
19590 if (Stack->getParentOrderedRegionParam().first &&
19591 DepCounter >= TotalDepCount) {
19592 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19593 continue;
19594 }
19595 ++DepCounter;
19596 // OpenMP [2.13.9, Summary]
19597 // depend(dependence-type : vec), where dependence-type is:
19598 // 'sink' and where vec is the iteration vector, which has the form:
19599 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
19600 // where n is the value specified by the ordered clause in the loop
19601 // directive, xi denotes the loop iteration variable of the i-th nested
19602 // loop associated with the loop directive, and di is a constant
19603 // non-negative integer.
19604 if (SemaRef.CurContext->isDependentContext()) {
19605 // It will be analyzed later.
19606 Vars.push_back(RefExpr);
19607 continue;
19608 }
19609 SimpleExpr = SimpleExpr->IgnoreImplicit();
19611 SourceLocation OOLoc;
19612 Expr *LHS = SimpleExpr;
19613 Expr *RHS = nullptr;
19614 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19615 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
19616 OOLoc = BO->getOperatorLoc();
19617 LHS = BO->getLHS()->IgnoreParenImpCasts();
19618 RHS = BO->getRHS()->IgnoreParenImpCasts();
19619 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19620 OOK = OCE->getOperator();
19621 OOLoc = OCE->getOperatorLoc();
19622 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19623 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
19624 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19625 OOK = MCE->getMethodDecl()
19626 ->getNameInfo()
19627 .getName()
19628 .getCXXOverloadedOperator();
19629 OOLoc = MCE->getCallee()->getExprLoc();
19630 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
19631 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19632 }
19633 SourceLocation ELoc;
19634 SourceRange ERange;
19635 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
19636 if (Res.second) {
19637 // It will be analyzed later.
19638 Vars.push_back(RefExpr);
19639 }
19640 ValueDecl *D = Res.first;
19641 if (!D)
19642 continue;
19643
19644 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
19645 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19646 continue;
19647 }
19648 if (RHS) {
19649 ExprResult RHSRes =
19651 RHS, OMPC_depend, /*StrictlyPositive=*/false);
19652 if (RHSRes.isInvalid())
19653 continue;
19654 }
19655 if (!SemaRef.CurContext->isDependentContext() &&
19656 Stack->getParentOrderedRegionParam().first &&
19657 DepCounter != Stack->isParentLoopControlVariable(D).first) {
19658 const ValueDecl *VD =
19659 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19660 if (VD)
19661 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19662 << 1 << VD;
19663 else
19664 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19665 << 0;
19666 continue;
19667 }
19668 OpsOffs.emplace_back(RHS, OOK);
19669 }
19670 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19671 }
19672 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
19673 TotalDepCount > VarList.size() &&
19674 Stack->getParentOrderedRegionParam().first &&
19675 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19676 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19677 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19678 }
19679 return {Vars, OpsOffs, TotalDepCount};
19680}
19681
19683 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
19684 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19685 SourceLocation EndLoc) {
19686 OpenMPDependClauseKind DepKind = Data.DepKind;
19687 SourceLocation DepLoc = Data.DepLoc;
19688 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
19689 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19690 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19691 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19692 return nullptr;
19693 }
19694 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
19695 DepKind == OMPC_DEPEND_mutexinoutset) {
19696 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19697 return nullptr;
19698 }
19699 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
19700 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19701 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
19702 DepKind == OMPC_DEPEND_sink ||
19703 ((getLangOpts().OpenMP < 50 ||
19704 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19705 DepKind == OMPC_DEPEND_depobj))) {
19706 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
19707 OMPC_DEPEND_outallmemory,
19708 OMPC_DEPEND_inoutallmemory};
19709 if (getLangOpts().OpenMP < 50 ||
19710 DSAStack->getCurrentDirective() == OMPD_depobj)
19711 Except.push_back(OMPC_DEPEND_depobj);
19712 if (getLangOpts().OpenMP < 51)
19713 Except.push_back(OMPC_DEPEND_inoutset);
19714 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
19715 ? "depend modifier(iterator) or "
19716 : "";
19717 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19718 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
19719 /*Last=*/OMPC_DEPEND_unknown,
19720 Except)
19721 << getOpenMPClauseName(OMPC_depend);
19722 return nullptr;
19723 }
19724 if (DepModifier &&
19725 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
19726 Diag(DepModifier->getExprLoc(),
19727 diag::err_omp_depend_sink_source_with_modifier);
19728 return nullptr;
19729 }
19730 if (DepModifier &&
19731 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
19732 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
19733
19736 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19737
19738 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
19739 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
19740 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
19741 Vars = VarOffset.Vars;
19742 OpsOffs = VarOffset.OpsOffs;
19743 TotalDepCount = VarOffset.TotalDepCount;
19744 } else {
19745 for (Expr *RefExpr : VarList) {
19746 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19747 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19748 // It will be analyzed later.
19749 Vars.push_back(RefExpr);
19750 continue;
19751 }
19752
19753 SourceLocation ELoc = RefExpr->getExprLoc();
19754 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19755 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
19756 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
19757 if (OMPDependTFound)
19758 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
19759 DepKind == OMPC_DEPEND_depobj);
19760 if (DepKind == OMPC_DEPEND_depobj) {
19761 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
19762 // List items used in depend clauses with the depobj dependence type
19763 // must be expressions of the omp_depend_t type.
19764 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19765 !RefExpr->isInstantiationDependent() &&
19766 !RefExpr->containsUnexpandedParameterPack() &&
19767 (OMPDependTFound &&
19768 !getASTContext().hasSameUnqualifiedType(
19769 DSAStack->getOMPDependT(), RefExpr->getType()))) {
19770 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19771 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
19772 continue;
19773 }
19774 if (!RefExpr->isLValue()) {
19775 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19776 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
19777 continue;
19778 }
19779 } else {
19780 // OpenMP 5.0 [2.17.11, Restrictions]
19781 // List items used in depend clauses cannot be zero-length array
19782 // sections.
19783 QualType ExprTy = RefExpr->getType().getNonReferenceType();
19784 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
19785 if (OASE) {
19786 QualType BaseType =
19788 if (BaseType.isNull())
19789 return nullptr;
19790 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19791 ExprTy = ATy->getElementType();
19792 else
19793 ExprTy = BaseType->getPointeeType();
19794 if (BaseType.isNull() || ExprTy.isNull())
19795 return nullptr;
19796 ExprTy = ExprTy.getNonReferenceType();
19797 const Expr *Length = OASE->getLength();
19799 if (Length && !Length->isValueDependent() &&
19800 Length->EvaluateAsInt(Result, getASTContext()) &&
19801 Result.Val.getInt().isZero()) {
19802 Diag(ELoc,
19803 diag::err_omp_depend_zero_length_array_section_not_allowed)
19804 << SimpleExpr->getSourceRange();
19805 continue;
19806 }
19807 }
19808
19809 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
19810 // List items used in depend clauses with the in, out, inout,
19811 // inoutset, or mutexinoutset dependence types cannot be
19812 // expressions of the omp_depend_t type.
19813 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19814 !RefExpr->isInstantiationDependent() &&
19815 !RefExpr->containsUnexpandedParameterPack() &&
19816 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
19817 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
19818 ExprTy.getTypePtr()))) {
19819 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19820 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19821 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19822 << RefExpr->getSourceRange();
19823 continue;
19824 }
19825
19826 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
19827 if (ASE && !ASE->getBase()->isTypeDependent() &&
19828 !ASE->getBase()
19829 ->getType()
19830 .getNonReferenceType()
19831 ->isPointerType() &&
19832 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
19833 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19834 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19835 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19836 << RefExpr->getSourceRange();
19837 continue;
19838 }
19839
19840 ExprResult Res;
19841 {
19843 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
19844 RefExpr->IgnoreParenImpCasts());
19845 }
19846 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
19847 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
19848 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
19849 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19850 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
19851 << RefExpr->getSourceRange();
19852 continue;
19853 }
19854 }
19855 }
19856 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19857 }
19858 }
19859
19860 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
19861 DepKind != OMPC_DEPEND_outallmemory &&
19862 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
19863 return nullptr;
19864
19865 auto *C = OMPDependClause::Create(
19866 getASTContext(), StartLoc, LParenLoc, EndLoc,
19867 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
19868 TotalDepCount.getZExtValue());
19869 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
19870 DSAStack->isParentOrderedRegion())
19871 DSAStack->addDoacrossDependClause(C, OpsOffs);
19872 return C;
19873}
19874
19877 SourceLocation LParenLoc, SourceLocation ModifierLoc,
19878 SourceLocation EndLoc) {
19879 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
19880 "Unexpected device modifier in OpenMP < 50.");
19881
19882 bool ErrorFound = false;
19883 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
19884 std::string Values =
19885 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
19886 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
19887 << Values << getOpenMPClauseName(OMPC_device);
19888 ErrorFound = true;
19889 }
19890
19891 Expr *ValExpr = Device;
19892 Stmt *HelperValStmt = nullptr;
19893
19894 // OpenMP [2.9.1, Restrictions]
19895 // The device expression must evaluate to a non-negative integer value.
19896 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
19897 /*StrictlyPositive=*/false) ||
19898 ErrorFound;
19899 if (ErrorFound)
19900 return nullptr;
19901
19902 // OpenMP 5.0 [2.12.5, Restrictions]
19903 // In case of ancestor device-modifier, a requires directive with
19904 // the reverse_offload clause must be specified.
19905 if (Modifier == OMPC_DEVICE_ancestor) {
19906 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
19908 StartLoc,
19909 diag::err_omp_device_ancestor_without_requires_reverse_offload);
19910 ErrorFound = true;
19911 }
19912 }
19913
19914 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19915 OpenMPDirectiveKind CaptureRegion =
19916 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
19917 if (CaptureRegion != OMPD_unknown &&
19919 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
19920 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19921 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
19922 HelperValStmt = buildPreInits(getASTContext(), Captures);
19923 }
19924
19925 return new (getASTContext())
19926 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
19927 LParenLoc, ModifierLoc, EndLoc);
19928}
19929
19931 DSAStackTy *Stack, QualType QTy,
19932 bool FullCheck = true) {
19933 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
19934 return false;
19935 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
19936 !QTy.isTriviallyCopyableType(SemaRef.Context))
19937 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
19938 return true;
19939}
19940
19941/// Return true if it can be proven that the provided array expression
19942/// (array section or array subscript) does NOT specify the whole size of the
19943/// array whose base type is \a BaseQTy.
19945 const Expr *E,
19946 QualType BaseQTy) {
19947 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
19948
19949 // If this is an array subscript, it refers to the whole size if the size of
19950 // the dimension is constant and equals 1. Also, an array section assumes the
19951 // format of an array subscript if no colon is used.
19952 if (isa<ArraySubscriptExpr>(E) ||
19953 (OASE && OASE->getColonLocFirst().isInvalid())) {
19954 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
19955 return ATy->getSExtSize() != 1;
19956 // Size can't be evaluated statically.
19957 return false;
19958 }
19959
19960 assert(OASE && "Expecting array section if not an array subscript.");
19961 const Expr *LowerBound = OASE->getLowerBound();
19962 const Expr *Length = OASE->getLength();
19963
19964 // If there is a lower bound that does not evaluates to zero, we are not
19965 // covering the whole dimension.
19966 if (LowerBound) {
19968 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
19969 return false; // Can't get the integer value as a constant.
19970
19971 llvm::APSInt ConstLowerBound = Result.Val.getInt();
19972 if (ConstLowerBound.getSExtValue())
19973 return true;
19974 }
19975
19976 // If we don't have a length we covering the whole dimension.
19977 if (!Length)
19978 return false;
19979
19980 // If the base is a pointer, we don't have a way to get the size of the
19981 // pointee.
19982 if (BaseQTy->isPointerType())
19983 return false;
19984
19985 // We can only check if the length is the same as the size of the dimension
19986 // if we have a constant array.
19987 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
19988 if (!CATy)
19989 return false;
19990
19992 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
19993 return false; // Can't get the integer value as a constant.
19994
19995 llvm::APSInt ConstLength = Result.Val.getInt();
19996 return CATy->getSExtSize() != ConstLength.getSExtValue();
19997}
19998
19999// Return true if it can be proven that the provided array expression (array
20000// section or array subscript) does NOT specify a single element of the array
20001// whose base type is \a BaseQTy.
20003 const Expr *E,
20004 QualType BaseQTy) {
20005 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20006
20007 // An array subscript always refer to a single element. Also, an array section
20008 // assumes the format of an array subscript if no colon is used.
20009 if (isa<ArraySubscriptExpr>(E) ||
20010 (OASE && OASE->getColonLocFirst().isInvalid()))
20011 return false;
20012
20013 assert(OASE && "Expecting array section if not an array subscript.");
20014 const Expr *Length = OASE->getLength();
20015
20016 // If we don't have a length we have to check if the array has unitary size
20017 // for this dimension. Also, we should always expect a length if the base type
20018 // is pointer.
20019 if (!Length) {
20020 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20021 return ATy->getSExtSize() != 1;
20022 // We cannot assume anything.
20023 return false;
20024 }
20025
20026 // Check if the length evaluates to 1.
20028 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20029 return false; // Can't get the integer value as a constant.
20030
20031 llvm::APSInt ConstLength = Result.Val.getInt();
20032 return ConstLength.getSExtValue() != 1;
20033}
20034
20035// The base of elements of list in a map clause have to be either:
20036// - a reference to variable or field.
20037// - a member expression.
20038// - an array expression.
20039//
20040// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20041// reference to 'r'.
20042//
20043// If we have:
20044//
20045// struct SS {
20046// Bla S;
20047// foo() {
20048// #pragma omp target map (S.Arr[:12]);
20049// }
20050// }
20051//
20052// We want to retrieve the member expression 'this->S';
20053
20054// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20055// If a list item is an array section, it must specify contiguous storage.
20056//
20057// For this restriction it is sufficient that we make sure only references
20058// to variables or fields and array expressions, and that no array sections
20059// exist except in the rightmost expression (unless they cover the whole
20060// dimension of the array). E.g. these would be invalid:
20061//
20062// r.ArrS[3:5].Arr[6:7]
20063//
20064// r.ArrS[3:5].x
20065//
20066// but these would be valid:
20067// r.ArrS[3].Arr[6:7]
20068//
20069// r.ArrS[3].x
20070namespace {
20071class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20072 Sema &SemaRef;
20073 OpenMPClauseKind CKind = OMPC_unknown;
20074 OpenMPDirectiveKind DKind = OMPD_unknown;
20076 bool IsNonContiguous = false;
20077 bool NoDiagnose = false;
20078 const Expr *RelevantExpr = nullptr;
20079 bool AllowUnitySizeArraySection = true;
20080 bool AllowWholeSizeArraySection = true;
20081 bool AllowAnotherPtr = true;
20082 SourceLocation ELoc;
20083 SourceRange ERange;
20084
20085 void emitErrorMsg() {
20086 // If nothing else worked, this is not a valid map clause expression.
20087 if (SemaRef.getLangOpts().OpenMP < 50) {
20088 SemaRef.Diag(ELoc,
20089 diag::err_omp_expected_named_var_member_or_array_expression)
20090 << ERange;
20091 } else {
20092 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20093 << getOpenMPClauseName(CKind) << ERange;
20094 }
20095 }
20096
20097public:
20098 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20099 if (!isa<VarDecl>(DRE->getDecl())) {
20100 emitErrorMsg();
20101 return false;
20102 }
20103 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20104 RelevantExpr = DRE;
20105 // Record the component.
20106 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20107 return true;
20108 }
20109
20110 bool VisitMemberExpr(MemberExpr *ME) {
20111 Expr *E = ME;
20112 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20113
20114 if (isa<CXXThisExpr>(BaseE)) {
20115 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20116 // We found a base expression: this->Val.
20117 RelevantExpr = ME;
20118 } else {
20119 E = BaseE;
20120 }
20121
20122 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20123 if (!NoDiagnose) {
20124 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20125 << ME->getSourceRange();
20126 return false;
20127 }
20128 if (RelevantExpr)
20129 return false;
20130 return Visit(E);
20131 }
20132
20133 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20134
20135 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20136 // A bit-field cannot appear in a map clause.
20137 //
20138 if (FD->isBitField()) {
20139 if (!NoDiagnose) {
20140 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20141 << ME->getSourceRange() << getOpenMPClauseName(CKind);
20142 return false;
20143 }
20144 if (RelevantExpr)
20145 return false;
20146 return Visit(E);
20147 }
20148
20149 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20150 // If the type of a list item is a reference to a type T then the type
20151 // will be considered to be T for all purposes of this clause.
20152 QualType CurType = BaseE->getType().getNonReferenceType();
20153
20154 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20155 // A list item cannot be a variable that is a member of a structure with
20156 // a union type.
20157 //
20158 if (CurType->isUnionType()) {
20159 if (!NoDiagnose) {
20160 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20161 << ME->getSourceRange();
20162 return false;
20163 }
20164 return RelevantExpr || Visit(E);
20165 }
20166
20167 // If we got a member expression, we should not expect any array section
20168 // before that:
20169 //
20170 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20171 // If a list item is an element of a structure, only the rightmost symbol
20172 // of the variable reference can be an array section.
20173 //
20174 AllowUnitySizeArraySection = false;
20175 AllowWholeSizeArraySection = false;
20176
20177 // Record the component.
20178 Components.emplace_back(ME, FD, IsNonContiguous);
20179 return RelevantExpr || Visit(E);
20180 }
20181
20182 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20183 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20184
20185 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20186 if (!NoDiagnose) {
20187 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20188 << 0 << AE->getSourceRange();
20189 return false;
20190 }
20191 return RelevantExpr || Visit(E);
20192 }
20193
20194 // If we got an array subscript that express the whole dimension we
20195 // can have any array expressions before. If it only expressing part of
20196 // the dimension, we can only have unitary-size array expressions.
20198 AllowWholeSizeArraySection = false;
20199
20200 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20201 Expr::EvalResult Result;
20202 if (!AE->getIdx()->isValueDependent() &&
20203 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20204 !Result.Val.getInt().isZero()) {
20205 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20206 diag::err_omp_invalid_map_this_expr);
20207 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20208 diag::note_omp_invalid_subscript_on_this_ptr_map);
20209 }
20210 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20211 RelevantExpr = TE;
20212 }
20213
20214 // Record the component - we don't have any declaration associated.
20215 Components.emplace_back(AE, nullptr, IsNonContiguous);
20216
20217 return RelevantExpr || Visit(E);
20218 }
20219
20220 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
20221 // After OMP 5.0 Array section in reduction clause will be implicitly
20222 // mapped
20223 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20224 "Array sections cannot be implicitly mapped.");
20225 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20226 QualType CurType =
20228
20229 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20230 // If the type of a list item is a reference to a type T then the type
20231 // will be considered to be T for all purposes of this clause.
20232 if (CurType->isReferenceType())
20233 CurType = CurType->getPointeeType();
20234
20235 bool IsPointer = CurType->isAnyPointerType();
20236
20237 if (!IsPointer && !CurType->isArrayType()) {
20238 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20239 << 0 << OASE->getSourceRange();
20240 return false;
20241 }
20242
20243 bool NotWhole =
20244 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20245 bool NotUnity =
20246 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20247
20248 if (AllowWholeSizeArraySection) {
20249 // Any array section is currently allowed. Allowing a whole size array
20250 // section implies allowing a unity array section as well.
20251 //
20252 // If this array section refers to the whole dimension we can still
20253 // accept other array sections before this one, except if the base is a
20254 // pointer. Otherwise, only unitary sections are accepted.
20255 if (NotWhole || IsPointer)
20256 AllowWholeSizeArraySection = false;
20257 } else if (DKind == OMPD_target_update &&
20258 SemaRef.getLangOpts().OpenMP >= 50) {
20259 if (IsPointer && !AllowAnotherPtr)
20260 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20261 << /*array of unknown bound */ 1;
20262 else
20263 IsNonContiguous = true;
20264 } else if (AllowUnitySizeArraySection && NotUnity) {
20265 // A unity or whole array section is not allowed and that is not
20266 // compatible with the properties of the current array section.
20267 if (NoDiagnose)
20268 return false;
20269 SemaRef.Diag(ELoc,
20270 diag::err_array_section_does_not_specify_contiguous_storage)
20271 << OASE->getSourceRange();
20272 return false;
20273 }
20274
20275 if (IsPointer)
20276 AllowAnotherPtr = false;
20277
20278 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20279 Expr::EvalResult ResultR;
20280 Expr::EvalResult ResultL;
20281 if (!OASE->getLength()->isValueDependent() &&
20282 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20283 !ResultR.Val.getInt().isOne()) {
20284 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20285 diag::err_omp_invalid_map_this_expr);
20286 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20287 diag::note_omp_invalid_length_on_this_ptr_mapping);
20288 }
20289 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20290 OASE->getLowerBound()->EvaluateAsInt(ResultL,
20291 SemaRef.getASTContext()) &&
20292 !ResultL.Val.getInt().isZero()) {
20293 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20294 diag::err_omp_invalid_map_this_expr);
20295 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20296 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20297 }
20298 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20299 RelevantExpr = TE;
20300 }
20301
20302 // Record the component - we don't have any declaration associated.
20303 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20304 return RelevantExpr || Visit(E);
20305 }
20306 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20307 Expr *Base = E->getBase();
20308
20309 // Record the component - we don't have any declaration associated.
20310 Components.emplace_back(E, nullptr, IsNonContiguous);
20311
20312 return Visit(Base->IgnoreParenImpCasts());
20313 }
20314
20315 bool VisitUnaryOperator(UnaryOperator *UO) {
20316 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20317 UO->getOpcode() != UO_Deref) {
20318 emitErrorMsg();
20319 return false;
20320 }
20321 if (!RelevantExpr) {
20322 // Record the component if haven't found base decl.
20323 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20324 }
20325 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20326 }
20327 bool VisitBinaryOperator(BinaryOperator *BO) {
20328 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20329 emitErrorMsg();
20330 return false;
20331 }
20332
20333 // Pointer arithmetic is the only thing we expect to happen here so after we
20334 // make sure the binary operator is a pointer type, the only thing we need
20335 // to do is to visit the subtree that has the same type as root (so that we
20336 // know the other subtree is just an offset)
20337 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20338 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20339 Components.emplace_back(BO, nullptr, false);
20340 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20341 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20342 "Either LHS or RHS have base decl inside");
20343 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20344 return RelevantExpr || Visit(LE);
20345 return RelevantExpr || Visit(RE);
20346 }
20347 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20348 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20349 RelevantExpr = CTE;
20350 Components.emplace_back(CTE, nullptr, IsNonContiguous);
20351 return true;
20352 }
20353 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20354 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20355 Components.emplace_back(COCE, nullptr, IsNonContiguous);
20356 return true;
20357 }
20358 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20359 Expr *Source = E->getSourceExpr();
20360 if (!Source) {
20361 emitErrorMsg();
20362 return false;
20363 }
20364 return Visit(Source);
20365 }
20366 bool VisitStmt(Stmt *) {
20367 emitErrorMsg();
20368 return false;
20369 }
20370 const Expr *getFoundBase() const { return RelevantExpr; }
20371 explicit MapBaseChecker(
20372 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20374 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20375 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20376 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20377};
20378} // namespace
20379
20380/// Return the expression of the base of the mappable expression or null if it
20381/// cannot be determined and do all the necessary checks to see if the
20382/// expression is valid as a standalone mappable expression. In the process,
20383/// record all the components of the expression.
20385 Sema &SemaRef, Expr *E,
20387 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20388 SourceLocation ELoc = E->getExprLoc();
20389 SourceRange ERange = E->getSourceRange();
20390 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20391 ERange);
20392 if (Checker.Visit(E->IgnoreParens())) {
20393 // Check if the highest dimension array section has length specified
20394 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20395 (CKind == OMPC_to || CKind == OMPC_from)) {
20396 auto CI = CurComponents.rbegin();
20397 auto CE = CurComponents.rend();
20398 for (; CI != CE; ++CI) {
20399 const auto *OASE =
20400 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20401 if (!OASE)
20402 continue;
20403 if (OASE && OASE->getLength())
20404 break;
20405 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
20406 << ERange;
20407 }
20408 }
20409 return Checker.getFoundBase();
20410 }
20411 return nullptr;
20412}
20413
20414// Return true if expression E associated with value VD has conflicts with other
20415// map information.
20417 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
20418 bool CurrentRegionOnly,
20420 OpenMPClauseKind CKind) {
20421 assert(VD && E);
20422 SourceLocation ELoc = E->getExprLoc();
20423 SourceRange ERange = E->getSourceRange();
20424
20425 // In order to easily check the conflicts we need to match each component of
20426 // the expression under test with the components of the expressions that are
20427 // already in the stack.
20428
20429 assert(!CurComponents.empty() && "Map clause expression with no components!");
20430 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20431 "Map clause expression with unexpected base!");
20432
20433 // Variables to help detecting enclosing problems in data environment nests.
20434 bool IsEnclosedByDataEnvironmentExpr = false;
20435 const Expr *EnclosingExpr = nullptr;
20436
20437 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20438 VD, CurrentRegionOnly,
20439 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20440 ERange, CKind, &EnclosingExpr,
20442 StackComponents,
20443 OpenMPClauseKind Kind) {
20444 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
20445 return false;
20446 assert(!StackComponents.empty() &&
20447 "Map clause expression with no components!");
20448 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20449 "Map clause expression with unexpected base!");
20450 (void)VD;
20451
20452 // The whole expression in the stack.
20453 const Expr *RE = StackComponents.front().getAssociatedExpression();
20454
20455 // Expressions must start from the same base. Here we detect at which
20456 // point both expressions diverge from each other and see if we can
20457 // detect if the memory referred to both expressions is contiguous and
20458 // do not overlap.
20459 auto CI = CurComponents.rbegin();
20460 auto CE = CurComponents.rend();
20461 auto SI = StackComponents.rbegin();
20462 auto SE = StackComponents.rend();
20463 for (; CI != CE && SI != SE; ++CI, ++SI) {
20464
20465 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
20466 // At most one list item can be an array item derived from a given
20467 // variable in map clauses of the same construct.
20468 if (CurrentRegionOnly &&
20469 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20470 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20471 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20472 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20473 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20474 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20475 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20476 diag::err_omp_multiple_array_items_in_map_clause)
20477 << CI->getAssociatedExpression()->getSourceRange();
20478 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20479 diag::note_used_here)
20480 << SI->getAssociatedExpression()->getSourceRange();
20481 return true;
20482 }
20483
20484 // Do both expressions have the same kind?
20485 if (CI->getAssociatedExpression()->getStmtClass() !=
20486 SI->getAssociatedExpression()->getStmtClass())
20487 break;
20488
20489 // Are we dealing with different variables/fields?
20490 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20491 break;
20492 }
20493 // Check if the extra components of the expressions in the enclosing
20494 // data environment are redundant for the current base declaration.
20495 // If they are, the maps completely overlap, which is legal.
20496 for (; SI != SE; ++SI) {
20497 QualType Type;
20498 if (const auto *ASE =
20499 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20500 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20501 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
20502 SI->getAssociatedExpression())) {
20503 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20504 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20505 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20506 SI->getAssociatedExpression())) {
20507 Type = OASE->getBase()->getType()->getPointeeType();
20508 }
20509 if (Type.isNull() || Type->isAnyPointerType() ||
20511 SemaRef, SI->getAssociatedExpression(), Type))
20512 break;
20513 }
20514
20515 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20516 // List items of map clauses in the same construct must not share
20517 // original storage.
20518 //
20519 // If the expressions are exactly the same or one is a subset of the
20520 // other, it means they are sharing storage.
20521 if (CI == CE && SI == SE) {
20522 if (CurrentRegionOnly) {
20523 if (CKind == OMPC_map) {
20524 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20525 } else {
20526 assert(CKind == OMPC_to || CKind == OMPC_from);
20527 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20528 << ERange;
20529 }
20530 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20531 << RE->getSourceRange();
20532 return true;
20533 }
20534 // If we find the same expression in the enclosing data environment,
20535 // that is legal.
20536 IsEnclosedByDataEnvironmentExpr = true;
20537 return false;
20538 }
20539
20540 QualType DerivedType =
20541 std::prev(CI)->getAssociatedDeclaration()->getType();
20542 SourceLocation DerivedLoc =
20543 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20544
20545 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20546 // If the type of a list item is a reference to a type T then the type
20547 // will be considered to be T for all purposes of this clause.
20548 DerivedType = DerivedType.getNonReferenceType();
20549
20550 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
20551 // A variable for which the type is pointer and an array section
20552 // derived from that variable must not appear as list items of map
20553 // clauses of the same construct.
20554 //
20555 // Also, cover one of the cases in:
20556 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20557 // If any part of the original storage of a list item has corresponding
20558 // storage in the device data environment, all of the original storage
20559 // must have corresponding storage in the device data environment.
20560 //
20561 if (DerivedType->isAnyPointerType()) {
20562 if (CI == CE || SI == SE) {
20563 SemaRef.Diag(
20564 DerivedLoc,
20565 diag::err_omp_pointer_mapped_along_with_derived_section)
20566 << DerivedLoc;
20567 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20568 << RE->getSourceRange();
20569 return true;
20570 }
20571 if (CI->getAssociatedExpression()->getStmtClass() !=
20572 SI->getAssociatedExpression()->getStmtClass() ||
20573 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20574 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20575 assert(CI != CE && SI != SE);
20576 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20577 << DerivedLoc;
20578 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20579 << RE->getSourceRange();
20580 return true;
20581 }
20582 }
20583
20584 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20585 // List items of map clauses in the same construct must not share
20586 // original storage.
20587 //
20588 // An expression is a subset of the other.
20589 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20590 if (CKind == OMPC_map) {
20591 if (CI != CE || SI != SE) {
20592 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
20593 // a pointer.
20594 auto Begin =
20595 CI != CE ? CurComponents.begin() : StackComponents.begin();
20596 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20597 auto It = Begin;
20598 while (It != End && !It->getAssociatedDeclaration())
20599 std::advance(It, 1);
20600 assert(It != End &&
20601 "Expected at least one component with the declaration.");
20602 if (It != Begin && It->getAssociatedDeclaration()
20603 ->getType()
20604 .getCanonicalType()
20605 ->isAnyPointerType()) {
20606 IsEnclosedByDataEnvironmentExpr = false;
20607 EnclosingExpr = nullptr;
20608 return false;
20609 }
20610 }
20611 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20612 } else {
20613 assert(CKind == OMPC_to || CKind == OMPC_from);
20614 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20615 << ERange;
20616 }
20617 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20618 << RE->getSourceRange();
20619 return true;
20620 }
20621
20622 // The current expression uses the same base as other expression in the
20623 // data environment but does not contain it completely.
20624 if (!CurrentRegionOnly && SI != SE)
20625 EnclosingExpr = RE;
20626
20627 // The current expression is a subset of the expression in the data
20628 // environment.
20629 IsEnclosedByDataEnvironmentExpr |=
20630 (!CurrentRegionOnly && CI != CE && SI == SE);
20631
20632 return false;
20633 });
20634
20635 if (CurrentRegionOnly)
20636 return FoundError;
20637
20638 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20639 // If any part of the original storage of a list item has corresponding
20640 // storage in the device data environment, all of the original storage must
20641 // have corresponding storage in the device data environment.
20642 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
20643 // If a list item is an element of a structure, and a different element of
20644 // the structure has a corresponding list item in the device data environment
20645 // prior to a task encountering the construct associated with the map clause,
20646 // then the list item must also have a corresponding list item in the device
20647 // data environment prior to the task encountering the construct.
20648 //
20649 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20650 SemaRef.Diag(ELoc,
20651 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20652 << ERange;
20653 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
20654 << EnclosingExpr->getSourceRange();
20655 return true;
20656 }
20657
20658 return FoundError;
20659}
20660
20661// Look up the user-defined mapper given the mapper name and mapped type, and
20662// build a reference to it.
20664 CXXScopeSpec &MapperIdScopeSpec,
20665 const DeclarationNameInfo &MapperId,
20666 QualType Type,
20667 Expr *UnresolvedMapper) {
20668 if (MapperIdScopeSpec.isInvalid())
20669 return ExprError();
20670 // Get the actual type for the array type.
20671 if (Type->isArrayType()) {
20672 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
20674 }
20675 // Find all user-defined mappers with the given MapperId.
20676 SmallVector<UnresolvedSet<8>, 4> Lookups;
20677 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
20678 Lookup.suppressDiagnostics();
20679 if (S) {
20680 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
20681 /*ObjectType=*/QualType())) {
20682 NamedDecl *D = Lookup.getRepresentativeDecl();
20683 while (S && !S->isDeclScope(D))
20684 S = S->getParent();
20685 if (S)
20686 S = S->getParent();
20687 Lookups.emplace_back();
20688 Lookups.back().append(Lookup.begin(), Lookup.end());
20689 Lookup.clear();
20690 }
20691 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20692 // Extract the user-defined mappers with the given MapperId.
20693 Lookups.push_back(UnresolvedSet<8>());
20694 for (NamedDecl *D : ULE->decls()) {
20695 auto *DMD = cast<OMPDeclareMapperDecl>(D);
20696 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
20697 Lookups.back().addDecl(DMD);
20698 }
20699 }
20700 // Defer the lookup for dependent types. The results will be passed through
20701 // UnresolvedMapper on instantiation.
20702 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
20705 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
20706 return !D->isInvalidDecl() &&
20707 (D->getType()->isDependentType() ||
20708 D->getType()->isInstantiationDependentType() ||
20709 D->getType()->containsUnexpandedParameterPack());
20710 })) {
20711 UnresolvedSet<8> URS;
20712 for (const UnresolvedSet<8> &Set : Lookups) {
20713 if (Set.empty())
20714 continue;
20715 URS.append(Set.begin(), Set.end());
20716 }
20718 SemaRef.Context, /*NamingClass=*/nullptr,
20719 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
20720 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false);
20721 }
20722 SourceLocation Loc = MapperId.getLoc();
20723 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
20724 // The type must be of struct, union or class type in C and C++
20726 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
20727 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
20728 return ExprError();
20729 }
20730 // Perform argument dependent lookup.
20731 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
20732 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
20733 // Return the first user-defined mapper with the desired type.
20734 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20735 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
20736 if (!D->isInvalidDecl() &&
20737 SemaRef.Context.hasSameType(D->getType(), Type))
20738 return D;
20739 return nullptr;
20740 }))
20741 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
20742 // Find the first user-defined mapper with a type derived from the desired
20743 // type.
20744 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20745 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
20746 if (!D->isInvalidDecl() &&
20747 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
20748 !Type.isMoreQualifiedThan(D->getType()))
20749 return D;
20750 return nullptr;
20751 })) {
20752 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
20753 /*DetectVirtual=*/false);
20754 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
20755 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
20756 VD->getType().getUnqualifiedType()))) {
20757 if (SemaRef.CheckBaseClassAccess(
20758 Loc, VD->getType(), Type, Paths.front(),
20759 /*DiagID=*/0) != Sema::AR_inaccessible) {
20760 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
20761 }
20762 }
20763 }
20764 }
20765 // Report error if a mapper is specified, but cannot be found.
20766 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
20767 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
20768 << Type << MapperId.getName();
20769 return ExprError();
20770 }
20771 return ExprEmpty();
20772}
20773
20774namespace {
20775// Utility struct that gathers all the related lists associated with a mappable
20776// expression.
20777struct MappableVarListInfo {
20778 // The list of expressions.
20779 ArrayRef<Expr *> VarList;
20780 // The list of processed expressions.
20781 SmallVector<Expr *, 16> ProcessedVarList;
20782 // The mappble components for each expression.
20784 // The base declaration of the variable.
20785 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
20786 // The reference to the user-defined mapper associated with every expression.
20787 SmallVector<Expr *, 16> UDMapperList;
20788
20789 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
20790 // We have a list of components and base declarations for each entry in the
20791 // variable list.
20792 VarComponents.reserve(VarList.size());
20793 VarBaseDeclarations.reserve(VarList.size());
20794 }
20795};
20796} // namespace
20797
20798// Check the validity of the provided variable list for the provided clause kind
20799// \a CKind. In the check process the valid expressions, mappable expression
20800// components, variables, and user-defined mappers are extracted and used to
20801// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
20802// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
20803// and \a MapperId are expected to be valid if the clause kind is 'map'.
20805 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
20806 MappableVarListInfo &MVLI, SourceLocation StartLoc,
20807 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
20808 ArrayRef<Expr *> UnresolvedMappers,
20810 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
20811 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
20812 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
20813 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
20814 "Unexpected clause kind with mappable expressions!");
20815
20816 // If the identifier of user-defined mapper is not specified, it is "default".
20817 // We do not change the actual name in this clause to distinguish whether a
20818 // mapper is specified explicitly, i.e., it is not explicitly specified when
20819 // MapperId.getName() is empty.
20820 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
20821 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
20822 MapperId.setName(DeclNames.getIdentifier(
20823 &SemaRef.getASTContext().Idents.get("default")));
20824 MapperId.setLoc(StartLoc);
20825 }
20826
20827 // Iterators to find the current unresolved mapper expression.
20828 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
20829 bool UpdateUMIt = false;
20830 Expr *UnresolvedMapper = nullptr;
20831
20832 bool HasHoldModifier =
20833 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
20834
20835 // Keep track of the mappable components and base declarations in this clause.
20836 // Each entry in the list is going to have a list of components associated. We
20837 // record each set of the components so that we can build the clause later on.
20838 // In the end we should have the same amount of declarations and component
20839 // lists.
20840
20841 for (Expr *RE : MVLI.VarList) {
20842 assert(RE && "Null expr in omp to/from/map clause");
20843 SourceLocation ELoc = RE->getExprLoc();
20844
20845 // Find the current unresolved mapper expression.
20846 if (UpdateUMIt && UMIt != UMEnd) {
20847 UMIt++;
20848 assert(
20849 UMIt != UMEnd &&
20850 "Expect the size of UnresolvedMappers to match with that of VarList");
20851 }
20852 UpdateUMIt = true;
20853 if (UMIt != UMEnd)
20854 UnresolvedMapper = *UMIt;
20855
20856 const Expr *VE = RE->IgnoreParenLValueCasts();
20857
20858 if (VE->isValueDependent() || VE->isTypeDependent() ||
20861 // Try to find the associated user-defined mapper.
20863 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
20864 VE->getType().getCanonicalType(), UnresolvedMapper);
20865 if (ER.isInvalid())
20866 continue;
20867 MVLI.UDMapperList.push_back(ER.get());
20868 // We can only analyze this information once the missing information is
20869 // resolved.
20870 MVLI.ProcessedVarList.push_back(RE);
20871 continue;
20872 }
20873
20874 Expr *SimpleExpr = RE->IgnoreParenCasts();
20875
20876 if (!RE->isLValue()) {
20877 if (SemaRef.getLangOpts().OpenMP < 50) {
20878 SemaRef.Diag(
20879 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
20880 << RE->getSourceRange();
20881 } else {
20882 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20883 << getOpenMPClauseName(CKind) << RE->getSourceRange();
20884 }
20885 continue;
20886 }
20887
20889 ValueDecl *CurDeclaration = nullptr;
20890
20891 // Obtain the array or member expression bases if required. Also, fill the
20892 // components array with all the components identified in the process.
20893 const Expr *BE =
20894 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
20895 DSAS->getCurrentDirective(), NoDiagnose);
20896 if (!BE)
20897 continue;
20898
20899 assert(!CurComponents.empty() &&
20900 "Invalid mappable expression information.");
20901
20902 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
20903 // Add store "this" pointer to class in DSAStackTy for future checking
20904 DSAS->addMappedClassesQualTypes(TE->getType());
20905 // Try to find the associated user-defined mapper.
20907 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
20908 VE->getType().getCanonicalType(), UnresolvedMapper);
20909 if (ER.isInvalid())
20910 continue;
20911 MVLI.UDMapperList.push_back(ER.get());
20912 // Skip restriction checking for variable or field declarations
20913 MVLI.ProcessedVarList.push_back(RE);
20914 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
20915 MVLI.VarComponents.back().append(CurComponents.begin(),
20916 CurComponents.end());
20917 MVLI.VarBaseDeclarations.push_back(nullptr);
20918 continue;
20919 }
20920
20921 // For the following checks, we rely on the base declaration which is
20922 // expected to be associated with the last component. The declaration is
20923 // expected to be a variable or a field (if 'this' is being mapped).
20924 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
20925 assert(CurDeclaration && "Null decl on map clause.");
20926 assert(
20927 CurDeclaration->isCanonicalDecl() &&
20928 "Expecting components to have associated only canonical declarations.");
20929
20930 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
20931 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
20932
20933 assert((VD || FD) && "Only variables or fields are expected here!");
20934 (void)FD;
20935
20936 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
20937 // threadprivate variables cannot appear in a map clause.
20938 // OpenMP 4.5 [2.10.5, target update Construct]
20939 // threadprivate variables cannot appear in a from clause.
20940 if (VD && DSAS->isThreadPrivate(VD)) {
20941 if (NoDiagnose)
20942 continue;
20943 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
20944 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
20945 << getOpenMPClauseName(CKind);
20946 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
20947 continue;
20948 }
20949
20950 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
20951 // A list item cannot appear in both a map clause and a data-sharing
20952 // attribute clause on the same construct.
20953
20954 // Check conflicts with other map clause expressions. We check the conflicts
20955 // with the current construct separately from the enclosing data
20956 // environment, because the restrictions are different. We only have to
20957 // check conflicts across regions for the map clauses.
20958 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
20959 /*CurrentRegionOnly=*/true, CurComponents, CKind))
20960 break;
20961 if (CKind == OMPC_map &&
20962 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
20963 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
20964 /*CurrentRegionOnly=*/false, CurComponents, CKind))
20965 break;
20966
20967 // OpenMP 4.5 [2.10.5, target update Construct]
20968 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20969 // If the type of a list item is a reference to a type T then the type will
20970 // be considered to be T for all purposes of this clause.
20971 auto I = llvm::find_if(
20972 CurComponents,
20974 return MC.getAssociatedDeclaration();
20975 });
20976 assert(I != CurComponents.end() && "Null decl on map clause.");
20977 (void)I;
20978 QualType Type;
20979 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
20980 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
20981 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
20982 if (ASE) {
20983 Type = ASE->getType().getNonReferenceType();
20984 } else if (OASE) {
20985 QualType BaseType =
20987 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20988 Type = ATy->getElementType();
20989 else
20990 Type = BaseType->getPointeeType();
20991 Type = Type.getNonReferenceType();
20992 } else if (OAShE) {
20993 Type = OAShE->getBase()->getType()->getPointeeType();
20994 } else {
20995 Type = VE->getType();
20996 }
20997
20998 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
20999 // A list item in a to or from clause must have a mappable type.
21000 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21001 // A list item must have a mappable type.
21002 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21003 DSAS, Type, /*FullCheck=*/true))
21004 continue;
21005
21006 if (CKind == OMPC_map) {
21007 // target enter data
21008 // OpenMP [2.10.2, Restrictions, p. 99]
21009 // A map-type must be specified in all map clauses and must be either
21010 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21011 // no map type is present.
21012 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21013 if (DKind == OMPD_target_enter_data &&
21014 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21015 SemaRef.getLangOpts().OpenMP >= 52)) {
21016 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21017 << (IsMapTypeImplicit ? 1 : 0)
21018 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21019 << getOpenMPDirectiveName(DKind);
21020 continue;
21021 }
21022
21023 // target exit_data
21024 // OpenMP [2.10.3, Restrictions, p. 102]
21025 // A map-type must be specified in all map clauses and must be either
21026 // from, release, or delete. Starting with OpenMP 5.2 the default map
21027 // type is `from` if no map type is present.
21028 if (DKind == OMPD_target_exit_data &&
21029 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21030 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21031 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21032 << (IsMapTypeImplicit ? 1 : 0)
21033 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21034 << getOpenMPDirectiveName(DKind);
21035 continue;
21036 }
21037
21038 // The 'ompx_hold' modifier is specifically intended to be used on a
21039 // 'target' or 'target data' directive to prevent data from being unmapped
21040 // during the associated statement. It is not permitted on a 'target
21041 // enter data' or 'target exit data' directive, which have no associated
21042 // statement.
21043 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21044 HasHoldModifier) {
21045 SemaRef.Diag(StartLoc,
21046 diag::err_omp_invalid_map_type_modifier_for_directive)
21048 OMPC_MAP_MODIFIER_ompx_hold)
21049 << getOpenMPDirectiveName(DKind);
21050 continue;
21051 }
21052
21053 // target, target data
21054 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21055 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21056 // A map-type in a map clause must be to, from, tofrom or alloc
21057 if ((DKind == OMPD_target_data ||
21059 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21060 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21061 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21062 << (IsMapTypeImplicit ? 1 : 0)
21063 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21064 << getOpenMPDirectiveName(DKind);
21065 continue;
21066 }
21067
21068 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21069 // A list item cannot appear in both a map clause and a data-sharing
21070 // attribute clause on the same construct
21071 //
21072 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21073 // A list item cannot appear in both a map clause and a data-sharing
21074 // attribute clause on the same construct unless the construct is a
21075 // combined construct.
21076 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21078 DKind == OMPD_target)) {
21079 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21080 if (isOpenMPPrivate(DVar.CKind)) {
21081 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21082 << getOpenMPClauseName(DVar.CKind)
21083 << getOpenMPClauseName(OMPC_map)
21084 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21085 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21086 continue;
21087 }
21088 }
21089 }
21090
21091 // Try to find the associated user-defined mapper.
21093 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21094 Type.getCanonicalType(), UnresolvedMapper);
21095 if (ER.isInvalid())
21096 continue;
21097 MVLI.UDMapperList.push_back(ER.get());
21098
21099 // Save the current expression.
21100 MVLI.ProcessedVarList.push_back(RE);
21101
21102 // Store the components in the stack so that they can be used to check
21103 // against other clauses later on.
21104 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21105 /*WhereFoundClauseKind=*/OMPC_map);
21106
21107 // Save the components and declaration to create the clause. For purposes of
21108 // the clause creation, any component list that has base 'this' uses
21109 // null as base declaration.
21110 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21111 MVLI.VarComponents.back().append(CurComponents.begin(),
21112 CurComponents.end());
21113 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21114 : CurDeclaration);
21115 }
21116}
21117
21119 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21120 ArrayRef<SourceLocation> MapTypeModifiersLoc,
21121 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21122 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21123 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21124 const OMPVarListLocTy &Locs, bool NoDiagnose,
21125 ArrayRef<Expr *> UnresolvedMappers) {
21126 OpenMPMapModifierKind Modifiers[] = {
21131
21132 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
21133 BuiltinType::OMPIterator))
21134 Diag(IteratorModifier->getExprLoc(),
21135 diag::err_omp_map_modifier_not_iterator);
21136
21137 // Process map-type-modifiers, flag errors for duplicate modifiers.
21138 unsigned Count = 0;
21139 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21140 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21141 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21142 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21143 continue;
21144 }
21145 assert(Count < NumberOfOMPMapClauseModifiers &&
21146 "Modifiers exceed the allowed number of map type modifiers");
21147 Modifiers[Count] = MapTypeModifiers[I];
21148 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21149 ++Count;
21150 }
21151
21152 MappableVarListInfo MVLI(VarList);
21154 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21155 MapType, Modifiers, IsMapTypeImplicit,
21156 NoDiagnose);
21157
21158 // We need to produce a map clause even if we don't have variables so that
21159 // other diagnostics related with non-existing map clauses are accurate.
21160 return OMPMapClause::Create(
21161 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21162 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21163 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
21164 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21165}
21166
21169 assert(ParsedType.isUsable());
21170
21171 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
21172 if (ReductionType.isNull())
21173 return QualType();
21174
21175 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21176 // A type name in a declare reduction directive cannot be a function type, an
21177 // array type, a reference type, or a type qualified with const, volatile or
21178 // restrict.
21179 if (ReductionType.hasQualifiers()) {
21180 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21181 return QualType();
21182 }
21183
21184 if (ReductionType->isFunctionType()) {
21185 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21186 return QualType();
21187 }
21188 if (ReductionType->isReferenceType()) {
21189 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21190 return QualType();
21191 }
21192 if (ReductionType->isArrayType()) {
21193 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21194 return QualType();
21195 }
21196 return ReductionType;
21197}
21198
21201 Scope *S, DeclContext *DC, DeclarationName Name,
21202 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21203 AccessSpecifier AS, Decl *PrevDeclInScope) {
21205 Decls.reserve(ReductionTypes.size());
21206
21207 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21210 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21211 // A reduction-identifier may not be re-declared in the current scope for the
21212 // same type or for a type that is compatible according to the base language
21213 // rules.
21214 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21215 OMPDeclareReductionDecl *PrevDRD = nullptr;
21216 bool InCompoundScope = true;
21217 if (S != nullptr) {
21218 // Find previous declaration with the same name not referenced in other
21219 // declarations.
21221 InCompoundScope =
21222 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21223 SemaRef.LookupName(Lookup, S);
21224 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21225 /*AllowInlineNamespace=*/false);
21226 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21227 LookupResult::Filter Filter = Lookup.makeFilter();
21228 while (Filter.hasNext()) {
21229 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21230 if (InCompoundScope) {
21231 auto I = UsedAsPrevious.find(PrevDecl);
21232 if (I == UsedAsPrevious.end())
21233 UsedAsPrevious[PrevDecl] = false;
21234 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21235 UsedAsPrevious[D] = true;
21236 }
21237 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21238 PrevDecl->getLocation();
21239 }
21240 Filter.done();
21241 if (InCompoundScope) {
21242 for (const auto &PrevData : UsedAsPrevious) {
21243 if (!PrevData.second) {
21244 PrevDRD = PrevData.first;
21245 break;
21246 }
21247 }
21248 }
21249 } else if (PrevDeclInScope != nullptr) {
21250 auto *PrevDRDInScope = PrevDRD =
21251 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21252 do {
21253 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21254 PrevDRDInScope->getLocation();
21255 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21256 } while (PrevDRDInScope != nullptr);
21257 }
21258 for (const auto &TyData : ReductionTypes) {
21259 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21260 bool Invalid = false;
21261 if (I != PreviousRedeclTypes.end()) {
21262 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21263 << TyData.first;
21264 Diag(I->second, diag::note_previous_definition);
21265 Invalid = true;
21266 }
21267 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21269 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21270 DC->addDecl(DRD);
21271 DRD->setAccess(AS);
21272 Decls.push_back(DRD);
21273 if (Invalid)
21274 DRD->setInvalidDecl();
21275 else
21276 PrevDRD = DRD;
21277 }
21278
21279 return DeclGroupPtrTy::make(
21280 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
21281}
21282
21284 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21285
21286 // Enter new function scope.
21290
21291 if (S != nullptr)
21292 SemaRef.PushDeclContext(S, DRD);
21293 else
21294 SemaRef.CurContext = DRD;
21295
21298
21299 QualType ReductionType = DRD->getType();
21300 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21301 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21302 // uses semantics of argument handles by value, but it should be passed by
21303 // reference. C lang does not support references, so pass all parameters as
21304 // pointers.
21305 // Create 'T omp_in;' variable.
21306 VarDecl *OmpInParm =
21307 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
21308 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21309 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21310 // uses semantics of argument handles by value, but it should be passed by
21311 // reference. C lang does not support references, so pass all parameters as
21312 // pointers.
21313 // Create 'T omp_out;' variable.
21314 VarDecl *OmpOutParm =
21315 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
21316 if (S != nullptr) {
21317 SemaRef.PushOnScopeChains(OmpInParm, S);
21318 SemaRef.PushOnScopeChains(OmpOutParm, S);
21319 } else {
21320 DRD->addDecl(OmpInParm);
21321 DRD->addDecl(OmpOutParm);
21322 }
21323 Expr *InE =
21324 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
21325 Expr *OutE =
21326 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
21327 DRD->setCombinerData(InE, OutE);
21328}
21329
21331 Expr *Combiner) {
21332 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21335
21338
21339 if (Combiner != nullptr)
21340 DRD->setCombiner(Combiner);
21341 else
21342 DRD->setInvalidDecl();
21343}
21344
21346 Decl *D) {
21347 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21348
21349 // Enter new function scope.
21352
21353 if (S != nullptr)
21354 SemaRef.PushDeclContext(S, DRD);
21355 else
21356 SemaRef.CurContext = DRD;
21357
21360
21361 QualType ReductionType = DRD->getType();
21362 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21363 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21364 // uses semantics of argument handles by value, but it should be passed by
21365 // reference. C lang does not support references, so pass all parameters as
21366 // pointers.
21367 // Create 'T omp_priv;' variable.
21368 VarDecl *OmpPrivParm =
21369 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
21370 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21371 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21372 // uses semantics of argument handles by value, but it should be passed by
21373 // reference. C lang does not support references, so pass all parameters as
21374 // pointers.
21375 // Create 'T omp_orig;' variable.
21376 VarDecl *OmpOrigParm =
21377 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
21378 if (S != nullptr) {
21379 SemaRef.PushOnScopeChains(OmpPrivParm, S);
21380 SemaRef.PushOnScopeChains(OmpOrigParm, S);
21381 } else {
21382 DRD->addDecl(OmpPrivParm);
21383 DRD->addDecl(OmpOrigParm);
21384 }
21385 Expr *OrigE =
21386 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
21387 Expr *PrivE =
21388 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
21389 DRD->setInitializerData(OrigE, PrivE);
21390 return OmpPrivParm;
21391}
21392
21394 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
21395 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21398
21401
21402 if (Initializer != nullptr) {
21403 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
21404 } else if (OmpPrivParm->hasInit()) {
21405 DRD->setInitializer(OmpPrivParm->getInit(),
21406 OmpPrivParm->isDirectInit()
21409 } else {
21410 DRD->setInvalidDecl();
21411 }
21412}
21413
21415 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
21416 for (Decl *D : DeclReductions.get()) {
21417 if (IsValid) {
21418 if (S)
21419 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
21420 /*AddToContext=*/false);
21421 } else {
21422 D->setInvalidDecl();
21423 }
21424 }
21425 return DeclReductions;
21426}
21427
21429 Declarator &D) {
21431 QualType T = TInfo->getType();
21432 if (D.isInvalidType())
21433 return true;
21434
21435 if (getLangOpts().CPlusPlus) {
21436 // Check that there are no default arguments (C++ only).
21438 }
21439
21440 return SemaRef.CreateParsedType(T, TInfo);
21441}
21442
21445 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
21446
21448 assert(!MapperType.isNull() && "Expect valid mapper type");
21449
21450 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21451 // The type must be of struct, union or class type in C and C++
21452 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
21453 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21454 return QualType();
21455 }
21456 return MapperType;
21457}
21458
21460 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
21462 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
21463 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21466 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21467 // A mapper-identifier may not be redeclared in the current scope for the
21468 // same type or for a type that is compatible according to the base language
21469 // rules.
21470 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21471 OMPDeclareMapperDecl *PrevDMD = nullptr;
21472 bool InCompoundScope = true;
21473 if (S != nullptr) {
21474 // Find previous declaration with the same name not referenced in other
21475 // declarations.
21477 InCompoundScope =
21478 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21479 SemaRef.LookupName(Lookup, S);
21480 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21481 /*AllowInlineNamespace=*/false);
21482 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21483 LookupResult::Filter Filter = Lookup.makeFilter();
21484 while (Filter.hasNext()) {
21485 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21486 if (InCompoundScope) {
21487 auto I = UsedAsPrevious.find(PrevDecl);
21488 if (I == UsedAsPrevious.end())
21489 UsedAsPrevious[PrevDecl] = false;
21490 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
21491 UsedAsPrevious[D] = true;
21492 }
21493 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21494 PrevDecl->getLocation();
21495 }
21496 Filter.done();
21497 if (InCompoundScope) {
21498 for (const auto &PrevData : UsedAsPrevious) {
21499 if (!PrevData.second) {
21500 PrevDMD = PrevData.first;
21501 break;
21502 }
21503 }
21504 }
21505 } else if (PrevDeclInScope) {
21506 auto *PrevDMDInScope = PrevDMD =
21507 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
21508 do {
21509 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
21510 PrevDMDInScope->getLocation();
21511 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
21512 } while (PrevDMDInScope != nullptr);
21513 }
21514 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
21515 bool Invalid = false;
21516 if (I != PreviousRedeclTypes.end()) {
21517 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
21518 << MapperType << Name;
21519 Diag(I->second, diag::note_previous_definition);
21520 Invalid = true;
21521 }
21522 // Build expressions for implicit maps of data members with 'default'
21523 // mappers.
21524 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses.begin(),
21525 Clauses.end());
21526 if (getLangOpts().OpenMP >= 50)
21528 ClausesWithImplicit);
21529 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
21530 MapperType, VN, ClausesWithImplicit,
21531 PrevDMD);
21532 if (S)
21533 SemaRef.PushOnScopeChains(DMD, S);
21534 else
21535 DC->addDecl(DMD);
21536 DMD->setAccess(AS);
21537 if (Invalid)
21538 DMD->setInvalidDecl();
21539
21540 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21541 VD->setDeclContext(DMD);
21542 VD->setLexicalDeclContext(DMD);
21543 DMD->addDecl(VD);
21544 DMD->setMapperVarRef(MapperVarRef);
21545
21547}
21548
21550 Scope *S, QualType MapperType, SourceLocation StartLoc,
21551 DeclarationName VN) {
21552 TypeSourceInfo *TInfo =
21553 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
21554 auto *VD = VarDecl::Create(
21555 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
21556 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
21557 if (S)
21558 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
21559 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
21560 DSAStack->addDeclareMapperVarRef(E);
21561 return E;
21562}
21563
21565 if (DSAStack->getDeclareMapperVarRef())
21566 DSAStack->addIteratorVarDecl(VD);
21567}
21568
21570 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
21571 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
21572 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
21573 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
21574 return true;
21576 return true;
21577 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
21578 return true;
21579 return false;
21580 }
21581 return true;
21582}
21583
21585 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
21586 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
21587}
21588
21590 SourceLocation StartLoc,
21591 SourceLocation LParenLoc,
21592 SourceLocation EndLoc) {
21593 Expr *ValExpr = NumTeams;
21594 Stmt *HelperValStmt = nullptr;
21595
21596 // OpenMP [teams Constrcut, Restrictions]
21597 // The num_teams expression must evaluate to a positive integer value.
21598 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
21599 /*StrictlyPositive=*/true))
21600 return nullptr;
21601
21602 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21604 DKind, OMPC_num_teams, getLangOpts().OpenMP);
21605 if (CaptureRegion != OMPD_unknown &&
21607 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21608 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21609 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21610 HelperValStmt = buildPreInits(getASTContext(), Captures);
21611 }
21612
21613 return new (getASTContext()) OMPNumTeamsClause(
21614 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21615}
21616
21618 SourceLocation StartLoc,
21619 SourceLocation LParenLoc,
21620 SourceLocation EndLoc) {
21621 Expr *ValExpr = ThreadLimit;
21622 Stmt *HelperValStmt = nullptr;
21623
21624 // OpenMP [teams Constrcut, Restrictions]
21625 // The thread_limit expression must evaluate to a positive integer value.
21626 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
21627 /*StrictlyPositive=*/true))
21628 return nullptr;
21629
21630 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
21632 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
21633 if (CaptureRegion != OMPD_unknown &&
21635 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21636 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21637 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21638 HelperValStmt = buildPreInits(getASTContext(), Captures);
21639 }
21640
21641 return new (getASTContext()) OMPThreadLimitClause(
21642 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21643}
21644
21646 SourceLocation StartLoc,
21647 SourceLocation LParenLoc,
21648 SourceLocation EndLoc) {
21649 Expr *ValExpr = Priority;
21650 Stmt *HelperValStmt = nullptr;
21651 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
21652
21653 // OpenMP [2.9.1, task Constrcut]
21654 // The priority-value is a non-negative numerical scalar expression.
21656 ValExpr, SemaRef, OMPC_priority,
21657 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
21658 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
21659 return nullptr;
21660
21661 return new (getASTContext()) OMPPriorityClause(
21662 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
21663}
21664
21666 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
21667 SourceLocation StartLoc, SourceLocation LParenLoc,
21668 SourceLocation ModifierLoc, SourceLocation EndLoc) {
21669 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
21670 "Unexpected grainsize modifier in OpenMP < 51.");
21671
21672 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
21673 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
21675 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21676 << Values << getOpenMPClauseName(OMPC_grainsize);
21677 return nullptr;
21678 }
21679
21680 Expr *ValExpr = Grainsize;
21681 Stmt *HelperValStmt = nullptr;
21682 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
21683
21684 // OpenMP [2.9.2, taskloop Constrcut]
21685 // The parameter of the grainsize clause must be a positive integer
21686 // expression.
21687 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
21688 /*StrictlyPositive=*/true,
21689 /*BuildCapture=*/true,
21690 DSAStack->getCurrentDirective(),
21691 &CaptureRegion, &HelperValStmt))
21692 return nullptr;
21693
21694 return new (getASTContext())
21695 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
21696 StartLoc, LParenLoc, ModifierLoc, EndLoc);
21697}
21698
21700 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
21701 SourceLocation StartLoc, SourceLocation LParenLoc,
21702 SourceLocation ModifierLoc, SourceLocation EndLoc) {
21703 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
21704 "Unexpected num_tasks modifier in OpenMP < 51.");
21705
21706 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
21707 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
21709 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21710 << Values << getOpenMPClauseName(OMPC_num_tasks);
21711 return nullptr;
21712 }
21713
21714 Expr *ValExpr = NumTasks;
21715 Stmt *HelperValStmt = nullptr;
21716 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
21717
21718 // OpenMP [2.9.2, taskloop Constrcut]
21719 // The parameter of the num_tasks clause must be a positive integer
21720 // expression.
21722 ValExpr, SemaRef, OMPC_num_tasks,
21723 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
21724 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
21725 return nullptr;
21726
21727 return new (getASTContext())
21728 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
21729 StartLoc, LParenLoc, ModifierLoc, EndLoc);
21730}
21731
21733 SourceLocation StartLoc,
21734 SourceLocation LParenLoc,
21735 SourceLocation EndLoc) {
21736 // OpenMP [2.13.2, critical construct, Description]
21737 // ... where hint-expression is an integer constant expression that evaluates
21738 // to a valid lock hint.
21739 ExprResult HintExpr =
21740 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
21741 if (HintExpr.isInvalid())
21742 return nullptr;
21743 return new (getASTContext())
21744 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
21745}
21746
21747/// Tries to find omp_event_handle_t type.
21749 DSAStackTy *Stack) {
21750 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
21751 if (!OMPEventHandleT.isNull())
21752 return true;
21753 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
21754 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21755 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21756 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
21757 return false;
21758 }
21759 Stack->setOMPEventHandleT(PT.get());
21760 return true;
21761}
21762
21764 SourceLocation StartLoc,
21765 SourceLocation LParenLoc,
21766 SourceLocation EndLoc) {
21767 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
21768 !Evt->isInstantiationDependent() &&
21771 return nullptr;
21772 // OpenMP 5.0, 2.10.1 task Construct.
21773 // event-handle is a variable of the omp_event_handle_t type.
21774 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
21775 if (!Ref) {
21776 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
21777 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
21778 return nullptr;
21779 }
21780 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
21781 if (!VD) {
21782 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
21783 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
21784 return nullptr;
21785 }
21786 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
21787 VD->getType()) ||
21788 VD->getType().isConstant(getASTContext())) {
21789 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
21790 << "omp_event_handle_t" << 1 << VD->getType()
21791 << Evt->getSourceRange();
21792 return nullptr;
21793 }
21794 // OpenMP 5.0, 2.10.1 task Construct
21795 // [detach clause]... The event-handle will be considered as if it was
21796 // specified on a firstprivate clause.
21797 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
21798 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
21799 DVar.RefExpr) {
21800 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
21801 << getOpenMPClauseName(DVar.CKind)
21802 << getOpenMPClauseName(OMPC_firstprivate);
21804 return nullptr;
21805 }
21806 }
21807
21808 return new (getASTContext())
21809 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
21810}
21811
21813 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
21814 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
21815 SourceLocation EndLoc) {
21816 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
21817 std::string Values;
21818 Values += "'";
21819 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
21820 Values += "'";
21821 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21822 << Values << getOpenMPClauseName(OMPC_dist_schedule);
21823 return nullptr;
21824 }
21825 Expr *ValExpr = ChunkSize;
21826 Stmt *HelperValStmt = nullptr;
21827 if (ChunkSize) {
21828 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
21829 !ChunkSize->isInstantiationDependent() &&
21830 !ChunkSize->containsUnexpandedParameterPack()) {
21831 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
21832 ExprResult Val =
21833 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
21834 if (Val.isInvalid())
21835 return nullptr;
21836
21837 ValExpr = Val.get();
21838
21839 // OpenMP [2.7.1, Restrictions]
21840 // chunk_size must be a loop invariant integer expression with a positive
21841 // value.
21842 if (std::optional<llvm::APSInt> Result =
21844 if (Result->isSigned() && !Result->isStrictlyPositive()) {
21845 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
21846 << "dist_schedule" << ChunkSize->getSourceRange();
21847 return nullptr;
21848 }
21850 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
21851 getLangOpts().OpenMP) != OMPD_unknown &&
21853 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
21854 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
21855 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
21856 HelperValStmt = buildPreInits(getASTContext(), Captures);
21857 }
21858 }
21859 }
21860
21861 return new (getASTContext())
21862 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
21863 Kind, ValExpr, HelperValStmt);
21864}
21865
21868 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
21869 SourceLocation KindLoc, SourceLocation EndLoc) {
21870 if (getLangOpts().OpenMP < 50) {
21871 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
21872 Kind != OMPC_DEFAULTMAP_scalar) {
21873 std::string Value;
21875 Value += "'";
21876 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
21877 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
21878 OMPC_DEFAULTMAP_MODIFIER_tofrom);
21879 Loc = MLoc;
21880 } else {
21881 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
21882 OMPC_DEFAULTMAP_scalar);
21883 Loc = KindLoc;
21884 }
21885 Value += "'";
21886 Diag(Loc, diag::err_omp_unexpected_clause_value)
21887 << Value << getOpenMPClauseName(OMPC_defaultmap);
21888 return nullptr;
21889 }
21890 } else {
21891 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
21892 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
21893 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
21894 if (!isDefaultmapKind || !isDefaultmapModifier) {
21895 StringRef KindValue = "'scalar', 'aggregate', 'pointer'";
21896 if (getLangOpts().OpenMP == 50) {
21897 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
21898 "'firstprivate', 'none', 'default'";
21899 if (!isDefaultmapKind && isDefaultmapModifier) {
21900 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21901 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
21902 } else if (isDefaultmapKind && !isDefaultmapModifier) {
21903 Diag(MLoc, diag::err_omp_unexpected_clause_value)
21904 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
21905 } else {
21906 Diag(MLoc, diag::err_omp_unexpected_clause_value)
21907 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
21908 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21909 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
21910 }
21911 } else {
21912 StringRef ModifierValue =
21913 "'alloc', 'from', 'to', 'tofrom', "
21914 "'firstprivate', 'none', 'default', 'present'";
21915 if (!isDefaultmapKind && isDefaultmapModifier) {
21916 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21917 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
21918 } else if (isDefaultmapKind && !isDefaultmapModifier) {
21919 Diag(MLoc, diag::err_omp_unexpected_clause_value)
21920 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
21921 } else {
21922 Diag(MLoc, diag::err_omp_unexpected_clause_value)
21923 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
21924 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
21925 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
21926 }
21927 }
21928 return nullptr;
21929 }
21930
21931 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
21932 // At most one defaultmap clause for each category can appear on the
21933 // directive.
21934 if (DSAStack->checkDefaultmapCategory(Kind)) {
21935 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
21936 return nullptr;
21937 }
21938 }
21939 if (Kind == OMPC_DEFAULTMAP_unknown) {
21940 // Variable category is not specified - mark all categories.
21941 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
21942 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
21943 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
21944 } else {
21945 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
21946 }
21947
21948 return new (getASTContext())
21949 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
21950}
21951
21954 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
21955 if (!CurLexicalContext->isFileContext() &&
21956 !CurLexicalContext->isExternCContext() &&
21957 !CurLexicalContext->isExternCXXContext() &&
21958 !isa<CXXRecordDecl>(CurLexicalContext) &&
21959 !isa<ClassTemplateDecl>(CurLexicalContext) &&
21960 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
21961 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
21962 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
21963 return false;
21964 }
21965
21966 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
21967 if (getLangOpts().HIP)
21968 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
21969
21970 DeclareTargetNesting.push_back(DTCI);
21971 return true;
21972}
21973
21976 assert(!DeclareTargetNesting.empty() &&
21977 "check isInOpenMPDeclareTargetContext() first!");
21978 return DeclareTargetNesting.pop_back_val();
21979}
21980
21983 for (auto &It : DTCI.ExplicitlyMapped)
21984 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
21985}
21986
21988 if (DeclareTargetNesting.empty())
21989 return;
21990 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
21991 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
21992 << getOpenMPDirectiveName(DTCI.Kind);
21993}
21994
21996 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
21998 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
21999 /*ObjectType=*/QualType(),
22000 /*AllowBuiltinCreation=*/true);
22001
22002 if (Lookup.isAmbiguous())
22003 return nullptr;
22004 Lookup.suppressDiagnostics();
22005
22006 if (!Lookup.isSingleResult()) {
22007 VarOrFuncDeclFilterCCC CCC(SemaRef);
22008 if (TypoCorrection Corrected =
22009 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
22011 SemaRef.diagnoseTypo(Corrected,
22012 PDiag(diag::err_undeclared_var_use_suggest)
22013 << Id.getName());
22014 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22015 return nullptr;
22016 }
22017
22018 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22019 return nullptr;
22020 }
22021
22022 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22023 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22024 !isa<FunctionTemplateDecl>(ND)) {
22025 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22026 return nullptr;
22027 }
22028 return ND;
22029}
22030
22032 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
22034 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22035 isa<FunctionTemplateDecl>(ND)) &&
22036 "Expected variable, function or function template.");
22037
22038 if (auto *VD = dyn_cast<VarDecl>(ND)) {
22039 // Only global variables can be marked as declare target.
22040 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22041 !VD->isStaticDataMember()) {
22042 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
22043 << VD->getNameAsString();
22044 return;
22045 }
22046 }
22047 // Diagnose marking after use as it may lead to incorrect diagnosis and
22048 // codegen.
22049 if (getLangOpts().OpenMP >= 50 &&
22050 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22051 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22052
22053 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22054 if (getLangOpts().HIP)
22055 Diag(Loc, diag::warn_hip_omp_target_directives);
22056
22057 // Explicit declare target lists have precedence.
22058 const unsigned Level = -1;
22059
22060 auto *VD = cast<ValueDecl>(ND);
22061 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22062 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22063 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22064 (*ActiveAttr)->getLevel() == Level) {
22065 Diag(Loc, diag::err_omp_device_type_mismatch)
22066 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22067 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22068 (*ActiveAttr)->getDevType());
22069 return;
22070 }
22071 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22072 (*ActiveAttr)->getLevel() == Level) {
22073 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22074 return;
22075 }
22076
22077 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22078 return;
22079
22080 Expr *IndirectE = nullptr;
22081 bool IsIndirect = false;
22082 if (DTCI.Indirect) {
22083 IndirectE = *DTCI.Indirect;
22084 if (!IndirectE)
22085 IsIndirect = true;
22086 }
22087 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22088 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
22089 SourceRange(Loc, Loc));
22090 ND->addAttr(A);
22091 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22092 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22094 if (auto *VD = dyn_cast<VarDecl>(ND);
22095 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
22096 VD->hasGlobalStorage())
22098}
22099
22101 Sema &SemaRef, Decl *D) {
22102 if (!D || !isa<VarDecl>(D))
22103 return;
22104 auto *VD = cast<VarDecl>(D);
22105 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22106 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22107 if (SemaRef.LangOpts.OpenMP >= 50 &&
22108 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22109 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22110 VD->hasGlobalStorage()) {
22111 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22112 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22113 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22114 // If a lambda declaration and definition appears between a
22115 // declare target directive and the matching end declare target
22116 // directive, all variables that are captured by the lambda
22117 // expression must also appear in a to clause.
22118 SemaRef.Diag(VD->getLocation(),
22119 diag::err_omp_lambda_capture_in_declare_target_not_to);
22120 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22121 << VD << 0 << SR;
22122 return;
22123 }
22124 }
22125 if (MapTy)
22126 return;
22127 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22128 SemaRef.Diag(SL, diag::note_used_here) << SR;
22129}
22130
22132 Sema &SemaRef, DSAStackTy *Stack,
22133 ValueDecl *VD) {
22134 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22135 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22136 /*FullCheck=*/false);
22137}
22138
22140 SourceLocation IdLoc) {
22141 if (!D || D->isInvalidDecl())
22142 return;
22144 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22145 if (auto *VD = dyn_cast<VarDecl>(D)) {
22146 // Only global variables can be marked as declare target.
22147 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22148 !VD->isStaticDataMember())
22149 return;
22150 // 2.10.6: threadprivate variable cannot appear in a declare target
22151 // directive.
22152 if (DSAStack->isThreadPrivate(VD)) {
22153 Diag(SL, diag::err_omp_threadprivate_in_target);
22154 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22155 return;
22156 }
22157 }
22158 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22159 D = FTD->getTemplatedDecl();
22160 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22161 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22162 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22163 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22164 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22165 Diag(FD->getLocation(), diag::note_defined_here) << FD;
22166 return;
22167 }
22168 }
22169 if (auto *VD = dyn_cast<ValueDecl>(D)) {
22170 // Problem if any with var declared with incomplete type will be reported
22171 // as normal, so no need to check it here.
22172 if ((E || !VD->getType()->isIncompleteType()) &&
22174 return;
22176 // Checking declaration inside declare target region.
22177 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22178 isa<FunctionTemplateDecl>(D)) {
22179 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22180 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22181 unsigned Level = DeclareTargetNesting.size();
22182 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22183 return;
22184 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22185 Expr *IndirectE = nullptr;
22186 bool IsIndirect = false;
22187 if (DTCI.Indirect) {
22188 IndirectE = *DTCI.Indirect;
22189 if (!IndirectE)
22190 IsIndirect = true;
22191 }
22192 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22193 getASTContext(),
22194 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22195 : OMPDeclareTargetDeclAttr::MT_To,
22196 DTCI.DT, IndirectE, IsIndirect, Level,
22197 SourceRange(DTCI.Loc, DTCI.Loc));
22198 D->addAttr(A);
22199 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22200 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22201 }
22202 return;
22203 }
22204 }
22205 if (!E)
22206 return;
22208}
22209
22210/// This class visits every VarDecl that the initializer references and adds
22211/// OMPDeclareTargetDeclAttr to each of them.
22212class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
22213 SmallVector<VarDecl *> DeclVector;
22214 Attr *A;
22215
22216public:
22217 /// A StmtVisitor class function that visits all DeclRefExpr and adds
22218 /// OMPDeclareTargetDeclAttr to them.
22220 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
22221 VD->addAttr(A);
22222 DeclVector.push_back(VD);
22223 }
22224 }
22225 /// A function that iterates across each of the Expr's children.
22226 void VisitExpr(Expr *Ex) {
22227 for (auto *Child : Ex->children()) {
22228 Visit(Child);
22229 }
22230 }
22231 /// A function that keeps a record of all the Decls that are variables, has
22232 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
22233 /// each Decl one at a time and use the inherited 'visit' functions to look
22234 /// for DeclRefExpr.
22236 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
22237 DeclVector.push_back(cast<VarDecl>(TD));
22238 while (!DeclVector.empty()) {
22239 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22240 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
22241 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
22242 if (Expr *Ex = TargetVarDecl->getInit())
22243 Visit(Ex);
22244 }
22245 }
22246 }
22247};
22248
22249/// Adding OMPDeclareTargetDeclAttr to variables with static storage
22250/// duration that are referenced in the initializer expression list of
22251/// variables with static storage duration in declare target directive.
22253 GlobalDeclRefChecker Checker;
22254 if (isa<VarDecl>(TargetDecl))
22255 Checker.declareTargetInitializer(TargetDecl);
22256}
22257
22259 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22260 ArrayRef<SourceLocation> MotionModifiersLoc,
22261 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22262 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22263 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22267
22268 // Process motion-modifiers, flag errors for duplicate modifiers.
22269 unsigned Count = 0;
22270 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22271 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22272 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22273 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22274 continue;
22275 }
22276 assert(Count < NumberOfOMPMotionModifiers &&
22277 "Modifiers exceed the allowed number of motion modifiers");
22278 Modifiers[Count] = MotionModifiers[I];
22279 ModifiersLoc[Count] = MotionModifiersLoc[I];
22280 ++Count;
22281 }
22282
22283 MappableVarListInfo MVLI(VarList);
22285 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22286 if (MVLI.ProcessedVarList.empty())
22287 return nullptr;
22288
22289 return OMPToClause::Create(
22290 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22291 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22292 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22293}
22294
22296 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22297 ArrayRef<SourceLocation> MotionModifiersLoc,
22298 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22299 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22300 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22304
22305 // Process motion-modifiers, flag errors for duplicate modifiers.
22306 unsigned Count = 0;
22307 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22308 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22309 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22310 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22311 continue;
22312 }
22313 assert(Count < NumberOfOMPMotionModifiers &&
22314 "Modifiers exceed the allowed number of motion modifiers");
22315 Modifiers[Count] = MotionModifiers[I];
22316 ModifiersLoc[Count] = MotionModifiersLoc[I];
22317 ++Count;
22318 }
22319
22320 MappableVarListInfo MVLI(VarList);
22321 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22322 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22323 if (MVLI.ProcessedVarList.empty())
22324 return nullptr;
22325
22326 return OMPFromClause::Create(
22327 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22328 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22329 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22330}
22331
22332OMPClause *
22334 const OMPVarListLocTy &Locs) {
22335 MappableVarListInfo MVLI(VarList);
22336 SmallVector<Expr *, 8> PrivateCopies;
22338
22339 for (Expr *RefExpr : VarList) {
22340 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22341 SourceLocation ELoc;
22342 SourceRange ERange;
22343 Expr *SimpleRefExpr = RefExpr;
22344 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22345 if (Res.second) {
22346 // It will be analyzed later.
22347 MVLI.ProcessedVarList.push_back(RefExpr);
22348 PrivateCopies.push_back(nullptr);
22349 Inits.push_back(nullptr);
22350 }
22351 ValueDecl *D = Res.first;
22352 if (!D)
22353 continue;
22354
22355 QualType Type = D->getType();
22356 Type = Type.getNonReferenceType().getUnqualifiedType();
22357
22358 auto *VD = dyn_cast<VarDecl>(D);
22359
22360 // Item should be a pointer or reference to pointer.
22361 if (!Type->isPointerType()) {
22362 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22363 << 0 << RefExpr->getSourceRange();
22364 continue;
22365 }
22366
22367 // Build the private variable and the expression that refers to it.
22368 auto VDPrivate =
22369 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
22370 D->hasAttrs() ? &D->getAttrs() : nullptr,
22371 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22372 if (VDPrivate->isInvalidDecl())
22373 continue;
22374
22375 SemaRef.CurContext->addDecl(VDPrivate);
22376 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22377 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22378
22379 // Add temporary variable to initialize the private copy of the pointer.
22380 VarDecl *VDInit =
22381 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
22382 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22383 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22385 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
22386 /*DirectInit=*/false);
22387
22388 // If required, build a capture to implement the privatization initialized
22389 // with the current list item value.
22390 DeclRefExpr *Ref = nullptr;
22391 if (!VD)
22392 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22393 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22394 PrivateCopies.push_back(VDPrivateRefExpr);
22395 Inits.push_back(VDInitRefExpr);
22396
22397 // We need to add a data sharing attribute for this variable to make sure it
22398 // is correctly captured. A variable that shows up in a use_device_ptr has
22399 // similar properties of a first private variable.
22400 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22401
22402 // Create a mappable component for the list item. List items in this clause
22403 // only need a component.
22404 MVLI.VarBaseDeclarations.push_back(D);
22405 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22406 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22407 /*IsNonContiguous=*/false);
22408 }
22409
22410 if (MVLI.ProcessedVarList.empty())
22411 return nullptr;
22412
22414 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22415 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22416}
22417
22418OMPClause *
22420 const OMPVarListLocTy &Locs) {
22421 MappableVarListInfo MVLI(VarList);
22422
22423 for (Expr *RefExpr : VarList) {
22424 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22425 SourceLocation ELoc;
22426 SourceRange ERange;
22427 Expr *SimpleRefExpr = RefExpr;
22428 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22429 /*AllowArraySection=*/true);
22430 if (Res.second) {
22431 // It will be analyzed later.
22432 MVLI.ProcessedVarList.push_back(RefExpr);
22433 }
22434 ValueDecl *D = Res.first;
22435 if (!D)
22436 continue;
22437 auto *VD = dyn_cast<VarDecl>(D);
22438
22439 // If required, build a capture to implement the privatization initialized
22440 // with the current list item value.
22441 DeclRefExpr *Ref = nullptr;
22442 if (!VD)
22443 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22444 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22445
22446 // We need to add a data sharing attribute for this variable to make sure it
22447 // is correctly captured. A variable that shows up in a use_device_addr has
22448 // similar properties of a first private variable.
22449 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22450
22451 // Create a mappable component for the list item. List items in this clause
22452 // only need a component.
22453 MVLI.VarBaseDeclarations.push_back(D);
22454 MVLI.VarComponents.emplace_back();
22455 Expr *Component = SimpleRefExpr;
22456 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22457 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22458 Component =
22460 MVLI.VarComponents.back().emplace_back(Component, D,
22461 /*IsNonContiguous=*/false);
22462 }
22463
22464 if (MVLI.ProcessedVarList.empty())
22465 return nullptr;
22466
22468 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22469 MVLI.VarComponents);
22470}
22471
22472OMPClause *
22474 const OMPVarListLocTy &Locs) {
22475 MappableVarListInfo MVLI(VarList);
22476 for (Expr *RefExpr : VarList) {
22477 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
22478 SourceLocation ELoc;
22479 SourceRange ERange;
22480 Expr *SimpleRefExpr = RefExpr;
22481 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22482 if (Res.second) {
22483 // It will be analyzed later.
22484 MVLI.ProcessedVarList.push_back(RefExpr);
22485 }
22486 ValueDecl *D = Res.first;
22487 if (!D)
22488 continue;
22489
22490 QualType Type = D->getType();
22491 // item should be a pointer or array or reference to pointer or array
22492 if (!Type.getNonReferenceType()->isPointerType() &&
22493 !Type.getNonReferenceType()->isArrayType()) {
22494 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22495 << 0 << RefExpr->getSourceRange();
22496 continue;
22497 }
22498
22499 // Check if the declaration in the clause does not show up in any data
22500 // sharing attribute.
22501 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22502 if (isOpenMPPrivate(DVar.CKind)) {
22503 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22504 << getOpenMPClauseName(DVar.CKind)
22505 << getOpenMPClauseName(OMPC_is_device_ptr)
22506 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22508 continue;
22509 }
22510
22511 const Expr *ConflictExpr;
22512 if (DSAStack->checkMappableExprComponentListsForDecl(
22513 D, /*CurrentRegionOnly=*/true,
22514 [&ConflictExpr](
22516 OpenMPClauseKind) -> bool {
22517 ConflictExpr = R.front().getAssociatedExpression();
22518 return true;
22519 })) {
22520 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22521 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22522 << ConflictExpr->getSourceRange();
22523 continue;
22524 }
22525
22526 // Store the components in the stack so that they can be used to check
22527 // against other clauses later on.
22529 SimpleRefExpr, D, /*IsNonContiguous=*/false);
22530 DSAStack->addMappableExpressionComponents(
22531 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
22532
22533 // Record the expression we've just processed.
22534 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
22535
22536 // Create a mappable component for the list item. List items in this clause
22537 // only need a component. We use a null declaration to signal fields in
22538 // 'this'.
22539 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22540 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22541 "Unexpected device pointer expression!");
22542 MVLI.VarBaseDeclarations.push_back(
22543 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
22544 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22545 MVLI.VarComponents.back().push_back(MC);
22546 }
22547
22548 if (MVLI.ProcessedVarList.empty())
22549 return nullptr;
22550
22552 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22553 MVLI.VarComponents);
22554}
22555
22556OMPClause *
22558 const OMPVarListLocTy &Locs) {
22559 MappableVarListInfo MVLI(VarList);
22560 for (Expr *RefExpr : VarList) {
22561 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
22562 SourceLocation ELoc;
22563 SourceRange ERange;
22564 Expr *SimpleRefExpr = RefExpr;
22565 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22566 /*AllowArraySection=*/true);
22567 if (Res.second) {
22568 // It will be analyzed later.
22569 MVLI.ProcessedVarList.push_back(RefExpr);
22570 }
22571 ValueDecl *D = Res.first;
22572 if (!D)
22573 continue;
22574
22575 // Check if the declaration in the clause does not show up in any data
22576 // sharing attribute.
22577 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22578 if (isOpenMPPrivate(DVar.CKind)) {
22579 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22580 << getOpenMPClauseName(DVar.CKind)
22581 << getOpenMPClauseName(OMPC_has_device_addr)
22582 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22584 continue;
22585 }
22586
22587 const Expr *ConflictExpr;
22588 if (DSAStack->checkMappableExprComponentListsForDecl(
22589 D, /*CurrentRegionOnly=*/true,
22590 [&ConflictExpr](
22592 OpenMPClauseKind) -> bool {
22593 ConflictExpr = R.front().getAssociatedExpression();
22594 return true;
22595 })) {
22596 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22597 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22598 << ConflictExpr->getSourceRange();
22599 continue;
22600 }
22601
22602 // Store the components in the stack so that they can be used to check
22603 // against other clauses later on.
22604 Expr *Component = SimpleRefExpr;
22605 auto *VD = dyn_cast<VarDecl>(D);
22606 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22607 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22608 Component =
22611 Component, D, /*IsNonContiguous=*/false);
22612 DSAStack->addMappableExpressionComponents(
22613 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
22614
22615 // Record the expression we've just processed.
22616 if (!VD && !SemaRef.CurContext->isDependentContext()) {
22617 DeclRefExpr *Ref =
22618 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22619 assert(Ref && "has_device_addr capture failed");
22620 MVLI.ProcessedVarList.push_back(Ref);
22621 } else
22622 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
22623
22624 // Create a mappable component for the list item. List items in this clause
22625 // only need a component. We use a null declaration to signal fields in
22626 // 'this'.
22627 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22628 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22629 "Unexpected device pointer expression!");
22630 MVLI.VarBaseDeclarations.push_back(
22631 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
22632 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22633 MVLI.VarComponents.back().push_back(MC);
22634 }
22635
22636 if (MVLI.ProcessedVarList.empty())
22637 return nullptr;
22638
22640 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22641 MVLI.VarComponents);
22642}
22643
22645 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
22646 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
22647 if (Allocator) {
22648 // OpenMP [2.11.4 allocate Clause, Description]
22649 // allocator is an expression of omp_allocator_handle_t type.
22650 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
22651 return nullptr;
22652
22653 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
22654 if (AllocatorRes.isInvalid())
22655 return nullptr;
22656 AllocatorRes = SemaRef.PerformImplicitConversion(
22657 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
22659 /*AllowExplicit=*/true);
22660 if (AllocatorRes.isInvalid())
22661 return nullptr;
22662 Allocator = AllocatorRes.get();
22663 } else {
22664 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
22665 // allocate clauses that appear on a target construct or on constructs in a
22666 // target region must specify an allocator expression unless a requires
22667 // directive with the dynamic_allocators clause is present in the same
22668 // compilation unit.
22669 if (getLangOpts().OpenMPIsTargetDevice &&
22670 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
22671 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
22672 }
22673 // Analyze and build list of variables.
22675 for (Expr *RefExpr : VarList) {
22676 assert(RefExpr && "NULL expr in OpenMP private clause.");
22677 SourceLocation ELoc;
22678 SourceRange ERange;
22679 Expr *SimpleRefExpr = RefExpr;
22680 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22681 if (Res.second) {
22682 // It will be analyzed later.
22683 Vars.push_back(RefExpr);
22684 }
22685 ValueDecl *D = Res.first;
22686 if (!D)
22687 continue;
22688
22689 auto *VD = dyn_cast<VarDecl>(D);
22690 DeclRefExpr *Ref = nullptr;
22691 if (!VD && !SemaRef.CurContext->isDependentContext())
22692 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
22693 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
22694 ? RefExpr->IgnoreParens()
22695 : Ref);
22696 }
22697
22698 if (Vars.empty())
22699 return nullptr;
22700
22701 if (Allocator)
22702 DSAStack->addInnerAllocatorExpr(Allocator);
22703 return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc,
22704 Allocator, ColonLoc, EndLoc, Vars);
22705}
22706
22708 SourceLocation StartLoc,
22709 SourceLocation LParenLoc,
22710 SourceLocation EndLoc) {
22712 for (Expr *RefExpr : VarList) {
22713 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
22714 SourceLocation ELoc;
22715 SourceRange ERange;
22716 Expr *SimpleRefExpr = RefExpr;
22717 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22718 if (Res.second)
22719 // It will be analyzed later.
22720 Vars.push_back(RefExpr);
22721 ValueDecl *D = Res.first;
22722 if (!D)
22723 continue;
22724
22725 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
22726 // A list-item cannot appear in more than one nontemporal clause.
22727 if (const Expr *PrevRef =
22728 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
22729 Diag(ELoc, diag::err_omp_used_in_clause_twice)
22730 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
22731 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
22732 << getOpenMPClauseName(OMPC_nontemporal);
22733 continue;
22734 }
22735
22736 Vars.push_back(RefExpr);
22737 }
22738
22739 if (Vars.empty())
22740 return nullptr;
22741
22742 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
22743 EndLoc, Vars);
22744}
22745
22747 Stmt *AStmt,
22748 SourceLocation StartLoc,
22749 SourceLocation EndLoc) {
22750 if (!AStmt)
22751 return StmtError();
22752
22754
22755 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
22756 AStmt);
22757}
22758
22760 SourceLocation StartLoc,
22761 SourceLocation LParenLoc,
22762 SourceLocation EndLoc) {
22764 for (Expr *RefExpr : VarList) {
22765 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
22766 SourceLocation ELoc;
22767 SourceRange ERange;
22768 Expr *SimpleRefExpr = RefExpr;
22769 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22770 /*AllowArraySection=*/true);
22771 if (Res.second)
22772 // It will be analyzed later.
22773 Vars.push_back(RefExpr);
22774 ValueDecl *D = Res.first;
22775 if (!D)
22776 continue;
22777
22778 const DSAStackTy::DSAVarData DVar =
22779 DSAStack->getTopDSA(D, /*FromParent=*/true);
22780 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
22781 // A list item that appears in the inclusive or exclusive clause must appear
22782 // in a reduction clause with the inscan modifier on the enclosing
22783 // worksharing-loop, worksharing-loop SIMD, or simd construct.
22784 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
22785 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
22786 << RefExpr->getSourceRange();
22787
22788 if (DSAStack->getParentDirective() != OMPD_unknown)
22789 DSAStack->markDeclAsUsedInScanDirective(D);
22790 Vars.push_back(RefExpr);
22791 }
22792
22793 if (Vars.empty())
22794 return nullptr;
22795
22796 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
22797 EndLoc, Vars);
22798}
22799
22801 SourceLocation StartLoc,
22802 SourceLocation LParenLoc,
22803 SourceLocation EndLoc) {
22805 for (Expr *RefExpr : VarList) {
22806 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
22807 SourceLocation ELoc;
22808 SourceRange ERange;
22809 Expr *SimpleRefExpr = RefExpr;
22810 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22811 /*AllowArraySection=*/true);
22812 if (Res.second)
22813 // It will be analyzed later.
22814 Vars.push_back(RefExpr);
22815 ValueDecl *D = Res.first;
22816 if (!D)
22817 continue;
22818
22819 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
22820 DSAStackTy::DSAVarData DVar;
22821 if (ParentDirective != OMPD_unknown)
22822 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
22823 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
22824 // A list item that appears in the inclusive or exclusive clause must appear
22825 // in a reduction clause with the inscan modifier on the enclosing
22826 // worksharing-loop, worksharing-loop SIMD, or simd construct.
22827 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
22828 DVar.Modifier != OMPC_REDUCTION_inscan) {
22829 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
22830 << RefExpr->getSourceRange();
22831 } else {
22832 DSAStack->markDeclAsUsedInScanDirective(D);
22833 }
22834 Vars.push_back(RefExpr);
22835 }
22836
22837 if (Vars.empty())
22838 return nullptr;
22839
22840 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
22841 EndLoc, Vars);
22842}
22843
22844/// Tries to find omp_alloctrait_t type.
22845static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
22846 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
22847 if (!OMPAlloctraitT.isNull())
22848 return true;
22849 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
22850 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
22851 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22852 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
22853 return false;
22854 }
22855 Stack->setOMPAlloctraitT(PT.get());
22856 return true;
22857}
22858
22860 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
22862 ASTContext &Context = getASTContext();
22863 // OpenMP [2.12.5, target Construct]
22864 // allocator is an identifier of omp_allocator_handle_t type.
22865 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
22866 return nullptr;
22867 // OpenMP [2.12.5, target Construct]
22868 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
22869 if (llvm::any_of(
22870 Data,
22871 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
22872 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
22873 return nullptr;
22874 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
22875 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
22876 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
22877 StringRef Allocator =
22878 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
22879 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
22880 PredefinedAllocators.insert(SemaRef.LookupSingleName(
22881 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
22882 }
22883
22885 for (const UsesAllocatorsData &D : Data) {
22886 Expr *AllocatorExpr = nullptr;
22887 // Check allocator expression.
22888 if (D.Allocator->isTypeDependent()) {
22889 AllocatorExpr = D.Allocator;
22890 } else {
22891 // Traits were specified - need to assign new allocator to the specified
22892 // allocator, so it must be an lvalue.
22893 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
22894 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
22895 bool IsPredefinedAllocator = false;
22896 if (DRE) {
22897 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
22898 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
22899 IsPredefinedAllocator =
22900 AllocatorTy !=
22901 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
22902 }
22903 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
22904 QualType AllocatorExprType = AllocatorExpr->getType();
22905 bool IsTypeCompatible = IsPredefinedAllocator;
22906 IsTypeCompatible = IsTypeCompatible ||
22907 Context.hasSameUnqualifiedType(AllocatorExprType,
22908 OMPAllocatorHandleT);
22909 IsTypeCompatible =
22910 IsTypeCompatible ||
22911 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
22912 bool IsNonConstantLValue =
22913 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
22914 if (!DRE || !IsTypeCompatible ||
22915 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
22916 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
22917 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
22918 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
22919 continue;
22920 }
22921 // OpenMP [2.12.5, target Construct]
22922 // Predefined allocators appearing in a uses_allocators clause cannot have
22923 // traits specified.
22924 if (IsPredefinedAllocator && D.AllocatorTraits) {
22925 Diag(D.AllocatorTraits->getExprLoc(),
22926 diag::err_omp_predefined_allocator_with_traits)
22927 << D.AllocatorTraits->getSourceRange();
22928 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
22929 << cast<NamedDecl>(DRE->getDecl())->getName()
22930 << D.Allocator->getSourceRange();
22931 continue;
22932 }
22933 // OpenMP [2.12.5, target Construct]
22934 // Non-predefined allocators appearing in a uses_allocators clause must
22935 // have traits specified.
22936 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
22937 Diag(D.Allocator->getExprLoc(),
22938 diag::err_omp_nonpredefined_allocator_without_traits);
22939 continue;
22940 }
22941 // No allocator traits - just convert it to rvalue.
22942 if (!D.AllocatorTraits)
22943 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
22944 DSAStack->addUsesAllocatorsDecl(
22945 DRE->getDecl(),
22946 IsPredefinedAllocator
22947 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
22948 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
22949 }
22950 Expr *AllocatorTraitsExpr = nullptr;
22951 if (D.AllocatorTraits) {
22952 if (D.AllocatorTraits->isTypeDependent()) {
22953 AllocatorTraitsExpr = D.AllocatorTraits;
22954 } else {
22955 // OpenMP [2.12.5, target Construct]
22956 // Arrays that contain allocator traits that appear in a uses_allocators
22957 // clause must be constant arrays, have constant values and be defined
22958 // in the same scope as the construct in which the clause appears.
22959 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
22960 // Check that traits expr is a constant array.
22961 QualType TraitTy;
22962 if (const ArrayType *Ty =
22963 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
22964 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
22965 TraitTy = ConstArrayTy->getElementType();
22966 if (TraitTy.isNull() ||
22967 !(Context.hasSameUnqualifiedType(TraitTy,
22968 DSAStack->getOMPAlloctraitT()) ||
22969 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
22970 /*CompareUnqualified=*/true))) {
22971 Diag(D.AllocatorTraits->getExprLoc(),
22972 diag::err_omp_expected_array_alloctraits)
22973 << AllocatorTraitsExpr->getType();
22974 continue;
22975 }
22976 // Do not map by default allocator traits if it is a standalone
22977 // variable.
22978 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
22979 DSAStack->addUsesAllocatorsDecl(
22980 DRE->getDecl(),
22981 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
22982 }
22983 }
22984 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
22985 NewD.Allocator = AllocatorExpr;
22986 NewD.AllocatorTraits = AllocatorTraitsExpr;
22987 NewD.LParenLoc = D.LParenLoc;
22988 NewD.RParenLoc = D.RParenLoc;
22989 }
22990 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
22991 EndLoc, NewData);
22992}
22993
22995 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
22996 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
22998 for (Expr *RefExpr : Locators) {
22999 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23000 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23001 // It will be analyzed later.
23002 Vars.push_back(RefExpr);
23003 continue;
23004 }
23005
23006 SourceLocation ELoc = RefExpr->getExprLoc();
23007 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23008
23009 if (!SimpleExpr->isLValue()) {
23010 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23011 << 1 << 0 << RefExpr->getSourceRange();
23012 continue;
23013 }
23014
23015 ExprResult Res;
23016 {
23018 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23019 }
23020 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23021 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23022 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23023 << 1 << 0 << RefExpr->getSourceRange();
23024 continue;
23025 }
23026 Vars.push_back(SimpleExpr);
23027 }
23028
23029 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
23030 ColonLoc, EndLoc, Modifier, Vars);
23031}
23032
23034 SourceLocation KindLoc,
23035 SourceLocation StartLoc,
23036 SourceLocation LParenLoc,
23037 SourceLocation EndLoc) {
23038 if (Kind == OMPC_BIND_unknown) {
23039 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23040 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23041 /*Last=*/unsigned(OMPC_BIND_unknown))
23042 << getOpenMPClauseName(OMPC_bind);
23043 return nullptr;
23044 }
23045
23046 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
23047 LParenLoc, EndLoc);
23048}
23049
23051 SourceLocation StartLoc,
23052 SourceLocation LParenLoc,
23053 SourceLocation EndLoc) {
23054 Expr *ValExpr = Size;
23055 Stmt *HelperValStmt = nullptr;
23056
23057 // OpenMP [2.5, Restrictions]
23058 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23059 // value.
23060 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
23061 /*StrictlyPositive=*/false))
23062 return nullptr;
23063
23064 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23066 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
23067 if (CaptureRegion != OMPD_unknown &&
23069 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23070 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23071 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23072 HelperValStmt = buildPreInits(getASTContext(), Captures);
23073 }
23074
23076 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23077}
23078
23081 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23082 SourceLocation LParenLoc, SourceLocation EndLoc) {
23083
23084 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
23085 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23086 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23087 DepType != OMPC_DOACROSS_source_omp_cur_iteration &&
23088 DepType != OMPC_DOACROSS_source) {
23089 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23090 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23091 return nullptr;
23092 }
23093
23096 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23097 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
23098 SemaRef,
23099 DepType == OMPC_DOACROSS_source ||
23100 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23101 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23102 VarList, DSAStack, EndLoc);
23103 Vars = VarOffset.Vars;
23104 OpsOffs = VarOffset.OpsOffs;
23105 TotalDepCount = VarOffset.TotalDepCount;
23106 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
23107 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23108 TotalDepCount.getZExtValue());
23109 if (DSAStack->isParentOrderedRegion())
23110 DSAStack->addDoacrossDependClause(C, OpsOffs);
23111 return C;
23112}
23113
23115 SourceLocation StartLoc,
23116 SourceLocation LParenLoc,
23117 SourceLocation EndLoc) {
23118 return new (getASTContext())
23119 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
23120}
23121
23123 SourceLocation EndLoc) {
23124 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
23125}
23126
23128 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
23129 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
23130 Expr *Stride, SourceLocation RBLoc) {
23131 ASTContext &Context = getASTContext();
23132 if (Base->hasPlaceholderType() &&
23133 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23135 if (Result.isInvalid())
23136 return ExprError();
23137 Base = Result.get();
23138 }
23139 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
23141 if (Result.isInvalid())
23142 return ExprError();
23144 if (Result.isInvalid())
23145 return ExprError();
23146 LowerBound = Result.get();
23147 }
23148 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23150 if (Result.isInvalid())
23151 return ExprError();
23153 if (Result.isInvalid())
23154 return ExprError();
23155 Length = Result.get();
23156 }
23157 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
23159 if (Result.isInvalid())
23160 return ExprError();
23162 if (Result.isInvalid())
23163 return ExprError();
23164 Stride = Result.get();
23165 }
23166
23167 // Build an unanalyzed expression if either operand is type-dependent.
23168 if (Base->isTypeDependent() ||
23169 (LowerBound &&
23170 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
23171 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23172 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
23173 return new (Context) ArraySectionExpr(
23174 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
23175 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23176 }
23177
23178 // Perform default conversions.
23180 QualType ResultTy;
23181 if (OriginalTy->isAnyPointerType()) {
23182 ResultTy = OriginalTy->getPointeeType();
23183 } else if (OriginalTy->isArrayType()) {
23184 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
23185 } else {
23186 return ExprError(
23187 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23188 << Base->getSourceRange());
23189 }
23190 // C99 6.5.2.1p1
23191 if (LowerBound) {
23192 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
23193 LowerBound);
23194 if (Res.isInvalid())
23195 return ExprError(Diag(LowerBound->getExprLoc(),
23196 diag::err_omp_typecheck_section_not_integer)
23197 << 0 << LowerBound->getSourceRange());
23198 LowerBound = Res.get();
23199
23200 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23201 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23202 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
23203 << 0 << LowerBound->getSourceRange();
23204 }
23205 if (Length) {
23206 auto Res =
23207 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
23208 if (Res.isInvalid())
23209 return ExprError(Diag(Length->getExprLoc(),
23210 diag::err_omp_typecheck_section_not_integer)
23211 << 1 << Length->getSourceRange());
23212 Length = Res.get();
23213
23214 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23215 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23216 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23217 << 1 << Length->getSourceRange();
23218 }
23219 if (Stride) {
23220 ExprResult Res =
23222 if (Res.isInvalid())
23223 return ExprError(Diag(Stride->getExprLoc(),
23224 diag::err_omp_typecheck_section_not_integer)
23225 << 1 << Stride->getSourceRange());
23226 Stride = Res.get();
23227
23228 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23229 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23230 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
23231 << 1 << Stride->getSourceRange();
23232 }
23233
23234 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
23235 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
23236 // type. Note that functions are not objects, and that (in C99 parlance)
23237 // incomplete types are not object types.
23238 if (ResultTy->isFunctionType()) {
23239 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
23240 << ResultTy << Base->getSourceRange();
23241 return ExprError();
23242 }
23243
23244 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
23245 diag::err_omp_section_incomplete_type, Base))
23246 return ExprError();
23247
23248 if (LowerBound && !OriginalTy->isAnyPointerType()) {
23250 if (LowerBound->EvaluateAsInt(Result, Context)) {
23251 // OpenMP 5.0, [2.1.5 Array Sections]
23252 // The array section must be a subset of the original array.
23253 llvm::APSInt LowerBoundValue = Result.Val.getInt();
23254 if (LowerBoundValue.isNegative()) {
23255 Diag(LowerBound->getExprLoc(),
23256 diag::err_omp_section_not_subset_of_array)
23257 << LowerBound->getSourceRange();
23258 return ExprError();
23259 }
23260 }
23261 }
23262
23263 if (Length) {
23265 if (Length->EvaluateAsInt(Result, Context)) {
23266 // OpenMP 5.0, [2.1.5 Array Sections]
23267 // The length must evaluate to non-negative integers.
23268 llvm::APSInt LengthValue = Result.Val.getInt();
23269 if (LengthValue.isNegative()) {
23270 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23271 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
23272 << Length->getSourceRange();
23273 return ExprError();
23274 }
23275 }
23276 } else if (ColonLocFirst.isValid() &&
23277 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
23278 !OriginalTy->isVariableArrayType()))) {
23279 // OpenMP 5.0, [2.1.5 Array Sections]
23280 // When the size of the array dimension is not known, the length must be
23281 // specified explicitly.
23282 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23283 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
23284 return ExprError();
23285 }
23286
23287 if (Stride) {
23289 if (Stride->EvaluateAsInt(Result, Context)) {
23290 // OpenMP 5.0, [2.1.5 Array Sections]
23291 // The stride must evaluate to a positive integer.
23292 llvm::APSInt StrideValue = Result.Val.getInt();
23293 if (!StrideValue.isStrictlyPositive()) {
23294 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
23295 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
23296 << Stride->getSourceRange();
23297 return ExprError();
23298 }
23299 }
23300 }
23301
23302 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23304 if (Result.isInvalid())
23305 return ExprError();
23306 Base = Result.get();
23307 }
23308 return new (Context) ArraySectionExpr(
23309 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
23310 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23311}
23312
23314 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
23315 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
23316 ASTContext &Context = getASTContext();
23317 if (Base->hasPlaceholderType()) {
23319 if (Result.isInvalid())
23320 return ExprError();
23322 if (Result.isInvalid())
23323 return ExprError();
23324 Base = Result.get();
23325 }
23326 QualType BaseTy = Base->getType();
23327 // Delay analysis of the types/expressions if instantiation/specialization is
23328 // required.
23329 if (!BaseTy->isPointerType() && Base->isTypeDependent())
23330 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
23331 LParenLoc, RParenLoc, Dims, Brackets);
23332 if (!BaseTy->isPointerType() ||
23333 (!Base->isTypeDependent() &&
23334 BaseTy->getPointeeType()->isIncompleteType()))
23335 return ExprError(Diag(Base->getExprLoc(),
23336 diag::err_omp_non_pointer_type_array_shaping_base)
23337 << Base->getSourceRange());
23338
23339 SmallVector<Expr *, 4> NewDims;
23340 bool ErrorFound = false;
23341 for (Expr *Dim : Dims) {
23342 if (Dim->hasPlaceholderType()) {
23344 if (Result.isInvalid()) {
23345 ErrorFound = true;
23346 continue;
23347 }
23349 if (Result.isInvalid()) {
23350 ErrorFound = true;
23351 continue;
23352 }
23353 Dim = Result.get();
23354 }
23355 if (!Dim->isTypeDependent()) {
23357 PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
23358 if (Result.isInvalid()) {
23359 ErrorFound = true;
23360 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23361 << Dim->getSourceRange();
23362 continue;
23363 }
23364 Dim = Result.get();
23365 Expr::EvalResult EvResult;
23366 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23367 // OpenMP 5.0, [2.1.4 Array Shaping]
23368 // Each si is an integral type expression that must evaluate to a
23369 // positive integer.
23370 llvm::APSInt Value = EvResult.Val.getInt();
23371 if (!Value.isStrictlyPositive()) {
23372 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23373 << toString(Value, /*Radix=*/10, /*Signed=*/true)
23374 << Dim->getSourceRange();
23375 ErrorFound = true;
23376 continue;
23377 }
23378 }
23379 }
23380 NewDims.push_back(Dim);
23381 }
23382 if (ErrorFound)
23383 return ExprError();
23384 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
23385 LParenLoc, RParenLoc, NewDims, Brackets);
23386}
23387
23389 SourceLocation IteratorKwLoc,
23390 SourceLocation LLoc,
23391 SourceLocation RLoc,
23393 ASTContext &Context = getASTContext();
23395 bool IsCorrect = true;
23396 for (const OMPIteratorData &D : Data) {
23397 TypeSourceInfo *TInfo = nullptr;
23398 SourceLocation StartLoc;
23399 QualType DeclTy;
23400 if (!D.Type.getAsOpaquePtr()) {
23401 // OpenMP 5.0, 2.1.6 Iterators
23402 // In an iterator-specifier, if the iterator-type is not specified then
23403 // the type of that iterator is of int type.
23404 DeclTy = Context.IntTy;
23405 StartLoc = D.DeclIdentLoc;
23406 } else {
23407 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
23408 StartLoc = TInfo->getTypeLoc().getBeginLoc();
23409 }
23410
23411 bool IsDeclTyDependent = DeclTy->isDependentType() ||
23412 DeclTy->containsUnexpandedParameterPack() ||
23413 DeclTy->isInstantiationDependentType();
23414 if (!IsDeclTyDependent) {
23415 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23416 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23417 // The iterator-type must be an integral or pointer type.
23418 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23419 << DeclTy;
23420 IsCorrect = false;
23421 continue;
23422 }
23423 if (DeclTy.isConstant(Context)) {
23424 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23425 // The iterator-type must not be const qualified.
23426 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23427 << DeclTy;
23428 IsCorrect = false;
23429 continue;
23430 }
23431 }
23432
23433 // Iterator declaration.
23434 assert(D.DeclIdent && "Identifier expected.");
23435 // Always try to create iterator declarator to avoid extra error messages
23436 // about unknown declarations use.
23437 auto *VD =
23438 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
23439 D.DeclIdent, DeclTy, TInfo, SC_None);
23440 VD->setImplicit();
23441 if (S) {
23442 // Check for conflicting previous declaration.
23443 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
23445 RedeclarationKind::ForVisibleRedeclaration);
23446 Previous.suppressDiagnostics();
23448
23450 /*ConsiderLinkage=*/false,
23451 /*AllowInlineNamespace=*/false);
23452 if (!Previous.empty()) {
23453 NamedDecl *Old = Previous.getRepresentativeDecl();
23454 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
23455 Diag(Old->getLocation(), diag::note_previous_definition);
23456 } else {
23458 }
23459 } else {
23461 }
23462
23463 /// Act on the iterator variable declaration.
23465
23466 Expr *Begin = D.Range.Begin;
23467 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
23468 ExprResult BeginRes =
23470 Begin = BeginRes.get();
23471 }
23472 Expr *End = D.Range.End;
23473 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
23474 ExprResult EndRes =
23476 End = EndRes.get();
23477 }
23478 Expr *Step = D.Range.Step;
23479 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
23480 if (!Step->getType()->isIntegralType(Context)) {
23481 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
23482 << Step << Step->getSourceRange();
23483 IsCorrect = false;
23484 continue;
23485 }
23486 std::optional<llvm::APSInt> Result =
23487 Step->getIntegerConstantExpr(Context);
23488 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
23489 // If the step expression of a range-specification equals zero, the
23490 // behavior is unspecified.
23491 if (Result && Result->isZero()) {
23492 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
23493 << Step << Step->getSourceRange();
23494 IsCorrect = false;
23495 continue;
23496 }
23497 }
23498 if (!Begin || !End || !IsCorrect) {
23499 IsCorrect = false;
23500 continue;
23501 }
23502 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
23503 IDElem.IteratorDecl = VD;
23504 IDElem.AssignmentLoc = D.AssignLoc;
23505 IDElem.Range.Begin = Begin;
23506 IDElem.Range.End = End;
23507 IDElem.Range.Step = Step;
23508 IDElem.ColonLoc = D.ColonLoc;
23509 IDElem.SecondColonLoc = D.SecColonLoc;
23510 }
23511 if (!IsCorrect) {
23512 // Invalidate all created iterator declarations if error is found.
23513 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
23514 if (Decl *ID = D.IteratorDecl)
23515 ID->setInvalidDecl();
23516 }
23517 return ExprError();
23518 }
23521 // Build number of ityeration for each iteration range.
23522 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
23523 // ((Begini-Stepi-1-Endi) / -Stepi);
23525 // (Endi - Begini)
23526 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
23527 D.Range.End, D.Range.Begin);
23528 if (!Res.isUsable()) {
23529 IsCorrect = false;
23530 continue;
23531 }
23532 ExprResult St, St1;
23533 if (D.Range.Step) {
23534 St = D.Range.Step;
23535 // (Endi - Begini) + Stepi
23536 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
23537 St.get());
23538 if (!Res.isUsable()) {
23539 IsCorrect = false;
23540 continue;
23541 }
23542 // (Endi - Begini) + Stepi - 1
23544 D.AssignmentLoc, BO_Sub, Res.get(),
23545 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
23546 if (!Res.isUsable()) {
23547 IsCorrect = false;
23548 continue;
23549 }
23550 // ((Endi - Begini) + Stepi - 1) / Stepi
23551 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
23552 St.get());
23553 if (!Res.isUsable()) {
23554 IsCorrect = false;
23555 continue;
23556 }
23557 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
23558 D.Range.Step);
23559 // (Begini - Endi)
23561 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
23562 if (!Res1.isUsable()) {
23563 IsCorrect = false;
23564 continue;
23565 }
23566 // (Begini - Endi) - Stepi
23567 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
23568 St1.get());
23569 if (!Res1.isUsable()) {
23570 IsCorrect = false;
23571 continue;
23572 }
23573 // (Begini - Endi) - Stepi - 1
23575 D.AssignmentLoc, BO_Sub, Res1.get(),
23576 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
23577 if (!Res1.isUsable()) {
23578 IsCorrect = false;
23579 continue;
23580 }
23581 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
23582 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
23583 St1.get());
23584 if (!Res1.isUsable()) {
23585 IsCorrect = false;
23586 continue;
23587 }
23588 // Stepi > 0.
23590 D.AssignmentLoc, BO_GT, D.Range.Step,
23591 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
23592 if (!CmpRes.isUsable()) {
23593 IsCorrect = false;
23594 continue;
23595 }
23596 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
23597 CmpRes.get(), Res.get(), Res1.get());
23598 if (!Res.isUsable()) {
23599 IsCorrect = false;
23600 continue;
23601 }
23602 }
23603 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
23604 if (!Res.isUsable()) {
23605 IsCorrect = false;
23606 continue;
23607 }
23608
23609 // Build counter update.
23610 // Build counter.
23611 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
23612 D.IteratorDecl->getBeginLoc(),
23613 D.IteratorDecl->getBeginLoc(), nullptr,
23614 Res.get()->getType(), nullptr, SC_None);
23615 CounterVD->setImplicit();
23616 ExprResult RefRes =
23617 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
23618 D.IteratorDecl->getBeginLoc());
23619 // Build counter update.
23620 // I = Begini + counter * Stepi;
23621 ExprResult UpdateRes;
23622 if (D.Range.Step) {
23623 UpdateRes = SemaRef.CreateBuiltinBinOp(
23624 D.AssignmentLoc, BO_Mul,
23625 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
23626 } else {
23627 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
23628 }
23629 if (!UpdateRes.isUsable()) {
23630 IsCorrect = false;
23631 continue;
23632 }
23633 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
23634 D.Range.Begin, UpdateRes.get());
23635 if (!UpdateRes.isUsable()) {
23636 IsCorrect = false;
23637 continue;
23638 }
23639 ExprResult VDRes =
23640 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
23641 cast<VarDecl>(D.IteratorDecl)->getType(),
23642 VK_LValue, D.IteratorDecl->getBeginLoc());
23643 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
23644 VDRes.get(), UpdateRes.get());
23645 if (!UpdateRes.isUsable()) {
23646 IsCorrect = false;
23647 continue;
23648 }
23649 UpdateRes =
23650 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
23651 if (!UpdateRes.isUsable()) {
23652 IsCorrect = false;
23653 continue;
23654 }
23655 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
23656 D.AssignmentLoc, UO_PreInc, RefRes.get());
23657 if (!CounterUpdateRes.isUsable()) {
23658 IsCorrect = false;
23659 continue;
23660 }
23661 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
23662 /*DiscardedValue=*/true);
23663 if (!CounterUpdateRes.isUsable()) {
23664 IsCorrect = false;
23665 continue;
23666 }
23667 OMPIteratorHelperData &HD = Helpers.emplace_back();
23668 HD.CounterVD = CounterVD;
23669 HD.Upper = Res.get();
23670 HD.Update = UpdateRes.get();
23671 HD.CounterUpdate = CounterUpdateRes.get();
23672 }
23673 } else {
23674 Helpers.assign(ID.size(), {});
23675 }
23676 if (!IsCorrect) {
23677 // Invalidate all created iterator declarations if error is found.
23678 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
23679 if (Decl *ID = D.IteratorDecl)
23680 ID->setInvalidDecl();
23681 }
23682 return ExprError();
23683 }
23684 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
23685 LLoc, RLoc, ID, Helpers);
23686}
23687
23688/// Check if \p AssumptionStr is a known assumption and warn if not.
23690 StringRef AssumptionStr) {
23691 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
23692 return;
23693
23694 unsigned BestEditDistance = 3;
23695 StringRef Suggestion;
23696 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
23697 unsigned EditDistance =
23698 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
23699 if (EditDistance < BestEditDistance) {
23700 Suggestion = KnownAssumptionIt.getKey();
23701 BestEditDistance = EditDistance;
23702 }
23703 }
23704
23705 if (!Suggestion.empty())
23706 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
23707 << AssumptionStr << Suggestion;
23708 else
23709 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
23710 << AssumptionStr;
23711}
23712
23714 // Handle the case where the attribute has a text message.
23715 StringRef Str;
23716 SourceLocation AttrStrLoc;
23717 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
23718 return;
23719
23720 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
23721
23722 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
23723}
23724
23726 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3338
NodeId Parent
Definition: ASTDiff.cpp:191
DynTypedNode Node
StringRef P
const Decl * D
Expr * E
enum clang::sema::@1651::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:2993
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 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 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 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 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 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:186
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:663
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:1239
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2625
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2641
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:1159
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1145
void Deallocate(void *Ptr) const
Definition: ASTContext.h:739
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:1146
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:1634
CanQualType OMPIteratorTy
Definition: ASTContext.h:1159
IdentifierTable & Idents
Definition: ASTContext.h:659
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:1158
CanQualType BoolTy
Definition: ASTContext.h:1119
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:1146
CanQualType IntTy
Definition: ASTContext.h:1127
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:2672
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:2391
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1118
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:1612
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:778
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:3540
QualType getElementType() const
Definition: Type.h:3552
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:2535
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2862
A call to an overloaded operator written using operator syntax.
Definition: ExprCXX.h:81
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition: DeclCXX.h:1234
bool hasDefinition() const
Definition: DeclCXX.h:571
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition: DeclSpec.h:215
SourceLocation getBeginLoc() const
Definition: DeclSpec.h:84
bool isSet() const
Deprecated.
Definition: DeclSpec.h:228
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition: DeclSpec.cpp:152
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition: DeclSpec.h:213
Represents the this expression in C++.
Definition: ExprCXX.h: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:349
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition: Decl.h:4666
unsigned getNumParams() const
Definition: Decl.h:4708
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5432
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4710
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:3108
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:1358
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1425
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2079
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2208
bool isFileContext() const
Definition: DeclBase.h:2150
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1375
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1309
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
Definition: DeclBase.h:2095
bool isNamespace() const
Definition: DeclBase.h:2168
bool isTranslationUnit() const
Definition: DeclBase.h:2155
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1742
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2339
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1360
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
Definition: DeclBase.cpp:1379
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1716
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:579
bool hasAttrs() const
Definition: DeclBase.h:524
void addAttr(Attr *A)
Definition: DeclBase.cpp:1014
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:599
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp: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:963
bool isInvalidDecl() const
Definition: DeclBase.h:594
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:565
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:508
SourceLocation getLocation() const
Definition: DeclBase.h:445
void setImplicit(bool I=true)
Definition: DeclBase.h:600
void setReferenced(bool R=true)
Definition: DeclBase.h:629
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: DeclBase.h:1028
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:454
AccessSpecifier getAccess() const
Definition: DeclBase.h:513
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:437
AttrVec & getAttrs()
Definition: DeclBase.h:530
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition: DeclBase.cpp:358
bool hasAttr() const
Definition: DeclBase.h:583
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:362
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:957
Kind getKind() const
Definition: DeclBase.h:448
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:433
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1900
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
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3254
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:3680
Represents a prototype with parameter type info, e.g.
Definition: Type.h:4973
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:7482
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.
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
Definition: OpenMPClause.h:515
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
Definition: DeclOpenMP.cpp:57
This represents 'allocator' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:354
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
Definition: ExprOpenMP.h:24
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Definition: Expr.cpp:5167
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:953
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:817
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:873
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Definition: StmtOpenMP.cpp:859
static OMPCanonicalLoop * create(const ASTContext &Ctx, Stmt *LoopStmt, CapturedStmt *DistanceFunc, CapturedStmt *LoopVarFunc, DeclRefExpr *LoopVarRef)
Create a new OMPCanonicalLoop.
Definition: StmtOpenMP.h:163
This represents 'capture' clause in the '#pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
Definition: DeclOpenMP.h:383
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Definition: DeclOpenMP.cpp:176
Class that represents a component of a mappable expression.
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'shedule', 'firstprivate' etc.
Definition: OpenMPClause.h:195
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
Definition: OpenMPClause.h:71
SourceLocation getEndLoc() const
Returns the ending location of the clause.
Definition: OpenMPClause.h:74
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
Definition: OpenMPClause.h:83
This represents 'collapse' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:977
This represents 'compare' clause in the '#pragma omp atomic' directive.
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents '#pragma omp critical' directive.
Definition: StmtOpenMP.h: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:904
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:802
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:630
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFlushDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:889
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:879
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the '#pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the '#pragma omp ...' directive.
This represents 'if' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:527
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static 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 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the '#pragma omp ...' directive.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
This represents 'num_teams' clause in the '#pragma omp ...' directive.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:676
This represents 'order' clause in the '#pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the '#pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
static OMPOrderedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:934
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:907
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
Definition: OpenMPClause.h:946
This represents 'priority' clause in the '#pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents 'read' clause in the '#pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
This represents '#pragma omp requires...' directive.
Definition: DeclOpenMP.h:417
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:721
Expr * getSafelen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:741
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:919
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:756
Expr * getSimdlen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:776
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp: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:978
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:994
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:843
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
Definition: StmtOpenMP.cpp:829
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.
This represents 'thread_limit' clause in the '#pragma omp ...' directive.
This represents '#pragma omp threadprivate ...' directive.
Definition: DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
Definition: DeclOpenMP.cpp:28
This represents 'threads' clause in the '#pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp tile'.
Definition: StmtOpenMP.cpp: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 varlists()
Definition: OpenMPClause.h:319
SourceLocation getLParenLoc() const
Returns the location of '('.
Definition: OpenMPClause.h:335
unsigned varlist_size() const
Definition: OpenMPClause.h:316
This represents 'weak' clause in the '#pragma omp atomic' directives.
This represents 'write' clause in the '#pragma omp atomic' directive.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the '#pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the '#pragma omp target ...' directive.
Wrapper for void* pointer.
Definition: Ownership.h:50
void * getAsOpaquePtr() const
Definition: Ownership.h:90
PtrTy get() const
Definition: Ownership.h:80
static OpaquePtr make(PtrTy P)
Definition: Ownership.h:60
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h: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:2748
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: Type.h:7832
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:3469
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:7743
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:7944
QualType getCanonicalType() const
Definition: Type.h:7795
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7837
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition: Type.h:7915
const Type * getTypePtrOrNull() const
Definition: Type.h:7747
Represents a struct/union/class.
Definition: Decl.h:4141
field_range fields() const
Definition: Decl.h:4347
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5936
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Definition: Redeclarable.h:204
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Definition: Redeclarable.h:226
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3402
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.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'reduction' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the '#pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'from' clause.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'to' clause.
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition: SemaOpenMP.h: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...
OMPClause * ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'task_reduction' clause.
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_ptr' clause.
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition: SemaOpenMP.h: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 ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
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.
OMPClause * ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
Definition: SemaOpenMP.h:408
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
Definition: Sema.h:1009
Expr * get() const
Definition: Sema.h:7284
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:12119
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:7233
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:6321
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:803
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:3578
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15265
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:8999
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:9040
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:9042
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:9044
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
SemaOpenMP & OpenMP()
Definition: Sema.h:1219
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition: Sema.h:4322
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17159
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:20110
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:940
@ AR_inaccessible
Definition: Sema.h:1335
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:2276
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:6202
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:16917
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1731
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:19897
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:1547
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ASTContext & Context
Definition: Sema.h:1002
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4556
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:71
@ AllowFold
Definition: Sema.h:7249
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:19391
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:747
ASTContext & getASTContext() const
Definition: Sema.h:600
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15544
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:18673
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:19639
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:17580
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:908
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2186
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:2164
const LangOptions & getLangOpts() const
Definition: Sema.h:593
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:1001
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:6394
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:1000
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2389
DeclContext * getCurLexicalContext() const
Definition: Sema.h:807
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:4467
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:1033
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:635
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition: Sema.h:14960
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20131
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2345
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1137
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4571
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4081
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:20694
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:13471
@ TryCapture_ExplicitByVal
Definition: Sema.h:6599
@ AA_Initializing
Definition: Sema.h:6484
@ AA_Converting
Definition: Sema.h:6483
@ AA_Casting
Definition: Sema.h:6486
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:11063
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:8691
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:14915
@ CTK_ErrorRecovery
Definition: Sema.h:9393
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2330
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:10923
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:5090
@ 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:5645
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:8885
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:963
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:17658
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:13784
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13224
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition: Sema.cpp:1947
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
Definition: SemaExpr.cpp:15112
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:14577
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:2360
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2718
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:2723
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:415
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:7298
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:8277
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:185
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:350
child_range children()
Definition: Stmt.cpp:287
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
Definition: Stmt.cpp:197
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
bool isTLSSupported() const
Whether the target supports thread-local storage.
Definition: TargetInfo.h: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:3363
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7714
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:7725
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:8068
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:8064
bool isArithmeticType() const
Definition: Type.cpp:2281
bool isPointerType() const
Definition: Type.h:7996
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8335
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8583
bool isReferenceType() const
Definition: Type.h:8010
bool isEnumeralType() const
Definition: Type.h:8096
bool isScalarType() const
Definition: Type.h:8394
bool isVariableArrayType() const
Definition: Type.h:8076
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:8289
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2680
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:8264
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2672
bool isAnyComplexType() const
Definition: Type.h:8100
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: Type.h:2336
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:2510
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition: Type.h:8436
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: Type.h:2690
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8569
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:8533
bool isFunctionType() const
Definition: Type.h:7992
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:8000
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8516
bool isRecordType() const
Definition: Type.h:8092
bool isUnionType() const
Definition: Type.cpp:671
bool isFunctionNoProtoType() const
Definition: Type.h:2509
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)
Definition: ExprCXX.cpp:419
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
Definition: UnresolvedSet.h:92
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h: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:146
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:148
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Definition: OpenMPKinds.h:135
@ OMPC_AT_unknown
Definition: OpenMPKinds.h:138
Expr * AssertSuccess(ExprResult R)
Definition: Ownership.h:274
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
Definition: Lambda.h:37
@ LCK_This
Capturing the *this object by reference.
Definition: Lambda.h:34
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
Definition: OpenMPKinds.h:186
@ OMPC_REDUCTION_unknown
Definition: OpenMPKinds.h:189
BinaryOperatorKind
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition: OpenMPKinds.h:38
@ OMPC_SCHEDULE_MODIFIER_last
Definition: OpenMPKinds.h:43
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition: OpenMPKinds.h:39
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:27
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
@ CR_Default
Definition: CapturedStmt.h:17
@ CR_OpenMP
Definition: CapturedStmt.h:19
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
@ SC_Auto
Definition: Specifiers.h:253
@ SC_Register
Definition: Specifiers.h:254
@ SC_None
Definition: Specifiers.h:247
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
Definition: OpenMPKinds.h:103
@ OMPC_DIST_SCHEDULE_unknown
Definition: OpenMPKinds.h:106
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition: Decl.h:5027
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
Definition: OpenMPKinds.h:219
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
Definition: OpenMPKinds.h:87
ExprResult ExprEmpty()
Definition: Ownership.h:271
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
StmtResult StmtError()
Definition: Ownership.h:265
@ SD_Static
Static storage duration.
Definition: Specifiers.h:328
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
Definition: OpenMPKinds.h:200
@ OMPC_BIND_unknown
Definition: OpenMPKinds.h:203
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
Definition: OpenMPKinds.h:157
@ OMPC_LASTPRIVATE_unknown
Definition: OpenMPKinds.h:160
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition: OpenMPKinds.h:54
@ OMPC_DEPEND_unknown
Definition: OpenMPKinds.h:58
OpenMPGrainsizeClauseModifier
Definition: OpenMPKinds.h:206
@ OMPC_GRAINSIZE_unknown
Definition: OpenMPKinds.h:209
OpenMPNumTasksClauseModifier
Definition: OpenMPKinds.h:212
@ OMPC_NUMTASKS_unknown
Definition: OpenMPKinds.h:215
ActionResult< Expr * > ExprResult
Definition: Ownership.h:248
ExprResult ExprError()
Definition: Ownership.h:264
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
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 isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:129
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:132
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:136
for(const auto &A :T->param_types())
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
Definition: OpenMPKinds.h:127
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
Definition: OpenMPKinds.h:131
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ActionResult< Decl * > DeclResult
Definition: Ownership.h:254
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
Definition: OpenMPKinds.h:47
@ OMPC_DEVICE_unknown
Definition: OpenMPKinds.h:50
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition: OpenMPKinds.h:78
@ OMPC_MAP_MODIFIER_unknown
Definition: OpenMPKinds.h:79
bool isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a combined construct for which the first construct is a parallel...
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
Definition: OpenMPKinds.h:164
@ OMPC_ORDER_unknown
Definition: OpenMPKinds.h:167
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition: OpenMPKinds.h:30
@ OMPC_SCHEDULE_unknown
Definition: OpenMPKinds.h:34
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:120
@ AS_public
Definition: Specifiers.h:121
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition: OpenMPKinds.h:70
@ OMPC_MAP_unknown
Definition: OpenMPKinds.h:74
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition: Specifiers.h:174
unsigned long uint64_t
#define true
Definition: stdbool.h:25
#define false
Definition: stdbool.h:26
#define bool
Definition: stdbool.h:24
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
const Expr * RHS
The original right-hand side.
Definition: ExprCXX.h:310
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition: ExprCXX.h:306
const Expr * LHS
The original left-hand side.
Definition: ExprCXX.h:308
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:642
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:644
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:630
Extra information about a function prototype.
Definition: Type.h:5058
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:1346
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1091
Data for list of allocators.
Definition: SemaOpenMP.h:1286
Clang specific specialization of the OMPContext to lookup target features.