clang 20.0.0git
SemaOpenMP.cpp
Go to the documentation of this file.
1//===--- SemaOpenMP.cpp - Semantic Analysis for OpenMP constructs ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file implements semantic analysis for OpenMP directives and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
15
16#include "TreeTransform.h"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclCXX.h"
25#include "clang/AST/StmtCXX.h"
35#include "clang/Sema/Lookup.h"
37#include "clang/Sema/Scope.h"
39#include "clang/Sema/Sema.h"
41#include "llvm/ADT/IndexedMap.h"
42#include "llvm/ADT/PointerEmbeddedInt.h"
43#include "llvm/ADT/STLExtras.h"
44#include "llvm/ADT/Sequence.h"
45#include "llvm/ADT/SmallSet.h"
46#include "llvm/ADT/StringExtras.h"
47#include "llvm/Frontend/OpenMP/OMPAssume.h"
48#include "llvm/Frontend/OpenMP/OMPConstants.h"
49#include "llvm/IR/Assumptions.h"
50#include <optional>
51#include <set>
52
53using namespace clang;
54using namespace llvm::omp;
55
56//===----------------------------------------------------------------------===//
57// Stack of data-sharing attributes for variables
58//===----------------------------------------------------------------------===//
59
61 Sema &SemaRef, Expr *E,
63 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
64
65namespace {
66/// Default data sharing attributes, which can be applied to directive.
67enum DefaultDataSharingAttributes {
68 DSA_unspecified = 0, /// Data sharing attribute not specified.
69 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
70 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
71 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
72 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
73};
74
75/// Stack for tracking declarations used in OpenMP directives and
76/// clauses and their data-sharing attributes.
77class DSAStackTy {
78public:
79 struct DSAVarData {
80 OpenMPDirectiveKind DKind = OMPD_unknown;
81 OpenMPClauseKind CKind = OMPC_unknown;
82 unsigned Modifier = 0;
83 const Expr *RefExpr = nullptr;
84 DeclRefExpr *PrivateCopy = nullptr;
85 SourceLocation ImplicitDSALoc;
86 bool AppliedToPointee = false;
87 DSAVarData() = default;
88 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
89 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
90 SourceLocation ImplicitDSALoc, unsigned Modifier,
91 bool AppliedToPointee)
92 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
93 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
94 AppliedToPointee(AppliedToPointee) {}
95 };
96 using OperatorOffsetTy =
98 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
99 /// Kind of the declaration used in the uses_allocators clauses.
100 enum class UsesAllocatorsDeclKind {
101 /// Predefined allocator
102 PredefinedAllocator,
103 /// User-defined allocator
104 UserDefinedAllocator,
105 /// The declaration that represent allocator trait
106 AllocatorTrait,
107 };
108
109private:
110 struct DSAInfo {
111 OpenMPClauseKind Attributes = OMPC_unknown;
112 unsigned Modifier = 0;
113 /// Pointer to a reference expression and a flag which shows that the
114 /// variable is marked as lastprivate(true) or not (false).
115 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
116 DeclRefExpr *PrivateCopy = nullptr;
117 /// true if the attribute is applied to the pointee, not the variable
118 /// itself.
119 bool AppliedToPointee = false;
120 };
121 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
122 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
123 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
124 using LoopControlVariablesMapTy =
125 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
126 /// Struct that associates a component with the clause kind where they are
127 /// found.
128 struct MappedExprComponentTy {
130 OpenMPClauseKind Kind = OMPC_unknown;
131 };
132 using MappedExprComponentsTy =
133 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
134 using CriticalsWithHintsTy =
135 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
136 struct ReductionData {
137 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
138 SourceRange ReductionRange;
139 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
140 ReductionData() = default;
141 void set(BinaryOperatorKind BO, SourceRange RR) {
142 ReductionRange = RR;
143 ReductionOp = BO;
144 }
145 void set(const Expr *RefExpr, SourceRange RR) {
146 ReductionRange = RR;
147 ReductionOp = RefExpr;
148 }
149 };
150 using DeclReductionMapTy =
151 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
152 struct DefaultmapInfo {
153 OpenMPDefaultmapClauseModifier ImplicitBehavior =
155 SourceLocation SLoc;
156 DefaultmapInfo() = default;
158 : ImplicitBehavior(M), SLoc(Loc) {}
159 };
160
161 struct SharingMapTy {
162 DeclSAMapTy SharingMap;
163 DeclReductionMapTy ReductionMap;
164 UsedRefMapTy AlignedMap;
165 UsedRefMapTy NontemporalMap;
166 MappedExprComponentsTy MappedExprComponents;
167 LoopControlVariablesMapTy LCVMap;
168 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
169 SourceLocation DefaultAttrLoc;
170 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
171 OpenMPDirectiveKind Directive = OMPD_unknown;
172 DeclarationNameInfo DirectiveName;
173 Scope *CurScope = nullptr;
174 DeclContext *Context = nullptr;
175 SourceLocation ConstructLoc;
176 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
177 /// get the data (loop counters etc.) about enclosing loop-based construct.
178 /// This data is required during codegen.
179 DoacrossClauseMapTy DoacrossDepends;
180 /// First argument (Expr *) contains optional argument of the
181 /// 'ordered' clause, the second one is true if the regions has 'ordered'
182 /// clause, false otherwise.
183 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
184 bool RegionHasOrderConcurrent = false;
185 unsigned AssociatedLoops = 1;
186 bool HasMutipleLoops = false;
187 const Decl *PossiblyLoopCounter = nullptr;
188 bool NowaitRegion = false;
189 bool UntiedRegion = false;
190 bool CancelRegion = false;
191 bool LoopStart = false;
192 bool BodyComplete = false;
193 SourceLocation PrevScanLocation;
194 SourceLocation PrevOrderedLocation;
195 SourceLocation InnerTeamsRegionLoc;
196 /// Reference to the taskgroup task_reduction reference expression.
197 Expr *TaskgroupReductionRef = nullptr;
198 llvm::DenseSet<QualType> MappedClassesQualTypes;
199 SmallVector<Expr *, 4> InnerUsedAllocators;
200 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
201 /// List of globals marked as declare target link in this target region
202 /// (isOpenMPTargetExecutionDirective(Directive) == true).
203 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
204 /// List of decls used in inclusive/exclusive clauses of the scan directive.
205 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
206 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
207 UsesAllocatorsDecls;
208 /// Data is required on creating capture fields for implicit
209 /// default first|private clause.
210 struct ImplicitDefaultFDInfoTy {
211 /// Field decl.
212 const FieldDecl *FD = nullptr;
213 /// Nesting stack level
214 size_t StackLevel = 0;
215 /// Capture variable decl.
216 VarDecl *VD = nullptr;
217 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
218 VarDecl *VD)
219 : FD(FD), StackLevel(StackLevel), VD(VD) {}
220 };
221 /// List of captured fields
223 ImplicitDefaultFirstprivateFDs;
224 Expr *DeclareMapperVar = nullptr;
225 SmallVector<VarDecl *, 16> IteratorVarDecls;
226 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
227 Scope *CurScope, SourceLocation Loc)
228 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
229 ConstructLoc(Loc) {}
230 SharingMapTy() = default;
231 };
232
233 using StackTy = SmallVector<SharingMapTy, 4>;
234
235 /// Stack of used declaration and their data-sharing attributes.
236 DeclSAMapTy Threadprivates;
237 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
239 /// true, if check for DSA must be from parent directive, false, if
240 /// from current directive.
241 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
242 Sema &SemaRef;
243 bool ForceCapturing = false;
244 /// true if all the variables in the target executable directives must be
245 /// captured by reference.
246 bool ForceCaptureByReferenceInTargetExecutable = false;
247 CriticalsWithHintsTy Criticals;
248 unsigned IgnoredStackElements = 0;
249
250 /// Iterators over the stack iterate in order from innermost to outermost
251 /// directive.
252 using const_iterator = StackTy::const_reverse_iterator;
253 const_iterator begin() const {
254 return Stack.empty() ? const_iterator()
255 : Stack.back().first.rbegin() + IgnoredStackElements;
256 }
257 const_iterator end() const {
258 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
259 }
260 using iterator = StackTy::reverse_iterator;
261 iterator begin() {
262 return Stack.empty() ? iterator()
263 : Stack.back().first.rbegin() + IgnoredStackElements;
264 }
265 iterator end() {
266 return Stack.empty() ? iterator() : Stack.back().first.rend();
267 }
268
269 // Convenience operations to get at the elements of the stack.
270
271 bool isStackEmpty() const {
272 return Stack.empty() ||
273 Stack.back().second != CurrentNonCapturingFunctionScope ||
274 Stack.back().first.size() <= IgnoredStackElements;
275 }
276 size_t getStackSize() const {
277 return isStackEmpty() ? 0
278 : Stack.back().first.size() - IgnoredStackElements;
279 }
280
281 SharingMapTy *getTopOfStackOrNull() {
282 size_t Size = getStackSize();
283 if (Size == 0)
284 return nullptr;
285 return &Stack.back().first[Size - 1];
286 }
287 const SharingMapTy *getTopOfStackOrNull() const {
288 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
289 }
290 SharingMapTy &getTopOfStack() {
291 assert(!isStackEmpty() && "no current directive");
292 return *getTopOfStackOrNull();
293 }
294 const SharingMapTy &getTopOfStack() const {
295 return const_cast<DSAStackTy &>(*this).getTopOfStack();
296 }
297
298 SharingMapTy *getSecondOnStackOrNull() {
299 size_t Size = getStackSize();
300 if (Size <= 1)
301 return nullptr;
302 return &Stack.back().first[Size - 2];
303 }
304 const SharingMapTy *getSecondOnStackOrNull() const {
305 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
306 }
307
308 /// Get the stack element at a certain level (previously returned by
309 /// \c getNestingLevel).
310 ///
311 /// Note that nesting levels count from outermost to innermost, and this is
312 /// the reverse of our iteration order where new inner levels are pushed at
313 /// the front of the stack.
314 SharingMapTy &getStackElemAtLevel(unsigned Level) {
315 assert(Level < getStackSize() && "no such stack element");
316 return Stack.back().first[Level];
317 }
318 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
319 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
320 }
321
322 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
323
324 /// Checks if the variable is a local for OpenMP region.
325 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
326
327 /// Vector of previously declared requires directives
329 /// omp_allocator_handle_t type.
330 QualType OMPAllocatorHandleT;
331 /// omp_depend_t type.
332 QualType OMPDependT;
333 /// omp_event_handle_t type.
334 QualType OMPEventHandleT;
335 /// omp_alloctrait_t type.
336 QualType OMPAlloctraitT;
337 /// Expression for the predefined allocators.
338 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
339 nullptr};
340 /// Vector of previously encountered target directives
341 SmallVector<SourceLocation, 2> TargetLocations;
342 SourceLocation AtomicLocation;
343 /// Vector of declare variant construct traits.
345
346public:
347 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
348
349 /// Sets omp_allocator_handle_t type.
350 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
351 /// Gets omp_allocator_handle_t type.
352 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
353 /// Sets omp_alloctrait_t type.
354 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
355 /// Gets omp_alloctrait_t type.
356 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
357 /// Sets the given default allocator.
358 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
359 Expr *Allocator) {
360 OMPPredefinedAllocators[AllocatorKind] = Allocator;
361 }
362 /// Returns the specified default allocator.
363 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
364 return OMPPredefinedAllocators[AllocatorKind];
365 }
366 /// Sets omp_depend_t type.
367 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
368 /// Gets omp_depend_t type.
369 QualType getOMPDependT() const { return OMPDependT; }
370
371 /// Sets omp_event_handle_t type.
372 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
373 /// Gets omp_event_handle_t type.
374 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
375
376 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
377 OpenMPClauseKind getClauseParsingMode() const {
378 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
379 return ClauseKindMode;
380 }
381 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
382
383 bool isBodyComplete() const {
384 const SharingMapTy *Top = getTopOfStackOrNull();
385 return Top && Top->BodyComplete;
386 }
387 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
388
389 bool isForceVarCapturing() const { return ForceCapturing; }
390 void setForceVarCapturing(bool V) { ForceCapturing = V; }
391
392 void setForceCaptureByReferenceInTargetExecutable(bool V) {
393 ForceCaptureByReferenceInTargetExecutable = V;
394 }
395 bool isForceCaptureByReferenceInTargetExecutable() const {
396 return ForceCaptureByReferenceInTargetExecutable;
397 }
398
399 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
400 Scope *CurScope, SourceLocation Loc) {
401 assert(!IgnoredStackElements &&
402 "cannot change stack while ignoring elements");
403 if (Stack.empty() ||
404 Stack.back().second != CurrentNonCapturingFunctionScope)
405 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
406 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
407 Stack.back().first.back().DefaultAttrLoc = Loc;
408 }
409
410 void pop() {
411 assert(!IgnoredStackElements &&
412 "cannot change stack while ignoring elements");
413 assert(!Stack.back().first.empty() &&
414 "Data-sharing attributes stack is empty!");
415 Stack.back().first.pop_back();
416 }
417
418 /// RAII object to temporarily leave the scope of a directive when we want to
419 /// logically operate in its parent.
420 class ParentDirectiveScope {
421 DSAStackTy &Self;
422 bool Active;
423
424 public:
425 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
426 : Self(Self), Active(false) {
427 if (Activate)
428 enable();
429 }
430 ~ParentDirectiveScope() { disable(); }
431 void disable() {
432 if (Active) {
433 --Self.IgnoredStackElements;
434 Active = false;
435 }
436 }
437 void enable() {
438 if (!Active) {
439 ++Self.IgnoredStackElements;
440 Active = true;
441 }
442 }
443 };
444
445 /// Marks that we're started loop parsing.
446 void loopInit() {
447 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
448 "Expected loop-based directive.");
449 getTopOfStack().LoopStart = true;
450 }
451 /// Start capturing of the variables in the loop context.
452 void loopStart() {
453 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
454 "Expected loop-based directive.");
455 getTopOfStack().LoopStart = false;
456 }
457 /// true, if variables are captured, false otherwise.
458 bool isLoopStarted() const {
459 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
460 "Expected loop-based directive.");
461 return !getTopOfStack().LoopStart;
462 }
463 /// Marks (or clears) declaration as possibly loop counter.
464 void resetPossibleLoopCounter(const Decl *D = nullptr) {
465 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
466 }
467 /// Gets the possible loop counter decl.
468 const Decl *getPossiblyLoopCounter() const {
469 return getTopOfStack().PossiblyLoopCounter;
470 }
471 /// Start new OpenMP region stack in new non-capturing function.
472 void pushFunction() {
473 assert(!IgnoredStackElements &&
474 "cannot change stack while ignoring elements");
475 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
476 assert(!isa<CapturingScopeInfo>(CurFnScope));
477 CurrentNonCapturingFunctionScope = CurFnScope;
478 }
479 /// Pop region stack for non-capturing function.
480 void popFunction(const FunctionScopeInfo *OldFSI) {
481 assert(!IgnoredStackElements &&
482 "cannot change stack while ignoring elements");
483 if (!Stack.empty() && Stack.back().second == OldFSI) {
484 assert(Stack.back().first.empty());
485 Stack.pop_back();
486 }
487 CurrentNonCapturingFunctionScope = nullptr;
488 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
489 if (!isa<CapturingScopeInfo>(FSI)) {
490 CurrentNonCapturingFunctionScope = FSI;
491 break;
492 }
493 }
494 }
495
496 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
497 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
498 }
499 const std::pair<const OMPCriticalDirective *, llvm::APSInt>
500 getCriticalWithHint(const DeclarationNameInfo &Name) const {
501 auto I = Criticals.find(Name.getAsString());
502 if (I != Criticals.end())
503 return I->second;
504 return std::make_pair(nullptr, llvm::APSInt());
505 }
506 /// If 'aligned' declaration for given variable \a D was not seen yet,
507 /// add it and return NULL; otherwise return previous occurrence's expression
508 /// for diagnostics.
509 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
510 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
511 /// add it and return NULL; otherwise return previous occurrence's expression
512 /// for diagnostics.
513 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
514
515 /// Register specified variable as loop control variable.
516 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
517 /// Check if the specified variable is a loop control variable for
518 /// current region.
519 /// \return The index of the loop control variable in the list of associated
520 /// for-loops (from outer to inner).
521 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
522 /// Check if the specified variable is a loop control variable for
523 /// parent region.
524 /// \return The index of the loop control variable in the list of associated
525 /// for-loops (from outer to inner).
526 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
527 /// Check if the specified variable is a loop control variable for
528 /// current region.
529 /// \return The index of the loop control variable in the list of associated
530 /// for-loops (from outer to inner).
531 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
532 unsigned Level) const;
533 /// Get the loop control variable for the I-th loop (or nullptr) in
534 /// parent directive.
535 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
536
537 /// Marks the specified decl \p D as used in scan directive.
538 void markDeclAsUsedInScanDirective(ValueDecl *D) {
539 if (SharingMapTy *Stack = getSecondOnStackOrNull())
540 Stack->UsedInScanDirective.insert(D);
541 }
542
543 /// Checks if the specified declaration was used in the inner scan directive.
544 bool isUsedInScanDirective(ValueDecl *D) const {
545 if (const SharingMapTy *Stack = getTopOfStackOrNull())
546 return Stack->UsedInScanDirective.contains(D);
547 return false;
548 }
549
550 /// Adds explicit data sharing attribute to the specified declaration.
551 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
552 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
553 bool AppliedToPointee = false);
554
555 /// Adds additional information for the reduction items with the reduction id
556 /// represented as an operator.
557 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
559 /// Adds additional information for the reduction items with the reduction id
560 /// represented as reduction identifier.
561 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
562 const Expr *ReductionRef);
563 /// Returns the location and reduction operation from the innermost parent
564 /// region for the given \p D.
565 const DSAVarData
566 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
568 Expr *&TaskgroupDescriptor) const;
569 /// Returns the location and reduction operation from the innermost parent
570 /// region for the given \p D.
571 const DSAVarData
572 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
573 const Expr *&ReductionRef,
574 Expr *&TaskgroupDescriptor) const;
575 /// Return reduction reference expression for the current taskgroup or
576 /// parallel/worksharing directives with task reductions.
577 Expr *getTaskgroupReductionRef() const {
578 assert((getTopOfStack().Directive == OMPD_taskgroup ||
579 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
580 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
581 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
582 "taskgroup reference expression requested for non taskgroup or "
583 "parallel/worksharing directive.");
584 return getTopOfStack().TaskgroupReductionRef;
585 }
586 /// Checks if the given \p VD declaration is actually a taskgroup reduction
587 /// descriptor variable at the \p Level of OpenMP regions.
588 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
589 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
590 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
591 ->getDecl() == VD;
592 }
593
594 /// Returns data sharing attributes from top of the stack for the
595 /// specified declaration.
596 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
597 /// Returns data-sharing attributes for the specified declaration.
598 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
599 /// Returns data-sharing attributes for the specified declaration.
600 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
601 /// Checks if the specified variables has data-sharing attributes which
602 /// match specified \a CPred predicate in any directive which matches \a DPred
603 /// predicate.
604 const DSAVarData
605 hasDSA(ValueDecl *D,
606 const llvm::function_ref<bool(OpenMPClauseKind, bool,
607 DefaultDataSharingAttributes)>
608 CPred,
609 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
610 bool FromParent) const;
611 /// Checks if the specified variables has data-sharing attributes which
612 /// match specified \a CPred predicate in any innermost directive which
613 /// matches \a DPred predicate.
614 const DSAVarData
615 hasInnermostDSA(ValueDecl *D,
616 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
617 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
618 bool FromParent) const;
619 /// Checks if the specified variables has explicit data-sharing
620 /// attributes which match specified \a CPred predicate at the specified
621 /// OpenMP region.
622 bool
623 hasExplicitDSA(const ValueDecl *D,
624 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
625 unsigned Level, bool NotLastprivate = false) const;
626
627 /// Returns true if the directive at level \Level matches in the
628 /// specified \a DPred predicate.
629 bool hasExplicitDirective(
630 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
631 unsigned Level) const;
632
633 /// Finds a directive which matches specified \a DPred predicate.
634 bool hasDirective(
635 const llvm::function_ref<bool(
637 DPred,
638 bool FromParent) const;
639
640 /// Returns currently analyzed directive.
641 OpenMPDirectiveKind getCurrentDirective() const {
642 const SharingMapTy *Top = getTopOfStackOrNull();
643 return Top ? Top->Directive : OMPD_unknown;
644 }
645 /// Returns directive kind at specified level.
646 OpenMPDirectiveKind getDirective(unsigned Level) const {
647 assert(!isStackEmpty() && "No directive at specified level.");
648 return getStackElemAtLevel(Level).Directive;
649 }
650 /// Returns the capture region at the specified level.
651 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
652 unsigned OpenMPCaptureLevel) const {
654 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
655 return CaptureRegions[OpenMPCaptureLevel];
656 }
657 /// Returns parent directive.
658 OpenMPDirectiveKind getParentDirective() const {
659 const SharingMapTy *Parent = getSecondOnStackOrNull();
660 return Parent ? Parent->Directive : OMPD_unknown;
661 }
662
663 /// Add requires decl to internal vector
664 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
665
666 /// Checks if the defined 'requires' directive has specified type of clause.
667 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
668 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
669 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
670 return isa<ClauseType>(C);
671 });
672 });
673 }
674
675 /// Checks for a duplicate clause amongst previously declared requires
676 /// directives
677 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
678 bool IsDuplicate = false;
679 for (OMPClause *CNew : ClauseList) {
680 for (const OMPRequiresDecl *D : RequiresDecls) {
681 for (const OMPClause *CPrev : D->clauselists()) {
682 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
683 SemaRef.Diag(CNew->getBeginLoc(),
684 diag::err_omp_requires_clause_redeclaration)
685 << getOpenMPClauseName(CNew->getClauseKind());
686 SemaRef.Diag(CPrev->getBeginLoc(),
687 diag::note_omp_requires_previous_clause)
688 << getOpenMPClauseName(CPrev->getClauseKind());
689 IsDuplicate = true;
690 }
691 }
692 }
693 }
694 return IsDuplicate;
695 }
696
697 /// Add location of previously encountered target to internal vector
698 void addTargetDirLocation(SourceLocation LocStart) {
699 TargetLocations.push_back(LocStart);
700 }
701
702 /// Add location for the first encountered atomic directive.
703 void addAtomicDirectiveLoc(SourceLocation Loc) {
704 if (AtomicLocation.isInvalid())
705 AtomicLocation = Loc;
706 }
707
708 /// Returns the location of the first encountered atomic directive in the
709 /// module.
710 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
711
712 // Return previously encountered target region locations.
713 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
714 return TargetLocations;
715 }
716
717 /// Set default data sharing attribute to none.
718 void setDefaultDSANone(SourceLocation Loc) {
719 getTopOfStack().DefaultAttr = DSA_none;
720 getTopOfStack().DefaultAttrLoc = Loc;
721 }
722 /// Set default data sharing attribute to shared.
723 void setDefaultDSAShared(SourceLocation Loc) {
724 getTopOfStack().DefaultAttr = DSA_shared;
725 getTopOfStack().DefaultAttrLoc = Loc;
726 }
727 /// Set default data sharing attribute to private.
728 void setDefaultDSAPrivate(SourceLocation Loc) {
729 getTopOfStack().DefaultAttr = DSA_private;
730 getTopOfStack().DefaultAttrLoc = Loc;
731 }
732 /// Set default data sharing attribute to firstprivate.
733 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_firstprivate;
735 getTopOfStack().DefaultAttrLoc = Loc;
736 }
737 /// Set default data mapping attribute to Modifier:Kind
738 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
740 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
741 DMI.ImplicitBehavior = M;
742 DMI.SLoc = Loc;
743 }
744 /// Check whether the implicit-behavior has been set in defaultmap
745 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
746 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
747 return getTopOfStack()
748 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
749 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
750 getTopOfStack()
751 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
752 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
753 getTopOfStack()
754 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
755 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
756 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
758 }
759
760 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
761 return ConstructTraits;
762 }
763 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
764 bool ScopeEntry) {
765 if (ScopeEntry)
766 ConstructTraits.append(Traits.begin(), Traits.end());
767 else
768 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
769 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
770 assert(Top == Trait && "Something left a trait on the stack!");
771 (void)Trait;
772 (void)Top;
773 }
774 }
775
776 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
777 return getStackSize() <= Level ? DSA_unspecified
778 : getStackElemAtLevel(Level).DefaultAttr;
779 }
780 DefaultDataSharingAttributes getDefaultDSA() const {
781 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
782 }
783 SourceLocation getDefaultDSALocation() const {
784 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
785 }
787 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
788 return isStackEmpty()
790 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
791 }
793 getDefaultmapModifierAtLevel(unsigned Level,
794 OpenMPDefaultmapClauseKind Kind) const {
795 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
796 }
797 bool isDefaultmapCapturedByRef(unsigned Level,
798 OpenMPDefaultmapClauseKind Kind) const {
800 getDefaultmapModifierAtLevel(Level, Kind);
801 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
802 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
803 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
804 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
805 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
806 (M == OMPC_DEFAULTMAP_MODIFIER_present);
807 }
808 return true;
809 }
810 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
812 switch (Kind) {
813 case OMPC_DEFAULTMAP_scalar:
814 case OMPC_DEFAULTMAP_pointer:
815 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
816 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
817 (M == OMPC_DEFAULTMAP_MODIFIER_default);
818 case OMPC_DEFAULTMAP_aggregate:
819 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
820 default:
821 break;
822 }
823 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
824 }
825 bool mustBeFirstprivateAtLevel(unsigned Level,
826 OpenMPDefaultmapClauseKind Kind) const {
828 getDefaultmapModifierAtLevel(Level, Kind);
829 return mustBeFirstprivateBase(M, Kind);
830 }
831 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
832 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
833 return mustBeFirstprivateBase(M, Kind);
834 }
835
836 /// Checks if the specified variable is a threadprivate.
837 bool isThreadPrivate(VarDecl *D) {
838 const DSAVarData DVar = getTopDSA(D, false);
839 return isOpenMPThreadPrivate(DVar.CKind);
840 }
841
842 /// Marks current region as ordered (it has an 'ordered' clause).
843 void setOrderedRegion(bool IsOrdered, const Expr *Param,
844 OMPOrderedClause *Clause) {
845 if (IsOrdered)
846 getTopOfStack().OrderedRegion.emplace(Param, Clause);
847 else
848 getTopOfStack().OrderedRegion.reset();
849 }
850 /// Returns true, if region is ordered (has associated 'ordered' clause),
851 /// false - otherwise.
852 bool isOrderedRegion() const {
853 if (const SharingMapTy *Top = getTopOfStackOrNull())
854 return Top->OrderedRegion.has_value();
855 return false;
856 }
857 /// Returns optional parameter for the ordered region.
858 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
859 if (const SharingMapTy *Top = getTopOfStackOrNull())
860 if (Top->OrderedRegion)
861 return *Top->OrderedRegion;
862 return std::make_pair(nullptr, nullptr);
863 }
864 /// Returns true, if parent region is ordered (has associated
865 /// 'ordered' clause), false - otherwise.
866 bool isParentOrderedRegion() const {
867 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
868 return Parent->OrderedRegion.has_value();
869 return false;
870 }
871 /// Returns optional parameter for the ordered region.
872 std::pair<const Expr *, OMPOrderedClause *>
873 getParentOrderedRegionParam() const {
874 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
875 if (Parent->OrderedRegion)
876 return *Parent->OrderedRegion;
877 return std::make_pair(nullptr, nullptr);
878 }
879 /// Marks current region as having an 'order' clause.
880 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
881 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
882 }
883 /// Returns true, if parent region is order (has associated
884 /// 'order' clause), false - otherwise.
885 bool isParentOrderConcurrent() const {
886 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
887 return Parent->RegionHasOrderConcurrent;
888 return false;
889 }
890 /// Marks current region as nowait (it has a 'nowait' clause).
891 void setNowaitRegion(bool IsNowait = true) {
892 getTopOfStack().NowaitRegion = IsNowait;
893 }
894 /// Returns true, if parent region is nowait (has associated
895 /// 'nowait' clause), false - otherwise.
896 bool isParentNowaitRegion() const {
897 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
898 return Parent->NowaitRegion;
899 return false;
900 }
901 /// Marks current region as untied (it has a 'untied' clause).
902 void setUntiedRegion(bool IsUntied = true) {
903 getTopOfStack().UntiedRegion = IsUntied;
904 }
905 /// Return true if current region is untied.
906 bool isUntiedRegion() const {
907 const SharingMapTy *Top = getTopOfStackOrNull();
908 return Top ? Top->UntiedRegion : false;
909 }
910 /// Marks parent region as cancel region.
911 void setParentCancelRegion(bool Cancel = true) {
912 if (SharingMapTy *Parent = getSecondOnStackOrNull())
913 Parent->CancelRegion |= Cancel;
914 }
915 /// Return true if current region has inner cancel construct.
916 bool isCancelRegion() const {
917 const SharingMapTy *Top = getTopOfStackOrNull();
918 return Top ? Top->CancelRegion : false;
919 }
920
921 /// Mark that parent region already has scan directive.
922 void setParentHasScanDirective(SourceLocation Loc) {
923 if (SharingMapTy *Parent = getSecondOnStackOrNull())
924 Parent->PrevScanLocation = Loc;
925 }
926 /// Return true if current region has inner cancel construct.
927 bool doesParentHasScanDirective() const {
928 const SharingMapTy *Top = getSecondOnStackOrNull();
929 return Top ? Top->PrevScanLocation.isValid() : false;
930 }
931 /// Return true if current region has inner cancel construct.
932 SourceLocation getParentScanDirectiveLoc() const {
933 const SharingMapTy *Top = getSecondOnStackOrNull();
934 return Top ? Top->PrevScanLocation : SourceLocation();
935 }
936 /// Mark that parent region already has ordered directive.
937 void setParentHasOrderedDirective(SourceLocation Loc) {
938 if (SharingMapTy *Parent = getSecondOnStackOrNull())
939 Parent->PrevOrderedLocation = Loc;
940 }
941 /// Return true if current region has inner ordered construct.
942 bool doesParentHasOrderedDirective() const {
943 const SharingMapTy *Top = getSecondOnStackOrNull();
944 return Top ? Top->PrevOrderedLocation.isValid() : false;
945 }
946 /// Returns the location of the previously specified ordered directive.
947 SourceLocation getParentOrderedDirectiveLoc() const {
948 const SharingMapTy *Top = getSecondOnStackOrNull();
949 return Top ? Top->PrevOrderedLocation : SourceLocation();
950 }
951
952 /// Set collapse value for the region.
953 void setAssociatedLoops(unsigned Val) {
954 getTopOfStack().AssociatedLoops = Val;
955 if (Val > 1)
956 getTopOfStack().HasMutipleLoops = true;
957 }
958 /// Return collapse value for region.
959 unsigned getAssociatedLoops() const {
960 const SharingMapTy *Top = getTopOfStackOrNull();
961 return Top ? Top->AssociatedLoops : 0;
962 }
963 /// Returns true if the construct is associated with multiple loops.
964 bool hasMutipleLoops() const {
965 const SharingMapTy *Top = getTopOfStackOrNull();
966 return Top ? Top->HasMutipleLoops : false;
967 }
968
969 /// Marks current target region as one with closely nested teams
970 /// region.
971 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
972 if (SharingMapTy *Parent = getSecondOnStackOrNull())
973 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
974 }
975 /// Returns true, if current region has closely nested teams region.
976 bool hasInnerTeamsRegion() const {
977 return getInnerTeamsRegionLoc().isValid();
978 }
979 /// Returns location of the nested teams region (if any).
980 SourceLocation getInnerTeamsRegionLoc() const {
981 const SharingMapTy *Top = getTopOfStackOrNull();
982 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
983 }
984
985 Scope *getCurScope() const {
986 const SharingMapTy *Top = getTopOfStackOrNull();
987 return Top ? Top->CurScope : nullptr;
988 }
989 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
990 SourceLocation getConstructLoc() const {
991 const SharingMapTy *Top = getTopOfStackOrNull();
992 return Top ? Top->ConstructLoc : SourceLocation();
993 }
994
995 /// Do the check specified in \a Check to all component lists and return true
996 /// if any issue is found.
997 bool checkMappableExprComponentListsForDecl(
998 const ValueDecl *VD, bool CurrentRegionOnly,
999 const llvm::function_ref<
1002 Check) const {
1003 if (isStackEmpty())
1004 return false;
1005 auto SI = begin();
1006 auto SE = end();
1007
1008 if (SI == SE)
1009 return false;
1010
1011 if (CurrentRegionOnly)
1012 SE = std::next(SI);
1013 else
1014 std::advance(SI, 1);
1015
1016 for (; SI != SE; ++SI) {
1017 auto MI = SI->MappedExprComponents.find(VD);
1018 if (MI != SI->MappedExprComponents.end())
1020 MI->second.Components)
1021 if (Check(L, MI->second.Kind))
1022 return true;
1023 }
1024 return false;
1025 }
1026
1027 /// Do the check specified in \a Check to all component lists at a given level
1028 /// and return true if any issue is found.
1029 bool checkMappableExprComponentListsForDeclAtLevel(
1030 const ValueDecl *VD, unsigned Level,
1031 const llvm::function_ref<
1034 Check) const {
1035 if (getStackSize() <= Level)
1036 return false;
1037
1038 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1039 auto MI = StackElem.MappedExprComponents.find(VD);
1040 if (MI != StackElem.MappedExprComponents.end())
1042 MI->second.Components)
1043 if (Check(L, MI->second.Kind))
1044 return true;
1045 return false;
1046 }
1047
1048 /// Create a new mappable expression component list associated with a given
1049 /// declaration and initialize it with the provided list of components.
1050 void addMappableExpressionComponents(
1051 const ValueDecl *VD,
1053 OpenMPClauseKind WhereFoundClauseKind) {
1054 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1055 // Create new entry and append the new components there.
1056 MEC.Components.resize(MEC.Components.size() + 1);
1057 MEC.Components.back().append(Components.begin(), Components.end());
1058 MEC.Kind = WhereFoundClauseKind;
1059 }
1060
1061 unsigned getNestingLevel() const {
1062 assert(!isStackEmpty());
1063 return getStackSize() - 1;
1064 }
1065 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1066 SharingMapTy *Parent = getSecondOnStackOrNull();
1067 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1068 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1069 }
1070 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1071 getDoacrossDependClauses() const {
1072 const SharingMapTy &StackElem = getTopOfStack();
1073 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1074 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1075 return llvm::make_range(Ref.begin(), Ref.end());
1076 }
1077 return llvm::make_range(StackElem.DoacrossDepends.end(),
1078 StackElem.DoacrossDepends.end());
1079 }
1080
1081 // Store types of classes which have been explicitly mapped
1082 void addMappedClassesQualTypes(QualType QT) {
1083 SharingMapTy &StackElem = getTopOfStack();
1084 StackElem.MappedClassesQualTypes.insert(QT);
1085 }
1086
1087 // Return set of mapped classes types
1088 bool isClassPreviouslyMapped(QualType QT) const {
1089 const SharingMapTy &StackElem = getTopOfStack();
1090 return StackElem.MappedClassesQualTypes.contains(QT);
1091 }
1092
1093 /// Adds global declare target to the parent target region.
1094 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1095 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1096 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1097 "Expected declare target link global.");
1098 for (auto &Elem : *this) {
1099 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1100 Elem.DeclareTargetLinkVarDecls.push_back(E);
1101 return;
1102 }
1103 }
1104 }
1105
1106 /// Returns the list of globals with declare target link if current directive
1107 /// is target.
1108 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1109 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1110 "Expected target executable directive.");
1111 return getTopOfStack().DeclareTargetLinkVarDecls;
1112 }
1113
1114 /// Adds list of allocators expressions.
1115 void addInnerAllocatorExpr(Expr *E) {
1116 getTopOfStack().InnerUsedAllocators.push_back(E);
1117 }
1118 /// Return list of used allocators.
1119 ArrayRef<Expr *> getInnerAllocators() const {
1120 return getTopOfStack().InnerUsedAllocators;
1121 }
1122 /// Marks the declaration as implicitly firstprivate nin the task-based
1123 /// regions.
1124 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1125 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1126 }
1127 /// Checks if the decl is implicitly firstprivate in the task-based region.
1128 bool isImplicitTaskFirstprivate(Decl *D) const {
1129 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1130 }
1131
1132 /// Marks decl as used in uses_allocators clause as the allocator.
1133 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1134 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1135 }
1136 /// Checks if specified decl is used in uses allocator clause as the
1137 /// allocator.
1138 std::optional<UsesAllocatorsDeclKind>
1139 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1140 const SharingMapTy &StackElem = getTopOfStack();
1141 auto I = StackElem.UsesAllocatorsDecls.find(D);
1142 if (I == StackElem.UsesAllocatorsDecls.end())
1143 return std::nullopt;
1144 return I->getSecond();
1145 }
1146 std::optional<UsesAllocatorsDeclKind>
1147 isUsesAllocatorsDecl(const Decl *D) const {
1148 const SharingMapTy &StackElem = getTopOfStack();
1149 auto I = StackElem.UsesAllocatorsDecls.find(D);
1150 if (I == StackElem.UsesAllocatorsDecls.end())
1151 return std::nullopt;
1152 return I->getSecond();
1153 }
1154
1155 void addDeclareMapperVarRef(Expr *Ref) {
1156 SharingMapTy &StackElem = getTopOfStack();
1157 StackElem.DeclareMapperVar = Ref;
1158 }
1159 const Expr *getDeclareMapperVarRef() const {
1160 const SharingMapTy *Top = getTopOfStackOrNull();
1161 return Top ? Top->DeclareMapperVar : nullptr;
1162 }
1163
1164 /// Add a new iterator variable.
1165 void addIteratorVarDecl(VarDecl *VD) {
1166 SharingMapTy &StackElem = getTopOfStack();
1167 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1168 }
1169 /// Check if variable declaration is an iterator VarDecl.
1170 bool isIteratorVarDecl(const VarDecl *VD) const {
1171 const SharingMapTy *Top = getTopOfStackOrNull();
1172 if (!Top)
1173 return false;
1174
1175 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1176 }
1177 /// get captured field from ImplicitDefaultFirstprivateFDs
1178 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1179 const_iterator I = begin();
1180 const_iterator EndI = end();
1181 size_t StackLevel = getStackSize();
1182 for (; I != EndI; ++I) {
1183 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1184 break;
1185 StackLevel--;
1186 }
1187 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1188 if (I == EndI)
1189 return nullptr;
1190 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1191 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1192 return IFD.VD;
1193 return nullptr;
1194 }
1195 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1196 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1197 const_iterator I = begin();
1198 const_iterator EndI = end();
1199 for (; I != EndI; ++I)
1200 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1201 break;
1202 if (I == EndI)
1203 return false;
1204 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1205 if (IFD.VD == VD)
1206 return true;
1207 return false;
1208 }
1209 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1210 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1211 iterator I = begin();
1212 const_iterator EndI = end();
1213 size_t StackLevel = getStackSize();
1214 for (; I != EndI; ++I) {
1215 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1216 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1217 break;
1218 }
1219 StackLevel--;
1220 }
1221 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1222 }
1223};
1224
1225bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1226 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1227}
1228
1229bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1230 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1231 DKind == OMPD_unknown;
1232}
1233
1234} // namespace
1235
1236static const Expr *getExprAsWritten(const Expr *E) {
1237 if (const auto *FE = dyn_cast<FullExpr>(E))
1238 E = FE->getSubExpr();
1239
1240 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1241 E = MTE->getSubExpr();
1242
1243 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1244 E = Binder->getSubExpr();
1245
1246 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1247 E = ICE->getSubExprAsWritten();
1248 return E->IgnoreParens();
1249}
1250
1252 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1253}
1254
1255static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1256 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1257 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1258 D = ME->getMemberDecl();
1259
1260 D = cast<ValueDecl>(D->getCanonicalDecl());
1261 return D;
1262}
1263
1265 return const_cast<ValueDecl *>(
1266 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1267}
1268
1269DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1270 ValueDecl *D) const {
1271 D = getCanonicalDecl(D);
1272 auto *VD = dyn_cast<VarDecl>(D);
1273 const auto *FD = dyn_cast<FieldDecl>(D);
1274 DSAVarData DVar;
1275 if (Iter == end()) {
1276 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1277 // in a region but not in construct]
1278 // File-scope or namespace-scope variables referenced in called routines
1279 // in the region are shared unless they appear in a threadprivate
1280 // directive.
1281 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1282 DVar.CKind = OMPC_shared;
1283
1284 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1285 // in a region but not in construct]
1286 // Variables with static storage duration that are declared in called
1287 // routines in the region are shared.
1288 if (VD && VD->hasGlobalStorage())
1289 DVar.CKind = OMPC_shared;
1290
1291 // Non-static data members are shared by default.
1292 if (FD)
1293 DVar.CKind = OMPC_shared;
1294
1295 return DVar;
1296 }
1297
1298 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1299 // in a Construct, C/C++, predetermined, p.1]
1300 // Variables with automatic storage duration that are declared in a scope
1301 // inside the construct are private.
1302 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1303 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1304 DVar.CKind = OMPC_private;
1305 return DVar;
1306 }
1307
1308 DVar.DKind = Iter->Directive;
1309 // Explicitly specified attributes and local variables with predetermined
1310 // attributes.
1311 if (Iter->SharingMap.count(D)) {
1312 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1313 DVar.RefExpr = Data.RefExpr.getPointer();
1314 DVar.PrivateCopy = Data.PrivateCopy;
1315 DVar.CKind = Data.Attributes;
1316 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1317 DVar.Modifier = Data.Modifier;
1318 DVar.AppliedToPointee = Data.AppliedToPointee;
1319 return DVar;
1320 }
1321
1322 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1323 // in a Construct, C/C++, implicitly determined, p.1]
1324 // In a parallel or task construct, the data-sharing attributes of these
1325 // variables are determined by the default clause, if present.
1326 switch (Iter->DefaultAttr) {
1327 case DSA_shared:
1328 DVar.CKind = OMPC_shared;
1329 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1330 return DVar;
1331 case DSA_none:
1332 return DVar;
1333 case DSA_firstprivate:
1334 if (VD && VD->getStorageDuration() == SD_Static &&
1335 VD->getDeclContext()->isFileContext()) {
1336 DVar.CKind = OMPC_unknown;
1337 } else {
1338 DVar.CKind = OMPC_firstprivate;
1339 }
1340 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1341 return DVar;
1342 case DSA_private:
1343 // each variable with static storage duration that is declared
1344 // in a namespace or global scope and referenced in the construct,
1345 // and that does not have a predetermined data-sharing attribute
1346 if (VD && VD->getStorageDuration() == SD_Static &&
1347 VD->getDeclContext()->isFileContext()) {
1348 DVar.CKind = OMPC_unknown;
1349 } else {
1350 DVar.CKind = OMPC_private;
1351 }
1352 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1353 return DVar;
1354 case DSA_unspecified:
1355 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1356 // in a Construct, implicitly determined, p.2]
1357 // In a parallel construct, if no default clause is present, these
1358 // variables are shared.
1359 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1360 if ((isOpenMPParallelDirective(DVar.DKind) &&
1361 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1362 isOpenMPTeamsDirective(DVar.DKind)) {
1363 DVar.CKind = OMPC_shared;
1364 return DVar;
1365 }
1366
1367 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1368 // in a Construct, implicitly determined, p.4]
1369 // In a task construct, if no default clause is present, a variable that in
1370 // the enclosing context is determined to be shared by all implicit tasks
1371 // bound to the current team is shared.
1372 if (isOpenMPTaskingDirective(DVar.DKind)) {
1373 DSAVarData DVarTemp;
1374 const_iterator I = Iter, E = end();
1375 do {
1376 ++I;
1377 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1378 // Referenced in a Construct, implicitly determined, p.6]
1379 // In a task construct, if no default clause is present, a variable
1380 // whose data-sharing attribute is not determined by the rules above is
1381 // firstprivate.
1382 DVarTemp = getDSA(I, D);
1383 if (DVarTemp.CKind != OMPC_shared) {
1384 DVar.RefExpr = nullptr;
1385 DVar.CKind = OMPC_firstprivate;
1386 return DVar;
1387 }
1388 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1389 DVar.CKind =
1390 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1391 return DVar;
1392 }
1393 }
1394 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1395 // in a Construct, implicitly determined, p.3]
1396 // For constructs other than task, if no default clause is present, these
1397 // variables inherit their data-sharing attributes from the enclosing
1398 // context.
1399 return getDSA(++Iter, D);
1400}
1401
1402const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1403 const Expr *NewDE) {
1404 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1405 D = getCanonicalDecl(D);
1406 SharingMapTy &StackElem = getTopOfStack();
1407 auto It = StackElem.AlignedMap.find(D);
1408 if (It == StackElem.AlignedMap.end()) {
1409 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1410 StackElem.AlignedMap[D] = NewDE;
1411 return nullptr;
1412 }
1413 assert(It->second && "Unexpected nullptr expr in the aligned map");
1414 return It->second;
1415}
1416
1417const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1418 const Expr *NewDE) {
1419 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1420 D = getCanonicalDecl(D);
1421 SharingMapTy &StackElem = getTopOfStack();
1422 auto It = StackElem.NontemporalMap.find(D);
1423 if (It == StackElem.NontemporalMap.end()) {
1424 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1425 StackElem.NontemporalMap[D] = NewDE;
1426 return nullptr;
1427 }
1428 assert(It->second && "Unexpected nullptr expr in the aligned map");
1429 return It->second;
1430}
1431
1432void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1433 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1434 D = getCanonicalDecl(D);
1435 SharingMapTy &StackElem = getTopOfStack();
1436 StackElem.LCVMap.try_emplace(
1437 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1438}
1439
1440const DSAStackTy::LCDeclInfo
1441DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1442 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1443 D = getCanonicalDecl(D);
1444 const SharingMapTy &StackElem = getTopOfStack();
1445 auto It = StackElem.LCVMap.find(D);
1446 if (It != StackElem.LCVMap.end())
1447 return It->second;
1448 return {0, nullptr};
1449}
1450
1451const DSAStackTy::LCDeclInfo
1452DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1453 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1454 D = getCanonicalDecl(D);
1455 for (unsigned I = Level + 1; I > 0; --I) {
1456 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1457 auto It = StackElem.LCVMap.find(D);
1458 if (It != StackElem.LCVMap.end())
1459 return It->second;
1460 }
1461 return {0, nullptr};
1462}
1463
1464const DSAStackTy::LCDeclInfo
1465DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1466 const SharingMapTy *Parent = getSecondOnStackOrNull();
1467 assert(Parent && "Data-sharing attributes stack is empty");
1468 D = getCanonicalDecl(D);
1469 auto It = Parent->LCVMap.find(D);
1470 if (It != Parent->LCVMap.end())
1471 return It->second;
1472 return {0, nullptr};
1473}
1474
1475const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1476 const SharingMapTy *Parent = getSecondOnStackOrNull();
1477 assert(Parent && "Data-sharing attributes stack is empty");
1478 if (Parent->LCVMap.size() < I)
1479 return nullptr;
1480 for (const auto &Pair : Parent->LCVMap)
1481 if (Pair.second.first == I)
1482 return Pair.first;
1483 return nullptr;
1484}
1485
1486void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1487 DeclRefExpr *PrivateCopy, unsigned Modifier,
1488 bool AppliedToPointee) {
1489 D = getCanonicalDecl(D);
1490 if (A == OMPC_threadprivate) {
1491 DSAInfo &Data = Threadprivates[D];
1492 Data.Attributes = A;
1493 Data.RefExpr.setPointer(E);
1494 Data.PrivateCopy = nullptr;
1495 Data.Modifier = Modifier;
1496 } else {
1497 DSAInfo &Data = getTopOfStack().SharingMap[D];
1498 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1499 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1500 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1501 (isLoopControlVariable(D).first && A == OMPC_private));
1502 Data.Modifier = Modifier;
1503 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1504 Data.RefExpr.setInt(/*IntVal=*/true);
1505 return;
1506 }
1507 const bool IsLastprivate =
1508 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1509 Data.Attributes = A;
1510 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1511 Data.PrivateCopy = PrivateCopy;
1512 Data.AppliedToPointee = AppliedToPointee;
1513 if (PrivateCopy) {
1514 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1515 Data.Modifier = Modifier;
1516 Data.Attributes = A;
1517 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1518 Data.PrivateCopy = nullptr;
1519 Data.AppliedToPointee = AppliedToPointee;
1520 }
1521 }
1522}
1523
1524/// Build a variable declaration for OpenMP loop iteration variable.
1526 StringRef Name, const AttrVec *Attrs = nullptr,
1527 DeclRefExpr *OrigRef = nullptr) {
1528 DeclContext *DC = SemaRef.CurContext;
1529 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1531 auto *Decl =
1532 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1533 if (Attrs) {
1534 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1535 I != E; ++I)
1536 Decl->addAttr(*I);
1537 }
1538 Decl->setImplicit();
1539 if (OrigRef) {
1540 Decl->addAttr(
1541 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1542 }
1543 return Decl;
1544}
1545
1548 bool RefersToCapture = false) {
1549 D->setReferenced();
1550 D->markUsed(S.Context);
1552 SourceLocation(), D, RefersToCapture, Loc, Ty,
1553 VK_LValue);
1554}
1555
1556void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1557 BinaryOperatorKind BOK) {
1558 D = getCanonicalDecl(D);
1559 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1560 assert(
1561 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1562 "Additional reduction info may be specified only for reduction items.");
1563 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1564 assert(ReductionData.ReductionRange.isInvalid() &&
1565 (getTopOfStack().Directive == OMPD_taskgroup ||
1566 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1567 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1568 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1569 "Additional reduction info may be specified only once for reduction "
1570 "items.");
1571 ReductionData.set(BOK, SR);
1572 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1573 if (!TaskgroupReductionRef) {
1574 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1575 SemaRef.Context.VoidPtrTy, ".task_red.");
1576 TaskgroupReductionRef =
1577 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1578 }
1579}
1580
1581void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1582 const Expr *ReductionRef) {
1583 D = getCanonicalDecl(D);
1584 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1585 assert(
1586 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1587 "Additional reduction info may be specified only for reduction items.");
1588 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1589 assert(ReductionData.ReductionRange.isInvalid() &&
1590 (getTopOfStack().Directive == OMPD_taskgroup ||
1591 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1592 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1593 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1594 "Additional reduction info may be specified only once for reduction "
1595 "items.");
1596 ReductionData.set(ReductionRef, SR);
1597 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1598 if (!TaskgroupReductionRef) {
1599 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1600 SemaRef.Context.VoidPtrTy, ".task_red.");
1601 TaskgroupReductionRef =
1602 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1603 }
1604}
1605
1606const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1607 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1608 Expr *&TaskgroupDescriptor) const {
1609 D = getCanonicalDecl(D);
1610 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1611 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1612 const DSAInfo &Data = I->SharingMap.lookup(D);
1613 if (Data.Attributes != OMPC_reduction ||
1614 Data.Modifier != OMPC_REDUCTION_task)
1615 continue;
1616 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1617 if (!ReductionData.ReductionOp ||
1618 ReductionData.ReductionOp.is<const Expr *>())
1619 return DSAVarData();
1620 SR = ReductionData.ReductionRange;
1621 BOK = ReductionData.ReductionOp.get<ReductionData::BOKPtrType>();
1622 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1623 "expression for the descriptor is not "
1624 "set.");
1625 TaskgroupDescriptor = I->TaskgroupReductionRef;
1626 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1627 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1628 /*AppliedToPointee=*/false);
1629 }
1630 return DSAVarData();
1631}
1632
1633const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1634 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1635 Expr *&TaskgroupDescriptor) const {
1636 D = getCanonicalDecl(D);
1637 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1638 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1639 const DSAInfo &Data = I->SharingMap.lookup(D);
1640 if (Data.Attributes != OMPC_reduction ||
1641 Data.Modifier != OMPC_REDUCTION_task)
1642 continue;
1643 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1644 if (!ReductionData.ReductionOp ||
1645 !ReductionData.ReductionOp.is<const Expr *>())
1646 return DSAVarData();
1647 SR = ReductionData.ReductionRange;
1648 ReductionRef = ReductionData.ReductionOp.get<const Expr *>();
1649 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1650 "expression for the descriptor is not "
1651 "set.");
1652 TaskgroupDescriptor = I->TaskgroupReductionRef;
1653 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1654 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1655 /*AppliedToPointee=*/false);
1656 }
1657 return DSAVarData();
1658}
1659
1660bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1661 D = D->getCanonicalDecl();
1662 for (const_iterator E = end(); I != E; ++I) {
1663 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1664 isOpenMPTargetExecutionDirective(I->Directive)) {
1665 if (I->CurScope) {
1666 Scope *TopScope = I->CurScope->getParent();
1667 Scope *CurScope = getCurScope();
1668 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1669 CurScope = CurScope->getParent();
1670 return CurScope != TopScope;
1671 }
1672 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1673 if (I->Context == DC)
1674 return true;
1675 return false;
1676 }
1677 }
1678 return false;
1679}
1680
1682 bool AcceptIfMutable = true,
1683 bool *IsClassType = nullptr) {
1684 ASTContext &Context = SemaRef.getASTContext();
1685 Type = Type.getNonReferenceType().getCanonicalType();
1686 bool IsConstant = Type.isConstant(Context);
1687 Type = Context.getBaseElementType(Type);
1688 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1690 : nullptr;
1691 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1692 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1693 RD = CTD->getTemplatedDecl();
1694 if (IsClassType)
1695 *IsClassType = RD;
1696 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1697 RD->hasDefinition() && RD->hasMutableFields());
1698}
1699
1700static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1702 SourceLocation ELoc,
1703 bool AcceptIfMutable = true,
1704 bool ListItemNotVar = false) {
1705 ASTContext &Context = SemaRef.getASTContext();
1706 bool IsClassType;
1707 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1708 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1709 : IsClassType ? diag::err_omp_const_not_mutable_variable
1710 : diag::err_omp_const_variable;
1711 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseName(CKind);
1712 if (!ListItemNotVar && D) {
1713 const VarDecl *VD = dyn_cast<VarDecl>(D);
1714 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1716 SemaRef.Diag(D->getLocation(),
1717 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1718 << D;
1719 }
1720 return true;
1721 }
1722 return false;
1723}
1724
1725const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1726 bool FromParent) {
1727 D = getCanonicalDecl(D);
1728 DSAVarData DVar;
1729
1730 auto *VD = dyn_cast<VarDecl>(D);
1731 auto TI = Threadprivates.find(D);
1732 if (TI != Threadprivates.end()) {
1733 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1734 DVar.CKind = OMPC_threadprivate;
1735 DVar.Modifier = TI->getSecond().Modifier;
1736 return DVar;
1737 }
1738 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1739 DVar.RefExpr = buildDeclRefExpr(
1740 SemaRef, VD, D->getType().getNonReferenceType(),
1741 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1742 DVar.CKind = OMPC_threadprivate;
1743 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1744 return DVar;
1745 }
1746 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1747 // in a Construct, C/C++, predetermined, p.1]
1748 // Variables appearing in threadprivate directives are threadprivate.
1749 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1750 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1751 SemaRef.getLangOpts().OpenMPUseTLS &&
1752 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1753 (VD && VD->getStorageClass() == SC_Register &&
1754 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1755 DVar.RefExpr = buildDeclRefExpr(
1756 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1757 DVar.CKind = OMPC_threadprivate;
1758 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1759 return DVar;
1760 }
1761 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1762 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1763 !isLoopControlVariable(D).first) {
1764 const_iterator IterTarget =
1765 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1766 return isOpenMPTargetExecutionDirective(Data.Directive);
1767 });
1768 if (IterTarget != end()) {
1769 const_iterator ParentIterTarget = IterTarget + 1;
1770 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1771 if (isOpenMPLocal(VD, Iter)) {
1772 DVar.RefExpr =
1773 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1774 D->getLocation());
1775 DVar.CKind = OMPC_threadprivate;
1776 return DVar;
1777 }
1778 }
1779 if (!isClauseParsingMode() || IterTarget != begin()) {
1780 auto DSAIter = IterTarget->SharingMap.find(D);
1781 if (DSAIter != IterTarget->SharingMap.end() &&
1782 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1783 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1784 DVar.CKind = OMPC_threadprivate;
1785 return DVar;
1786 }
1787 const_iterator End = end();
1788 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1789 D, std::distance(ParentIterTarget, End),
1790 /*OpenMPCaptureLevel=*/0)) {
1791 DVar.RefExpr =
1792 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1793 IterTarget->ConstructLoc);
1794 DVar.CKind = OMPC_threadprivate;
1795 return DVar;
1796 }
1797 }
1798 }
1799 }
1800
1801 if (isStackEmpty())
1802 // Not in OpenMP execution region and top scope was already checked.
1803 return DVar;
1804
1805 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1806 // in a Construct, C/C++, predetermined, p.4]
1807 // Static data members are shared.
1808 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1809 // in a Construct, C/C++, predetermined, p.7]
1810 // Variables with static storage duration that are declared in a scope
1811 // inside the construct are shared.
1812 if (VD && VD->isStaticDataMember()) {
1813 // Check for explicitly specified attributes.
1814 const_iterator I = begin();
1815 const_iterator EndI = end();
1816 if (FromParent && I != EndI)
1817 ++I;
1818 if (I != EndI) {
1819 auto It = I->SharingMap.find(D);
1820 if (It != I->SharingMap.end()) {
1821 const DSAInfo &Data = It->getSecond();
1822 DVar.RefExpr = Data.RefExpr.getPointer();
1823 DVar.PrivateCopy = Data.PrivateCopy;
1824 DVar.CKind = Data.Attributes;
1825 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1826 DVar.DKind = I->Directive;
1827 DVar.Modifier = Data.Modifier;
1828 DVar.AppliedToPointee = Data.AppliedToPointee;
1829 return DVar;
1830 }
1831 }
1832
1833 DVar.CKind = OMPC_shared;
1834 return DVar;
1835 }
1836
1837 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1838 // The predetermined shared attribute for const-qualified types having no
1839 // mutable members was removed after OpenMP 3.1.
1840 if (SemaRef.LangOpts.OpenMP <= 31) {
1841 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1842 // in a Construct, C/C++, predetermined, p.6]
1843 // Variables with const qualified type having no mutable member are
1844 // shared.
1845 if (isConstNotMutableType(SemaRef, D->getType())) {
1846 // Variables with const-qualified type having no mutable member may be
1847 // listed in a firstprivate clause, even if they are static data members.
1848 DSAVarData DVarTemp = hasInnermostDSA(
1849 D,
1850 [](OpenMPClauseKind C, bool) {
1851 return C == OMPC_firstprivate || C == OMPC_shared;
1852 },
1853 MatchesAlways, FromParent);
1854 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1855 return DVarTemp;
1856
1857 DVar.CKind = OMPC_shared;
1858 return DVar;
1859 }
1860 }
1861
1862 // Explicitly specified attributes and local variables with predetermined
1863 // attributes.
1864 const_iterator I = begin();
1865 const_iterator EndI = end();
1866 if (FromParent && I != EndI)
1867 ++I;
1868 if (I == EndI)
1869 return DVar;
1870 auto It = I->SharingMap.find(D);
1871 if (It != I->SharingMap.end()) {
1872 const DSAInfo &Data = It->getSecond();
1873 DVar.RefExpr = Data.RefExpr.getPointer();
1874 DVar.PrivateCopy = Data.PrivateCopy;
1875 DVar.CKind = Data.Attributes;
1876 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1877 DVar.DKind = I->Directive;
1878 DVar.Modifier = Data.Modifier;
1879 DVar.AppliedToPointee = Data.AppliedToPointee;
1880 }
1881
1882 return DVar;
1883}
1884
1885const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1886 bool FromParent) const {
1887 if (isStackEmpty()) {
1888 const_iterator I;
1889 return getDSA(I, D);
1890 }
1891 D = getCanonicalDecl(D);
1892 const_iterator StartI = begin();
1893 const_iterator EndI = end();
1894 if (FromParent && StartI != EndI)
1895 ++StartI;
1896 return getDSA(StartI, D);
1897}
1898
1899const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1900 unsigned Level) const {
1901 if (getStackSize() <= Level)
1902 return DSAVarData();
1903 D = getCanonicalDecl(D);
1904 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1905 return getDSA(StartI, D);
1906}
1907
1908const DSAStackTy::DSAVarData
1909DSAStackTy::hasDSA(ValueDecl *D,
1910 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1911 DefaultDataSharingAttributes)>
1912 CPred,
1913 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1914 bool FromParent) const {
1915 if (isStackEmpty())
1916 return {};
1917 D = getCanonicalDecl(D);
1918 const_iterator I = begin();
1919 const_iterator EndI = end();
1920 if (FromParent && I != EndI)
1921 ++I;
1922 for (; I != EndI; ++I) {
1923 if (!DPred(I->Directive) &&
1924 !isImplicitOrExplicitTaskingRegion(I->Directive))
1925 continue;
1926 const_iterator NewI = I;
1927 DSAVarData DVar = getDSA(NewI, D);
1928 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1929 return DVar;
1930 }
1931 return {};
1932}
1933
1934const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1935 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1936 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1937 bool FromParent) const {
1938 if (isStackEmpty())
1939 return {};
1940 D = getCanonicalDecl(D);
1941 const_iterator StartI = begin();
1942 const_iterator EndI = end();
1943 if (FromParent && StartI != EndI)
1944 ++StartI;
1945 if (StartI == EndI || !DPred(StartI->Directive))
1946 return {};
1947 const_iterator NewI = StartI;
1948 DSAVarData DVar = getDSA(NewI, D);
1949 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
1950 ? DVar
1951 : DSAVarData();
1952}
1953
1954bool DSAStackTy::hasExplicitDSA(
1955 const ValueDecl *D,
1956 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
1957 unsigned Level, bool NotLastprivate) const {
1958 if (getStackSize() <= Level)
1959 return false;
1960 D = getCanonicalDecl(D);
1961 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1962 auto I = StackElem.SharingMap.find(D);
1963 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
1964 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
1965 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
1966 return true;
1967 // Check predetermined rules for the loop control variables.
1968 auto LI = StackElem.LCVMap.find(D);
1969 if (LI != StackElem.LCVMap.end())
1970 return CPred(OMPC_private, /*AppliedToPointee=*/false);
1971 return false;
1972}
1973
1974bool DSAStackTy::hasExplicitDirective(
1975 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1976 unsigned Level) const {
1977 if (getStackSize() <= Level)
1978 return false;
1979 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1980 return DPred(StackElem.Directive);
1981}
1982
1983bool DSAStackTy::hasDirective(
1984 const llvm::function_ref<bool(OpenMPDirectiveKind,
1986 DPred,
1987 bool FromParent) const {
1988 // We look only in the enclosing region.
1989 size_t Skip = FromParent ? 2 : 1;
1990 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
1991 I != E; ++I) {
1992 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
1993 return true;
1994 }
1995 return false;
1996}
1997
1998void SemaOpenMP::InitDataSharingAttributesStack() {
1999 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2000}
2001
2002#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2003
2004void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2005
2006void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2007 DSAStack->popFunction(OldFSI);
2008}
2009
2011 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2012 "Expected OpenMP device compilation.");
2014}
2015
2016namespace {
2017/// Status of the function emission on the host/device.
2018enum class FunctionEmissionStatus {
2019 Emitted,
2020 Discarded,
2021 Unknown,
2022};
2023} // anonymous namespace
2024
2027 const FunctionDecl *FD) {
2028 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2029 "Expected OpenMP device compilation.");
2030
2031 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2032 if (FD) {
2034 switch (FES) {
2036 Kind = SemaDiagnosticBuilder::K_Immediate;
2037 break;
2039 // TODO: We should always delay diagnostics here in case a target
2040 // region is in a function we do not emit. However, as the
2041 // current diagnostics are associated with the function containing
2042 // the target region and we do not emit that one, we would miss out
2043 // on diagnostics for the target region itself. We need to anchor
2044 // the diagnostics with the new generated function *or* ensure we
2045 // emit diagnostics associated with the surrounding function.
2047 ? SemaDiagnosticBuilder::K_Deferred
2048 : SemaDiagnosticBuilder::K_Immediate;
2049 break;
2052 Kind = SemaDiagnosticBuilder::K_Nop;
2053 break;
2055 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2056 break;
2057 }
2058 }
2059
2060 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2061}
2062
2065 const FunctionDecl *FD) {
2066 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2067 "Expected OpenMP host compilation.");
2068
2069 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2070 if (FD) {
2072 switch (FES) {
2074 Kind = SemaDiagnosticBuilder::K_Immediate;
2075 break;
2077 Kind = SemaDiagnosticBuilder::K_Deferred;
2078 break;
2082 Kind = SemaDiagnosticBuilder::K_Nop;
2083 break;
2084 }
2085 }
2086
2087 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2088}
2089
2092 if (LO.OpenMP <= 45) {
2094 return OMPC_DEFAULTMAP_scalar;
2095 return OMPC_DEFAULTMAP_aggregate;
2096 }
2098 return OMPC_DEFAULTMAP_pointer;
2100 return OMPC_DEFAULTMAP_scalar;
2101 return OMPC_DEFAULTMAP_aggregate;
2102}
2103
2105 unsigned OpenMPCaptureLevel) const {
2106 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2107
2108 ASTContext &Ctx = getASTContext();
2109 bool IsByRef = true;
2110
2111 // Find the directive that is associated with the provided scope.
2112 D = cast<ValueDecl>(D->getCanonicalDecl());
2113 QualType Ty = D->getType();
2114
2115 bool IsVariableUsedInMapClause = false;
2116 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2117 // This table summarizes how a given variable should be passed to the device
2118 // given its type and the clauses where it appears. This table is based on
2119 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2120 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2121 //
2122 // =========================================================================
2123 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2124 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2125 // =========================================================================
2126 // | scl | | | | - | | bycopy|
2127 // | scl | | - | x | - | - | bycopy|
2128 // | scl | | x | - | - | - | null |
2129 // | scl | x | | | - | | byref |
2130 // | scl | x | - | x | - | - | bycopy|
2131 // | scl | x | x | - | - | - | null |
2132 // | scl | | - | - | - | x | byref |
2133 // | scl | x | - | - | - | x | byref |
2134 //
2135 // | agg | n.a. | | | - | | byref |
2136 // | agg | n.a. | - | x | - | - | byref |
2137 // | agg | n.a. | x | - | - | - | null |
2138 // | agg | n.a. | - | - | - | x | byref |
2139 // | agg | n.a. | - | - | - | x[] | byref |
2140 //
2141 // | ptr | n.a. | | | - | | bycopy|
2142 // | ptr | n.a. | - | x | - | - | bycopy|
2143 // | ptr | n.a. | x | - | - | - | null |
2144 // | ptr | n.a. | - | - | - | x | byref |
2145 // | ptr | n.a. | - | - | - | x[] | bycopy|
2146 // | ptr | n.a. | - | - | x | | bycopy|
2147 // | ptr | n.a. | - | - | x | x | bycopy|
2148 // | ptr | n.a. | - | - | x | x[] | bycopy|
2149 // =========================================================================
2150 // Legend:
2151 // scl - scalar
2152 // ptr - pointer
2153 // agg - aggregate
2154 // x - applies
2155 // - - invalid in this combination
2156 // [] - mapped with an array section
2157 // byref - should be mapped by reference
2158 // byval - should be mapped by value
2159 // null - initialize a local variable to null on the device
2160 //
2161 // Observations:
2162 // - All scalar declarations that show up in a map clause have to be passed
2163 // by reference, because they may have been mapped in the enclosing data
2164 // environment.
2165 // - If the scalar value does not fit the size of uintptr, it has to be
2166 // passed by reference, regardless the result in the table above.
2167 // - For pointers mapped by value that have either an implicit map or an
2168 // array section, the runtime library may pass the NULL value to the
2169 // device instead of the value passed to it by the compiler.
2170
2171 if (Ty->isReferenceType())
2172 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2173
2174 // Locate map clauses and see if the variable being captured is referred to
2175 // in any of those clauses. Here we only care about variables, not fields,
2176 // because fields are part of aggregates.
2177 bool IsVariableAssociatedWithSection = false;
2178
2179 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2180 D, Level,
2181 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2183 MapExprComponents,
2184 OpenMPClauseKind WhereFoundClauseKind) {
2185 // Both map and has_device_addr clauses information influences how a
2186 // variable is captured. E.g. is_device_ptr does not require changing
2187 // the default behavior.
2188 if (WhereFoundClauseKind != OMPC_map &&
2189 WhereFoundClauseKind != OMPC_has_device_addr)
2190 return false;
2191
2192 auto EI = MapExprComponents.rbegin();
2193 auto EE = MapExprComponents.rend();
2194
2195 assert(EI != EE && "Invalid map expression!");
2196
2197 if (isa<DeclRefExpr>(EI->getAssociatedExpression()))
2198 IsVariableUsedInMapClause |= EI->getAssociatedDeclaration() == D;
2199
2200 ++EI;
2201 if (EI == EE)
2202 return false;
2203 auto Last = std::prev(EE);
2204 const auto *UO =
2205 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2206 if ((UO && UO->getOpcode() == UO_Deref) ||
2207 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2208 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2209 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2210 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2211 IsVariableAssociatedWithSection = true;
2212 // There is nothing more we need to know about this variable.
2213 return true;
2214 }
2215
2216 // Keep looking for more map info.
2217 return false;
2218 });
2219
2220 if (IsVariableUsedInMapClause) {
2221 // If variable is identified in a map clause it is always captured by
2222 // reference except if it is a pointer that is dereferenced somehow.
2223 IsByRef = !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2224 } else {
2225 // By default, all the data that has a scalar type is mapped by copy
2226 // (except for reduction variables).
2227 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2228 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2229 !Ty->isAnyPointerType()) ||
2230 !Ty->isScalarType() ||
2231 DSAStack->isDefaultmapCapturedByRef(
2233 DSAStack->hasExplicitDSA(
2234 D,
2235 [](OpenMPClauseKind K, bool AppliedToPointee) {
2236 return K == OMPC_reduction && !AppliedToPointee;
2237 },
2238 Level);
2239 }
2240 }
2241
2242 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2243 IsByRef =
2244 ((IsVariableUsedInMapClause &&
2245 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2246 OMPD_target) ||
2247 !(DSAStack->hasExplicitDSA(
2248 D,
2249 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2250 return K == OMPC_firstprivate ||
2251 (K == OMPC_reduction && AppliedToPointee);
2252 },
2253 Level, /*NotLastprivate=*/true) ||
2254 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2255 // If the variable is artificial and must be captured by value - try to
2256 // capture by value.
2257 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2258 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2259 // If the variable is implicitly firstprivate and scalar - capture by
2260 // copy
2261 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2262 DSAStack->getDefaultDSA() == DSA_private) &&
2263 !DSAStack->hasExplicitDSA(
2264 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2265 Level) &&
2266 !DSAStack->isLoopControlVariable(D, Level).first);
2267 }
2268
2269 // When passing data by copy, we need to make sure it fits the uintptr size
2270 // and alignment, because the runtime library only deals with uintptr types.
2271 // If it does not fit the uintptr size, we need to pass the data by reference
2272 // instead.
2273 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2275 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2276 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2277 IsByRef = true;
2278 }
2279
2280 return IsByRef;
2281}
2282
2283unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2284 assert(getLangOpts().OpenMP);
2285 return DSAStack->getNestingLevel();
2286}
2287
2289 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2290 DSAStack->isUntiedRegion();
2291}
2292
2294 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2295 !DSAStack->isClauseParsingMode()) ||
2296 DSAStack->hasDirective(
2298 SourceLocation) -> bool {
2300 },
2301 false);
2302}
2303
2305 // Only rebuild for Field.
2306 if (!dyn_cast<FieldDecl>(D))
2307 return false;
2308 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2309 D,
2310 [](OpenMPClauseKind C, bool AppliedToPointee,
2311 DefaultDataSharingAttributes DefaultAttr) {
2312 return isOpenMPPrivate(C) && !AppliedToPointee &&
2313 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2314 },
2315 [](OpenMPDirectiveKind) { return true; },
2316 DSAStack->isClauseParsingMode());
2317 if (DVarPrivate.CKind != OMPC_unknown)
2318 return true;
2319 return false;
2320}
2321
2323 Expr *CaptureExpr, bool WithInit,
2324 DeclContext *CurContext,
2325 bool AsExpression);
2326
2328 unsigned StopAt) {
2329 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2330 D = getCanonicalDecl(D);
2331
2332 auto *VD = dyn_cast<VarDecl>(D);
2333 // Do not capture constexpr variables.
2334 if (VD && VD->isConstexpr())
2335 return nullptr;
2336
2337 // If we want to determine whether the variable should be captured from the
2338 // perspective of the current capturing scope, and we've already left all the
2339 // capturing scopes of the top directive on the stack, check from the
2340 // perspective of its parent directive (if any) instead.
2341 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2342 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2343
2344 // If we are attempting to capture a global variable in a directive with
2345 // 'target' we return true so that this global is also mapped to the device.
2346 //
2347 if (VD && !VD->hasLocalStorage() &&
2349 SemaRef.getCurLambda())) {
2351 DSAStackTy::DSAVarData DVarTop =
2352 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2353 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2354 return VD;
2355 // If the declaration is enclosed in a 'declare target' directive,
2356 // then it should not be captured.
2357 //
2358 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2359 return nullptr;
2360 CapturedRegionScopeInfo *CSI = nullptr;
2361 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2362 llvm::reverse(SemaRef.FunctionScopes),
2363 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2364 : 0)) {
2365 if (!isa<CapturingScopeInfo>(FSI))
2366 return nullptr;
2367 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2368 if (RSI->CapRegionKind == CR_OpenMP) {
2369 CSI = RSI;
2370 break;
2371 }
2372 }
2373 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2376 DSAStack->getDirective(CSI->OpenMPLevel));
2377 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2378 return VD;
2379 }
2381 // Try to mark variable as declare target if it is used in capturing
2382 // regions.
2383 if (getLangOpts().OpenMP <= 45 &&
2384 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2386 return nullptr;
2387 }
2388 }
2389
2390 if (CheckScopeInfo) {
2391 bool OpenMPFound = false;
2392 for (unsigned I = StopAt + 1; I > 0; --I) {
2394 if (!isa<CapturingScopeInfo>(FSI))
2395 return nullptr;
2396 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2397 if (RSI->CapRegionKind == CR_OpenMP) {
2398 OpenMPFound = true;
2399 break;
2400 }
2401 }
2402 if (!OpenMPFound)
2403 return nullptr;
2404 }
2405
2406 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2407 (!DSAStack->isClauseParsingMode() ||
2408 DSAStack->getParentDirective() != OMPD_unknown)) {
2409 auto &&Info = DSAStack->isLoopControlVariable(D);
2410 if (Info.first ||
2411 (VD && VD->hasLocalStorage() &&
2412 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2413 (VD && DSAStack->isForceVarCapturing()))
2414 return VD ? VD : Info.second;
2415 DSAStackTy::DSAVarData DVarTop =
2416 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2417 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2418 (!VD || VD->hasLocalStorage() || !DVarTop.AppliedToPointee))
2419 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2420 // Threadprivate variables must not be captured.
2421 if (isOpenMPThreadPrivate(DVarTop.CKind))
2422 return nullptr;
2423 // The variable is not private or it is the variable in the directive with
2424 // default(none) clause and not used in any clause.
2425 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2426 D,
2427 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2428 return isOpenMPPrivate(C) && !AppliedToPointee;
2429 },
2430 [](OpenMPDirectiveKind) { return true; },
2431 DSAStack->isClauseParsingMode());
2432 // Global shared must not be captured.
2433 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2434 ((DSAStack->getDefaultDSA() != DSA_none &&
2435 DSAStack->getDefaultDSA() != DSA_private &&
2436 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2437 DVarTop.CKind == OMPC_shared))
2438 return nullptr;
2439 auto *FD = dyn_cast<FieldDecl>(D);
2440 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2441 !DVarPrivate.PrivateCopy) {
2442 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2443 D,
2444 [](OpenMPClauseKind C, bool AppliedToPointee,
2445 DefaultDataSharingAttributes DefaultAttr) {
2446 return isOpenMPPrivate(C) && !AppliedToPointee &&
2447 (DefaultAttr == DSA_firstprivate ||
2448 DefaultAttr == DSA_private);
2449 },
2450 [](OpenMPDirectiveKind) { return true; },
2451 DSAStack->isClauseParsingMode());
2452 if (DVarPrivate.CKind == OMPC_unknown)
2453 return nullptr;
2454
2455 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2456 if (VD)
2457 return VD;
2459 return nullptr;
2462 /*IsImplicit=*/true);
2463 const CXXScopeSpec CS = CXXScopeSpec();
2465 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2468 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2471 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2472 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2473 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2475 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2476 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2477 return VD;
2478 }
2479 if (DVarPrivate.CKind != OMPC_unknown ||
2480 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2481 DSAStack->getDefaultDSA() == DSA_private ||
2482 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2483 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2484 }
2485 return nullptr;
2486}
2487
2488void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2489 unsigned Level) const {
2490 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2491}
2492
2494 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2495 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2496 DSAStack->loopInit();
2497}
2498
2500 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2501 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2502 DSAStack->resetPossibleLoopCounter();
2503 DSAStack->loopStart();
2504 }
2505}
2506
2508 unsigned CapLevel) const {
2509 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2510 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2511 (!DSAStack->isClauseParsingMode() ||
2512 DSAStack->getParentDirective() != OMPD_unknown)) {
2513 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2514 D,
2515 [](OpenMPClauseKind C, bool AppliedToPointee,
2516 DefaultDataSharingAttributes DefaultAttr) {
2517 return isOpenMPPrivate(C) && !AppliedToPointee &&
2518 DefaultAttr == DSA_private;
2519 },
2520 [](OpenMPDirectiveKind) { return true; },
2521 DSAStack->isClauseParsingMode());
2522 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2523 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2524 !DSAStack->isLoopControlVariable(D).first)
2525 return OMPC_private;
2526 }
2527 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2528 bool IsTriviallyCopyable =
2529 D->getType().getNonReferenceType().isTriviallyCopyableType(
2530 getASTContext()) &&
2531 !D->getType()
2532 .getNonReferenceType()
2533 .getCanonicalType()
2534 ->getAsCXXRecordDecl();
2535 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2537 getOpenMPCaptureRegions(CaptureRegions, DKind);
2538 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2539 (IsTriviallyCopyable ||
2540 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2541 if (DSAStack->hasExplicitDSA(
2542 D,
2543 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2544 Level, /*NotLastprivate=*/true))
2545 return OMPC_firstprivate;
2546 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2547 if (DVar.CKind != OMPC_shared &&
2548 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2549 DSAStack->addImplicitTaskFirstprivate(Level, D);
2550 return OMPC_firstprivate;
2551 }
2552 }
2553 }
2554 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2555 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2556 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2557 DSAStack->resetPossibleLoopCounter(D);
2558 DSAStack->loopStart();
2559 return OMPC_private;
2560 }
2561 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2562 DSAStack->isLoopControlVariable(D).first) &&
2563 !DSAStack->hasExplicitDSA(
2564 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2565 Level) &&
2566 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2567 return OMPC_private;
2568 }
2569 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2570 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2571 DSAStack->isForceVarCapturing() &&
2572 !DSAStack->hasExplicitDSA(
2573 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2574 Level))
2575 return OMPC_private;
2576 }
2577 // User-defined allocators are private since they must be defined in the
2578 // context of target region.
2579 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2580 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2581 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2582 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2583 return OMPC_private;
2584 return (DSAStack->hasExplicitDSA(
2585 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2586 Level) ||
2587 (DSAStack->isClauseParsingMode() &&
2588 DSAStack->getClauseParsingMode() == OMPC_private) ||
2589 // Consider taskgroup reduction descriptor variable a private
2590 // to avoid possible capture in the region.
2591 (DSAStack->hasExplicitDirective(
2592 [](OpenMPDirectiveKind K) {
2593 return K == OMPD_taskgroup ||
2594 ((isOpenMPParallelDirective(K) ||
2595 isOpenMPWorksharingDirective(K)) &&
2596 !isOpenMPSimdDirective(K));
2597 },
2598 Level) &&
2599 DSAStack->isTaskgroupReductionRef(D, Level)))
2600 ? OMPC_private
2601 : OMPC_unknown;
2602}
2603
2605 unsigned Level) {
2606 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2607 D = getCanonicalDecl(D);
2608 OpenMPClauseKind OMPC = OMPC_unknown;
2609 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2610 const unsigned NewLevel = I - 1;
2611 if (DSAStack->hasExplicitDSA(
2612 D,
2613 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2614 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2615 OMPC = K;
2616 return true;
2617 }
2618 return false;
2619 },
2620 NewLevel))
2621 break;
2622 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2623 D, NewLevel,
2625 OpenMPClauseKind) { return true; })) {
2626 OMPC = OMPC_map;
2627 break;
2628 }
2629 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2630 NewLevel)) {
2631 OMPC = OMPC_map;
2632 if (DSAStack->mustBeFirstprivateAtLevel(
2634 OMPC = OMPC_firstprivate;
2635 break;
2636 }
2637 }
2638 if (OMPC != OMPC_unknown)
2639 FD->addAttr(
2640 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2641}
2642
2644 unsigned CaptureLevel) const {
2645 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2646 // Return true if the current level is no longer enclosed in a target region.
2647
2649 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2650 const auto *VD = dyn_cast<VarDecl>(D);
2651 return VD && !VD->hasLocalStorage() &&
2652 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2653 Level) &&
2654 Regions[CaptureLevel] != OMPD_task;
2655}
2656
2658 unsigned CaptureLevel) const {
2659 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2660 // Return true if the current level is no longer enclosed in a target region.
2661
2662 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2663 if (!VD->hasLocalStorage()) {
2665 return true;
2666 DSAStackTy::DSAVarData TopDVar =
2667 DSAStack->getTopDSA(D, /*FromParent=*/false);
2668 unsigned NumLevels =
2669 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2670 if (Level == 0)
2671 // non-file scope static variable with default(firstprivate)
2672 // should be global captured.
2673 return (NumLevels == CaptureLevel + 1 &&
2674 (TopDVar.CKind != OMPC_shared ||
2675 DSAStack->getDefaultDSA() == DSA_firstprivate));
2676 do {
2677 --Level;
2678 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2679 if (DVar.CKind != OMPC_shared)
2680 return true;
2681 } while (Level > 0);
2682 }
2683 }
2684 return true;
2685}
2686
2687void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2688
2690 OMPTraitInfo &TI) {
2691 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2692}
2693
2696 "Not in OpenMP declare variant scope!");
2697
2698 OMPDeclareVariantScopes.pop_back();
2699}
2700
2702 const FunctionDecl *Callee,
2704 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2705 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2706 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2707 // Ignore host functions during device analysis.
2708 if (getLangOpts().OpenMPIsTargetDevice &&
2709 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2710 return;
2711 // Ignore nohost functions during host analysis.
2712 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2713 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2714 return;
2715 const FunctionDecl *FD = Callee->getMostRecentDecl();
2716 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2717 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2718 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2719 // Diagnose host function called during device codegen.
2720 StringRef HostDevTy =
2721 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2722 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2723 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2724 diag::note_omp_marked_device_type_here)
2725 << HostDevTy;
2726 return;
2727 }
2728 if (!getLangOpts().OpenMPIsTargetDevice &&
2729 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2730 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2731 // In OpenMP 5.2 or later, if the function has a host variant then allow
2732 // that to be called instead
2733 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2734 for (OMPDeclareVariantAttr *A :
2735 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2736 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2737 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2738 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2739 OMPDeclareTargetDeclAttr::getDeviceType(
2740 VariantFD->getMostRecentDecl());
2741 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2742 return true;
2743 }
2744 return false;
2745 };
2746 if (getLangOpts().OpenMP >= 52 &&
2747 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2748 return;
2749 // Diagnose nohost function called during host codegen.
2750 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2751 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2752 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2753 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2754 diag::note_omp_marked_device_type_here)
2755 << NoHostDevTy;
2756 }
2757}
2758
2760 const DeclarationNameInfo &DirName,
2761 Scope *CurScope, SourceLocation Loc) {
2762 DSAStack->push(DKind, DirName, CurScope, Loc);
2765}
2766
2768 DSAStack->setClauseParsingMode(K);
2769}
2770
2772 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2774}
2775
2776static std::pair<ValueDecl *, bool>
2777getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2778 SourceRange &ERange, bool AllowArraySection = false,
2779 StringRef DiagType = "");
2780
2781/// Check consistency of the reduction clauses.
2782static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2783 ArrayRef<OMPClause *> Clauses) {
2784 bool InscanFound = false;
2785 SourceLocation InscanLoc;
2786 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2787 // A reduction clause without the inscan reduction-modifier may not appear on
2788 // a construct on which a reduction clause with the inscan reduction-modifier
2789 // appears.
2790 for (OMPClause *C : Clauses) {
2791 if (C->getClauseKind() != OMPC_reduction)
2792 continue;
2793 auto *RC = cast<OMPReductionClause>(C);
2794 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2795 InscanFound = true;
2796 InscanLoc = RC->getModifierLoc();
2797 continue;
2798 }
2799 if (RC->getModifier() == OMPC_REDUCTION_task) {
2800 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2801 // A reduction clause with the task reduction-modifier may only appear on
2802 // a parallel construct, a worksharing construct or a combined or
2803 // composite construct for which any of the aforementioned constructs is a
2804 // constituent construct and simd or loop are not constituent constructs.
2805 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2806 if (!(isOpenMPParallelDirective(CurDir) ||
2808 isOpenMPSimdDirective(CurDir))
2809 S.Diag(RC->getModifierLoc(),
2810 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2811 continue;
2812 }
2813 }
2814 if (InscanFound) {
2815 for (OMPClause *C : Clauses) {
2816 if (C->getClauseKind() != OMPC_reduction)
2817 continue;
2818 auto *RC = cast<OMPReductionClause>(C);
2819 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2820 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2821 ? RC->getBeginLoc()
2822 : RC->getModifierLoc(),
2823 diag::err_omp_inscan_reduction_expected);
2824 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2825 continue;
2826 }
2827 for (Expr *Ref : RC->varlist()) {
2828 assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2829 SourceLocation ELoc;
2830 SourceRange ERange;
2831 Expr *SimpleRefExpr = Ref;
2832 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2833 /*AllowArraySection=*/true);
2834 ValueDecl *D = Res.first;
2835 if (!D)
2836 continue;
2837 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2838 S.Diag(Ref->getExprLoc(),
2839 diag::err_omp_reduction_not_inclusive_exclusive)
2840 << Ref->getSourceRange();
2841 }
2842 }
2843 }
2844 }
2845}
2846
2847static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2848 ArrayRef<OMPClause *> Clauses);
2849static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2850 bool WithInit);
2851
2852static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2853 const ValueDecl *D,
2854 const DSAStackTy::DSAVarData &DVar,
2855 bool IsLoopIterVar = false);
2856
2858 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2859 // A variable of class type (or array thereof) that appears in a lastprivate
2860 // clause requires an accessible, unambiguous default constructor for the
2861 // class type, unless the list item is also specified in a firstprivate
2862 // clause.
2863 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
2864 for (OMPClause *C : D->clauses()) {
2865 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
2866 SmallVector<Expr *, 8> PrivateCopies;
2867 for (Expr *DE : Clause->varlist()) {
2868 if (DE->isValueDependent() || DE->isTypeDependent()) {
2869 PrivateCopies.push_back(nullptr);
2870 continue;
2871 }
2872 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2873 auto *VD = cast<VarDecl>(DRE->getDecl());
2875 const DSAStackTy::DSAVarData DVar =
2876 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2877 if (DVar.CKind == OMPC_lastprivate) {
2878 // Generate helper private variable and initialize it with the
2879 // default value. The address of the original variable is replaced
2880 // by the address of the new private variable in CodeGen. This new
2881 // variable is not added to IdResolver, so the code in the OpenMP
2882 // region uses original variable for proper diagnostics.
2883 VarDecl *VDPrivate = buildVarDecl(
2884 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(),
2885 VD->getName(), VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2887 if (VDPrivate->isInvalidDecl()) {
2888 PrivateCopies.push_back(nullptr);
2889 continue;
2890 }
2891 PrivateCopies.push_back(buildDeclRefExpr(
2892 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2893 } else {
2894 // The variable is also a firstprivate, so initialization sequence
2895 // for private copy is generated already.
2896 PrivateCopies.push_back(nullptr);
2897 }
2898 }
2899 Clause->setPrivateCopies(PrivateCopies);
2900 continue;
2901 }
2902 // Finalize nontemporal clause by handling private copies, if any.
2903 if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
2904 SmallVector<Expr *, 8> PrivateRefs;
2905 for (Expr *RefExpr : Clause->varlist()) {
2906 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
2907 SourceLocation ELoc;
2908 SourceRange ERange;
2909 Expr *SimpleRefExpr = RefExpr;
2910 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
2911 if (Res.second)
2912 // It will be analyzed later.
2913 PrivateRefs.push_back(RefExpr);
2914 ValueDecl *D = Res.first;
2915 if (!D)
2916 continue;
2917
2918 const DSAStackTy::DSAVarData DVar =
2919 DSAStack->getTopDSA(D, /*FromParent=*/false);
2920 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
2921 : SimpleRefExpr);
2922 }
2923 Clause->setPrivateRefs(PrivateRefs);
2924 continue;
2925 }
2926 if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
2927 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
2928 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
2929 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
2930 if (!DRE)
2931 continue;
2932 ValueDecl *VD = DRE->getDecl();
2933 if (!VD || !isa<VarDecl>(VD))
2934 continue;
2935 DSAStackTy::DSAVarData DVar =
2936 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2937 // OpenMP [2.12.5, target Construct]
2938 // Memory allocators that appear in a uses_allocators clause cannot
2939 // appear in other data-sharing attribute clauses or data-mapping
2940 // attribute clauses in the same construct.
2941 Expr *MapExpr = nullptr;
2942 if (DVar.RefExpr ||
2943 DSAStack->checkMappableExprComponentListsForDecl(
2944 VD, /*CurrentRegionOnly=*/true,
2945 [VD, &MapExpr](
2947 MapExprComponents,
2949 auto MI = MapExprComponents.rbegin();
2950 auto ME = MapExprComponents.rend();
2951 if (MI != ME &&
2952 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
2953 VD->getCanonicalDecl()) {
2954 MapExpr = MI->getAssociatedExpression();
2955 return true;
2956 }
2957 return false;
2958 })) {
2959 Diag(D.Allocator->getExprLoc(),
2960 diag::err_omp_allocator_used_in_clauses)
2961 << D.Allocator->getSourceRange();
2962 if (DVar.RefExpr)
2964 else
2965 Diag(MapExpr->getExprLoc(), diag::note_used_here)
2966 << MapExpr->getSourceRange();
2967 }
2968 }
2969 continue;
2970 }
2971 }
2972 // Check allocate clauses.
2974 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
2976 }
2977
2978 DSAStack->pop();
2981}
2982
2984 Expr *NumIterations, Sema &SemaRef,
2985 Scope *S, DSAStackTy *Stack);
2986
2987static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
2989 DSAStackTy *Stack) {
2990 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
2991 "loop exprs were not built");
2992
2993 if (SemaRef.CurContext->isDependentContext())
2994 return false;
2995
2996 // Finalize the clauses that need pre-built expressions for CodeGen.
2997 for (OMPClause *C : Clauses) {
2998 auto *LC = dyn_cast<OMPLinearClause>(C);
2999 if (!LC)
3000 continue;
3001 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3002 B.NumIterations, SemaRef,
3003 SemaRef.getCurScope(), Stack))
3004 return true;
3005 }
3006
3007 return false;
3008}
3009
3010namespace {
3011
3012class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3013private:
3014 Sema &SemaRef;
3015
3016public:
3017 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3018 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3019 NamedDecl *ND = Candidate.getCorrectionDecl();
3020 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3021 return VD->hasGlobalStorage() &&
3022 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3023 SemaRef.getCurScope());
3024 }
3025 return false;
3026 }
3027
3028 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3029 return std::make_unique<VarDeclFilterCCC>(*this);
3030 }
3031};
3032
3033class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3034private:
3035 Sema &SemaRef;
3036
3037public:
3038 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3039 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3040 NamedDecl *ND = Candidate.getCorrectionDecl();
3041 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3042 isa<FunctionDecl>(ND))) {
3043 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3044 SemaRef.getCurScope());
3045 }
3046 return false;
3047 }
3048
3049 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3050 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3051 }
3052};
3053
3054} // namespace
3055
3057 CXXScopeSpec &ScopeSpec,
3058 const DeclarationNameInfo &Id,
3059 OpenMPDirectiveKind Kind) {
3060 ASTContext &Context = getASTContext();
3062 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3063 /*ObjectType=*/QualType(),
3064 /*AllowBuiltinCreation=*/true);
3065
3066 if (Lookup.isAmbiguous())
3067 return ExprError();
3068
3069 VarDecl *VD;
3070 if (!Lookup.isSingleResult()) {
3071 VarDeclFilterCCC CCC(SemaRef);
3072 if (TypoCorrection Corrected =
3073 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3076 Corrected,
3077 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3078 : diag::err_omp_expected_var_arg_suggest)
3079 << Id.getName());
3080 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3081 } else {
3082 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3083 : diag::err_omp_expected_var_arg)
3084 << Id.getName();
3085 return ExprError();
3086 }
3087 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3088 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3089 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3090 return ExprError();
3091 }
3092 Lookup.suppressDiagnostics();
3093
3094 // OpenMP [2.9.2, Syntax, C/C++]
3095 // Variables must be file-scope, namespace-scope, or static block-scope.
3096 if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
3097 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3098 << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
3099 bool IsDecl =
3101 Diag(VD->getLocation(),
3102 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3103 << VD;
3104 return ExprError();
3105 }
3106
3107 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3108 NamedDecl *ND = CanonicalVD;
3109 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3110 // A threadprivate directive for file-scope variables must appear outside
3111 // any definition or declaration.
3112 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3114 Diag(Id.getLoc(), diag::err_omp_var_scope)
3115 << getOpenMPDirectiveName(Kind) << VD;
3116 bool IsDecl =
3118 Diag(VD->getLocation(),
3119 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3120 << VD;
3121 return ExprError();
3122 }
3123 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3124 // A threadprivate directive for static class member variables must appear
3125 // in the class definition, in the same scope in which the member
3126 // variables are declared.
3127 if (CanonicalVD->isStaticDataMember() &&
3128 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3129 Diag(Id.getLoc(), diag::err_omp_var_scope)
3130 << getOpenMPDirectiveName(Kind) << VD;
3131 bool IsDecl =
3133 Diag(VD->getLocation(),
3134 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3135 << VD;
3136 return ExprError();
3137 }
3138 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3139 // A threadprivate directive for namespace-scope variables must appear
3140 // outside any definition or declaration other than the namespace
3141 // definition itself.
3142 if (CanonicalVD->getDeclContext()->isNamespace() &&
3145 CanonicalVD->getDeclContext()))) {
3146 Diag(Id.getLoc(), diag::err_omp_var_scope)
3147 << getOpenMPDirectiveName(Kind) << VD;
3148 bool IsDecl =
3150 Diag(VD->getLocation(),
3151 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3152 << VD;
3153 return ExprError();
3154 }
3155 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3156 // A threadprivate directive for static block-scope variables must appear
3157 // in the scope of the variable and not in a nested scope.
3158 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3160 Diag(Id.getLoc(), diag::err_omp_var_scope)
3161 << getOpenMPDirectiveName(Kind) << VD;
3162 bool IsDecl =
3164 Diag(VD->getLocation(),
3165 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3166 << VD;
3167 return ExprError();
3168 }
3169
3170 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3171 // A threadprivate directive must lexically precede all references to any
3172 // of the variables in its list.
3173 if (Kind == OMPD_threadprivate && VD->isUsed() &&
3174 !DSAStack->isThreadPrivate(VD)) {
3175 Diag(Id.getLoc(), diag::err_omp_var_used)
3176 << getOpenMPDirectiveName(Kind) << VD;
3177 return ExprError();
3178 }
3179
3180 QualType ExprType = VD->getType().getNonReferenceType();
3182 SourceLocation(), VD,
3183 /*RefersToEnclosingVariableOrCapture=*/false,
3184 Id.getLoc(), ExprType, VK_LValue);
3185}
3186
3189 ArrayRef<Expr *> VarList) {
3193 }
3194 return nullptr;
3195}
3196
3197namespace {
3198class LocalVarRefChecker final
3199 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3200 Sema &SemaRef;
3201
3202public:
3203 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3204 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3205 if (VD->hasLocalStorage()) {
3206 SemaRef.Diag(E->getBeginLoc(),
3207 diag::err_omp_local_var_in_threadprivate_init)
3208 << E->getSourceRange();
3209 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3210 << VD << VD->getSourceRange();
3211 return true;
3212 }
3213 }
3214 return false;
3215 }
3216 bool VisitStmt(const Stmt *S) {
3217 for (const Stmt *Child : S->children()) {
3218 if (Child && Visit(Child))
3219 return true;
3220 }
3221 return false;
3222 }
3223 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3224};
3225} // namespace
3226
3229 ArrayRef<Expr *> VarList) {
3230 ASTContext &Context = getASTContext();
3232 for (Expr *RefExpr : VarList) {
3233 auto *DE = cast<DeclRefExpr>(RefExpr);
3234 auto *VD = cast<VarDecl>(DE->getDecl());
3235 SourceLocation ILoc = DE->getExprLoc();
3236
3237 // Mark variable as used.
3238 VD->setReferenced();
3239 VD->markUsed(Context);
3240
3241 QualType QType = VD->getType();
3242 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3243 // It will be analyzed later.
3244 Vars.push_back(DE);
3245 continue;
3246 }
3247
3248 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3249 // A threadprivate variable must not have an incomplete type.
3251 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3252 continue;
3253 }
3254
3255 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3256 // A threadprivate variable must not have a reference type.
3257 if (VD->getType()->isReferenceType()) {
3258 Diag(ILoc, diag::err_omp_ref_type_arg)
3259 << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
3260 bool IsDecl =
3262 Diag(VD->getLocation(),
3263 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3264 << VD;
3265 continue;
3266 }
3267
3268 // Check if this is a TLS variable. If TLS is not being supported, produce
3269 // the corresponding diagnostic.
3270 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3271 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3272 getLangOpts().OpenMPUseTLS &&
3273 getASTContext().getTargetInfo().isTLSSupported())) ||
3274 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3275 !VD->isLocalVarDecl())) {
3276 Diag(ILoc, diag::err_omp_var_thread_local)
3277 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3278 bool IsDecl =
3280 Diag(VD->getLocation(),
3281 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3282 << VD;
3283 continue;
3284 }
3285
3286 // Check if initial value of threadprivate variable reference variable with
3287 // local storage (it is not supported by runtime).
3288 if (const Expr *Init = VD->getAnyInitializer()) {
3289 LocalVarRefChecker Checker(SemaRef);
3290 if (Checker.Visit(Init))
3291 continue;
3292 }
3293
3294 Vars.push_back(RefExpr);
3295 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3296 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3297 Context, SourceRange(Loc, Loc)));
3298 if (ASTMutationListener *ML = Context.getASTMutationListener())
3299 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3300 }
3301 OMPThreadPrivateDecl *D = nullptr;
3302 if (!Vars.empty()) {
3304 Loc, Vars);
3306 }
3307 return D;
3308}
3309
3310static OMPAllocateDeclAttr::AllocatorTypeTy
3311getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3312 if (!Allocator)
3313 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3314 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3315 Allocator->isInstantiationDependent() ||
3316 Allocator->containsUnexpandedParameterPack())
3317 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3318 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3319 llvm::FoldingSetNodeID AEId;
3320 const Expr *AE = Allocator->IgnoreParenImpCasts();
3321 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3322 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3323 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3324 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3325 llvm::FoldingSetNodeID DAEId;
3326 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3327 /*Canonical=*/true);
3328 if (AEId == DAEId) {
3329 AllocatorKindRes = AllocatorKind;
3330 break;
3331 }
3332 }
3333 return AllocatorKindRes;
3334}
3335
3337 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3338 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3339 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3340 return false;
3341 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3342 Expr *PrevAllocator = A->getAllocator();
3343 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3344 getAllocatorKind(S, Stack, PrevAllocator);
3345 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3346 if (AllocatorsMatch &&
3347 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3348 Allocator && PrevAllocator) {
3349 const Expr *AE = Allocator->IgnoreParenImpCasts();
3350 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3351 llvm::FoldingSetNodeID AEId, PAEId;
3352 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3353 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3354 AllocatorsMatch = AEId == PAEId;
3355 }
3356 if (!AllocatorsMatch) {
3357 SmallString<256> AllocatorBuffer;
3358 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3359 if (Allocator)
3360 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3361 SmallString<256> PrevAllocatorBuffer;
3362 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3363 if (PrevAllocator)
3364 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3365 S.getPrintingPolicy());
3366
3367 SourceLocation AllocatorLoc =
3368 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3369 SourceRange AllocatorRange =
3370 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3371 SourceLocation PrevAllocatorLoc =
3372 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3373 SourceRange PrevAllocatorRange =
3374 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3375 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3376 << (Allocator ? 1 : 0) << AllocatorStream.str()
3377 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3378 << AllocatorRange;
3379 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3380 << PrevAllocatorRange;
3381 return true;
3382 }
3383 return false;
3384}
3385
3386static void
3388 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3389 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3390 if (VD->hasAttr<OMPAllocateDeclAttr>())
3391 return;
3392 if (Alignment &&
3393 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3394 Alignment->isInstantiationDependent() ||
3395 Alignment->containsUnexpandedParameterPack()))
3396 // Apply later when we have a usable value.
3397 return;
3398 if (Allocator &&
3399 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3400 Allocator->isInstantiationDependent() ||
3401 Allocator->containsUnexpandedParameterPack()))
3402 return;
3403 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3404 Allocator, Alignment, SR);
3405 VD->addAttr(A);
3407 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3408}
3409
3412 DeclContext *Owner) {
3413 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3414 Expr *Alignment = nullptr;
3415 Expr *Allocator = nullptr;
3416 if (Clauses.empty()) {
3417 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3418 // allocate directives that appear in a target region must specify an
3419 // allocator clause unless a requires directive with the dynamic_allocators
3420 // clause is present in the same compilation unit.
3421 if (getLangOpts().OpenMPIsTargetDevice &&
3422 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3423 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3424 } else {
3425 for (const OMPClause *C : Clauses)
3426 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3427 Allocator = AC->getAllocator();
3428 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3429 Alignment = AC->getAlignment();
3430 else
3431 llvm_unreachable("Unexpected clause on allocate directive");
3432 }
3433 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3434 getAllocatorKind(SemaRef, DSAStack, Allocator);
3436 for (Expr *RefExpr : VarList) {
3437 auto *DE = cast<DeclRefExpr>(RefExpr);
3438 auto *VD = cast<VarDecl>(DE->getDecl());
3439
3440 // Check if this is a TLS variable or global register.
3441 if (VD->getTLSKind() != VarDecl::TLS_None ||
3442 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3443 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3444 !VD->isLocalVarDecl()))
3445 continue;
3446
3447 // If the used several times in the allocate directive, the same allocator
3448 // must be used.
3450 AllocatorKind, Allocator))
3451 continue;
3452
3453 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3454 // If a list item has a static storage type, the allocator expression in the
3455 // allocator clause must be a constant expression that evaluates to one of
3456 // the predefined memory allocator values.
3457 if (Allocator && VD->hasGlobalStorage()) {
3458 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3459 Diag(Allocator->getExprLoc(),
3460 diag::err_omp_expected_predefined_allocator)
3461 << Allocator->getSourceRange();
3462 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3464 Diag(VD->getLocation(),
3465 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3466 << VD;
3467 continue;
3468 }
3469 }
3470
3471 Vars.push_back(RefExpr);
3472 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3473 DE->getSourceRange());
3474 }
3475 if (Vars.empty())
3476 return nullptr;
3477 if (!Owner)
3478 Owner = SemaRef.getCurLexicalContext();
3479 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3481 Owner->addDecl(D);
3483}
3484
3487 ArrayRef<OMPClause *> ClauseList) {
3488 OMPRequiresDecl *D = nullptr;
3490 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3491 } else {
3492 D = CheckOMPRequiresDecl(Loc, ClauseList);
3493 if (D) {
3495 DSAStack->addRequiresDecl(D);
3496 }
3497 }
3499}
3500
3502 OpenMPDirectiveKind DKind,
3503 ArrayRef<std::string> Assumptions,
3504 bool SkippedClauses) {
3505 if (!SkippedClauses && Assumptions.empty())
3506 Diag(Loc, diag::err_omp_no_clause_for_directive)
3507 << llvm::omp::getAllAssumeClauseOptions()
3508 << llvm::omp::getOpenMPDirectiveName(DKind);
3509
3510 auto *AA =
3511 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3512 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3513 OMPAssumeScoped.push_back(AA);
3514 return;
3515 }
3516
3517 // Global assumes without assumption clauses are ignored.
3518 if (Assumptions.empty())
3519 return;
3520
3521 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3522 "Unexpected omp assumption directive!");
3523 OMPAssumeGlobal.push_back(AA);
3524
3525 // The OMPAssumeGlobal scope above will take care of new declarations but
3526 // we also want to apply the assumption to existing ones, e.g., to
3527 // declarations in included headers. To this end, we traverse all existing
3528 // declaration contexts and annotate function declarations here.
3529 SmallVector<DeclContext *, 8> DeclContexts;
3530 auto *Ctx = SemaRef.CurContext;
3531 while (Ctx->getLexicalParent())
3532 Ctx = Ctx->getLexicalParent();
3533 DeclContexts.push_back(Ctx);
3534 while (!DeclContexts.empty()) {
3535 DeclContext *DC = DeclContexts.pop_back_val();
3536 for (auto *SubDC : DC->decls()) {
3537 if (SubDC->isInvalidDecl())
3538 continue;
3539 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3540 DeclContexts.push_back(CTD->getTemplatedDecl());
3541 llvm::append_range(DeclContexts, CTD->specializations());
3542 continue;
3543 }
3544 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3545 DeclContexts.push_back(DC);
3546 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3547 F->addAttr(AA);
3548 continue;
3549 }
3550 }
3551 }
3552}
3553
3555 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3556 OMPAssumeScoped.pop_back();
3557}
3558
3560 Stmt *AStmt,
3561 SourceLocation StartLoc,
3562 SourceLocation EndLoc) {
3563 if (!AStmt)
3564 return StmtError();
3565
3566 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3567 AStmt);
3568}
3569
3572 ArrayRef<OMPClause *> ClauseList) {
3573 /// For target specific clauses, the requires directive cannot be
3574 /// specified after the handling of any of the target regions in the
3575 /// current compilation unit.
3576 ArrayRef<SourceLocation> TargetLocations =
3577 DSAStack->getEncounteredTargetLocs();
3578 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3579 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3580 for (const OMPClause *CNew : ClauseList) {
3581 // Check if any of the requires clauses affect target regions.
3582 if (isa<OMPUnifiedSharedMemoryClause>(CNew) ||
3583 isa<OMPUnifiedAddressClause>(CNew) ||
3584 isa<OMPReverseOffloadClause>(CNew) ||
3585 isa<OMPDynamicAllocatorsClause>(CNew)) {
3586 Diag(Loc, diag::err_omp_directive_before_requires)
3587 << "target" << getOpenMPClauseName(CNew->getClauseKind());
3588 for (SourceLocation TargetLoc : TargetLocations) {
3589 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3590 << "target";
3591 }
3592 } else if (!AtomicLoc.isInvalid() &&
3593 isa<OMPAtomicDefaultMemOrderClause>(CNew)) {
3594 Diag(Loc, diag::err_omp_directive_before_requires)
3595 << "atomic" << getOpenMPClauseName(CNew->getClauseKind());
3596 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3597 << "atomic";
3598 }
3599 }
3600 }
3601
3602 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3604 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3605 return nullptr;
3606}
3607
3608static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3609 const ValueDecl *D,
3610 const DSAStackTy::DSAVarData &DVar,
3611 bool IsLoopIterVar) {
3612 if (DVar.RefExpr) {
3613 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3614 << getOpenMPClauseName(DVar.CKind);
3615 return;
3616 }
3617 enum {
3618 PDSA_StaticMemberShared,
3619 PDSA_StaticLocalVarShared,
3620 PDSA_LoopIterVarPrivate,
3621 PDSA_LoopIterVarLinear,
3622 PDSA_LoopIterVarLastprivate,
3623 PDSA_ConstVarShared,
3624 PDSA_GlobalVarShared,
3625 PDSA_TaskVarFirstprivate,
3626 PDSA_LocalVarPrivate,
3627 PDSA_Implicit
3628 } Reason = PDSA_Implicit;
3629 bool ReportHint = false;
3630 auto ReportLoc = D->getLocation();
3631 auto *VD = dyn_cast<VarDecl>(D);
3632 if (IsLoopIterVar) {
3633 if (DVar.CKind == OMPC_private)
3634 Reason = PDSA_LoopIterVarPrivate;
3635 else if (DVar.CKind == OMPC_lastprivate)
3636 Reason = PDSA_LoopIterVarLastprivate;
3637 else
3638 Reason = PDSA_LoopIterVarLinear;
3639 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3640 DVar.CKind == OMPC_firstprivate) {
3641 Reason = PDSA_TaskVarFirstprivate;
3642 ReportLoc = DVar.ImplicitDSALoc;
3643 } else if (VD && VD->isStaticLocal())
3644 Reason = PDSA_StaticLocalVarShared;
3645 else if (VD && VD->isStaticDataMember())
3646 Reason = PDSA_StaticMemberShared;
3647 else if (VD && VD->isFileVarDecl())
3648 Reason = PDSA_GlobalVarShared;
3649 else if (D->getType().isConstant(SemaRef.getASTContext()))
3650 Reason = PDSA_ConstVarShared;
3651 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3652 ReportHint = true;
3653 Reason = PDSA_LocalVarPrivate;
3654 }
3655 if (Reason != PDSA_Implicit) {
3656 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3657 << Reason << ReportHint
3658 << getOpenMPDirectiveName(Stack->getCurrentDirective());
3659 } else if (DVar.ImplicitDSALoc.isValid()) {
3660 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3661 << getOpenMPClauseName(DVar.CKind);
3662 }
3663}
3664
3667 bool IsAggregateOrDeclareTarget) {
3669 switch (M) {
3670 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3671 Kind = OMPC_MAP_alloc;
3672 break;
3673 case OMPC_DEFAULTMAP_MODIFIER_to:
3674 Kind = OMPC_MAP_to;
3675 break;
3676 case OMPC_DEFAULTMAP_MODIFIER_from:
3677 Kind = OMPC_MAP_from;
3678 break;
3679 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3680 Kind = OMPC_MAP_tofrom;
3681 break;
3682 case OMPC_DEFAULTMAP_MODIFIER_present:
3683 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3684 // If implicit-behavior is present, each variable referenced in the
3685 // construct in the category specified by variable-category is treated as if
3686 // it had been listed in a map clause with the map-type of alloc and
3687 // map-type-modifier of present.
3688 Kind = OMPC_MAP_alloc;
3689 break;
3690 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3692 llvm_unreachable("Unexpected defaultmap implicit behavior");
3693 case OMPC_DEFAULTMAP_MODIFIER_none:
3694 case OMPC_DEFAULTMAP_MODIFIER_default:
3696 // IsAggregateOrDeclareTarget could be true if:
3697 // 1. the implicit behavior for aggregate is tofrom
3698 // 2. it's a declare target link
3699 if (IsAggregateOrDeclareTarget) {
3700 Kind = OMPC_MAP_tofrom;
3701 break;
3702 }
3703 llvm_unreachable("Unexpected defaultmap implicit behavior");
3704 }
3705 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3706 return Kind;
3707}
3708
3709namespace {
3710class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3711 DSAStackTy *Stack;
3712 Sema &SemaRef;
3713 OpenMPDirectiveKind DKind = OMPD_unknown;
3714 bool ErrorFound = false;
3715 bool TryCaptureCXXThisMembers = false;
3716 CapturedStmt *CS = nullptr;
3717 const static unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3718 llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
3719 llvm::SmallVector<Expr *, 4> ImplicitPrivate;
3720 llvm::SmallVector<Expr *, 4> ImplicitMap[DefaultmapKindNum][OMPC_MAP_delete];
3722 ImplicitMapModifier[DefaultmapKindNum];
3723 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3724 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3725
3726 void VisitSubCaptures(OMPExecutableDirective *S) {
3727 // Check implicitly captured variables.
3728 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3729 return;
3730 if (S->getDirectiveKind() == OMPD_atomic ||
3731 S->getDirectiveKind() == OMPD_critical ||
3732 S->getDirectiveKind() == OMPD_section ||
3733 S->getDirectiveKind() == OMPD_master ||
3734 S->getDirectiveKind() == OMPD_masked ||
3735 S->getDirectiveKind() == OMPD_scope ||
3736 S->getDirectiveKind() == OMPD_assume ||
3737 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3738 Visit(S->getAssociatedStmt());
3739 return;
3740 }
3741 visitSubCaptures(S->getInnermostCapturedStmt());
3742 // Try to capture inner this->member references to generate correct mappings
3743 // and diagnostics.
3744 if (TryCaptureCXXThisMembers ||
3746 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3747 [](const CapturedStmt::Capture &C) {
3748 return C.capturesThis();
3749 }))) {
3750 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3751 TryCaptureCXXThisMembers = true;
3752 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3753 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3754 }
3755 // In tasks firstprivates are not captured anymore, need to analyze them
3756 // explicitly.
3757 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3758 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3759 for (OMPClause *C : S->clauses())
3760 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3761 for (Expr *Ref : FC->varlist())
3762 Visit(Ref);
3763 }
3764 }
3765 }
3766
3767public:
3768 void VisitDeclRefExpr(DeclRefExpr *E) {
3769 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3772 E->isNonOdrUse() == clang::NOUR_Unevaluated)
3773 return;
3774 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3775 // Check the datasharing rules for the expressions in the clauses.
3776 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3777 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3778 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3779 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3780 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3781 Visit(CED->getInit());
3782 return;
3783 }
3784 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3785 // Do not analyze internal variables and do not enclose them into
3786 // implicit clauses.
3787 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3788 return;
3789 VD = VD->getCanonicalDecl();
3790 // Skip internally declared variables.
3791 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3792 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3793 !Stack->isImplicitTaskFirstprivate(VD))
3794 return;
3795 // Skip allocators in uses_allocators clauses.
3796 if (Stack->isUsesAllocatorsDecl(VD))
3797 return;
3798
3799 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
3800 // Check if the variable has explicit DSA set and stop analysis if it so.
3801 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
3802 return;
3803
3804 // Skip internally declared static variables.
3805 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
3806 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
3807 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
3808 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
3809 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
3810 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
3811 !Stack->isImplicitTaskFirstprivate(VD))
3812 return;
3813
3814 SourceLocation ELoc = E->getExprLoc();
3815 // The default(none) clause requires that each variable that is referenced
3816 // in the construct, and does not have a predetermined data-sharing
3817 // attribute, must have its data-sharing attribute explicitly determined
3818 // by being listed in a data-sharing attribute clause.
3819 if (DVar.CKind == OMPC_unknown &&
3820 (Stack->getDefaultDSA() == DSA_none ||
3821 Stack->getDefaultDSA() == DSA_private ||
3822 Stack->getDefaultDSA() == DSA_firstprivate) &&
3823 isImplicitOrExplicitTaskingRegion(DKind) &&
3824 VarsWithInheritedDSA.count(VD) == 0) {
3825 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
3826 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
3827 Stack->getDefaultDSA() == DSA_private)) {
3828 DSAStackTy::DSAVarData DVar =
3829 Stack->getImplicitDSA(VD, /*FromParent=*/false);
3830 InheritedDSA = DVar.CKind == OMPC_unknown;
3831 }
3832 if (InheritedDSA)
3833 VarsWithInheritedDSA[VD] = E;
3834 if (Stack->getDefaultDSA() == DSA_none)
3835 return;
3836 }
3837
3838 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
3839 // If implicit-behavior is none, each variable referenced in the
3840 // construct that does not have a predetermined data-sharing attribute
3841 // and does not appear in a to or link clause on a declare target
3842 // directive must be listed in a data-mapping attribute clause, a
3843 // data-sharing attribute clause (including a data-sharing attribute
3844 // clause on a combined construct where target. is one of the
3845 // constituent constructs), or an is_device_ptr clause.
3846 OpenMPDefaultmapClauseKind ClauseKind =
3848 if (SemaRef.getLangOpts().OpenMP >= 50) {
3849 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
3850 OMPC_DEFAULTMAP_MODIFIER_none;
3851 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
3852 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
3853 // Only check for data-mapping attribute and is_device_ptr here
3854 // since we have already make sure that the declaration does not
3855 // have a data-sharing attribute above
3856 if (!Stack->checkMappableExprComponentListsForDecl(
3857 VD, /*CurrentRegionOnly=*/true,
3859 MapExprComponents,
3861 auto MI = MapExprComponents.rbegin();
3862 auto ME = MapExprComponents.rend();
3863 return MI != ME && MI->getAssociatedDeclaration() == VD;
3864 })) {
3865 VarsWithInheritedDSA[VD] = E;
3866 return;
3867 }
3868 }
3869 }
3870 if (SemaRef.getLangOpts().OpenMP > 50) {
3871 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
3872 OMPC_DEFAULTMAP_MODIFIER_present;
3873 if (IsModifierPresent) {
3874 if (!llvm::is_contained(ImplicitMapModifier[ClauseKind],
3875 OMPC_MAP_MODIFIER_present)) {
3876 ImplicitMapModifier[ClauseKind].push_back(
3877 OMPC_MAP_MODIFIER_present);
3878 }
3879 }
3880 }
3881
3883 !Stack->isLoopControlVariable(VD).first) {
3884 if (!Stack->checkMappableExprComponentListsForDecl(
3885 VD, /*CurrentRegionOnly=*/true,
3887 StackComponents,
3889 if (SemaRef.LangOpts.OpenMP >= 50)
3890 return !StackComponents.empty();
3891 // Variable is used if it has been marked as an array, array
3892 // section, array shaping or the variable itself.
3893 return StackComponents.size() == 1 ||
3894 llvm::all_of(
3895 llvm::drop_begin(llvm::reverse(StackComponents)),
3896 [](const OMPClauseMappableExprCommon::
3897 MappableComponent &MC) {
3898 return MC.getAssociatedDeclaration() ==
3899 nullptr &&
3900 (isa<ArraySectionExpr>(
3901 MC.getAssociatedExpression()) ||
3902 isa<OMPArrayShapingExpr>(
3903 MC.getAssociatedExpression()) ||
3904 isa<ArraySubscriptExpr>(
3905 MC.getAssociatedExpression()));
3906 });
3907 })) {
3908 bool IsFirstprivate = false;
3909 // By default lambdas are captured as firstprivates.
3910 if (const auto *RD =
3912 IsFirstprivate = RD->isLambda();
3913 IsFirstprivate =
3914 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
3915 if (IsFirstprivate) {
3916 ImplicitFirstprivate.emplace_back(E);
3917 } else {
3919 Stack->getDefaultmapModifier(ClauseKind);
3921 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
3922 ImplicitMap[ClauseKind][Kind].emplace_back(E);
3923 }
3924 return;
3925 }
3926 }
3927
3928 // OpenMP [2.9.3.6, Restrictions, p.2]
3929 // A list item that appears in a reduction clause of the innermost
3930 // enclosing worksharing or parallel construct may not be accessed in an
3931 // explicit task.
3932 DVar = Stack->hasInnermostDSA(
3933 VD,
3934 [](OpenMPClauseKind C, bool AppliedToPointee) {
3935 return C == OMPC_reduction && !AppliedToPointee;
3936 },
3937 [](OpenMPDirectiveKind K) {
3938 return isOpenMPParallelDirective(K) ||
3940 },
3941 /*FromParent=*/true);
3942 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
3943 ErrorFound = true;
3944 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
3945 reportOriginalDsa(SemaRef, Stack, VD, DVar);
3946 return;
3947 }
3948
3949 // Define implicit data-sharing attributes for task.
3950 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
3951 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
3952 (((Stack->getDefaultDSA() == DSA_firstprivate &&
3953 DVar.CKind == OMPC_firstprivate) ||
3954 (Stack->getDefaultDSA() == DSA_private &&
3955 DVar.CKind == OMPC_private)) &&
3956 !DVar.RefExpr)) &&
3957 !Stack->isLoopControlVariable(VD).first) {
3958 if (Stack->getDefaultDSA() == DSA_private)
3959 ImplicitPrivate.push_back(E);
3960 else
3961 ImplicitFirstprivate.push_back(E);
3962 return;
3963 }
3964
3965 // Store implicitly used globals with declare target link for parent
3966 // target.
3967 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
3968 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
3969 Stack->addToParentTargetRegionLinkGlobals(E);
3970 return;
3971 }
3972 }
3973 }
3974 void VisitMemberExpr(MemberExpr *E) {
3975 if (E->isTypeDependent() || E->isValueDependent() ||
3977 return;
3978 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
3979 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
3980 if (!FD)
3981 return;
3982 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
3983 // Check if the variable has explicit DSA set and stop analysis if it
3984 // so.
3985 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
3986 return;
3987
3989 !Stack->isLoopControlVariable(FD).first &&
3990 !Stack->checkMappableExprComponentListsForDecl(
3991 FD, /*CurrentRegionOnly=*/true,
3993 StackComponents,
3995 return isa<CXXThisExpr>(
3996 cast<MemberExpr>(
3997 StackComponents.back().getAssociatedExpression())
3998 ->getBase()
3999 ->IgnoreParens());
4000 })) {
4001 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4002 // A bit-field cannot appear in a map clause.
4003 //
4004 if (FD->isBitField())
4005 return;
4006
4007 // Check to see if the member expression is referencing a class that
4008 // has already been explicitly mapped
4009 if (Stack->isClassPreviouslyMapped(TE->getType()))
4010 return;
4011
4013 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4014 OpenMPDefaultmapClauseKind ClauseKind =
4017 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4018 ImplicitMap[ClauseKind][Kind].emplace_back(E);
4019 return;
4020 }
4021
4022 SourceLocation ELoc = E->getExprLoc();
4023 // OpenMP [2.9.3.6, Restrictions, p.2]
4024 // A list item that appears in a reduction clause of the innermost
4025 // enclosing worksharing or parallel construct may not be accessed in
4026 // an explicit task.
4027 DVar = Stack->hasInnermostDSA(
4028 FD,
4029 [](OpenMPClauseKind C, bool AppliedToPointee) {
4030 return C == OMPC_reduction && !AppliedToPointee;
4031 },
4032 [](OpenMPDirectiveKind K) {
4033 return isOpenMPParallelDirective(K) ||
4035 },
4036 /*FromParent=*/true);
4037 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4038 ErrorFound = true;
4039 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4040 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4041 return;
4042 }
4043
4044 // Define implicit data-sharing attributes for task.
4045 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4046 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4047 !Stack->isLoopControlVariable(FD).first) {
4048 // Check if there is a captured expression for the current field in the
4049 // region. Do not mark it as firstprivate unless there is no captured
4050 // expression.
4051 // TODO: try to make it firstprivate.
4052 if (DVar.CKind != OMPC_unknown)
4053 ImplicitFirstprivate.push_back(E);
4054 }
4055 return;
4056 }
4059 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4060 DKind, /*NoDiagnose=*/true))
4061 return;
4062 const auto *VD = cast<ValueDecl>(
4063 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4064 if (!Stack->checkMappableExprComponentListsForDecl(
4065 VD, /*CurrentRegionOnly=*/true,
4066 [&CurComponents](
4068 StackComponents,
4070 auto CCI = CurComponents.rbegin();
4071 auto CCE = CurComponents.rend();
4072 for (const auto &SC : llvm::reverse(StackComponents)) {
4073 // Do both expressions have the same kind?
4074 if (CCI->getAssociatedExpression()->getStmtClass() !=
4075 SC.getAssociatedExpression()->getStmtClass())
4076 if (!((isa<ArraySectionExpr>(
4077 SC.getAssociatedExpression()) ||
4078 isa<OMPArrayShapingExpr>(
4079 SC.getAssociatedExpression())) &&
4080 isa<ArraySubscriptExpr>(
4081 CCI->getAssociatedExpression())))
4082 return false;
4083
4084 const Decl *CCD = CCI->getAssociatedDeclaration();
4085 const Decl *SCD = SC.getAssociatedDeclaration();
4086 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4087 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4088 if (SCD != CCD)
4089 return false;
4090 std::advance(CCI, 1);
4091 if (CCI == CCE)
4092 break;
4093 }
4094 return true;
4095 })) {
4096 Visit(E->getBase());
4097 }
4098 } else if (!TryCaptureCXXThisMembers) {
4099 Visit(E->getBase());
4100 }
4101 }
4102 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4103 for (OMPClause *C : S->clauses()) {
4104 // Skip analysis of arguments of private clauses for task|target
4105 // directives.
4106 if (isa_and_nonnull<OMPPrivateClause>(C))
4107 continue;
4108 // Skip analysis of arguments of implicitly defined firstprivate clause
4109 // for task|target directives.
4110 // Skip analysis of arguments of implicitly defined map clause for target
4111 // directives.
4112 if (C && !((isa<OMPFirstprivateClause>(C) || isa<OMPMapClause>(C)) &&
4113 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4114 for (Stmt *CC : C->children()) {
4115 if (CC)
4116 Visit(CC);
4117 }
4118 }
4119 }
4120 // Check implicitly captured variables.
4121 VisitSubCaptures(S);
4122 }
4123
4124 void VisitOMPLoopTransformationDirective(OMPLoopTransformationDirective *S) {
4125 // Loop transformation directives do not introduce data sharing
4126 VisitStmt(S);
4127 }
4128
4129 void VisitCallExpr(CallExpr *S) {
4130 for (Stmt *C : S->arguments()) {
4131 if (C) {
4132 // Check implicitly captured variables in the task-based directives to
4133 // check if they must be firstprivatized.
4134 Visit(C);
4135 }
4136 }
4137 if (Expr *Callee = S->getCallee()) {
4138 auto *CI = Callee->IgnoreParenImpCasts();
4139 if (auto *CE = dyn_cast<MemberExpr>(CI))
4140 Visit(CE->getBase());
4141 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4142 Visit(CE);
4143 }
4144 }
4145 void VisitStmt(Stmt *S) {
4146 for (Stmt *C : S->children()) {
4147 if (C) {
4148 // Check implicitly captured variables in the task-based directives to
4149 // check if they must be firstprivatized.
4150 Visit(C);
4151 }
4152 }
4153 }
4154
4155 void visitSubCaptures(CapturedStmt *S) {
4156 for (const CapturedStmt::Capture &Cap : S->captures()) {
4157 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4158 continue;
4159 VarDecl *VD = Cap.getCapturedVar();
4160 // Do not try to map the variable if it or its sub-component was mapped
4161 // already.
4163 Stack->checkMappableExprComponentListsForDecl(
4164 VD, /*CurrentRegionOnly=*/true,
4166 OpenMPClauseKind) { return true; }))
4167 continue;
4169 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4170 Cap.getLocation(), /*RefersToCapture=*/true);
4171 Visit(DRE);
4172 }
4173 }
4174 bool isErrorFound() const { return ErrorFound; }
4175 ArrayRef<Expr *> getImplicitFirstprivate() const {
4176 return ImplicitFirstprivate;
4177 }
4178 ArrayRef<Expr *> getImplicitPrivate() const { return ImplicitPrivate; }
4180 OpenMPMapClauseKind MK) const {
4181 return ImplicitMap[DK][MK];
4182 }
4184 getImplicitMapModifier(OpenMPDefaultmapClauseKind Kind) const {
4185 return ImplicitMapModifier[Kind];
4186 }
4187 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4188 return VarsWithInheritedDSA;
4189 }
4190
4191 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4192 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4193 DKind = S->getCurrentDirective();
4194 // Process declare target link variables for the target directives.
4196 for (DeclRefExpr *E : Stack->getLinkGlobals())
4197 Visit(E);
4198 }
4199 }
4200};
4201} // namespace
4202
4203static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4204 OpenMPDirectiveKind DKind,
4205 bool ScopeEntry) {
4208 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4209 if (isOpenMPTeamsDirective(DKind))
4210 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4211 if (isOpenMPParallelDirective(DKind))
4212 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4214 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4215 if (isOpenMPSimdDirective(DKind))
4216 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4217 Stack->handleConstructTrait(Traits, ScopeEntry);
4218}
4219
4221getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4222 ASTContext &Context = SemaRef.getASTContext();
4223 QualType KmpInt32Ty =
4224 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4225 QualType KmpInt32PtrTy =
4226 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4228 std::make_pair(".global_tid.", KmpInt32PtrTy),
4229 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4230 };
4231 if (LoopBoundSharing) {
4232 QualType KmpSizeTy = Context.getSizeType().withConst();
4233 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4234 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4235 }
4236
4237 // __context with shared vars
4238 Params.push_back(std::make_pair(StringRef(), QualType()));
4239 return Params;
4240}
4241
4244 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4245}
4246
4249 ASTContext &Context = SemaRef.getASTContext();
4250 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4251 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4252 QualType KmpInt32PtrTy =
4253 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4254 QualType Args[] = {VoidPtrTy};
4256 EPI.Variadic = true;
4257 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4259 std::make_pair(".global_tid.", KmpInt32Ty),
4260 std::make_pair(".part_id.", KmpInt32PtrTy),
4261 std::make_pair(".privates.", VoidPtrTy),
4262 std::make_pair(
4263 ".copy_fn.",
4264 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4265 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4266 std::make_pair(StringRef(), QualType()) // __context with shared vars
4267 };
4268 return Params;
4269}
4270
4273 ASTContext &Context = SemaRef.getASTContext();
4275 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4276 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4277 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4278 }
4279 // __context with shared vars
4280 Params.push_back(std::make_pair(StringRef(), QualType()));
4281 return Params;
4282}
4283
4287 std::make_pair(StringRef(), QualType()) // __context with shared vars
4288 };
4289 return Params;
4290}
4291
4294 ASTContext &Context = SemaRef.getASTContext();
4295 QualType KmpInt32Ty =
4296 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4297 QualType KmpUInt64Ty =
4298 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4299 QualType KmpInt64Ty =
4300 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4301 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4302 QualType KmpInt32PtrTy =
4303 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4304 QualType Args[] = {VoidPtrTy};
4306 EPI.Variadic = true;
4307 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4309 std::make_pair(".global_tid.", KmpInt32Ty),
4310 std::make_pair(".part_id.", KmpInt32PtrTy),
4311 std::make_pair(".privates.", VoidPtrTy),
4312 std::make_pair(
4313 ".copy_fn.",
4314 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4315 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4316 std::make_pair(".lb.", KmpUInt64Ty),
4317 std::make_pair(".ub.", KmpUInt64Ty),
4318 std::make_pair(".st.", KmpInt64Ty),
4319 std::make_pair(".liter.", KmpInt32Ty),
4320 std::make_pair(".reductions.", VoidPtrTy),
4321 std::make_pair(StringRef(), QualType()) // __context with shared vars
4322 };
4323 return Params;
4324}
4325
4327 Scope *CurScope, SourceLocation Loc) {
4329 getOpenMPCaptureRegions(Regions, DKind);
4330
4331 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4332
4333 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4334 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4335 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4336 };
4337
4338 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4339 switch (RKind) {
4340 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4341 // are listed here.
4342 case OMPD_parallel:
4344 Loc, CurScope, CR_OpenMP,
4345 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4346 break;
4347 case OMPD_teams:
4348 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4349 getTeamsRegionParams(SemaRef), Level);
4350 break;
4351 case OMPD_task:
4352 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4353 getTaskRegionParams(SemaRef), Level);
4354 // Mark this captured region as inlined, because we don't use outlined
4355 // function directly.
4356 MarkAsInlined(SemaRef.getCurCapturedRegion());
4357 break;
4358 case OMPD_taskloop:
4359 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4360 getTaskloopRegionParams(SemaRef), Level);
4361 // Mark this captured region as inlined, because we don't use outlined
4362 // function directly.
4363 MarkAsInlined(SemaRef.getCurCapturedRegion());
4364 break;
4365 case OMPD_target:
4366 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4367 getTargetRegionParams(SemaRef), Level);
4368 break;
4369 case OMPD_unknown:
4370 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4371 getUnknownRegionParams(SemaRef));
4372 break;
4373 case OMPD_metadirective:
4374 case OMPD_nothing:
4375 default:
4376 llvm_unreachable("Unexpected capture region");
4377 }
4378 }
4379}
4380
4382 Scope *CurScope) {
4383 switch (DKind) {
4384 case OMPD_atomic:
4385 case OMPD_critical:
4386 case OMPD_masked:
4387 case OMPD_master:
4388 case OMPD_section:
4389 case OMPD_tile:
4390 case OMPD_unroll:
4391 case OMPD_reverse:
4392 case OMPD_interchange:
4393 case OMPD_assume:
4394 break;
4395 default:
4396 processCapturedRegions(SemaRef, DKind, CurScope,
4397 DSAStack->getConstructLoc());
4398 break;
4399 }
4400
4401 DSAStack->setContext(SemaRef.CurContext);
4402 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4403}
4404
4405int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4406 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4407}
4408
4411 getOpenMPCaptureRegions(CaptureRegions, DKind);
4412 return CaptureRegions.size();
4413}
4414
4416 Expr *CaptureExpr, bool WithInit,
4417 DeclContext *CurContext,
4418 bool AsExpression) {
4419 assert(CaptureExpr);
4420 ASTContext &C = S.getASTContext();
4421 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4422 QualType Ty = Init->getType();
4423 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4424 if (S.getLangOpts().CPlusPlus) {
4425 Ty = C.getLValueReferenceType(Ty);
4426 } else {
4427 Ty = C.getPointerType(Ty);
4428 ExprResult Res =
4429 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4430 if (!Res.isUsable())
4431 return nullptr;
4432 Init = Res.get();
4433 }
4434 WithInit = true;
4435 }
4436 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4437 CaptureExpr->getBeginLoc());
4438 if (!WithInit)
4439 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4440 CurContext->addHiddenDecl(CED);
4442 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4443 return CED;
4444}
4445
4446static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4447 bool WithInit) {
4449 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4450 CD = cast<OMPCapturedExprDecl>(VD);
4451 else
4452 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4453 S.CurContext,
4454 /*AsExpression=*/false);
4455 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4456 CaptureExpr->getExprLoc());
4457}
4458
4459static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4460 StringRef Name) {
4461 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4462 if (!Ref) {
4464 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4465 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4466 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4467 CaptureExpr->getExprLoc());
4468 }
4469 ExprResult Res = Ref;
4470 if (!S.getLangOpts().CPlusPlus &&
4471 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4472 Ref->getType()->isPointerType()) {
4473 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4474 if (!Res.isUsable())
4475 return ExprError();
4476 }
4477 return S.DefaultLvalueConversion(Res.get());
4478}
4479
4480namespace {
4481// OpenMP directives parsed in this section are represented as a
4482// CapturedStatement with an associated statement. If a syntax error
4483// is detected during the parsing of the associated statement, the
4484// compiler must abort processing and close the CapturedStatement.
4485//
4486// Combined directives such as 'target parallel' have more than one
4487// nested CapturedStatements. This RAII ensures that we unwind out
4488// of all the nested CapturedStatements when an error is found.
4489class CaptureRegionUnwinderRAII {
4490private:
4491 Sema &S;
4492 bool &ErrorFound;
4493 OpenMPDirectiveKind DKind = OMPD_unknown;
4494
4495public:
4496 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4497 OpenMPDirectiveKind DKind)
4498 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4499 ~CaptureRegionUnwinderRAII() {
4500 if (ErrorFound) {
4501 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4502 while (--ThisCaptureLevel >= 0)
4504 }
4505 }
4506};
4507} // namespace
4508
4510 // Capture variables captured by reference in lambdas for target-based
4511 // directives.
4513 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4515 DSAStack->getCurrentDirective()))) {
4516 QualType Type = V->getType();
4517 if (const auto *RD = Type.getCanonicalType()
4518 .getNonReferenceType()
4519 ->getAsCXXRecordDecl()) {
4520 bool SavedForceCaptureByReferenceInTargetExecutable =
4521 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4522 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4523 /*V=*/true);
4524 if (RD->isLambda()) {
4525 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4526 FieldDecl *ThisCapture;
4527 RD->getCaptureFields(Captures, ThisCapture);
4528 for (const LambdaCapture &LC : RD->captures()) {
4529 if (LC.getCaptureKind() == LCK_ByRef) {
4530 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4531 DeclContext *VDC = VD->getDeclContext();
4532 if (!VDC->Encloses(SemaRef.CurContext))
4533 continue;
4534 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4535 } else if (LC.getCaptureKind() == LCK_This) {
4537 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4538 ThisTy, ThisCapture->getType()))
4539 SemaRef.CheckCXXThisCapture(LC.getLocation());
4540 }
4541 }
4542 }
4543 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4544 SavedForceCaptureByReferenceInTargetExecutable);
4545 }
4546 }
4547}
4548
4550 const ArrayRef<OMPClause *> Clauses) {
4551 const OMPOrderedClause *Ordered = nullptr;
4552 const OMPOrderClause *Order = nullptr;
4553
4554 for (const OMPClause *Clause : Clauses) {
4555 if (Clause->getClauseKind() == OMPC_ordered)
4556 Ordered = cast<OMPOrderedClause>(Clause);
4557 else if (Clause->getClauseKind() == OMPC_order) {
4558 Order = cast<OMPOrderClause>(Clause);
4559 if (Order->getKind() != OMPC_ORDER_concurrent)
4560 Order = nullptr;
4561 }
4562 if (Ordered && Order)
4563 break;
4564 }
4565
4566 if (Ordered && Order) {
4567 S.Diag(Order->getKindKwLoc(),
4568 diag::err_omp_simple_clause_incompatible_with_ordered)
4569 << getOpenMPClauseName(OMPC_order)
4570 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4571 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4572 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4573 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4574 return true;
4575 }
4576 return false;
4577}
4578
4580 ArrayRef<OMPClause *> Clauses) {
4582 /*ScopeEntry=*/false);
4583 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4584 return S;
4585
4586 bool ErrorFound = false;
4587 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4588 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4589 if (!S.isUsable()) {
4590 ErrorFound = true;
4591 return StmtError();
4592 }
4593
4595 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4596 OMPOrderedClause *OC = nullptr;
4597 OMPScheduleClause *SC = nullptr;
4600 // This is required for proper codegen.
4601 for (OMPClause *Clause : Clauses) {
4602 if (!getLangOpts().OpenMPSimd &&
4603 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4604 DSAStack->getCurrentDirective() == OMPD_target) &&
4605 Clause->getClauseKind() == OMPC_in_reduction) {
4606 // Capture taskgroup task_reduction descriptors inside the tasking regions
4607 // with the corresponding in_reduction items.
4608 auto *IRC = cast<OMPInReductionClause>(Clause);
4609 for (Expr *E : IRC->taskgroup_descriptors())
4610 if (E)
4612 }
4613 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4614 Clause->getClauseKind() == OMPC_copyprivate ||
4615 (getLangOpts().OpenMPUseTLS &&
4616 getASTContext().getTargetInfo().isTLSSupported() &&
4617 Clause->getClauseKind() == OMPC_copyin)) {
4618 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4619 // Mark all variables in private list clauses as used in inner region.
4620 for (Stmt *VarRef : Clause->children()) {
4621 if (auto *E = cast_or_null<Expr>(VarRef)) {
4623 }
4624 }
4625 DSAStack->setForceVarCapturing(/*V=*/false);
4626 } else if (CaptureRegions.size() > 1 ||
4627 CaptureRegions.back() != OMPD_unknown) {
4628 if (auto *C = OMPClauseWithPreInit::get(Clause))
4629 PICs.push_back(C);
4630 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4631 if (Expr *E = C->getPostUpdateExpr())
4633 }
4634 }
4635 if (Clause->getClauseKind() == OMPC_schedule)
4636 SC = cast<OMPScheduleClause>(Clause);
4637 else if (Clause->getClauseKind() == OMPC_ordered)
4638 OC = cast<OMPOrderedClause>(Clause);
4639 else if (Clause->getClauseKind() == OMPC_linear)
4640 LCs.push_back(cast<OMPLinearClause>(Clause));
4641 }
4642 // Capture allocator expressions if used.
4643 for (Expr *E : DSAStack->getInnerAllocators())
4645 // OpenMP, 2.7.1 Loop Construct, Restrictions
4646 // The nonmonotonic modifier cannot be specified if an ordered clause is
4647 // specified.
4648 if (SC &&
4649 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4651 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4652 OC) {
4653 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4656 diag::err_omp_simple_clause_incompatible_with_ordered)
4657 << getOpenMPClauseName(OMPC_schedule)
4658 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4659 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4660 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4661 ErrorFound = true;
4662 }
4663 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4664 // If an order(concurrent) clause is present, an ordered clause may not appear
4665 // on the same directive.
4666 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4667 ErrorFound = true;
4668 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4669 for (const OMPLinearClause *C : LCs) {
4670 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4671 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4672 }
4673 ErrorFound = true;
4674 }
4675 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4676 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4677 OC->getNumForLoops()) {
4678 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4679 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
4680 ErrorFound = true;
4681 }
4682 if (ErrorFound) {
4683 return StmtError();
4684 }
4685 StmtResult SR = S;
4686 unsigned CompletedRegions = 0;
4687 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4688 // Mark all variables in private list clauses as used in inner region.
4689 // Required for proper codegen of combined directives.
4690 // TODO: add processing for other clauses.
4691 if (ThisCaptureRegion != OMPD_unknown) {
4692 for (const clang::OMPClauseWithPreInit *C : PICs) {
4693 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4694 // Find the particular capture region for the clause if the
4695 // directive is a combined one with multiple capture regions.
4696 // If the directive is not a combined one, the capture region
4697 // associated with the clause is OMPD_unknown and is generated
4698 // only once.
4699 if (CaptureRegion == ThisCaptureRegion ||
4700 CaptureRegion == OMPD_unknown) {
4701 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4702 for (Decl *D : DS->decls())
4704 cast<VarDecl>(D));
4705 }
4706 }
4707 }
4708 }
4709 if (ThisCaptureRegion == OMPD_target) {
4710 // Capture allocator traits in the target region. They are used implicitly
4711 // and, thus, are not captured by default.
4712 for (OMPClause *C : Clauses) {
4713 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4714 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4715 ++I) {
4716 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4717 if (Expr *E = D.AllocatorTraits)
4719 }
4720 continue;
4721 }
4722 }
4723 }
4724 if (ThisCaptureRegion == OMPD_parallel) {
4725 // Capture temp arrays for inscan reductions and locals in aligned
4726 // clauses.
4727 for (OMPClause *C : Clauses) {
4728 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4729 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4730 continue;
4731 for (Expr *E : RC->copy_array_temps())
4732 if (E)
4734 }
4735 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4736 for (Expr *E : AC->varlist())
4738 }
4739 }
4740 }
4741 if (++CompletedRegions == CaptureRegions.size())
4742 DSAStack->setBodyComplete();
4744 }
4745 return SR;
4746}
4747
4748static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4749 OpenMPDirectiveKind CancelRegion,
4750 SourceLocation StartLoc) {
4751 // CancelRegion is only needed for cancel and cancellation_point.
4752 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4753 return false;
4754
4755 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4756 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4757 return false;
4758
4759 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4760 << getOpenMPDirectiveName(CancelRegion);
4761 return true;
4762}
4763
4764static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4765 OpenMPDirectiveKind CurrentRegion,
4766 const DeclarationNameInfo &CurrentName,
4767 OpenMPDirectiveKind CancelRegion,
4768 OpenMPBindClauseKind BindKind,
4769 SourceLocation StartLoc) {
4770 if (!Stack->getCurScope())
4771 return false;
4772
4773 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4774 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4775 bool NestingProhibited = false;
4776 bool CloseNesting = true;
4777 bool OrphanSeen = false;
4778 enum {
4779 NoRecommend,
4780 ShouldBeInParallelRegion,
4781 ShouldBeInOrderedRegion,
4782 ShouldBeInTargetRegion,
4783 ShouldBeInTeamsRegion,
4784 ShouldBeInLoopSimdRegion,
4785 } Recommend = NoRecommend;
4786
4789 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4790 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4791
4792 if (SemaRef.LangOpts.OpenMP >= 51 && Stack->isParentOrderConcurrent() &&
4793 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_loop &&
4794 CurrentRegion != OMPD_parallel &&
4795 !isOpenMPCombinedParallelADirective(CurrentRegion)) {
4796 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
4797 << getOpenMPDirectiveName(CurrentRegion);
4798 return true;
4799 }
4800 if (isOpenMPSimdDirective(ParentRegion) &&
4801 ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
4802 (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
4803 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
4804 CurrentRegion != OMPD_scan))) {
4805 // OpenMP [2.16, Nesting of Regions]
4806 // OpenMP constructs may not be nested inside a simd region.
4807 // OpenMP [2.8.1,simd Construct, Restrictions]
4808 // An ordered construct with the simd clause is the only OpenMP
4809 // construct that can appear in the simd region.
4810 // Allowing a SIMD construct nested in another SIMD construct is an
4811 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
4812 // message.
4813 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
4814 // The only OpenMP constructs that can be encountered during execution of
4815 // a simd region are the atomic construct, the loop construct, the simd
4816 // construct and the ordered construct with the simd clause.
4817 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
4818 ? diag::err_omp_prohibited_region_simd
4819 : diag::warn_omp_nesting_simd)
4820 << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
4821 return CurrentRegion != OMPD_simd;
4822 }
4823 if (EnclosingConstruct == OMPD_atomic) {
4824 // OpenMP [2.16, Nesting of Regions]
4825 // OpenMP constructs may not be nested inside an atomic region.
4826 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
4827 return true;
4828 }
4829 if (CurrentRegion == OMPD_section) {
4830 // OpenMP [2.7.2, sections Construct, Restrictions]
4831 // Orphaned section directives are prohibited. That is, the section
4832 // directives must appear within the sections construct and must not be
4833 // encountered elsewhere in the sections region.
4834 if (EnclosingConstruct != OMPD_sections) {
4835 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
4836 << (ParentRegion != OMPD_unknown)
4837 << getOpenMPDirectiveName(ParentRegion);
4838 return true;
4839 }
4840 return false;
4841 }
4842 // Allow some constructs (except teams and cancellation constructs) to be
4843 // orphaned (they could be used in functions, called from OpenMP regions
4844 // with the required preconditions).
4845 if (ParentRegion == OMPD_unknown &&
4846 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
4847 CurrentRegion != OMPD_cancellation_point &&
4848 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
4849 return false;
4850 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
4851 // for a detailed explanation
4852 if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
4853 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
4854 (isOpenMPWorksharingDirective(ParentRegion) ||
4855 EnclosingConstruct == OMPD_loop)) {
4856 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
4857 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
4858 << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
4859 << getOpenMPDirectiveName(CurrentRegion);
4860 return true;
4861 }
4862 if (CurrentRegion == OMPD_cancellation_point ||
4863 CurrentRegion == OMPD_cancel) {
4864 // OpenMP [2.16, Nesting of Regions]
4865 // A cancellation point construct for which construct-type-clause is
4866 // taskgroup must be nested inside a task construct. A cancellation
4867 // point construct for which construct-type-clause is not taskgroup must
4868 // be closely nested inside an OpenMP construct that matches the type
4869 // specified in construct-type-clause.
4870 // A cancel construct for which construct-type-clause is taskgroup must be
4871 // nested inside a task construct. A cancel construct for which
4872 // construct-type-clause is not taskgroup must be closely nested inside an
4873 // OpenMP construct that matches the type specified in
4874 // construct-type-clause.
4875 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
4876 if (CancelRegion == OMPD_taskgroup) {
4877 NestingProhibited = EnclosingConstruct != OMPD_task &&
4878 (SemaRef.getLangOpts().OpenMP < 50 ||
4879 EnclosingConstruct != OMPD_taskloop);
4880 } else if (CancelRegion == OMPD_sections) {
4881 NestingProhibited = EnclosingConstruct != OMPD_section &&
4882 EnclosingConstruct != OMPD_sections;
4883 } else {
4884 NestingProhibited = CancelRegion != Leafs.back();
4885 }
4886 OrphanSeen = ParentRegion == OMPD_unknown;
4887 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
4888 // OpenMP 5.1 [2.22, Nesting of Regions]
4889 // A masked region may not be closely nested inside a worksharing, loop,
4890 // atomic, task, or taskloop region.
4891 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4892 isOpenMPGenericLoopDirective(ParentRegion) ||
4893 isOpenMPTaskingDirective(ParentRegion);
4894 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
4895 // OpenMP [2.16, Nesting of Regions]
4896 // A critical region may not be nested (closely or otherwise) inside a
4897 // critical region with the same name. Note that this restriction is not
4898 // sufficient to prevent deadlock.
4899 SourceLocation PreviousCriticalLoc;
4900 bool DeadLock = Stack->hasDirective(
4901 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
4902 const DeclarationNameInfo &DNI,
4904 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
4905 PreviousCriticalLoc = Loc;
4906 return true;
4907 }
4908 return false;
4909 },
4910 false /* skip top directive */);
4911 if (DeadLock) {
4912 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
4913 << CurrentName.getName();
4914 if (PreviousCriticalLoc.isValid())
4915 SemaRef.Diag(PreviousCriticalLoc,
4916 diag::note_omp_previous_critical_region);
4917 return true;
4918 }
4919 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
4920 // OpenMP 5.1 [2.22, Nesting of Regions]
4921 // A scope region may not be closely nested inside a worksharing, loop,
4922 // task, taskloop, critical, ordered, atomic, or masked region.
4923 // OpenMP 5.1 [2.22, Nesting of Regions]
4924 // A barrier region may not be closely nested inside a worksharing, loop,
4925 // task, taskloop, critical, ordered, atomic, or masked region.
4926 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4927 isOpenMPGenericLoopDirective(ParentRegion) ||
4928 isOpenMPTaskingDirective(ParentRegion) ||
4929 llvm::is_contained({OMPD_masked, OMPD_master,
4930 OMPD_critical, OMPD_ordered},
4931 EnclosingConstruct);
4932 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
4933 !isOpenMPParallelDirective(CurrentRegion) &&
4934 !isOpenMPTeamsDirective(CurrentRegion)) {
4935 // OpenMP 5.1 [2.22, Nesting of Regions]
4936 // A loop region that binds to a parallel region or a worksharing region
4937 // may not be closely nested inside a worksharing, loop, task, taskloop,
4938 // critical, ordered, atomic, or masked region.
4939 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
4940 isOpenMPGenericLoopDirective(ParentRegion) ||
4941 isOpenMPTaskingDirective(ParentRegion) ||
4942 llvm::is_contained({OMPD_masked, OMPD_master,
4943 OMPD_critical, OMPD_ordered},
4944 EnclosingConstruct);
4945 Recommend = ShouldBeInParallelRegion;
4946 } else if (CurrentRegion == OMPD_ordered) {
4947 // OpenMP [2.16, Nesting of Regions]
4948 // An ordered region may not be closely nested inside a critical,
4949 // atomic, or explicit task region.
4950 // An ordered region must be closely nested inside a loop region (or
4951 // parallel loop region) with an ordered clause.
4952 // OpenMP [2.8.1,simd Construct, Restrictions]
4953 // An ordered construct with the simd clause is the only OpenMP construct
4954 // that can appear in the simd region.
4955 NestingProhibited = EnclosingConstruct == OMPD_critical ||
4956 isOpenMPTaskingDirective(ParentRegion) ||
4957 !(isOpenMPSimdDirective(ParentRegion) ||
4958 Stack->isParentOrderedRegion());
4959 Recommend = ShouldBeInOrderedRegion;
4960 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
4961 // OpenMP [2.16, Nesting of Regions]
4962 // If specified, a teams construct must be contained within a target
4963 // construct.
4964 NestingProhibited =
4965 (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
4966 (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
4967 EnclosingConstruct != OMPD_target);
4968 OrphanSeen = ParentRegion == OMPD_unknown;
4969 Recommend = ShouldBeInTargetRegion;
4970 } else if (CurrentRegion == OMPD_scan) {
4971 if (SemaRef.LangOpts.OpenMP >= 50) {
4972 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
4973 // simd, or for simd. This has to take into account combined directives.
4974 // In 5.2 this seems to be implied by the fact that the specified
4975 // separated constructs are do, for, and simd.
4976 NestingProhibited = !llvm::is_contained(
4977 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
4978 } else {
4979 NestingProhibited = true;
4980 }
4981 OrphanSeen = ParentRegion == OMPD_unknown;
4982 Recommend = ShouldBeInLoopSimdRegion;
4983 }
4984 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
4985 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
4986 EnclosingConstruct == OMPD_teams) {
4987 // OpenMP [5.1, 2.22, Nesting of Regions]
4988 // distribute, distribute simd, distribute parallel worksharing-loop,
4989 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
4990 // including any parallel regions arising from combined constructs,
4991 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
4992 // only OpenMP regions that may be strictly nested inside the teams
4993 // region.
4994 //
4995 // As an extension, we permit atomic within teams as well.
4996 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
4997 !isOpenMPDistributeDirective(CurrentRegion) &&
4998 CurrentRegion != OMPD_loop &&
4999 !(SemaRef.getLangOpts().OpenMPExtensions &&
5000 CurrentRegion == OMPD_atomic);
5001 Recommend = ShouldBeInParallelRegion;
5002 }
5003 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5004 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5005 // If the bind clause is present on the loop construct and binding is
5006 // teams then the corresponding loop region must be strictly nested inside
5007 // a teams region.
5008 NestingProhibited =
5009 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5010 Recommend = ShouldBeInTeamsRegion;
5011 }
5012 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5013 // OpenMP 4.5 [2.17 Nesting of Regions]
5014 // The region associated with the distribute construct must be strictly
5015 // nested inside a teams region
5016 NestingProhibited = EnclosingConstruct != OMPD_teams;
5017 Recommend = ShouldBeInTeamsRegion;
5018 }
5019 if (!NestingProhibited &&
5020 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5021 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5022 // OpenMP 4.5 [2.17 Nesting of Regions]
5023 // If a target, target update, target data, target enter data, or
5024 // target exit data construct is encountered during execution of a
5025 // target region, the behavior is unspecified.
5026 NestingProhibited = Stack->hasDirective(
5027 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5030 OffendingRegion = K;
5031 return true;
5032 }
5033 return false;
5034 },
5035 false /* don't skip top directive */);
5036 CloseNesting = false;
5037 }
5038 if (NestingProhibited) {
5039 if (OrphanSeen) {
5040 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5041 << getOpenMPDirectiveName(CurrentRegion) << Recommend;
5042 } else {
5043 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5044 << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
5045 << Recommend << getOpenMPDirectiveName(CurrentRegion);
5046 }
5047 return true;
5048 }
5049 return false;
5050}
5051
5054 unsigned operator()(argument_type DK) { return unsigned(DK); }
5055};
5057 ArrayRef<OMPClause *> Clauses,
5058 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5059 bool ErrorFound = false;
5060 unsigned NamedModifiersNumber = 0;
5061 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5062 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5063 SmallVector<SourceLocation, 4> NameModifierLoc;
5064 for (const OMPClause *C : Clauses) {
5065 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5066 // At most one if clause without a directive-name-modifier can appear on
5067 // the directive.
5068 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5069 if (FoundNameModifiers[CurNM]) {
5070 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5071 << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if)
5072 << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM);
5073 ErrorFound = true;
5074 } else if (CurNM != OMPD_unknown) {
5075 NameModifierLoc.push_back(IC->getNameModifierLoc());
5076 ++NamedModifiersNumber;
5077 }
5078 FoundNameModifiers[CurNM] = IC;
5079 if (CurNM == OMPD_unknown)
5080 continue;
5081 // Check if the specified name modifier is allowed for the current
5082 // directive.
5083 // At most one if clause with the particular directive-name-modifier can
5084 // appear on the directive.
5085 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5086 S.Diag(IC->getNameModifierLoc(),
5087 diag::err_omp_wrong_if_directive_name_modifier)
5088 << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
5089 ErrorFound = true;
5090 }
5091 }
5092 }
5093 // If any if clause on the directive includes a directive-name-modifier then
5094 // all if clauses on the directive must include a directive-name-modifier.
5095 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5096 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5097 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5098 diag::err_omp_no_more_if_clause);
5099 } else {
5100 std::string Values;
5101 std::string Sep(", ");
5102 unsigned AllowedCnt = 0;
5103 unsigned TotalAllowedNum =
5104 AllowedNameModifiers.size() - NamedModifiersNumber;
5105 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5106 ++Cnt) {
5107 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5108 if (!FoundNameModifiers[NM]) {
5109 Values += "'";
5110 Values += getOpenMPDirectiveName(NM);
5111 Values += "'";
5112 if (AllowedCnt + 2 == TotalAllowedNum)
5113 Values += " or ";
5114 else if (AllowedCnt + 1 != TotalAllowedNum)
5115 Values += Sep;
5116 ++AllowedCnt;
5117 }
5118 }
5119 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5120 diag::err_omp_unnamed_if_clause)
5121 << (TotalAllowedNum > 1) << Values;
5122 }
5123 for (SourceLocation Loc : NameModifierLoc) {
5124 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5125 }
5126 ErrorFound = true;
5127 }
5128 return ErrorFound;
5129}
5130
5131static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
5132 SourceLocation &ELoc,
5133 SourceRange &ERange,
5134 bool AllowArraySection,
5135 StringRef DiagType) {
5136 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5138 return std::make_pair(nullptr, true);
5139
5140 // OpenMP [3.1, C/C++]
5141 // A list item is a variable name.
5142 // OpenMP [2.9.3.3, Restrictions, p.1]
5143 // A variable that is part of another variable (as an array or
5144 // structure element) cannot appear in a private clause.
5145 RefExpr = RefExpr->IgnoreParens();
5146 enum {
5147 NoArrayExpr = -1,
5148 ArraySubscript = 0,
5149 OMPArraySection = 1
5150 } IsArrayExpr = NoArrayExpr;
5151 if (AllowArraySection) {
5152 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5153 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5154 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5155 Base = TempASE->getBase()->IgnoreParenImpCasts();
5156 RefExpr = Base;
5157 IsArrayExpr = ArraySubscript;
5158 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5159 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5160 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5161 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5162 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5163 Base = TempASE->getBase()->IgnoreParenImpCasts();
5164 RefExpr = Base;
5165 IsArrayExpr = OMPArraySection;
5166 }
5167 }
5168 ELoc = RefExpr->getExprLoc();
5169 ERange = RefExpr->getSourceRange();
5170 RefExpr = RefExpr->IgnoreParenImpCasts();
5171 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5172 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5173 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5174 (S.getCurrentThisType().isNull() || !ME ||
5175 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5176 !isa<FieldDecl>(ME->getMemberDecl()))) {
5177 if (IsArrayExpr != NoArrayExpr) {
5178 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5179 << IsArrayExpr << ERange;
5180 } else if (!DiagType.empty()) {
5181 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5182 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5183 : 0;
5184 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5185 << DiagSelect << DiagType << ERange;
5186 } else {
5187 S.Diag(ELoc,
5188 AllowArraySection
5189 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5190 : diag::err_omp_expected_var_name_member_expr)
5191 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5192 }
5193 return std::make_pair(nullptr, false);
5194 }
5195 return std::make_pair(
5196 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5197}
5198
5199namespace {
5200/// Checks if the allocator is used in uses_allocators clause to be allowed in
5201/// target regions.
5202class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5203 DSAStackTy *S = nullptr;
5204
5205public:
5206 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5207 return S->isUsesAllocatorsDecl(E->getDecl())
5208 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5209 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5210 }
5211 bool VisitStmt(const Stmt *S) {
5212 for (const Stmt *Child : S->children()) {
5213 if (Child && Visit(Child))
5214 return true;
5215 }
5216 return false;
5217 }
5218 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5219};
5220} // namespace
5221
5222static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5223 ArrayRef<OMPClause *> Clauses) {
5224 assert(!S.CurContext->isDependentContext() &&
5225 "Expected non-dependent context.");
5226 auto AllocateRange =
5227 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5228 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5229 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5230 return isOpenMPPrivate(C->getClauseKind());
5231 });
5232 for (OMPClause *Cl : PrivateRange) {
5234 if (Cl->getClauseKind() == OMPC_private) {
5235 auto *PC = cast<OMPPrivateClause>(Cl);
5236 I = PC->private_copies().begin();
5237 It = PC->varlist_begin();
5238 Et = PC->varlist_end();
5239 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5240 auto *PC = cast<OMPFirstprivateClause>(Cl);
5241 I = PC->private_copies().begin();
5242 It = PC->varlist_begin();
5243 Et = PC->varlist_end();
5244 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5245 auto *PC = cast<OMPLastprivateClause>(Cl);
5246 I = PC->private_copies().begin();
5247 It = PC->varlist_begin();
5248 Et = PC->varlist_end();
5249 } else if (Cl->getClauseKind() == OMPC_linear) {
5250 auto *PC = cast<OMPLinearClause>(Cl);
5251 I = PC->privates().begin();
5252 It = PC->varlist_begin();
5253 Et = PC->varlist_end();
5254 } else if (Cl->getClauseKind() == OMPC_reduction) {
5255 auto *PC = cast<OMPReductionClause>(Cl);
5256 I = PC->privates().begin();
5257 It = PC->varlist_begin();
5258 Et = PC->varlist_end();
5259 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5260 auto *PC = cast<OMPTaskReductionClause>(Cl);
5261 I = PC->privates().begin();
5262 It = PC->varlist_begin();
5263 Et = PC->varlist_end();
5264 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5265 auto *PC = cast<OMPInReductionClause>(Cl);
5266 I = PC->privates().begin();
5267 It = PC->varlist_begin();
5268 Et = PC->varlist_end();
5269 } else {
5270 llvm_unreachable("Expected private clause.");
5271 }
5272 for (Expr *E : llvm::make_range(It, Et)) {
5273 if (!*I) {
5274 ++I;
5275 continue;
5276 }
5277 SourceLocation ELoc;
5278 SourceRange ERange;
5279 Expr *SimpleRefExpr = E;
5280 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5281 /*AllowArraySection=*/true);
5282 DeclToCopy.try_emplace(Res.first,
5283 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5284 ++I;
5285 }
5286 }
5287 for (OMPClause *C : AllocateRange) {
5288 auto *AC = cast<OMPAllocateClause>(C);
5289 if (S.getLangOpts().OpenMP >= 50 &&
5290 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5291 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5292 AC->getAllocator()) {
5293 Expr *Allocator = AC->getAllocator();
5294 // OpenMP, 2.12.5 target Construct
5295 // Memory allocators that do not appear in a uses_allocators clause cannot
5296 // appear as an allocator in an allocate clause or be used in the target
5297 // region unless a requires directive with the dynamic_allocators clause
5298 // is present in the same compilation unit.
5299 AllocatorChecker Checker(Stack);
5300 if (Checker.Visit(Allocator))
5301 S.Diag(Allocator->getExprLoc(),
5302 diag::err_omp_allocator_not_in_uses_allocators)
5303 << Allocator->getSourceRange();
5304 }
5305 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5306 getAllocatorKind(S, Stack, AC->getAllocator());
5307 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5308 // For task, taskloop or target directives, allocation requests to memory
5309 // allocators with the trait access set to thread result in unspecified
5310 // behavior.
5311 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5312 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5313 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5314 S.Diag(AC->getAllocator()->getExprLoc(),
5315 diag::warn_omp_allocate_thread_on_task_target_directive)
5316 << getOpenMPDirectiveName(Stack->getCurrentDirective());
5317 }
5318 for (Expr *E : AC->varlist()) {
5319 SourceLocation ELoc;
5320 SourceRange ERange;
5321 Expr *SimpleRefExpr = E;
5322 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5323 ValueDecl *VD = Res.first;
5324 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5325 if (!isOpenMPPrivate(Data.CKind)) {
5326 S.Diag(E->getExprLoc(),
5327 diag::err_omp_expected_private_copy_for_allocate);
5328 continue;
5329 }
5330 VarDecl *PrivateVD = DeclToCopy[VD];
5331 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5332 AllocatorKind, AC->getAllocator()))
5333 continue;
5334 // Placeholder until allocate clause supports align modifier.
5335 Expr *Alignment = nullptr;
5336 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5337 Alignment, E->getSourceRange());
5338 }
5339 }
5340}
5341
5342namespace {
5343/// Rewrite statements and expressions for Sema \p Actions CurContext.
5344///
5345/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5346/// context. DeclRefExpr used inside the new context are changed to refer to the
5347/// captured variable instead.
5348class CaptureVars : public TreeTransform<CaptureVars> {
5349 using BaseTransform = TreeTransform<CaptureVars>;
5350
5351public:
5352 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5353
5354 bool AlwaysRebuild() { return true; }
5355};
5356} // namespace
5357
5358static VarDecl *precomputeExpr(Sema &Actions,
5359 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5360 StringRef Name) {
5361 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5362 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5363 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5364 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5365 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5366 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5367 BodyStmts.push_back(NewDeclStmt);
5368 return NewVar;
5369}
5370
5371/// Create a closure that computes the number of iterations of a loop.
5372///
5373/// \param Actions The Sema object.
5374/// \param LogicalTy Type for the logical iteration number.
5375/// \param Rel Comparison operator of the loop condition.
5376/// \param StartExpr Value of the loop counter at the first iteration.
5377/// \param StopExpr Expression the loop counter is compared against in the loop
5378/// condition. \param StepExpr Amount of increment after each iteration.
5379///
5380/// \return Closure (CapturedStmt) of the distance calculation.
5381static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5383 Expr *StartExpr, Expr *StopExpr,
5384 Expr *StepExpr) {
5385 ASTContext &Ctx = Actions.getASTContext();
5386 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5387
5388 // Captured regions currently don't support return values, we use an
5389 // out-parameter instead. All inputs are implicit captures.
5390 // TODO: Instead of capturing each DeclRefExpr occurring in
5391 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5392 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5393 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5394 {StringRef(), QualType()}};
5395 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5396
5397 Stmt *Body;
5398 {
5399 Sema::CompoundScopeRAII CompoundScope(Actions);
5400 CapturedDecl *CS = cast<CapturedDecl>(Actions.CurContext);
5401
5402 // Get the LValue expression for the result.
5403 ImplicitParamDecl *DistParam = CS->getParam(0);
5404 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5405 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5406
5407 SmallVector<Stmt *, 4> BodyStmts;
5408
5409 // Capture all referenced variable references.
5410 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5411 // CapturedStmt, we could compute them before and capture the result, to be
5412 // used jointly with the LoopVar function.
5413 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5414 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5415 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5416 auto BuildVarRef = [&](VarDecl *VD) {
5417 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5418 };
5419
5421 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5423 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5424 Expr *Dist;
5425 if (Rel == BO_NE) {
5426 // When using a != comparison, the increment can be +1 or -1. This can be
5427 // dynamic at runtime, so we need to check for the direction.
5428 Expr *IsNegStep = AssertSuccess(
5429 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5430
5431 // Positive increment.
5432 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5433 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5434 ForwardRange = AssertSuccess(
5435 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5436 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5437 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5438
5439 // Negative increment.
5440 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5441 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5442 BackwardRange = AssertSuccess(
5443 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5444 Expr *NegIncAmount = AssertSuccess(
5445 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5446 Expr *BackwardDist = AssertSuccess(
5447 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5448
5449 // Use the appropriate case.
5450 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5451 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5452 } else {
5453 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5454 "Expected one of these relational operators");
5455
5456 // We can derive the direction from any other comparison operator. It is
5457 // non well-formed OpenMP if Step increments/decrements in the other
5458 // directions. Whether at least the first iteration passes the loop
5459 // condition.
5460 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5461 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5462
5463 // Compute the range between first and last counter value.
5464 Expr *Range;
5465 if (Rel == BO_GE || Rel == BO_GT)
5466 Range = AssertSuccess(Actions.BuildBinOp(
5467 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5468 else
5469 Range = AssertSuccess(Actions.BuildBinOp(
5470 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5471
5472 // Ensure unsigned range space.
5473 Range =
5474 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5475
5476 if (Rel == BO_LE || Rel == BO_GE) {
5477 // Add one to the range if the relational operator is inclusive.
5478 Range =
5479 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5480 }
5481
5482 // Divide by the absolute step amount. If the range is not a multiple of
5483 // the step size, rounding-up the effective upper bound ensures that the
5484 // last iteration is included.
5485 // Note that the rounding-up may cause an overflow in a temporary that
5486 // could be avoided, but would have occurred in a C-style for-loop as
5487 // well.
5488 Expr *Divisor = BuildVarRef(NewStep);
5489 if (Rel == BO_GE || Rel == BO_GT)
5490 Divisor =
5491 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5492 Expr *DivisorMinusOne =
5493 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5494 Expr *RangeRoundUp = AssertSuccess(
5495 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5496 Dist = AssertSuccess(
5497 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5498
5499 // If there is not at least one iteration, the range contains garbage. Fix
5500 // to zero in this case.
5501 Dist = AssertSuccess(
5502 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5503 }
5504
5505 // Assign the result to the out-parameter.
5506 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5507 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5508 BodyStmts.push_back(ResultAssign);
5509
5510 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5511 }
5512
5513 return cast<CapturedStmt>(
5514 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5515}
5516
5517/// Create a closure that computes the loop variable from the logical iteration
5518/// number.
5519///
5520/// \param Actions The Sema object.
5521/// \param LoopVarTy Type for the loop variable used for result value.
5522/// \param LogicalTy Type for the logical iteration number.
5523/// \param StartExpr Value of the loop counter at the first iteration.
5524/// \param Step Amount of increment after each iteration.
5525/// \param Deref Whether the loop variable is a dereference of the loop
5526/// counter variable.
5527///
5528/// \return Closure (CapturedStmt) of the loop value calculation.
5529static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5530 QualType LogicalTy,
5531 DeclRefExpr *StartExpr, Expr *Step,
5532 bool Deref) {
5533 ASTContext &Ctx = Actions.getASTContext();
5534
5535 // Pass the result as an out-parameter. Passing as return value would require
5536 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5537 // invoke a copy constructor.
5538 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5539 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5540 {"Logical", LogicalTy},
5541 {StringRef(), QualType()}};
5542 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5543
5544 // Capture the initial iterator which represents the LoopVar value at the
5545 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5546 // it in every iteration, capture it by value before it is modified.
5547 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5548 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5550 (void)Invalid;
5551 assert(!Invalid && "Expecting capture-by-value to work.");
5552
5553 Expr *Body;
5554 {
5555 Sema::CompoundScopeRAII CompoundScope(Actions);
5556 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5557
5558 ImplicitParamDecl *TargetParam = CS->getParam(0);
5559 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5560 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5561 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5562 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5563 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5564
5565 // Capture the Start expression.
5566 CaptureVars Recap(Actions);
5567 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5568 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5569
5570 Expr *Skip = AssertSuccess(
5571 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5572 // TODO: Explicitly cast to the iterator's difference_type instead of
5573 // relying on implicit conversion.
5574 Expr *Advanced =
5575 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5576
5577 if (Deref) {
5578 // For range-based for-loops convert the loop counter value to a concrete
5579 // loop variable value by dereferencing the iterator.
5580 Advanced =
5581 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5582 }
5583
5584 // Assign the result to the output parameter.
5585 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5586 BO_Assign, TargetRef, Advanced));
5587 }
5588 return cast<CapturedStmt>(
5589 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5590}
5591
5593 ASTContext &Ctx = getASTContext();
5594
5595 // Extract the common elements of ForStmt and CXXForRangeStmt:
5596 // Loop variable, repeat condition, increment
5597 Expr *Cond, *Inc;
5598 VarDecl *LIVDecl, *LUVDecl;
5599 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5600 Stmt *Init = For->getInit();
5601 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5602 // For statement declares loop variable.
5603 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5604 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5605 // For statement reuses variable.
5606 assert(LCAssign->getOpcode() == BO_Assign &&
5607 "init part must be a loop variable assignment");
5608 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5609 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5610 } else
5611 llvm_unreachable("Cannot determine loop variable");
5612 LUVDecl = LIVDecl;
5613
5614 Cond = For->getCond();
5615 Inc = For->getInc();
5616 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5617 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5618 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5619 LUVDecl = RangeFor->getLoopVariable();
5620
5621 Cond = RangeFor->getCond();
5622 Inc = RangeFor->getInc();
5623 } else
5624 llvm_unreachable("unhandled kind of loop");
5625
5626 QualType CounterTy = LIVDecl->getType();
5627 QualType LVTy = LUVDecl->getType();
5628
5629 // Analyze the loop condition.
5630 Expr *LHS, *RHS;
5631 BinaryOperator::Opcode CondRel;
5632 Cond = Cond->IgnoreImplicit();
5633 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5634 LHS = CondBinExpr->getLHS();
5635 RHS = CondBinExpr->getRHS();
5636 CondRel = CondBinExpr->getOpcode();
5637 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5638 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5639 LHS = CondCXXOp->getArg(0);
5640 RHS = CondCXXOp->getArg(1);
5641 switch (CondCXXOp->getOperator()) {
5642 case OO_ExclaimEqual:
5643 CondRel = BO_NE;
5644 break;
5645 case OO_Less:
5646 CondRel = BO_LT;
5647 break;
5648 case OO_LessEqual:
5649 CondRel = BO_LE;
5650 break;
5651 case OO_Greater:
5652 CondRel = BO_GT;
5653 break;
5654 case OO_GreaterEqual:
5655 CondRel = BO_GE;
5656 break;
5657 default:
5658 llvm_unreachable("unexpected iterator operator");
5659 }
5660 } else
5661 llvm_unreachable("unexpected loop condition");
5662
5663 // Normalize such that the loop counter is on the LHS.
5664 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5665 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5666 std::swap(LHS, RHS);
5667 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5668 }
5669 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5670
5671 // Decide the bit width for the logical iteration counter. By default use the
5672 // unsigned ptrdiff_t integer size (for iterators and pointers).
5673 // TODO: For iterators, use iterator::difference_type,
5674 // std::iterator_traits<>::difference_type or decltype(it - end).
5675 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5676 if (CounterTy->isIntegerType()) {
5677 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5678 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5679 }
5680
5681 // Analyze the loop increment.
5682 Expr *Step;
5683 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5684 int Direction;
5685 switch (IncUn->getOpcode()) {
5686 case UO_PreInc:
5687 case UO_PostInc:
5688 Direction = 1;
5689 break;
5690 case UO_PreDec:
5691 case UO_PostDec:
5692 Direction = -1;
5693 break;
5694 default:
5695 llvm_unreachable("unhandled unary increment operator");
5696 }
5698 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction), LogicalTy, {});
5699 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5700 if (IncBin->getOpcode() == BO_AddAssign) {
5701 Step = IncBin->getRHS();
5702 } else if (IncBin->getOpcode() == BO_SubAssign) {
5703 Step = AssertSuccess(
5704 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5705 } else
5706 llvm_unreachable("unhandled binary increment operator");
5707 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5708 switch (CondCXXOp->getOperator()) {
5709 case OO_PlusPlus:
5711 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5712 break;
5713 case OO_MinusMinus:
5715 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5716 break;
5717 case OO_PlusEqual:
5718 Step = CondCXXOp->getArg(1);
5719 break;
5720 case OO_MinusEqual:
5721 Step = AssertSuccess(
5722 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5723 break;
5724 default:
5725 llvm_unreachable("unhandled overloaded increment operator");
5726 }
5727 } else
5728 llvm_unreachable("unknown increment expression");
5729
5730 CapturedStmt *DistanceFunc =
5731 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5732 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5733 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5734 DeclRefExpr *LVRef =
5735 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5736 nullptr, nullptr, {}, nullptr);
5737 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5738 LoopVarFunc, LVRef);
5739}
5740
5742 // Handle a literal loop.
5743 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5744 return ActOnOpenMPCanonicalLoop(AStmt);
5745
5746 // If not a literal loop, it must be the result of a loop transformation.
5747 OMPExecutableDirective *LoopTransform = cast<OMPExecutableDirective>(AStmt);
5748 assert(
5750 "Loop transformation directive expected");
5751 return LoopTransform;
5752}
5753
5755 CXXScopeSpec &MapperIdScopeSpec,
5756 const DeclarationNameInfo &MapperId,
5757 QualType Type,
5758 Expr *UnresolvedMapper);
5759
5760/// Perform DFS through the structure/class data members trying to find
5761/// member(s) with user-defined 'default' mapper and generate implicit map
5762/// clauses for such members with the found 'default' mapper.
5763static void
5766 // Check for the default mapper for data members.
5767 if (S.getLangOpts().OpenMP < 50)
5768 return;
5769 SmallVector<OMPClause *, 4> ImplicitMaps;
5770 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
5771 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
5772 if (!C)
5773 continue;
5774 SmallVector<Expr *, 4> SubExprs;
5775 auto *MI = C->mapperlist_begin();
5776 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
5777 ++I, ++MI) {
5778 // Expression is mapped using mapper - skip it.
5779 if (*MI)
5780 continue;
5781 Expr *E = *I;
5782 // Expression is dependent - skip it, build the mapper when it gets
5783 // instantiated.
5784 if (E->isTypeDependent() || E->isValueDependent() ||
5786 continue;
5787 // Array section - need to check for the mapping of the array section
5788 // element.
5789 QualType CanonType = E->getType().getCanonicalType();
5790 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
5791 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
5792 QualType BaseType =
5794 QualType ElemType;
5795 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
5796 ElemType = ATy->getElementType();
5797 else
5798 ElemType = BaseType->getPointeeType();
5799 CanonType = ElemType;
5800 }
5801
5802 // DFS over data members in structures/classes.
5804 1, {CanonType, nullptr});
5805 llvm::DenseMap<const Type *, Expr *> Visited;
5807 1, {nullptr, 1});
5808 while (!Types.empty()) {
5809 QualType BaseType;
5810 FieldDecl *CurFD;
5811 std::tie(BaseType, CurFD) = Types.pop_back_val();
5812 while (ParentChain.back().second == 0)
5813 ParentChain.pop_back();
5814 --ParentChain.back().second;
5815 if (BaseType.isNull())
5816 continue;
5817 // Only structs/classes are allowed to have mappers.
5818 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
5819 if (!RD)
5820 continue;
5821 auto It = Visited.find(BaseType.getTypePtr());
5822 if (It == Visited.end()) {
5823 // Try to find the associated user-defined mapper.
5824 CXXScopeSpec MapperIdScopeSpec;
5825 DeclarationNameInfo DefaultMapperId;
5827 &S.Context.Idents.get("default")));
5828 DefaultMapperId.setLoc(E->getExprLoc());
5830 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
5831 BaseType, /*UnresolvedMapper=*/nullptr);
5832 if (ER.isInvalid())
5833 continue;
5834 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
5835 }
5836 // Found default mapper.
5837 if (It->second) {
5838 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
5840 OE->setIsUnique(/*V=*/true);
5841 Expr *BaseExpr = OE;
5842 for (const auto &P : ParentChain) {
5843 if (P.first) {
5844 BaseExpr = S.BuildMemberExpr(
5845 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5847 DeclAccessPair::make(P.first, P.first->getAccess()),
5848 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5849 P.first->getType(), VK_LValue, OK_Ordinary);
5850 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
5851 }
5852 }
5853 if (CurFD)
5854 BaseExpr = S.BuildMemberExpr(
5855 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
5857 DeclAccessPair::make(CurFD, CurFD->getAccess()),
5858 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
5859 CurFD->getType(), VK_LValue, OK_Ordinary);
5860 SubExprs.push_back(BaseExpr);
5861 continue;
5862 }
5863 // Check for the "default" mapper for data members.
5864 bool FirstIter = true;
5865 for (FieldDecl *FD : RD->fields()) {
5866 if (!FD)
5867 continue;
5868 QualType FieldTy = FD->getType();
5869 if (FieldTy.isNull() ||
5870 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
5871 continue;
5872 if (FirstIter) {
5873 FirstIter = false;
5874 ParentChain.emplace_back(CurFD, 1);
5875 } else {
5876 ++ParentChain.back().second;
5877 }
5878 Types.emplace_back(FieldTy, FD);
5879 }
5880 }
5881 }
5882 if (SubExprs.empty())
5883 continue;
5884 CXXScopeSpec MapperIdScopeSpec;
5885 DeclarationNameInfo MapperId;
5886 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
5887 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
5888 MapperIdScopeSpec, MapperId, C->getMapType(),
5889 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
5890 SubExprs, OMPVarListLocTy()))
5891 Clauses.push_back(NewClause);
5892 }
5893}
5894
5895namespace {
5896/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
5897/// call in the associated loop-nest cannot be a 'parallel for'.
5898class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
5899 Sema &SemaRef;
5900
5901public:
5902 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
5903
5904 // Is there a nested OpenMP loop bind(parallel)
5905 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
5906 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
5907 if (const auto *C = D->getSingleClause<OMPBindClause>())
5908 if (C->getBindKind() == OMPC_BIND_parallel) {
5909 TeamsLoopCanBeParallelFor = false;
5910 // No need to continue visiting any more
5911 return;
5912 }
5913 }
5914 for (const Stmt *Child : D->children())
5915 if (Child)
5916 Visit(Child);
5917 }
5918
5919 void VisitCallExpr(const CallExpr *C) {
5920 // Function calls inhibit parallel loop translation of 'target teams loop'
5921 // unless the assume-no-nested-parallelism flag has been specified.
5922 // OpenMP API runtime library calls do not inhibit parallel loop
5923 // translation, regardless of the assume-no-nested-parallelism.
5924 bool IsOpenMPAPI = false;
5925 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
5926 if (FD) {
5927 std::string Name = FD->getNameInfo().getAsString();
5928 IsOpenMPAPI = Name.find("omp_") == 0;
5929 }
5930 TeamsLoopCanBeParallelFor =
5931 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
5932 if (!TeamsLoopCanBeParallelFor)
5933 return;
5934
5935 for (const Stmt *Child : C->children())
5936 if (Child)
5937 Visit(Child);
5938 }
5939
5940 void VisitCapturedStmt(const CapturedStmt *S) {
5941 if (!S)
5942 return;
5943 Visit(S->getCapturedDecl()->getBody());
5944 }
5945
5946 void VisitStmt(const Stmt *S) {
5947 if (!S)
5948 return;
5949 for (const Stmt *Child : S->children())
5950 if (Child)
5951 Visit(Child);
5952 }
5953 explicit TeamsLoopChecker(Sema &SemaRef)
5954 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
5955
5956private:
5957 bool TeamsLoopCanBeParallelFor;
5958};
5959} // namespace
5960
5961static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
5962 TeamsLoopChecker Checker(SemaRef);
5963 Checker.Visit(AStmt);
5964 return Checker.teamsLoopCanBeParallelFor();
5965}
5966
5968 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
5969 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
5970 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
5971 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
5972
5973 StmtResult Res = StmtError();
5975 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
5976
5977 if (const OMPBindClause *BC =
5978 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
5979 BindKind = BC->getBindKind();
5980
5981 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
5982 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
5983
5984 // Setting the enclosing teams or parallel construct for the loop
5985 // directive without bind clause.
5986 // [5.0:129:25-28] If the bind clause is not present on the construct and
5987 // the loop construct is closely nested inside a teams or parallel
5988 // construct, the binding region is the corresponding teams or parallel
5989 // region. If none of those conditions hold, the binding region is not
5990 // defined.
5991 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
5992 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
5993 getLeafConstructsOrSelf(ParentDirective);
5994
5995 if (ParentDirective == OMPD_unknown) {
5996 Diag(DSAStack->getDefaultDSALocation(),
5997 diag::err_omp_bind_required_on_loop);
5998 } else if (ParentLeafs.back() == OMPD_parallel) {
5999 BindKind = OMPC_BIND_parallel;
6000 } else if (ParentLeafs.back() == OMPD_teams) {
6001 BindKind = OMPC_BIND_teams;
6002 }
6003
6004 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6005
6006 OMPClause *C =
6009 ClausesWithImplicit.push_back(C);
6010 }
6011
6012 // Diagnose "loop bind(teams)" with "reduction".
6013 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6014 for (OMPClause *C : Clauses) {
6015 if (C->getClauseKind() == OMPC_reduction)
6016 Diag(DSAStack->getDefaultDSALocation(),
6017 diag::err_omp_loop_reduction_clause);
6018 }
6019 }
6020
6021 // First check CancelRegion which is then used in checkNestingOfRegions.
6022 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6023 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6024 BindKind, StartLoc)) {
6025 return StmtError();
6026 }
6027
6028 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6031 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6032
6033 VarsWithInheritedDSAType VarsWithInheritedDSA;
6034 bool ErrorFound = false;
6035 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6036
6037 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6039 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6040
6041 // Check default data sharing attributes for referenced variables.
6042 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6043 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6044 Stmt *S = AStmt;
6045 while (--ThisCaptureLevel >= 0)
6046 S = cast<CapturedStmt>(S)->getCapturedStmt();
6047 DSAChecker.Visit(S);
6049 !isOpenMPTaskingDirective(Kind)) {
6050 // Visit subcaptures to generate implicit clauses for captured vars.
6051 auto *CS = cast<CapturedStmt>(AStmt);
6053 getOpenMPCaptureRegions(CaptureRegions, Kind);
6054 // Ignore outer tasking regions for target directives.
6055 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6056 CS = cast<CapturedStmt>(CS->getCapturedStmt());
6057 DSAChecker.visitSubCaptures(CS);
6058 }
6059 if (DSAChecker.isErrorFound())
6060 return StmtError();
6061 // Generate list of implicitly defined firstprivate variables.
6062 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6063
6064 SmallVector<Expr *, 4> ImplicitFirstprivates(
6065 DSAChecker.getImplicitFirstprivate());
6066 SmallVector<Expr *, 4> ImplicitPrivates(DSAChecker.getImplicitPrivate());
6067 const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
6068 SmallVector<Expr *, 4> ImplicitMaps[DefaultmapKindNum][OMPC_MAP_delete];
6070 ImplicitMapModifiers[DefaultmapKindNum];
6072 ImplicitMapModifiersLoc[DefaultmapKindNum];
6073 // Get the original location of present modifier from Defaultmap clause.
6074 SourceLocation PresentModifierLocs[DefaultmapKindNum];
6075 for (OMPClause *C : Clauses) {
6076 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6077 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6078 PresentModifierLocs[DMC->getDefaultmapKind()] =
6079 DMC->getDefaultmapModifierLoc();
6080 }
6081 for (unsigned VC = 0; VC < DefaultmapKindNum; ++VC) {
6082 auto K = static_cast<OpenMPDefaultmapClauseKind>(VC);
6083 for (unsigned I = 0; I < OMPC_MAP_delete; ++I) {
6084 ArrayRef<Expr *> ImplicitMap =
6085 DSAChecker.getImplicitMap(K, static_cast<OpenMPMapClauseKind>(I));
6086 ImplicitMaps[VC][I].append(ImplicitMap.begin(), ImplicitMap.end());
6087 }
6088 ArrayRef<OpenMPMapModifierKind> ImplicitModifier =
6089 DSAChecker.getImplicitMapModifier(K);
6090 ImplicitMapModifiers[VC].append(ImplicitModifier.begin(),
6091 ImplicitModifier.end());
6092 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[VC]),
6093 ImplicitModifier.size(), PresentModifierLocs[VC]);
6094 }
6095 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6096 for (OMPClause *C : Clauses) {
6097 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6098 for (Expr *E : IRC->taskgroup_descriptors())
6099 if (E)
6100 ImplicitFirstprivates.emplace_back(E);
6101 }
6102 // OpenMP 5.0, 2.10.1 task Construct
6103 // [detach clause]... The event-handle will be considered as if it was
6104 // specified on a firstprivate clause.
6105 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6106 ImplicitFirstprivates.push_back(DC->getEventHandler());
6107 }
6108 if (!ImplicitFirstprivates.empty()) {
6110 ImplicitFirstprivates, SourceLocation(), SourceLocation(),
6111 SourceLocation())) {
6112 ClausesWithImplicit.push_back(Implicit);
6113 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6114 ImplicitFirstprivates.size();
6115 } else {
6116 ErrorFound = true;
6117 }
6118 }
6119 if (!ImplicitPrivates.empty()) {
6120 if (OMPClause *Implicit =
6121 ActOnOpenMPPrivateClause(ImplicitPrivates, SourceLocation(),
6123 ClausesWithImplicit.push_back(Implicit);
6124 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6125 ImplicitPrivates.size();
6126 } else {
6127 ErrorFound = true;
6128 }
6129 }
6130 // OpenMP 5.0 [2.19.7]
6131 // If a list item appears in a reduction, lastprivate or linear
6132 // clause on a combined target construct then it is treated as
6133 // if it also appears in a map clause with a map-type of tofrom
6134 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6136 SmallVector<Expr *, 4> ImplicitExprs;
6137 for (OMPClause *C : Clauses) {
6138 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6139 for (Expr *E : RC->varlist())
6140 if (!isa<DeclRefExpr>(E->IgnoreParenImpCasts()))
6141 ImplicitExprs.emplace_back(E);
6142 }
6143 if (!ImplicitExprs.empty()) {
6144 ArrayRef<Expr *> Exprs = ImplicitExprs;
6145 CXXScopeSpec MapperIdScopeSpec;
6146 DeclarationNameInfo MapperId;
6149 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6150 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6151 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6152 ClausesWithImplicit.emplace_back(Implicit);
6153 }
6154 }
6155 for (unsigned I = 0, E = DefaultmapKindNum; I < E; ++I) {
6156 int ClauseKindCnt = -1;
6157 for (ArrayRef<Expr *> ImplicitMap : ImplicitMaps[I]) {
6158 ++ClauseKindCnt;
6159 if (ImplicitMap.empty())
6160 continue;
6161 CXXScopeSpec MapperIdScopeSpec;
6162 DeclarationNameInfo MapperId;
6163 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6165 nullptr, ImplicitMapModifiers[I], ImplicitMapModifiersLoc[I],
6166 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6167 SourceLocation(), SourceLocation(), ImplicitMap,
6168 OMPVarListLocTy())) {
6169 ClausesWithImplicit.emplace_back(Implicit);
6170 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6171 ImplicitMap.size();
6172 } else {
6173 ErrorFound = true;
6174 }
6175 }
6176 }
6177 // Build expressions for implicit maps of data members with 'default'
6178 // mappers.
6179 if (getLangOpts().OpenMP >= 50)
6181 ClausesWithImplicit);
6182 }
6183
6184 switch (Kind) {
6185 case OMPD_parallel:
6186 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6187 EndLoc);
6188 break;
6189 case OMPD_simd:
6190 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6191 VarsWithInheritedDSA);
6192 break;
6193 case OMPD_tile:
6194 Res =
6195 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6196 break;
6197 case OMPD_unroll:
6198 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6199 EndLoc);
6200 break;
6201 case OMPD_reverse:
6202 assert(ClausesWithImplicit.empty() &&
6203 "reverse directive does not support any clauses");
6204 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6205 break;
6206 case OMPD_interchange:
6207 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6208 EndLoc);
6209 break;
6210 case OMPD_for:
6211 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6212 VarsWithInheritedDSA);
6213 break;
6214 case OMPD_for_simd:
6215 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6216 EndLoc, VarsWithInheritedDSA);
6217 break;
6218 case OMPD_sections:
6219 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6220 EndLoc);
6221 break;
6222 case OMPD_section:
6223 assert(ClausesWithImplicit.empty() &&
6224 "No clauses are allowed for 'omp section' directive");
6225 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6226 break;
6227 case OMPD_single:
6228 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6229 EndLoc);
6230 break;
6231 case OMPD_master:
6232 assert(ClausesWithImplicit.empty() &&
6233 "No clauses are allowed for 'omp master' directive");
6234 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6235 break;
6236 case OMPD_masked:
6237 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6238 EndLoc);
6239 break;
6240 case OMPD_critical:
6241 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6242 StartLoc, EndLoc);
6243 break;
6244 case OMPD_parallel_for:
6245 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6246 EndLoc, VarsWithInheritedDSA);
6247 break;
6248 case OMPD_parallel_for_simd:
6250 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6251 break;
6252 case OMPD_scope:
6253 Res =
6254 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6255 break;
6256 case OMPD_parallel_master:
6257 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6258 StartLoc, EndLoc);
6259 break;
6260 case OMPD_parallel_masked:
6261 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6262 StartLoc, EndLoc);
6263 break;
6264 case OMPD_parallel_sections:
6265 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6266 StartLoc, EndLoc);
6267 break;
6268 case OMPD_task:
6269 Res =
6270 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6271 break;
6272 case OMPD_taskyield:
6273 assert(ClausesWithImplicit.empty() &&
6274 "No clauses are allowed for 'omp taskyield' directive");
6275 assert(AStmt == nullptr &&
6276 "No associated statement allowed for 'omp taskyield' directive");
6277 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6278 break;
6279 case OMPD_error:
6280 assert(AStmt == nullptr &&
6281 "No associated statement allowed for 'omp error' directive");
6282 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6283 break;
6284 case OMPD_barrier:
6285 assert(ClausesWithImplicit.empty() &&
6286 "No clauses are allowed for 'omp barrier' directive");
6287 assert(AStmt == nullptr &&
6288 "No associated statement allowed for 'omp barrier' directive");
6289 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6290 break;
6291 case OMPD_taskwait:
6292 assert(AStmt == nullptr &&
6293 "No associated statement allowed for 'omp taskwait' directive");
6294 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6295 break;
6296 case OMPD_taskgroup:
6297 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6298 EndLoc);
6299 break;
6300 case OMPD_flush:
6301 assert(AStmt == nullptr &&
6302 "No associated statement allowed for 'omp flush' directive");
6303 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6304 break;
6305 case OMPD_depobj:
6306 assert(AStmt == nullptr &&
6307 "No associated statement allowed for 'omp depobj' directive");
6308 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6309 break;
6310 case OMPD_scan:
6311 assert(AStmt == nullptr &&
6312 "No associated statement allowed for 'omp scan' directive");
6313 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6314 break;
6315 case OMPD_ordered:
6316 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6317 EndLoc);
6318 break;
6319 case OMPD_atomic:
6320 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6321 EndLoc);
6322 break;
6323 case OMPD_teams:
6324 Res =
6325 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6326 break;
6327 case OMPD_target:
6328 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6329 EndLoc);
6330 break;
6331 case OMPD_target_parallel:
6332 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6333 StartLoc, EndLoc);
6334 break;
6335 case OMPD_target_parallel_for:
6337 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6338 break;
6339 case OMPD_cancellation_point:
6340 assert(ClausesWithImplicit.empty() &&
6341 "No clauses are allowed for 'omp cancellation point' directive");
6342 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6343 "cancellation point' directive");
6344 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6345 break;
6346 case OMPD_cancel:
6347 assert(AStmt == nullptr &&
6348 "No associated statement allowed for 'omp cancel' directive");
6349 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6350 CancelRegion);
6351 break;
6352 case OMPD_target_data:
6353 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6354 EndLoc);
6355 break;
6356 case OMPD_target_enter_data:
6357 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6358 EndLoc, AStmt);
6359 break;
6360 case OMPD_target_exit_data:
6361 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6362 EndLoc, AStmt);
6363 break;
6364 case OMPD_taskloop:
6365 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6366 EndLoc, VarsWithInheritedDSA);
6367 break;
6368 case OMPD_taskloop_simd:
6369 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6370 EndLoc, VarsWithInheritedDSA);
6371 break;
6372 case OMPD_master_taskloop:
6374 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6375 break;
6376 case OMPD_masked_taskloop:
6378 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6379 break;
6380 case OMPD_master_taskloop_simd:
6382 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6383 break;
6384 case OMPD_masked_taskloop_simd:
6386 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6387 break;
6388 case OMPD_parallel_master_taskloop:
6390 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6391 break;
6392 case OMPD_parallel_masked_taskloop:
6394 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6395 break;
6396 case OMPD_parallel_master_taskloop_simd:
6398 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6399 break;
6400 case OMPD_parallel_masked_taskloop_simd:
6402 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6403 break;
6404 case OMPD_distribute:
6405 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6406 EndLoc, VarsWithInheritedDSA);
6407 break;
6408 case OMPD_target_update:
6409 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6410 EndLoc, AStmt);
6411 break;
6412 case OMPD_distribute_parallel_for:
6414 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6415 break;
6416 case OMPD_distribute_parallel_for_simd:
6418 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6419 break;
6420 case OMPD_distribute_simd:
6422 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6423 break;
6424 case OMPD_target_parallel_for_simd:
6426 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6427 break;
6428 case OMPD_target_simd:
6429 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6430 EndLoc, VarsWithInheritedDSA);
6431 break;
6432 case OMPD_teams_distribute:
6434 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6435 break;
6436 case OMPD_teams_distribute_simd:
6438 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6439 break;
6440 case OMPD_teams_distribute_parallel_for_simd:
6442 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6443 break;
6444 case OMPD_teams_distribute_parallel_for:
6446 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6447 break;
6448 case OMPD_target_teams:
6449 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6450 EndLoc);
6451 break;
6452 case OMPD_target_teams_distribute:
6454 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6455 break;
6456 case OMPD_target_teams_distribute_parallel_for:
6458 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6459 break;
6460 case OMPD_target_teams_distribute_parallel_for_simd:
6462 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6463 break;
6464 case OMPD_target_teams_distribute_simd:
6466 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6467 break;
6468 case OMPD_interop:
6469 assert(AStmt == nullptr &&
6470 "No associated statement allowed for 'omp interop' directive");
6471 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6472 break;
6473 case OMPD_dispatch:
6474 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6475 EndLoc);
6476 break;
6477 case OMPD_loop:
6478 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6479 EndLoc, VarsWithInheritedDSA);
6480 break;
6481 case OMPD_teams_loop:
6483 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6484 break;
6485 case OMPD_target_teams_loop:
6487 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6488 break;
6489 case OMPD_parallel_loop:
6491 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6492 break;
6493 case OMPD_target_parallel_loop:
6495 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6496 break;
6497 case OMPD_declare_target:
6498 case OMPD_end_declare_target:
6499 case OMPD_threadprivate:
6500 case OMPD_allocate:
6501 case OMPD_declare_reduction:
6502 case OMPD_declare_mapper:
6503 case OMPD_declare_simd:
6504 case OMPD_requires:
6505 case OMPD_declare_variant:
6506 case OMPD_begin_declare_variant:
6507 case OMPD_end_declare_variant:
6508 llvm_unreachable("OpenMP Directive is not allowed");
6509 case OMPD_unknown:
6510 default:
6511 llvm_unreachable("Unknown OpenMP directive");
6512 }
6513
6514 ErrorFound = Res.isInvalid() || ErrorFound;
6515
6516 // Check variables in the clauses if default(none) or
6517 // default(firstprivate) was specified.
6518 if (DSAStack->getDefaultDSA() == DSA_none ||
6519 DSAStack->getDefaultDSA() == DSA_private ||
6520 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6521 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6522 for (OMPClause *C : Clauses) {
6523 switch (C->getClauseKind()) {
6524 case OMPC_num_threads:
6525 case OMPC_dist_schedule:
6526 // Do not analyze if no parent teams directive.
6527 if (isOpenMPTeamsDirective(Kind))
6528 break;
6529 continue;
6530 case OMPC_if:
6531 if (isOpenMPTeamsDirective(Kind) &&
6532 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6533 break;
6534 if (isOpenMPParallelDirective(Kind) &&
6536 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6537 break;
6538 continue;
6539 case OMPC_schedule:
6540 case OMPC_detach:
6541 break;
6542 case OMPC_grainsize:
6543 case OMPC_num_tasks:
6544 case OMPC_final:
6545 case OMPC_priority:
6546 case OMPC_novariants:
6547 case OMPC_nocontext:
6548 // Do not analyze if no parent parallel directive.
6549 if (isOpenMPParallelDirective(Kind))
6550 break;
6551 continue;
6552 case OMPC_ordered:
6553 case OMPC_device:
6554 case OMPC_num_teams:
6555 case OMPC_thread_limit:
6556 case OMPC_hint:
6557 case OMPC_collapse:
6558 case OMPC_safelen:
6559 case OMPC_simdlen:
6560 case OMPC_sizes:
6561 case OMPC_default:
6562 case OMPC_proc_bind:
6563 case OMPC_private:
6564 case OMPC_firstprivate:
6565 case OMPC_lastprivate:
6566 case OMPC_shared:
6567 case OMPC_reduction:
6568 case OMPC_task_reduction:
6569 case OMPC_in_reduction:
6570 case OMPC_linear:
6571 case OMPC_aligned:
6572 case OMPC_copyin:
6573 case OMPC_copyprivate:
6574 case OMPC_nowait:
6575 case OMPC_untied:
6576 case OMPC_mergeable:
6577 case OMPC_allocate:
6578 case OMPC_read:
6579 case OMPC_write:
6580 case OMPC_update:
6581 case OMPC_capture:
6582 case OMPC_compare:
6583 case OMPC_seq_cst:
6584 case OMPC_acq_rel:
6585 case OMPC_acquire:
6586 case OMPC_release:
6587 case OMPC_relaxed:
6588 case OMPC_depend:
6589 case OMPC_threads:
6590 case OMPC_simd:
6591 case OMPC_map:
6592 case OMPC_nogroup:
6593 case OMPC_defaultmap:
6594 case OMPC_to:
6595 case OMPC_from:
6596 case OMPC_use_device_ptr:
6597 case OMPC_use_device_addr:
6598 case OMPC_is_device_ptr:
6599 case OMPC_has_device_addr:
6600 case OMPC_nontemporal:
6601 case OMPC_order:
6602 case OMPC_destroy:
6603 case OMPC_inclusive:
6604 case OMPC_exclusive:
6605 case OMPC_uses_allocators:
6606 case OMPC_affinity:
6607 case OMPC_bind:
6608 case OMPC_filter:
6609 continue;
6610 case OMPC_allocator:
6611 case OMPC_flush:
6612 case OMPC_depobj:
6613 case OMPC_threadprivate:
6614 case OMPC_uniform:
6615 case OMPC_unknown:
6616 case OMPC_unified_address:
6617 case OMPC_unified_shared_memory:
6618 case OMPC_reverse_offload:
6619 case OMPC_dynamic_allocators:
6620 case OMPC_atomic_default_mem_order:
6621 case OMPC_device_type:
6622 case OMPC_match:
6623 case OMPC_when:
6624 case OMPC_at:
6625 case OMPC_severity:
6626 case OMPC_message:
6627 default:
6628 llvm_unreachable("Unexpected clause");
6629 }
6630 for (Stmt *CC : C->children()) {
6631 if (CC)
6632 DSAChecker.Visit(CC);
6633 }
6634 }
6635 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6636 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6637 }
6638 for (const auto &P : VarsWithInheritedDSA) {
6639 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6640 continue;
6641 ErrorFound = true;
6642 if (DSAStack->getDefaultDSA() == DSA_none ||
6643 DSAStack->getDefaultDSA() == DSA_private ||
6644 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6645 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6646 << P.first << P.second->getSourceRange();
6647 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6648 } else if (getLangOpts().OpenMP >= 50) {
6649 Diag(P.second->getExprLoc(),
6650 diag::err_omp_defaultmap_no_attr_for_variable)
6651 << P.first << P.second->getSourceRange();
6652 Diag(DSAStack->getDefaultDSALocation(),
6653 diag::note_omp_defaultmap_attr_none);
6654 }
6655 }
6656
6657 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6658 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6659 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6660 AllowedNameModifiers.push_back(D);
6661 }
6662 if (!AllowedNameModifiers.empty())
6663 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6664 ErrorFound;
6665
6666 if (ErrorFound)
6667 return StmtError();
6668
6671 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6672 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6673 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6674 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6675 // Register target to DSA Stack.
6676 DSAStack->addTargetDirLocation(StartLoc);
6677 }
6678
6679 return Res;
6680}
6681
6683 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6684 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6685 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6686 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6687 assert(Aligneds.size() == Alignments.size());
6688 assert(Linears.size() == LinModifiers.size());
6689 assert(Linears.size() == Steps.size());
6690 if (!DG || DG.get().isNull())
6691 return DeclGroupPtrTy();
6692
6693 const int SimdId = 0;
6694 if (!DG.get().isSingleDecl()) {
6695 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6696 << SimdId;
6697 return DG;
6698 }
6699 Decl *ADecl = DG.get().getSingleDecl();
6700 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6701 ADecl = FTD->getTemplatedDecl();
6702
6703 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6704 if (!FD) {
6705 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6706 return DeclGroupPtrTy();
6707 }
6708
6709 // OpenMP [2.8.2, declare simd construct, Description]
6710 // The parameter of the simdlen clause must be a constant positive integer
6711 // expression.
6712 ExprResult SL;
6713 if (Simdlen)
6714 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6715 // OpenMP [2.8.2, declare simd construct, Description]
6716 // The special this pointer can be used as if was one of the arguments to the
6717 // function in any of the linear, aligned, or uniform clauses.
6718 // The uniform clause declares one or more arguments to have an invariant
6719 // value for all concurrent invocations of the function in the execution of a
6720 // single SIMD loop.
6721 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6722 const Expr *UniformedLinearThis = nullptr;
6723 for (const Expr *E : Uniforms) {
6724 E = E->IgnoreParenImpCasts();
6725 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6726 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6727 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6728 FD->getParamDecl(PVD->getFunctionScopeIndex())
6729 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6730 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6731 continue;
6732 }
6733 if (isa<CXXThisExpr>(E)) {
6734 UniformedLinearThis = E;
6735 continue;
6736 }
6737 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6738 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6739 }
6740 // OpenMP [2.8.2, declare simd construct, Description]
6741 // The aligned clause declares that the object to which each list item points
6742 // is aligned to the number of bytes expressed in the optional parameter of
6743 // the aligned clause.
6744 // The special this pointer can be used as if was one of the arguments to the
6745 // function in any of the linear, aligned, or uniform clauses.
6746 // The type of list items appearing in the aligned clause must be array,
6747 // pointer, reference to array, or reference to pointer.
6748 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6749 const Expr *AlignedThis = nullptr;
6750 for (const Expr *E : Aligneds) {
6751 E = E->IgnoreParenImpCasts();
6752 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6753 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6754 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6755 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6756 FD->getParamDecl(PVD->getFunctionScopeIndex())
6757 ->getCanonicalDecl() == CanonPVD) {
6758 // OpenMP [2.8.1, simd construct, Restrictions]
6759 // A list-item cannot appear in more than one aligned clause.
6760 if (AlignedArgs.count(CanonPVD) > 0) {
6761 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6762 << 1 << getOpenMPClauseName(OMPC_aligned)
6763 << E->getSourceRange();
6764 Diag(AlignedArgs[CanonPVD]->getExprLoc(),
6765 diag::note_omp_explicit_dsa)
6766 << getOpenMPClauseName(OMPC_aligned);
6767 continue;
6768 }
6769 AlignedArgs[CanonPVD] = E;
6770 QualType QTy = PVD->getType()
6771 .getNonReferenceType()
6772 .getUnqualifiedType()
6773 .getCanonicalType();
6774 const Type *Ty = QTy.getTypePtrOrNull();
6775 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
6776 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
6777 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
6778 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
6779 }
6780 continue;
6781 }
6782 }
6783 if (isa<CXXThisExpr>(E)) {
6784 if (AlignedThis) {
6785 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6786 << 2 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange();
6787 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
6788 << getOpenMPClauseName(OMPC_aligned);
6789 }
6790 AlignedThis = E;
6791 continue;
6792 }
6793 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6794 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6795 }
6796 // The optional parameter of the aligned clause, alignment, must be a constant
6797 // positive integer expression. If no optional parameter is specified,
6798 // implementation-defined default alignments for SIMD instructions on the
6799 // target platforms are assumed.
6801 for (Expr *E : Alignments) {
6802 ExprResult Align;
6803 if (E)
6804 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
6805 NewAligns.push_back(Align.get());
6806 }
6807 // OpenMP [2.8.2, declare simd construct, Description]
6808 // The linear clause declares one or more list items to be private to a SIMD
6809 // lane and to have a linear relationship with respect to the iteration space
6810 // of a loop.
6811 // The special this pointer can be used as if was one of the arguments to the
6812 // function in any of the linear, aligned, or uniform clauses.
6813 // When a linear-step expression is specified in a linear clause it must be
6814 // either a constant integer expression or an integer-typed parameter that is
6815 // specified in a uniform clause on the directive.
6816 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
6817 const bool IsUniformedThis = UniformedLinearThis != nullptr;
6818 auto MI = LinModifiers.begin();
6819 for (const Expr *E : Linears) {
6820 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
6821 ++MI;
6822 E = E->IgnoreParenImpCasts();
6823 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6824 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6825 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6826 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6827 FD->getParamDecl(PVD->getFunctionScopeIndex())
6828 ->getCanonicalDecl() == CanonPVD) {
6829 // OpenMP [2.15.3.7, linear Clause, Restrictions]
6830 // A list-item cannot appear in more than one linear clause.
6831 if (LinearArgs.count(CanonPVD) > 0) {
6832 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6833 << getOpenMPClauseName(OMPC_linear)
6834 << getOpenMPClauseName(OMPC_linear) << E->getSourceRange();
6835 Diag(LinearArgs[CanonPVD]->getExprLoc(),
6836 diag::note_omp_explicit_dsa)
6837 << getOpenMPClauseName(OMPC_linear);
6838 continue;
6839 }
6840 // Each argument can appear in at most one uniform or linear clause.
6841 if (UniformedArgs.count(CanonPVD) > 0) {
6842 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6843 << getOpenMPClauseName(OMPC_linear)
6844 << getOpenMPClauseName(OMPC_uniform) << E->getSourceRange();
6845 Diag(UniformedArgs[CanonPVD]->getExprLoc(),
6846 diag::note_omp_explicit_dsa)
6847 << getOpenMPClauseName(OMPC_uniform);
6848 continue;
6849 }
6850 LinearArgs[CanonPVD] = E;
6851 if (E->isValueDependent() || E->isTypeDependent() ||
6854 continue;
6855 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
6856 PVD->getOriginalType(),
6857 /*IsDeclareSimd=*/true);
6858 continue;
6859 }
6860 }
6861 if (isa<CXXThisExpr>(E)) {
6862 if (UniformedLinearThis) {
6863 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
6864 << getOpenMPClauseName(OMPC_linear)
6865 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform : OMPC_linear)
6866 << E->getSourceRange();
6867 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
6868 << getOpenMPClauseName(IsUniformedThis ? OMPC_uniform
6869 : OMPC_linear);
6870 continue;
6871 }
6872 UniformedLinearThis = E;
6873 if (E->isValueDependent() || E->isTypeDependent() ||
6875 continue;
6876 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
6877 E->getType(), /*IsDeclareSimd=*/true);
6878 continue;
6879 }
6880 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6881 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6882 }
6883 Expr *Step = nullptr;
6884 Expr *NewStep = nullptr;
6885 SmallVector<Expr *, 4> NewSteps;
6886 for (Expr *E : Steps) {
6887 // Skip the same step expression, it was checked already.
6888 if (Step == E || !E) {
6889 NewSteps.push_back(E ? NewStep : nullptr);
6890 continue;
6891 }
6892 Step = E;
6893 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
6894 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6895 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6896 if (UniformedArgs.count(CanonPVD) == 0) {
6897 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
6898 << Step->getSourceRange();
6899 } else if (E->isValueDependent() || E->isTypeDependent() ||
6902 CanonPVD->getType()->hasIntegerRepresentation()) {
6903 NewSteps.push_back(Step);
6904 } else {
6905 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
6906 << Step->getSourceRange();
6907 }
6908 continue;
6909 }
6910 NewStep = Step;
6911 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
6912 !Step->isInstantiationDependent() &&
6914 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
6915 .get();
6916 if (NewStep)
6917 NewStep = SemaRef
6919 NewStep, /*FIXME*/ Sema::AllowFold)
6920 .get();
6921 }
6922 NewSteps.push_back(NewStep);
6923 }
6924 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
6925 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
6926 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
6927 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
6928 const_cast<Expr **>(Linears.data()), Linears.size(),
6929 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
6930 NewSteps.data(), NewSteps.size(), SR);
6931 ADecl->addAttr(NewAttr);
6932 return DG;
6933}
6934
6936 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6937 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
6938 SourceLocation EndLoc) {
6939 assert(isOpenMPInformationalDirective(Kind) &&
6940 "Unexpected directive category");
6941
6942 StmtResult Res = StmtError();
6943
6944 switch (Kind) {
6945 case OMPD_assume:
6946 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
6947 break;
6948 default:
6949 llvm_unreachable("Unknown OpenMP directive");
6950 }
6951
6952 return Res;
6953}
6954
6955static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
6956 QualType NewType) {
6957 assert(NewType->isFunctionProtoType() &&
6958 "Expected function type with prototype.");
6959 assert(FD->getType()->isFunctionNoProtoType() &&
6960 "Expected function with type with no prototype.");
6961 assert(FDWithProto->getType()->isFunctionProtoType() &&
6962 "Expected function with prototype.");
6963 // Synthesize parameters with the same types.
6964 FD->setType(NewType);
6966 for (const ParmVarDecl *P : FDWithProto->parameters()) {
6967 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
6968 SourceLocation(), nullptr, P->getType(),
6969 /*TInfo=*/nullptr, SC_None, nullptr);
6970 Param->setScopeInfo(0, Params.size());
6971 Param->setImplicit();
6972 Params.push_back(Param);
6973 }
6974
6975 FD->setParams(Params);
6976}
6977
6979 if (D->isInvalidDecl())
6980 return;
6981 FunctionDecl *FD = nullptr;
6982 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
6983 FD = UTemplDecl->getTemplatedDecl();
6984 else
6985 FD = cast<FunctionDecl>(D);
6986 assert(FD && "Expected a function declaration!");
6987
6988 // If we are instantiating templates we do *not* apply scoped assumptions but
6989 // only global ones. We apply scoped assumption to the template definition
6990 // though.
6992 for (OMPAssumeAttr *AA : OMPAssumeScoped)
6993 FD->addAttr(AA);
6994 }
6995 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
6996 FD->addAttr(AA);
6997}
6998
6999SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7000 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7001
7003 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7005 if (!D.getIdentifier())
7006 return;
7007
7008 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7009
7010 // Template specialization is an extension, check if we do it.
7011 bool IsTemplated = !TemplateParamLists.empty();
7012 if (IsTemplated &&
7013 !DVScope.TI->isExtensionActive(
7014 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7015 return;
7016
7017 const IdentifierInfo *BaseII = D.getIdentifier();
7018 LookupResult Lookup(SemaRef, DeclarationName(BaseII), D.getIdentifierLoc(),
7020 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7021 /*ObjectType=*/QualType());
7022
7024 QualType FType = TInfo->getType();
7025
7026 bool IsConstexpr =
7027 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Constexpr;
7028 bool IsConsteval =
7029 D.getDeclSpec().getConstexprSpecifier() == ConstexprSpecKind::Consteval;
7030
7031 for (auto *Candidate : Lookup) {
7032 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7033 FunctionDecl *UDecl = nullptr;
7034 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7035 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7036 if (FTD->getTemplateParameters()->size() == TemplateParamLists.size())
7037 UDecl = FTD->getTemplatedDecl();
7038 } else if (!IsTemplated)
7039 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7040 if (!UDecl)
7041 continue;
7042
7043 // Don't specialize constexpr/consteval functions with
7044 // non-constexpr/consteval functions.
7045 if (UDecl->isConstexpr() && !IsConstexpr)
7046 continue;
7047 if (UDecl->isConsteval() && !IsConsteval)
7048 continue;
7049
7050 QualType UDeclTy = UDecl->getType();
7051 if (!UDeclTy->isDependentType()) {
7053 FType, UDeclTy, /*OfBlockPointer=*/false,
7054 /*Unqualified=*/false, /*AllowCXX=*/true);
7055 if (NewType.isNull())
7056 continue;
7057 }
7058
7059 // Found a base!
7060 Bases.push_back(UDecl);
7061 }
7062
7063 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7064 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7065 // If no base was found we create a declaration that we use as base.
7066 if (Bases.empty() && UseImplicitBase) {
7067 D.setFunctionDefinitionKind(FunctionDefinitionKind::Declaration);
7068 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7069 BaseD->setImplicit(true);
7070 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7071 Bases.push_back(BaseTemplD->getTemplatedDecl());
7072 else
7073 Bases.push_back(cast<FunctionDecl>(BaseD));
7074 }
7075
7076 std::string MangledName;
7077 MangledName += D.getIdentifier()->getName();
7078 MangledName += getOpenMPVariantManglingSeparatorStr();
7079 MangledName += DVScope.NameSuffix;
7080 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7081
7082 VariantII.setMangledOpenMPVariantName(true);
7083 D.SetIdentifier(&VariantII, D.getBeginLoc());
7084}
7085
7088 // Do not mark function as is used to prevent its emission if this is the
7089 // only place where it is used.
7092
7093 FunctionDecl *FD = nullptr;
7094 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7095 FD = UTemplDecl->getTemplatedDecl();
7096 else
7097 FD = cast<FunctionDecl>(D);
7098 auto *VariantFuncRef = DeclRefExpr::Create(
7100 /*RefersToEnclosingVariableOrCapture=*/false,
7101 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7102
7103 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7104 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7105 getASTContext(), VariantFuncRef, DVScope.TI,
7106 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7107 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7108 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7109 for (FunctionDecl *BaseFD : Bases)
7110 BaseFD->addAttr(OMPDeclareVariantA);
7111}
7112
7114 SourceLocation LParenLoc,
7115 MultiExprArg ArgExprs,
7116 SourceLocation RParenLoc,
7117 Expr *ExecConfig) {
7118 // The common case is a regular call we do not want to specialize at all. Try
7119 // to make that case fast by bailing early.
7120 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7121 if (!CE)
7122 return Call;
7123
7124 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7125 if (!CalleeFnDecl)
7126 return Call;
7127
7128 if (getLangOpts().OpenMP >= 51 && CalleeFnDecl->getIdentifier() &&
7129 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7130 // checking for any calls inside an Order region
7132 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7133 }
7134
7135 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7136 return Call;
7137
7138 ASTContext &Context = getASTContext();
7139 std::function<void(StringRef)> DiagUnknownTrait = [this,
7140 CE](StringRef ISATrait) {
7141 // TODO Track the selector locations in a way that is accessible here to
7142 // improve the diagnostic location.
7143 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7144 << ISATrait;
7145 };
7146 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7148 DSAStack->getConstructTraits());
7149
7150 QualType CalleeFnType = CalleeFnDecl->getType();
7151
7154 while (CalleeFnDecl) {
7155 for (OMPDeclareVariantAttr *A :
7156 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7157 Expr *VariantRef = A->getVariantFuncRef();
7158
7159 VariantMatchInfo VMI;
7160 OMPTraitInfo &TI = A->getTraitInfo();
7161 TI.getAsVariantMatchInfo(Context, VMI);
7162 if (!isVariantApplicableInContext(VMI, OMPCtx,
7163 /*DeviceSetOnly=*/false))
7164 continue;
7165
7166 VMIs.push_back(VMI);
7167 Exprs.push_back(VariantRef);
7168 }
7169
7170 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7171 }
7172
7173 ExprResult NewCall;
7174 do {
7175 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7176 if (BestIdx < 0)
7177 return Call;
7178 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7179 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7180
7181 {
7182 // Try to build a (member) call expression for the current best applicable
7183 // variant expression. We allow this to fail in which case we continue
7184 // with the next best variant expression. The fail case is part of the
7185 // implementation defined behavior in the OpenMP standard when it talks
7186 // about what differences in the function prototypes: "Any differences
7187 // that the specific OpenMP context requires in the prototype of the
7188 // variant from the base function prototype are implementation defined."
7189 // This wording is there to allow the specialized variant to have a
7190 // different type than the base function. This is intended and OK but if
7191 // we cannot create a call the difference is not in the "implementation
7192 // defined range" we allow.
7194
7195 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7196 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7197 BestExpr = MemberExpr::CreateImplicit(
7198 Context, MemberCall->getImplicitObjectArgument(),
7199 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7200 MemberCall->getValueKind(), MemberCall->getObjectKind());
7201 }
7202 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7203 RParenLoc, ExecConfig);
7204 if (NewCall.isUsable()) {
7205 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7206 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7208 CalleeFnType, NewCalleeFnDecl->getType(),
7209 /*OfBlockPointer=*/false,
7210 /*Unqualified=*/false, /*AllowCXX=*/true);
7211 if (!NewType.isNull())
7212 break;
7213 // Don't use the call if the function type was not compatible.
7214 NewCall = nullptr;
7215 }
7216 }
7217 }
7218
7219 VMIs.erase(VMIs.begin() + BestIdx);
7220 Exprs.erase(Exprs.begin() + BestIdx);
7221 } while (!VMIs.empty());
7222
7223 if (!NewCall.isUsable())
7224 return Call;
7225 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7226}
7227
7228std::optional<std::pair<FunctionDecl *, Expr *>>
7230 Expr *VariantRef,
7231 OMPTraitInfo &TI,
7232 unsigned NumAppendArgs,
7233 SourceRange SR) {
7234 ASTContext &Context = getASTContext();
7235 if (!DG || DG.get().isNull())
7236 return std::nullopt;
7237
7238 const int VariantId = 1;
7239 // Must be applied only to single decl.
7240 if (!DG.get().isSingleDecl()) {
7241 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7242 << VariantId << SR;
7243 return std::nullopt;
7244 }
7245 Decl *ADecl = DG.get().getSingleDecl();
7246 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7247 ADecl = FTD->getTemplatedDecl();
7248
7249 // Decl must be a function.
7250 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7251 if (!FD) {
7252 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7253 << VariantId << SR;
7254 return std::nullopt;
7255 }
7256
7257 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7258 // The 'target' attribute needs to be separately checked because it does
7259 // not always signify a multiversion function declaration.
7260 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7261 };
7262 // OpenMP is not compatible with multiversion function attributes.
7263 if (HasMultiVersionAttributes(FD)) {
7264 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7265 << SR;
7266 return std::nullopt;
7267 }
7268
7269 // Allow #pragma omp declare variant only if the function is not used.
7270 if (FD->isUsed(false))
7271 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7272 << FD->getLocation();
7273
7274 // Check if the function was emitted already.
7275 const FunctionDecl *Definition;
7276 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7277 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7278 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7279 << FD->getLocation();
7280
7281 // The VariantRef must point to function.
7282 if (!VariantRef) {
7283 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7284 return std::nullopt;
7285 }
7286
7287 auto ShouldDelayChecks = [](Expr *&E, bool) {
7288 return E && (E->isTypeDependent() || E->isValueDependent() ||
7291 };
7292 // Do not check templates, wait until instantiation.
7293 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7294 TI.anyScoreOrCondition(ShouldDelayChecks))
7295 return std::make_pair(FD, VariantRef);
7296
7297 // Deal with non-constant score and user condition expressions.
7298 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7299 bool IsScore) -> bool {
7301 return false;
7302
7303 if (IsScore) {
7304 // We warn on non-constant scores and pretend they were not present.
7305 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7306 << E;
7307 E = nullptr;
7308 } else {
7309 // We could replace a non-constant user condition with "false" but we
7310 // will soon need to handle these anyway for the dynamic version of
7311 // OpenMP context selectors.
7312 Diag(E->getExprLoc(),
7313 diag::err_omp_declare_variant_user_condition_not_constant)
7314 << E;
7315 }
7316 return true;
7317 };
7318 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7319 return std::nullopt;
7320
7321 QualType AdjustedFnType = FD->getType();
7322 if (NumAppendArgs) {
7323 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7324 if (!PTy) {
7325 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7326 << SR;
7327 return std::nullopt;
7328 }
7329 // Adjust the function type to account for an extra omp_interop_t for each
7330 // specified in the append_args clause.
7331 const TypeDecl *TD = nullptr;
7332 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7335 NamedDecl *ND = Result.getFoundDecl();
7336 TD = dyn_cast_or_null<TypeDecl>(ND);
7337 }
7338 if (!TD) {
7339 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7340 return std::nullopt;
7341 }
7342 QualType InteropType = Context.getTypeDeclType(TD);
7343 if (PTy->isVariadic()) {
7344 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7345 return std::nullopt;
7346 }
7348 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7349 Params.insert(Params.end(), NumAppendArgs, InteropType);
7350 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7351 PTy->getExtProtoInfo());
7352 }
7353
7354 // Convert VariantRef expression to the type of the original function to
7355 // resolve possible conflicts.
7356 ExprResult VariantRefCast = VariantRef;
7357 if (getLangOpts().CPlusPlus) {
7358 QualType FnPtrType;
7359 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7360 if (Method && !Method->isStatic()) {
7361 const Type *ClassType =
7362 Context.getTypeDeclType(Method->getParent()).getTypePtr();
7363 FnPtrType = Context.getMemberPointerType(AdjustedFnType, ClassType);
7364 ExprResult ER;
7365 {
7366 // Build addr_of unary op to correctly handle type checks for member
7367 // functions.
7369 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7370 VariantRef);
7371 }
7372 if (!ER.isUsable()) {
7373 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7374 << VariantId << VariantRef->getSourceRange();
7375 return std::nullopt;
7376 }
7377 VariantRef = ER.get();
7378 } else {
7379 FnPtrType = Context.getPointerType(AdjustedFnType);
7380 }
7381 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7382 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7384 VariantRef, FnPtrType.getUnqualifiedType(),
7385 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7386 /*InOverloadResolution=*/false,
7387 /*CStyle=*/false,
7388 /*AllowObjCWritebackConversion=*/false);
7389 if (ICS.isFailure()) {
7390 Diag(VariantRef->getExprLoc(),
7391 diag::err_omp_declare_variant_incompat_types)
7392 << VariantRef->getType()
7393 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7394 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7395 return std::nullopt;
7396 }
7397 VariantRefCast = SemaRef.PerformImplicitConversion(
7398 VariantRef, FnPtrType.getUnqualifiedType(), Sema::AA_Converting);
7399 if (!VariantRefCast.isUsable())
7400 return std::nullopt;
7401 }
7402 // Drop previously built artificial addr_of unary op for member functions.
7403 if (Method && !Method->isStatic()) {
7404 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7405 if (auto *UO = dyn_cast<UnaryOperator>(
7406 PossibleAddrOfVariantRef->IgnoreImplicit()))
7407 VariantRefCast = UO->getSubExpr();
7408 }
7409 }
7410
7411 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7412 if (!ER.isUsable() ||
7414 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7415 << VariantId << VariantRef->getSourceRange();
7416 return std::nullopt;
7417 }
7418
7419 // The VariantRef must point to function.
7420 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7421 if (!DRE) {
7422 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7423 << VariantId << VariantRef->getSourceRange();
7424 return std::nullopt;
7425 }
7426 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7427 if (!NewFD) {
7428 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7429 << VariantId << VariantRef->getSourceRange();
7430 return std::nullopt;
7431 }
7432
7433 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7434 Diag(VariantRef->getExprLoc(),
7435 diag::err_omp_declare_variant_same_base_function)
7436 << VariantRef->getSourceRange();
7437 return std::nullopt;
7438 }
7439
7440 // Check if function types are compatible in C.
7441 if (!getLangOpts().CPlusPlus) {
7442 QualType NewType =
7443 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7444 if (NewType.isNull()) {
7445 Diag(VariantRef->getExprLoc(),
7446 diag::err_omp_declare_variant_incompat_types)
7447 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7448 << VariantRef->getSourceRange();
7449 return std::nullopt;
7450 }
7451 if (NewType->isFunctionProtoType()) {
7452 if (FD->getType()->isFunctionNoProtoType())
7453 setPrototype(SemaRef, FD, NewFD, NewType);
7454 else if (NewFD->getType()->isFunctionNoProtoType())
7455 setPrototype(SemaRef, NewFD, FD, NewType);
7456 }
7457 }
7458
7459 // Check if variant function is not marked with declare variant directive.
7460 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7461 Diag(VariantRef->getExprLoc(),
7462 diag::warn_omp_declare_variant_marked_as_declare_variant)
7463 << VariantRef->getSourceRange();
7464 SourceRange SR =
7465 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7466 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7467 return std::nullopt;
7468 }
7469
7470 enum DoesntSupport {
7471 VirtFuncs = 1,
7472 Constructors = 3,
7473 Destructors = 4,
7474 DeletedFuncs = 5,
7475 DefaultedFuncs = 6,
7476 ConstexprFuncs = 7,
7477 ConstevalFuncs = 8,
7478 };
7479 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7480 if (CXXFD->isVirtual()) {
7481 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7482 << VirtFuncs;
7483 return std::nullopt;
7484 }
7485
7486 if (isa<CXXConstructorDecl>(FD)) {
7487 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7488 << Constructors;
7489 return std::nullopt;
7490 }
7491
7492 if (isa<CXXDestructorDecl>(FD)) {
7493 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7494 << Destructors;
7495 return std::nullopt;
7496 }
7497 }
7498
7499 if (FD->isDeleted()) {
7500 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7501 << DeletedFuncs;
7502 return std::nullopt;
7503 }
7504
7505 if (FD->isDefaulted()) {
7506 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7507 << DefaultedFuncs;
7508 return std::nullopt;
7509 }
7510
7511 if (FD->isConstexpr()) {
7512 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7513 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7514 return std::nullopt;
7515 }
7516
7517 // Check general compatibility.
7523 VariantRef->getExprLoc(),
7524 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7525 PartialDiagnosticAt(VariantRef->getExprLoc(),
7526 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7527 << FD->getLocation()),
7528 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7529 /*CLinkageMayDiffer=*/true))
7530 return std::nullopt;
7531 return std::make_pair(FD, cast<Expr>(DRE));
7532}
7533
7535 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7536 ArrayRef<Expr *> AdjustArgsNothing,
7537 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7538 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7539 SourceLocation AppendArgsLoc, SourceRange SR) {
7540
7541 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7542 // An adjust_args clause or append_args clause can only be specified if the
7543 // dispatch selector of the construct selector set appears in the match
7544 // clause.
7545
7546 SmallVector<Expr *, 8> AllAdjustArgs;
7547 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7548 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7549
7550 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7551 VariantMatchInfo VMI;
7553 if (!llvm::is_contained(
7554 VMI.ConstructTraits,
7555 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7556 if (!AllAdjustArgs.empty())
7557 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7558 << getOpenMPClauseName(OMPC_adjust_args);
7559 if (!AppendArgs.empty())
7560 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7561 << getOpenMPClauseName(OMPC_append_args);
7562 return;
7563 }
7564 }
7565
7566 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7567 // Each argument can only appear in a single adjust_args clause for each
7568 // declare variant directive.
7570
7571 for (Expr *E : AllAdjustArgs) {
7572 E = E->IgnoreParenImpCasts();
7573 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7574 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7575 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7576 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7577 FD->getParamDecl(PVD->getFunctionScopeIndex())
7578 ->getCanonicalDecl() == CanonPVD) {
7579 // It's a parameter of the function, check duplicates.
7580 if (!AdjustVars.insert(CanonPVD).second) {
7581 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7582 << PVD;
7583 return;
7584 }
7585 continue;
7586 }
7587 }
7588 }
7589 // Anything that is not a function parameter is an error.
7590 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7591 return;
7592 }
7593
7594 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7595 getASTContext(), VariantRef, &TI,
7596 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7597 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7598 AdjustArgsNeedDevicePtr.size(),
7599 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7600 FD->addAttr(NewAttr);
7601}
7602
7603static CapturedStmt *
7605 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7606 assert(CS && "Captured statement expected");
7607 // 1.2.2 OpenMP Language Terminology
7608 // Structured block - An executable statement with a single entry at the
7609 // top and a single exit at the bottom.
7610 // The point of exit cannot be a branch out of the structured block.
7611 // longjmp() and throw() must not violate the entry/exit criteria.
7612 CS->getCapturedDecl()->setNothrow();
7613
7614 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7615 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7616 CS = cast<CapturedStmt>(CS->getCapturedStmt());
7617 // 1.2.2 OpenMP Language Terminology
7618 // Structured block - An executable statement with a single entry at the
7619 // top and a single exit at the bottom.
7620 // The point of exit cannot be a branch out of the structured block.
7621 // longjmp() and throw() must not violate the entry/exit criteria.
7622 CS->getCapturedDecl()->setNothrow();
7623 }
7625 return CS;
7626}
7627
7630 Stmt *AStmt, SourceLocation StartLoc,
7631 SourceLocation EndLoc) {
7632 if (!AStmt)
7633 return StmtError();
7634
7635 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7636
7638 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7639 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7640}
7641
7642namespace {
7643/// Iteration space of a single for loop.
7644struct LoopIterationSpace final {
7645 /// True if the condition operator is the strict compare operator (<, > or
7646 /// !=).
7647 bool IsStrictCompare = false;
7648 /// Condition of the loop.
7649 Expr *PreCond = nullptr;
7650 /// This expression calculates the number of iterations in the loop.
7651 /// It is always possible to calculate it before starting the loop.
7652 Expr *NumIterations = nullptr;
7653 /// The loop counter variable.
7654 Expr *CounterVar = nullptr;
7655 /// Private loop counter variable.
7656 Expr *PrivateCounterVar = nullptr;
7657 /// This is initializer for the initial value of #CounterVar.
7658 Expr *CounterInit = nullptr;
7659 /// This is step for the #CounterVar used to generate its update:
7660 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7661 Expr *CounterStep = nullptr;
7662 /// Should step be subtracted?
7663 bool Subtract = false;
7664 /// Source range of the loop init.
7665 SourceRange InitSrcRange;
7666 /// Source range of the loop condition.
7667 SourceRange CondSrcRange;
7668 /// Source range of the loop increment.
7669 SourceRange IncSrcRange;
7670 /// Minimum value that can have the loop control variable. Used to support
7671 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7672 /// since only such variables can be used in non-loop invariant expressions.
7673 Expr *MinValue = nullptr;
7674 /// Maximum value that can have the loop control variable. Used to support
7675 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7676 /// since only such variables can be used in non-loop invariant expressions.
7677 Expr *MaxValue = nullptr;
7678 /// true, if the lower bound depends on the outer loop control var.
7679 bool IsNonRectangularLB = false;
7680 /// true, if the upper bound depends on the outer loop control var.
7681 bool IsNonRectangularUB = false;
7682 /// Index of the loop this loop depends on and forms non-rectangular loop
7683 /// nest.
7684 unsigned LoopDependentIdx = 0;
7685 /// Final condition for the non-rectangular loop nest support. It is used to
7686 /// check that the number of iterations for this particular counter must be
7687 /// finished.
7688 Expr *FinalCondition = nullptr;
7689};
7690
7691/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7692/// set are referenced. Used for verifying loop nest structure before
7693/// performing a loop collapse operation.
7694class ForSubExprChecker final : public RecursiveASTVisitor<ForSubExprChecker> {
7695 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7696 VarDecl *ForbiddenVar = nullptr;
7697 SourceRange ErrLoc;
7698
7699public:
7700 explicit ForSubExprChecker(
7701 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7702 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {}
7703
7704 // We want to visit implicit code, i.e. synthetic initialisation statements
7705 // created during range-for lowering.
7706 bool shouldVisitImplicitCode() const { return true; }
7707
7708 bool VisitDeclRefExpr(DeclRefExpr *E) {
7709 ValueDecl *VD = E->getDecl();
7710 if (!isa<VarDecl, BindingDecl>(VD))
7711 return true;
7713 if (V->getType()->isReferenceType()) {
7714 VarDecl *VD = V->getDefinition();
7715 if (VD->hasInit()) {
7716 Expr *I = VD->getInit();
7717 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7718 if (!DRE)
7719 return true;
7721 }
7722 }
7723 Decl *Canon = V->getCanonicalDecl();
7724 if (CollapsedLoopVarDecls.contains(Canon)) {
7725 ForbiddenVar = V;
7726 ErrLoc = E->getSourceRange();
7727 return false;
7728 }
7729
7730 return true;
7731 }
7732
7733 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
7734 SourceRange getErrRange() const { return ErrLoc; }
7735};
7736
7737/// Helper class for checking canonical form of the OpenMP loops and
7738/// extracting iteration space of each loop in the loop nest, that will be used
7739/// for IR generation.
7740class OpenMPIterationSpaceChecker {
7741 /// Reference to Sema.
7742 Sema &SemaRef;
7743 /// Does the loop associated directive support non-rectangular loops?
7744 bool SupportsNonRectangular;
7745 /// Data-sharing stack.
7746 DSAStackTy &Stack;
7747 /// A location for diagnostics (when there is no some better location).
7748 SourceLocation DefaultLoc;
7749 /// A location for diagnostics (when increment is not compatible).
7750 SourceLocation ConditionLoc;
7751 /// The set of variables declared within the (to be collapsed) loop nest.
7752 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7753 /// A source location for referring to loop init later.
7754 SourceRange InitSrcRange;
7755 /// A source location for referring to condition later.
7756 SourceRange ConditionSrcRange;
7757 /// A source location for referring to increment later.
7758 SourceRange IncrementSrcRange;
7759 /// Loop variable.
7760 ValueDecl *LCDecl = nullptr;
7761 /// Reference to loop variable.
7762 Expr *LCRef = nullptr;
7763 /// Lower bound (initializer for the var).
7764 Expr *LB = nullptr;
7765 /// Upper bound.
7766 Expr *UB = nullptr;
7767 /// Loop step (increment).
7768 Expr *Step = nullptr;
7769 /// This flag is true when condition is one of:
7770 /// Var < UB
7771 /// Var <= UB
7772 /// UB > Var
7773 /// UB >= Var
7774 /// This will have no value when the condition is !=
7775 std::optional<bool> TestIsLessOp;
7776 /// This flag is true when condition is strict ( < or > ).
7777 bool TestIsStrictOp = false;
7778 /// This flag is true when step is subtracted on each iteration.
7779 bool SubtractStep = false;
7780 /// The outer loop counter this loop depends on (if any).
7781 const ValueDecl *DepDecl = nullptr;
7782 /// Contains number of loop (starts from 1) on which loop counter init
7783 /// expression of this loop depends on.
7784 std::optional<unsigned> InitDependOnLC;
7785 /// Contains number of loop (starts from 1) on which loop counter condition
7786 /// expression of this loop depends on.
7787 std::optional<unsigned> CondDependOnLC;
7788 /// Checks if the provide statement depends on the loop counter.
7789 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
7790 bool IsInitializer);
7791 /// Original condition required for checking of the exit condition for
7792 /// non-rectangular loop.
7793 Expr *Condition = nullptr;
7794
7795public:
7796 OpenMPIterationSpaceChecker(
7797 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
7798 SourceLocation DefaultLoc,
7799 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
7800 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7801 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7802 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7803 /// Check init-expr for canonical loop form and save loop counter
7804 /// variable - #Var and its initialization value - #LB.
7805 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
7806 /// Check test-expr for canonical form, save upper-bound (#UB), flags
7807 /// for less/greater and for strict/non-strict comparison.
7808 bool checkAndSetCond(Expr *S);
7809 /// Check incr-expr for canonical loop form and return true if it
7810 /// does not conform, otherwise save loop step (#Step).
7811 bool checkAndSetInc(Expr *S);
7812 /// Return the loop counter variable.
7813 ValueDecl *getLoopDecl() const { return LCDecl; }
7814 /// Return the reference expression to loop counter variable.
7815 Expr *getLoopDeclRefExpr() const { return LCRef; }
7816 /// Source range of the loop init.
7817 SourceRange getInitSrcRange() const { return InitSrcRange; }
7818 /// Source range of the loop condition.
7819 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
7820 /// Source range of the loop increment.
7821 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
7822 /// True if the step should be subtracted.
7823 bool shouldSubtractStep() const { return SubtractStep; }
7824 /// True, if the compare operator is strict (<, > or !=).
7825 bool isStrictTestOp() const { return TestIsStrictOp; }
7826 /// Build the expression to calculate the number of iterations.
7827 Expr *buildNumIterations(
7828 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
7829 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7830 /// Build the precondition expression for the loops.
7831 Expr *
7832 buildPreCond(Scope *S, Expr *Cond,
7833 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7834 /// Build reference expression to the counter be used for codegen.
7835 DeclRefExpr *
7836 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7837 DSAStackTy &DSA) const;
7838 /// Build reference expression to the private counter be used for
7839 /// codegen.
7840 Expr *buildPrivateCounterVar() const;
7841 /// Build initialization of the counter be used for codegen.
7842 Expr *buildCounterInit() const;
7843 /// Build step of the counter be used for codegen.
7844 Expr *buildCounterStep() const;
7845 /// Build loop data with counter value for depend clauses in ordered
7846 /// directives.
7847 Expr *
7848 buildOrderedLoopData(Scope *S, Expr *Counter,
7849 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
7850 SourceLocation Loc, Expr *Inc = nullptr,
7851 OverloadedOperatorKind OOK = OO_Amp);
7852 /// Builds the minimum value for the loop counter.
7853 std::pair<Expr *, Expr *> buildMinMaxValues(
7854 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
7855 /// Builds final condition for the non-rectangular loops.
7856 Expr *buildFinalCondition(Scope *S) const;
7857 /// Return true if any expression is dependent.
7858 bool dependent() const;
7859 /// Returns true if the initializer forms non-rectangular loop.
7860 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
7861 /// Returns true if the condition forms non-rectangular loop.
7862 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
7863 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
7864 unsigned getLoopDependentIdx() const {
7865 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
7866 }
7867
7868private:
7869 /// Check the right-hand side of an assignment in the increment
7870 /// expression.
7871 bool checkAndSetIncRHS(Expr *RHS);
7872 /// Helper to set loop counter variable and its initializer.
7873 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
7874 bool EmitDiags);
7875 /// Helper to set upper bound.
7876 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
7878 /// Helper to set loop increment.
7879 bool setStep(Expr *NewStep, bool Subtract);
7880};
7881
7882bool OpenMPIterationSpaceChecker::dependent() const {
7883 if (!LCDecl) {
7884 assert(!LB && !UB && !Step);
7885 return false;
7886 }
7887 return LCDecl->getType()->isDependentType() ||
7888 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
7889 (Step && Step->isValueDependent());
7890}
7891
7892bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
7893 Expr *NewLCRefExpr,
7894 Expr *NewLB, bool EmitDiags) {
7895 // State consistency checking to ensure correct usage.
7896 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
7897 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7898 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
7899 return true;
7900 LCDecl = getCanonicalDecl(NewLCDecl);
7901 LCRef = NewLCRefExpr;
7902 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
7903 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
7904 if ((Ctor->isCopyOrMoveConstructor() ||
7905 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
7906 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
7907 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
7908 LB = NewLB;
7909 if (EmitDiags)
7910 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
7911 return false;
7912}
7913
7914bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
7915 bool StrictOp, SourceRange SR,
7916 SourceLocation SL) {
7917 // State consistency checking to ensure correct usage.
7918 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
7919 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
7920 if (!NewUB || NewUB->containsErrors())
7921 return true;
7922 UB = NewUB;
7923 if (LessOp)
7924 TestIsLessOp = LessOp;
7925 TestIsStrictOp = StrictOp;
7926 ConditionSrcRange = SR;
7927 ConditionLoc = SL;
7928 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
7929 return false;
7930}
7931
7932bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
7933 // State consistency checking to ensure correct usage.
7934 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
7935 if (!NewStep || NewStep->containsErrors())
7936 return true;
7937 if (!NewStep->isValueDependent()) {
7938 // Check that the step is integer expression.
7939 SourceLocation StepLoc = NewStep->getBeginLoc();
7941 StepLoc, getExprAsWritten(NewStep));
7942 if (Val.isInvalid())
7943 return true;
7944 NewStep = Val.get();
7945
7946 // OpenMP [2.6, Canonical Loop Form, Restrictions]
7947 // If test-expr is of form var relational-op b and relational-op is < or
7948 // <= then incr-expr must cause var to increase on each iteration of the
7949 // loop. If test-expr is of form var relational-op b and relational-op is
7950 // > or >= then incr-expr must cause var to decrease on each iteration of
7951 // the loop.
7952 // If test-expr is of form b relational-op var and relational-op is < or
7953 // <= then incr-expr must cause var to decrease on each iteration of the
7954 // loop. If test-expr is of form b relational-op var and relational-op is
7955 // > or >= then incr-expr must cause var to increase on each iteration of
7956 // the loop.
7957 std::optional<llvm::APSInt> Result =
7958 NewStep->getIntegerConstantExpr(SemaRef.Context);
7959 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
7960 bool IsConstNeg =
7961 Result && Result->isSigned() && (Subtract != Result->isNegative());
7962 bool IsConstPos =
7963 Result && Result->isSigned() && (Subtract == Result->isNegative());
7964 bool IsConstZero = Result && !Result->getBoolValue();
7965
7966 // != with increment is treated as <; != with decrement is treated as >
7967 if (!TestIsLessOp)
7968 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
7969 if (UB && (IsConstZero ||
7970 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
7971 : (IsConstPos || (IsUnsigned && !Subtract))))) {
7972 SemaRef.Diag(NewStep->getExprLoc(),
7973 diag::err_omp_loop_incr_not_compatible)
7974 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
7975 SemaRef.Diag(ConditionLoc,
7976 diag::note_omp_loop_cond_requires_compatible_incr)
7977 << *TestIsLessOp << ConditionSrcRange;
7978 return true;
7979 }
7980 if (*TestIsLessOp == Subtract) {
7981 NewStep =
7982 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
7983 .get();
7984 Subtract = !Subtract;
7985 }
7986 }
7987
7988 Step = NewStep;
7989 SubtractStep = Subtract;
7990 return false;
7991}
7992
7993namespace {
7994/// Checker for the non-rectangular loops. Checks if the initializer or
7995/// condition expression references loop counter variable.
7996class LoopCounterRefChecker final
7997 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
7998 Sema &SemaRef;
7999 DSAStackTy &Stack;
8000 const ValueDecl *CurLCDecl = nullptr;
8001 const ValueDecl *DepDecl = nullptr;
8002 const ValueDecl *PrevDepDecl = nullptr;
8003 bool IsInitializer = true;
8004 bool SupportsNonRectangular;
8005 unsigned BaseLoopId = 0;
8006 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8007 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8008 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8009 << (IsInitializer ? 0 : 1);
8010 return false;
8011 }
8012 const auto &&Data = Stack.isLoopControlVariable(VD);
8013 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8014 // The type of the loop iterator on which we depend may not have a random
8015 // access iterator type.
8016 if (Data.first && VD->getType()->isRecordType()) {
8017 SmallString<128> Name;
8018 llvm::raw_svector_ostream OS(Name);
8019 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8020 /*Qualified=*/true);
8021 SemaRef.Diag(E->getExprLoc(),
8022 diag::err_omp_wrong_dependency_iterator_type)
8023 << OS.str();
8024 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8025 return false;
8026 }
8027 if (Data.first && !SupportsNonRectangular) {
8028 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8029 return false;
8030 }
8031 if (Data.first &&
8032 (DepDecl || (PrevDepDecl &&
8033 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8034 if (!DepDecl && PrevDepDecl)
8035 DepDecl = PrevDepDecl;
8036 SmallString<128> Name;
8037 llvm::raw_svector_ostream OS(Name);
8038 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8039 /*Qualified=*/true);
8040 SemaRef.Diag(E->getExprLoc(),
8041 diag::err_omp_invariant_or_linear_dependency)
8042 << OS.str();
8043 return false;
8044 }
8045 if (Data.first) {
8046 DepDecl = VD;
8047 BaseLoopId = Data.first;
8048 }
8049 return Data.first;
8050 }
8051
8052public:
8053 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8054 const ValueDecl *VD = E->getDecl();
8055 if (isa<VarDecl>(VD))
8056 return checkDecl(E, VD);
8057 return false;
8058 }
8059 bool VisitMemberExpr(const MemberExpr *E) {
8060 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8061 const ValueDecl *VD = E->getMemberDecl();
8062 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8063 return checkDecl(E, VD);
8064 }
8065 return false;
8066 }
8067 bool VisitStmt(const Stmt *S) {
8068 bool Res = false;
8069 for (const Stmt *Child : S->children())
8070 Res = (Child && Visit(Child)) || Res;
8071 return Res;
8072 }
8073 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8074 const ValueDecl *CurLCDecl, bool IsInitializer,
8075 const ValueDecl *PrevDepDecl = nullptr,
8076 bool SupportsNonRectangular = true)
8077 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8078 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8079 SupportsNonRectangular(SupportsNonRectangular) {}
8080 unsigned getBaseLoopId() const {
8081 assert(CurLCDecl && "Expected loop dependency.");
8082 return BaseLoopId;
8083 }
8084 const ValueDecl *getDepDecl() const {
8085 assert(CurLCDecl && "Expected loop dependency.");
8086 return DepDecl;
8087 }
8088};
8089} // namespace
8090
8091std::optional<unsigned>
8092OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8093 bool IsInitializer) {
8094 // Check for the non-rectangular loops.
8095 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8096 DepDecl, SupportsNonRectangular);
8097 if (LoopStmtChecker.Visit(S)) {
8098 DepDecl = LoopStmtChecker.getDepDecl();
8099 return LoopStmtChecker.getBaseLoopId();
8100 }
8101 return std::nullopt;
8102}
8103
8104bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8105 // Check init-expr for canonical loop form and save loop counter
8106 // variable - #Var and its initialization value - #LB.
8107 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8108 // var = lb
8109 // integer-type var = lb
8110 // random-access-iterator-type var = lb
8111 // pointer-type var = lb
8112 //
8113 if (!S) {
8114 if (EmitDiags) {
8115 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8116 }
8117 return true;
8118 }
8119 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8120 if (!ExprTemp->cleanupsHaveSideEffects())
8121 S = ExprTemp->getSubExpr();
8122
8123 if (!CollapsedLoopVarDecls.empty()) {
8124 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8125 if (!FSEC.TraverseStmt(S)) {
8126 SourceRange Range = FSEC.getErrRange();
8127 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8128 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8129 return true;
8130 }
8131 }
8132
8133 InitSrcRange = S->getSourceRange();
8134 if (Expr *E = dyn_cast<Expr>(S))
8135 S = E->IgnoreParens();
8136 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8137 if (BO->getOpcode() == BO_Assign) {
8138 Expr *LHS = BO->getLHS()->IgnoreParens();
8139 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8140 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8141 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8142 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8143 EmitDiags);
8144 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8145 }
8146 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8147 if (ME->isArrow() &&
8148 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8149 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8150 EmitDiags);
8151 }
8152 }
8153 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8154 if (DS->isSingleDecl()) {
8155 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8156 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8157 // Accept non-canonical init form here but emit ext. warning.
8158 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8159 SemaRef.Diag(S->getBeginLoc(),
8160 diag::ext_omp_loop_not_canonical_init)
8161 << S->getSourceRange();
8162 return setLCDeclAndLB(
8163 Var,
8164 buildDeclRefExpr(SemaRef, Var,
8165 Var->getType().getNonReferenceType(),
8166 DS->getBeginLoc()),
8167 Var->getInit(), EmitDiags);
8168 }
8169 }
8170 }
8171 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8172 if (CE->getOperator() == OO_Equal) {
8173 Expr *LHS = CE->getArg(0);
8174 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8175 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8176 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8177 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8178 EmitDiags);
8179 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8180 }
8181 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8182 if (ME->isArrow() &&
8183 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8184 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8185 EmitDiags);
8186 }
8187 }
8188 }
8189
8190 if (dependent() || SemaRef.CurContext->isDependentContext())
8191 return false;
8192 if (EmitDiags) {
8193 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8194 << S->getSourceRange();
8195 }
8196 return true;
8197}
8198
8199/// Ignore parenthesizes, implicit casts, copy constructor and return the
8200/// variable (which may be the loop variable) if possible.
8201static const ValueDecl *getInitLCDecl(const Expr *E) {
8202 if (!E)
8203 return nullptr;
8204 E = getExprAsWritten(E);
8205 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8206 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8207 if ((Ctor->isCopyOrMoveConstructor() ||
8208 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8209 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8210 E = CE->getArg(0)->IgnoreParenImpCasts();
8211 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8212 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8213 return getCanonicalDecl(VD);
8214 }
8215 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8216 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8217 return getCanonicalDecl(ME->getMemberDecl());
8218 return nullptr;
8219}
8220
8221bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8222 // Check test-expr for canonical form, save upper-bound UB, flags for
8223 // less/greater and for strict/non-strict comparison.
8224 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8225 // var relational-op b
8226 // b relational-op var
8227 //
8228 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8229 if (!S) {
8230 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8231 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8232 return true;
8233 }
8234 Condition = S;
8235 S = getExprAsWritten(S);
8236
8237 if (!CollapsedLoopVarDecls.empty()) {
8238 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8239 if (!FSEC.TraverseStmt(S)) {
8240 SourceRange Range = FSEC.getErrRange();
8241 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8242 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8243 return true;
8244 }
8245 }
8246
8247 SourceLocation CondLoc = S->getBeginLoc();
8248 auto &&CheckAndSetCond =
8249 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8250 const Expr *RHS, SourceRange SR,
8251 SourceLocation OpLoc) -> std::optional<bool> {
8252 if (BinaryOperator::isRelationalOp(Opcode)) {
8253 if (getInitLCDecl(LHS) == LCDecl)
8254 return setUB(const_cast<Expr *>(RHS),
8255 (Opcode == BO_LT || Opcode == BO_LE),
8256 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8257 if (getInitLCDecl(RHS) == LCDecl)
8258 return setUB(const_cast<Expr *>(LHS),
8259 (Opcode == BO_GT || Opcode == BO_GE),
8260 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8261 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8262 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8263 /*LessOp=*/std::nullopt,
8264 /*StrictOp=*/true, SR, OpLoc);
8265 }
8266 return std::nullopt;
8267 };
8268 std::optional<bool> Res;
8269 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8270 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8271 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8272 RBO->getOperatorLoc());
8273 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8274 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8275 BO->getSourceRange(), BO->getOperatorLoc());
8276 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8277 if (CE->getNumArgs() == 2) {
8278 Res = CheckAndSetCond(
8279 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8280 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8281 }
8282 }
8283 if (Res)
8284 return *Res;
8285 if (dependent() || SemaRef.CurContext->isDependentContext())
8286 return false;
8287 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8288 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8289 return true;
8290}
8291
8292bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8293 // RHS of canonical loop form increment can be:
8294 // var + incr
8295 // incr + var
8296 // var - incr
8297 //
8298 RHS = RHS->IgnoreParenImpCasts();
8299 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8300 if (BO->isAdditiveOp()) {
8301 bool IsAdd = BO->getOpcode() == BO_Add;
8302 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8303 return setStep(BO->getRHS(), !IsAdd);
8304 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8305 return setStep(BO->getLHS(), /*Subtract=*/false);
8306 }
8307 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8308 bool IsAdd = CE->getOperator() == OO_Plus;
8309 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8310 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8311 return setStep(CE->getArg(1), !IsAdd);
8312 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8313 return setStep(CE->getArg(0), /*Subtract=*/false);
8314 }
8315 }
8316 if (dependent() || SemaRef.CurContext->isDependentContext())
8317 return false;
8318 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8319 << RHS->getSourceRange() << LCDecl;
8320 return true;
8321}
8322
8323bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8324 // Check incr-expr for canonical loop form and return true if it
8325 // does not conform.
8326 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8327 // ++var
8328 // var++
8329 // --var
8330 // var--
8331 // var += incr
8332 // var -= incr
8333 // var = var + incr
8334 // var = incr + var
8335 // var = var - incr
8336 //
8337 if (!S) {
8338 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8339 return true;
8340 }
8341 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8342 if (!ExprTemp->cleanupsHaveSideEffects())
8343 S = ExprTemp->getSubExpr();
8344
8345 if (!CollapsedLoopVarDecls.empty()) {
8346 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8347 if (!FSEC.TraverseStmt(S)) {
8348 SourceRange Range = FSEC.getErrRange();
8349 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8350 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8351 return true;
8352 }
8353 }
8354
8355 IncrementSrcRange = S->getSourceRange();
8356 S = S->IgnoreParens();
8357 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8358 if (UO->isIncrementDecrementOp() &&
8359 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8360 return setStep(SemaRef
8361 .ActOnIntegerConstant(UO->getBeginLoc(),
8362 (UO->isDecrementOp() ? -1 : 1))
8363 .get(),
8364 /*Subtract=*/false);
8365 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8366 switch (BO->getOpcode()) {
8367 case BO_AddAssign:
8368 case BO_SubAssign:
8369 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8370 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8371 break;
8372 case BO_Assign:
8373 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8374 return checkAndSetIncRHS(BO->getRHS());
8375 break;
8376 default:
8377 break;
8378 }
8379 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8380 switch (CE->getOperator()) {
8381 case OO_PlusPlus:
8382 case OO_MinusMinus:
8383 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8384 return setStep(SemaRef
8385 .ActOnIntegerConstant(
8386 CE->getBeginLoc(),
8387 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8388 .get(),
8389 /*Subtract=*/false);
8390 break;
8391 case OO_PlusEqual:
8392 case OO_MinusEqual:
8393 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8394 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8395 break;
8396 case OO_Equal:
8397 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8398 return checkAndSetIncRHS(CE->getArg(1));
8399 break;
8400 default:
8401 break;
8402 }
8403 }
8404 if (dependent() || SemaRef.CurContext->isDependentContext())
8405 return false;
8406 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8407 << S->getSourceRange() << LCDecl;
8408 return true;
8409}
8410
8411static ExprResult
8412tryBuildCapture(Sema &SemaRef, Expr *Capture,
8413 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8414 StringRef Name = ".capture_expr.") {
8415 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8416 return Capture;
8417 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8418 return SemaRef.PerformImplicitConversion(
8419 Capture->IgnoreImpCasts(), Capture->getType(), Sema::AA_Converting,
8420 /*AllowExplicit=*/true);
8421 auto I = Captures.find(Capture);
8422 if (I != Captures.end())
8423 return buildCapture(SemaRef, Capture, I->second, Name);
8424 DeclRefExpr *Ref = nullptr;
8425 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8426 Captures[Capture] = Ref;
8427 return Res;
8428}
8429
8430/// Calculate number of iterations, transforming to unsigned, if number of
8431/// iterations may be larger than the original type.
8432static Expr *
8433calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8434 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8435 bool TestIsStrictOp, bool RoundToStep,
8436 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
8437 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8438 if (!NewStep.isUsable())
8439 return nullptr;
8440 llvm::APSInt LRes, SRes;
8441 bool IsLowerConst = false, IsStepConst = false;
8442 if (std::optional<llvm::APSInt> Res =
8443 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8444 LRes = *Res;
8445 IsLowerConst = true;
8446 }
8447 if (std::optional<llvm::APSInt> Res =
8448 Step->getIntegerConstantExpr(SemaRef.Context)) {
8449 SRes = *Res;
8450 IsStepConst = true;
8451 }
8452 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8453 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8454 (TestIsStrictOp && LRes.isStrictlyPositive()));
8455 bool NeedToReorganize = false;
8456 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8457 if (!NoNeedToConvert && IsLowerConst &&
8458 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8459 NoNeedToConvert = true;
8460 if (RoundToStep) {
8461 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8462 ? LRes.getBitWidth()
8463 : SRes.getBitWidth();
8464 LRes = LRes.extend(BW + 1);
8465 LRes.setIsSigned(true);
8466 SRes = SRes.extend(BW + 1);
8467 SRes.setIsSigned(true);
8468 LRes -= SRes;
8469 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8470 LRes = LRes.trunc(BW);
8471 }
8472 if (TestIsStrictOp) {
8473 unsigned BW = LRes.getBitWidth();
8474 LRes = LRes.extend(BW + 1);
8475 LRes.setIsSigned(true);
8476 ++LRes;
8477 NoNeedToConvert =
8478 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8479 // truncate to the original bitwidth.
8480 LRes = LRes.trunc(BW);
8481 }
8482 NeedToReorganize = NoNeedToConvert;
8483 }
8484 llvm::APSInt URes;
8485 bool IsUpperConst = false;
8486 if (std::optional<llvm::APSInt> Res =
8487 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8488 URes = *Res;
8489 IsUpperConst = true;
8490 }
8491 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8492 (!RoundToStep || IsStepConst)) {
8493 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8494 : URes.getBitWidth();
8495 LRes = LRes.extend(BW + 1);
8496 LRes.setIsSigned(true);
8497 URes = URes.extend(BW + 1);
8498 URes.setIsSigned(true);
8499 URes -= LRes;
8500 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8501 NeedToReorganize = NoNeedToConvert;
8502 }
8503 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8504 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8505 // unsigned.
8506 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8507 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8508 QualType LowerTy = Lower->getType();
8509 QualType UpperTy = Upper->getType();
8510 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8511 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8512 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8513 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8515 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8516 Upper =
8517 SemaRef
8519 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8521 .get();
8522 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8523 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8524 }
8525 }
8526 if (!Lower || !Upper || NewStep.isInvalid())
8527 return nullptr;
8528
8529 ExprResult Diff;
8530 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8531 // 1]).
8532 if (NeedToReorganize) {
8533 Diff = Lower;
8534
8535 if (RoundToStep) {
8536 // Lower - Step
8537 Diff =
8538 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8539 if (!Diff.isUsable())
8540 return nullptr;
8541 }
8542
8543 // Lower - Step [+ 1]
8544 if (TestIsStrictOp)
8545 Diff = SemaRef.BuildBinOp(
8546 S, DefaultLoc, BO_Add, Diff.get(),
8547 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8548 if (!Diff.isUsable())
8549 return nullptr;
8550
8551 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8552 if (!Diff.isUsable())
8553 return nullptr;
8554
8555 // Upper - (Lower - Step [+ 1]).
8556 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8557 if (!Diff.isUsable())
8558 return nullptr;
8559 } else {
8560 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8561
8562 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8563 // BuildBinOp already emitted error, this one is to point user to upper
8564 // and lower bound, and to tell what is passed to 'operator-'.
8565 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8566 << Upper->getSourceRange() << Lower->getSourceRange();
8567 return nullptr;
8568 }
8569
8570 if (!Diff.isUsable())
8571 return nullptr;
8572
8573 // Upper - Lower [- 1]
8574 if (TestIsStrictOp)
8575 Diff = SemaRef.BuildBinOp(
8576 S, DefaultLoc, BO_Sub, Diff.get(),
8577 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8578 if (!Diff.isUsable())
8579 return nullptr;
8580
8581 if (RoundToStep) {
8582 // Upper - Lower [- 1] + Step
8583 Diff =
8584 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8585 if (!Diff.isUsable())
8586 return nullptr;
8587 }
8588 }
8589
8590 // Parentheses (for dumping/debugging purposes only).
8591 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8592 if (!Diff.isUsable())
8593 return nullptr;
8594
8595 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8596 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8597 if (!Diff.isUsable())
8598 return nullptr;
8599
8600 return Diff.get();
8601}
8602
8603/// Build the expression to calculate the number of iterations.
8604Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8605 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8606 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8607 QualType VarType = LCDecl->getType().getNonReferenceType();
8608 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8609 !SemaRef.getLangOpts().CPlusPlus)
8610 return nullptr;
8611 Expr *LBVal = LB;
8612 Expr *UBVal = UB;
8613 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8614 // max(LB(MinVal), LB(MaxVal)))
8615 if (InitDependOnLC) {
8616 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8617 if (!IS.MinValue || !IS.MaxValue)
8618 return nullptr;
8619 // OuterVar = Min
8620 ExprResult MinValue =
8621 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8622 if (!MinValue.isUsable())
8623 return nullptr;
8624
8625 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8626 IS.CounterVar, MinValue.get());
8627 if (!LBMinVal.isUsable())
8628 return nullptr;
8629 // OuterVar = Min, LBVal
8630 LBMinVal =
8631 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8632 if (!LBMinVal.isUsable())
8633 return nullptr;
8634 // (OuterVar = Min, LBVal)
8635 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8636 if (!LBMinVal.isUsable())
8637 return nullptr;
8638
8639 // OuterVar = Max
8640 ExprResult MaxValue =
8641 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8642 if (!MaxValue.isUsable())
8643 return nullptr;
8644
8645 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8646 IS.CounterVar, MaxValue.get());
8647 if (!LBMaxVal.isUsable())
8648 return nullptr;
8649 // OuterVar = Max, LBVal
8650 LBMaxVal =
8651 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8652 if (!LBMaxVal.isUsable())
8653 return nullptr;
8654 // (OuterVar = Max, LBVal)
8655 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8656 if (!LBMaxVal.isUsable())
8657 return nullptr;
8658
8659 Expr *LBMin =
8660 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8661 Expr *LBMax =
8662 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8663 if (!LBMin || !LBMax)
8664 return nullptr;
8665 // LB(MinVal) < LB(MaxVal)
8666 ExprResult MinLessMaxRes =
8667 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8668 if (!MinLessMaxRes.isUsable())
8669 return nullptr;
8670 Expr *MinLessMax =
8671 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8672 .get();
8673 if (!MinLessMax)
8674 return nullptr;
8675 if (*TestIsLessOp) {
8676 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8677 // LB(MaxVal))
8678 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8679 MinLessMax, LBMin, LBMax);
8680 if (!MinLB.isUsable())
8681 return nullptr;
8682 LBVal = MinLB.get();
8683 } else {
8684 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8685 // LB(MaxVal))
8686 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8687 MinLessMax, LBMax, LBMin);
8688 if (!MaxLB.isUsable())
8689 return nullptr;
8690 LBVal = MaxLB.get();
8691 }
8692 // OuterVar = LB
8693 LBMinVal =
8694 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
8695 if (!LBMinVal.isUsable())
8696 return nullptr;
8697 LBVal = LBMinVal.get();
8698 }
8699 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
8700 // min(UB(MinVal), UB(MaxVal))
8701 if (CondDependOnLC) {
8702 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
8703 if (!IS.MinValue || !IS.MaxValue)
8704 return nullptr;
8705 // OuterVar = Min
8706 ExprResult MinValue =
8707 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8708 if (!MinValue.isUsable())
8709 return nullptr;
8710
8711 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8712 IS.CounterVar, MinValue.get());
8713 if (!UBMinVal.isUsable())
8714 return nullptr;
8715 // OuterVar = Min, UBVal
8716 UBMinVal =
8717 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
8718 if (!UBMinVal.isUsable())
8719 return nullptr;
8720 // (OuterVar = Min, UBVal)
8721 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
8722 if (!UBMinVal.isUsable())
8723 return nullptr;
8724
8725 // OuterVar = Max
8726 ExprResult MaxValue =
8727 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8728 if (!MaxValue.isUsable())
8729 return nullptr;
8730
8731 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8732 IS.CounterVar, MaxValue.get());
8733 if (!UBMaxVal.isUsable())
8734 return nullptr;
8735 // OuterVar = Max, UBVal
8736 UBMaxVal =
8737 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
8738 if (!UBMaxVal.isUsable())
8739 return nullptr;
8740 // (OuterVar = Max, UBVal)
8741 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
8742 if (!UBMaxVal.isUsable())
8743 return nullptr;
8744
8745 Expr *UBMin =
8746 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
8747 Expr *UBMax =
8748 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
8749 if (!UBMin || !UBMax)
8750 return nullptr;
8751 // UB(MinVal) > UB(MaxVal)
8752 ExprResult MinGreaterMaxRes =
8753 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
8754 if (!MinGreaterMaxRes.isUsable())
8755 return nullptr;
8756 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
8757 Captures, ".min_greater_max")
8758 .get();
8759 if (!MinGreaterMax)
8760 return nullptr;
8761 if (*TestIsLessOp) {
8762 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
8763 // UB(MaxVal))
8764 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
8765 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
8766 if (!MaxUB.isUsable())
8767 return nullptr;
8768 UBVal = MaxUB.get();
8769 } else {
8770 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
8771 // UB(MaxVal))
8772 ExprResult MinUB = SemaRef.ActOnConditionalOp(
8773 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
8774 if (!MinUB.isUsable())
8775 return nullptr;
8776 UBVal = MinUB.get();
8777 }
8778 }
8779 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
8780 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
8781 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
8782 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
8783 if (!Upper || !Lower)
8784 return nullptr;
8785
8786 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8787 Step, VarType, TestIsStrictOp,
8788 /*RoundToStep=*/true, Captures);
8789 if (!Diff.isUsable())
8790 return nullptr;
8791
8792 // OpenMP runtime requires 32-bit or 64-bit loop variables.
8793 QualType Type = Diff.get()->getType();
8794 ASTContext &C = SemaRef.Context;
8795 bool UseVarType = VarType->hasIntegerRepresentation() &&
8796 C.getTypeSize(Type) > C.getTypeSize(VarType);
8797 if (!Type->isIntegerType() || UseVarType) {
8798 unsigned NewSize =
8799 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
8800 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
8802 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
8803 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
8804 Diff = SemaRef.PerformImplicitConversion(
8805 Diff.get(), Type, Sema::AA_Converting, /*AllowExplicit=*/true);
8806 if (!Diff.isUsable())
8807 return nullptr;
8808 }
8809 }
8810 if (LimitedType) {
8811 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
8812 if (NewSize != C.getTypeSize(Type)) {
8813 if (NewSize < C.getTypeSize(Type)) {
8814 assert(NewSize == 64 && "incorrect loop var size");
8815 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
8816 << InitSrcRange << ConditionSrcRange;
8817 }
8818 QualType NewType = C.getIntTypeForBitwidth(
8820 C.getTypeSize(Type) < NewSize);
8821 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
8822 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
8823 Sema::AA_Converting, true);
8824 if (!Diff.isUsable())
8825 return nullptr;
8826 }
8827 }
8828 }
8829
8830 return Diff.get();
8831}
8832
8833std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
8834 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8835 // Do not build for iterators, they cannot be used in non-rectangular loop
8836 // nests.
8837 if (LCDecl->getType()->isRecordType())
8838 return std::make_pair(nullptr, nullptr);
8839 // If we subtract, the min is in the condition, otherwise the min is in the
8840 // init value.
8841 Expr *MinExpr = nullptr;
8842 Expr *MaxExpr = nullptr;
8843 Expr *LBExpr = *TestIsLessOp ? LB : UB;
8844 Expr *UBExpr = *TestIsLessOp ? UB : LB;
8845 bool LBNonRect =
8846 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
8847 bool UBNonRect =
8848 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
8849 Expr *Lower =
8850 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
8851 Expr *Upper =
8852 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
8853 if (!Upper || !Lower)
8854 return std::make_pair(nullptr, nullptr);
8855
8856 if (*TestIsLessOp)
8857 MinExpr = Lower;
8858 else
8859 MaxExpr = Upper;
8860
8861 // Build minimum/maximum value based on number of iterations.
8862 QualType VarType = LCDecl->getType().getNonReferenceType();
8863
8864 ExprResult Diff = calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper,
8865 Step, VarType, TestIsStrictOp,
8866 /*RoundToStep=*/false, Captures);
8867 if (!Diff.isUsable())
8868 return std::make_pair(nullptr, nullptr);
8869
8870 // ((Upper - Lower [- 1]) / Step) * Step
8871 // Parentheses (for dumping/debugging purposes only).
8872 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8873 if (!Diff.isUsable())
8874 return std::make_pair(nullptr, nullptr);
8875
8876 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8877 if (!NewStep.isUsable())
8878 return std::make_pair(nullptr, nullptr);
8879 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
8880 if (!Diff.isUsable())
8881 return std::make_pair(nullptr, nullptr);
8882
8883 // Parentheses (for dumping/debugging purposes only).
8884 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8885 if (!Diff.isUsable())
8886 return std::make_pair(nullptr, nullptr);
8887
8888 // Convert to the ptrdiff_t, if original type is pointer.
8889 if (VarType->isAnyPointerType() &&
8890 !SemaRef.Context.hasSameType(
8891 Diff.get()->getType(),
8893 Diff = SemaRef.PerformImplicitConversion(
8894 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
8895 Sema::AA_Converting, /*AllowExplicit=*/true);
8896 }
8897 if (!Diff.isUsable())
8898 return std::make_pair(nullptr, nullptr);
8899
8900 if (*TestIsLessOp) {
8901 // MinExpr = Lower;
8902 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
8903 Diff = SemaRef.BuildBinOp(
8904 S, DefaultLoc, BO_Add,
8905 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
8906 Diff.get());
8907 if (!Diff.isUsable())
8908 return std::make_pair(nullptr, nullptr);
8909 } else {
8910 // MaxExpr = Upper;
8911 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
8912 Diff = SemaRef.BuildBinOp(
8913 S, DefaultLoc, BO_Sub,
8914 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8915 Diff.get());
8916 if (!Diff.isUsable())
8917 return std::make_pair(nullptr, nullptr);
8918 }
8919
8920 // Convert to the original type.
8921 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
8922 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
8924 /*AllowExplicit=*/true);
8925 if (!Diff.isUsable())
8926 return std::make_pair(nullptr, nullptr);
8927
8928 Sema::TentativeAnalysisScope Trap(SemaRef);
8929 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
8930 if (!Diff.isUsable())
8931 return std::make_pair(nullptr, nullptr);
8932
8933 if (*TestIsLessOp)
8934 MaxExpr = Diff.get();
8935 else
8936 MinExpr = Diff.get();
8937
8938 return std::make_pair(MinExpr, MaxExpr);
8939}
8940
8941Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
8942 if (InitDependOnLC || CondDependOnLC)
8943 return Condition;
8944 return nullptr;
8945}
8946
8947Expr *OpenMPIterationSpaceChecker::buildPreCond(
8948 Scope *S, Expr *Cond,
8949 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8950 // Do not build a precondition when the condition/initialization is dependent
8951 // to prevent pessimistic early loop exit.
8952 // TODO: this can be improved by calculating min/max values but not sure that
8953 // it will be very effective.
8954 if (CondDependOnLC || InitDependOnLC)
8955 return SemaRef
8957 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
8958 SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8959 /*AllowExplicit=*/true)
8960 .get();
8961
8962 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
8963 Sema::TentativeAnalysisScope Trap(SemaRef);
8964
8965 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
8966 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
8967 if (!NewLB.isUsable() || !NewUB.isUsable())
8968 return nullptr;
8969
8970 ExprResult CondExpr =
8971 SemaRef.BuildBinOp(S, DefaultLoc,
8972 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
8973 : (TestIsStrictOp ? BO_GT : BO_GE),
8974 NewLB.get(), NewUB.get());
8975 if (CondExpr.isUsable()) {
8976 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
8977 SemaRef.Context.BoolTy))
8978 CondExpr = SemaRef.PerformImplicitConversion(
8979 CondExpr.get(), SemaRef.Context.BoolTy, /*Action=*/Sema::AA_Casting,
8980 /*AllowExplicit=*/true);
8981 }
8982
8983 // Otherwise use original loop condition and evaluate it in runtime.
8984 return CondExpr.isUsable() ? CondExpr.get() : Cond;
8985}
8986
8987/// Build reference expression to the counter be used for codegen.
8988DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
8989 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8990 DSAStackTy &DSA) const {
8991 auto *VD = dyn_cast<VarDecl>(LCDecl);
8992 if (!VD) {
8993 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
8995 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
8996 const DSAStackTy::DSAVarData Data =
8997 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
8998 // If the loop control decl is explicitly marked as private, do not mark it
8999 // as captured again.
9000 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9001 Captures.insert(std::make_pair(LCRef, Ref));
9002 return Ref;
9003 }
9004 return cast<DeclRefExpr>(LCRef);
9005}
9006
9007Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9008 if (LCDecl && !LCDecl->isInvalidDecl()) {
9010 VarDecl *PrivateVar = buildVarDecl(
9011 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9012 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9013 isa<VarDecl>(LCDecl)
9014 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9015 : nullptr);
9016 if (PrivateVar->isInvalidDecl())
9017 return nullptr;
9018 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9019 }
9020 return nullptr;
9021}
9022
9023/// Build initialization of the counter to be used for codegen.
9024Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9025
9026/// Build step of the counter be used for codegen.
9027Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9028
9029Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9030 Scope *S, Expr *Counter,
9031 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9032 Expr *Inc, OverloadedOperatorKind OOK) {
9033 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9034 if (!Cnt)
9035 return nullptr;
9036 if (Inc) {
9037 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9038 "Expected only + or - operations for depend clauses.");
9039 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9040 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9041 if (!Cnt)
9042 return nullptr;
9043 }
9044 QualType VarType = LCDecl->getType().getNonReferenceType();
9045 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9046 !SemaRef.getLangOpts().CPlusPlus)
9047 return nullptr;
9048 // Upper - Lower
9049 Expr *Upper =
9050 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9051 Expr *Lower =
9052 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9053 if (!Upper || !Lower)
9054 return nullptr;
9055
9056 ExprResult Diff = calculateNumIters(
9057 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9058 /*TestIsStrictOp=*/false, /*RoundToStep=*/false, Captures);
9059 if (!Diff.isUsable())
9060 return nullptr;
9061
9062 return Diff.get();
9063}
9064} // namespace
9065
9067 Stmt *Init) {
9068 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9069 assert(Init && "Expected loop in canonical form.");
9070 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9071 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9072 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9073 return;
9074
9075 DSAStack->loopStart();
9077 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9078 *DSAStack, ForLoc, EmptyDeclSet);
9079 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9080 if (ValueDecl *D = ISC.getLoopDecl()) {
9081 auto *VD = dyn_cast<VarDecl>(D);
9082 DeclRefExpr *PrivateRef = nullptr;
9083 if (!VD) {
9085 VD = Private;
9086 } else {
9087 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9088 /*WithInit=*/false);
9089 VD = cast<VarDecl>(PrivateRef->getDecl());
9090 }
9091 }
9092 DSAStack->addLoopControlVariable(D, VD);
9093 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9094 if (LD != D->getCanonicalDecl()) {
9095 DSAStack->resetPossibleLoopCounter();
9096 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9098 SemaRef, const_cast<VarDecl *>(Var),
9099 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9100 /*RefersToCapture=*/true));
9101 }
9102 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9103 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9104 // associated for-loop of a simd construct with just one associated
9105 // for-loop may be listed in a linear clause with a constant-linear-step
9106 // that is the increment of the associated for-loop. The loop iteration
9107 // variable(s) in the associated for-loop(s) of a for or parallel for
9108 // construct may be listed in a private or lastprivate clause.
9109 DSAStackTy::DSAVarData DVar =
9110 DSAStack->getTopDSA(D, /*FromParent=*/false);
9111 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9112 // is declared in the loop and it is predetermined as a private.
9113 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9114 OpenMPClauseKind PredeterminedCKind =
9116 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9117 : OMPC_private;
9118 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9119 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9120 };
9121 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9122 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9123 (getLangOpts().OpenMP <= 45 ||
9124 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9126 IsOpenMPTaskloopDirective(DKind) ||
9128 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9129 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9130 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9131 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9132 << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind)
9133 << getOpenMPClauseName(PredeterminedCKind);
9134 if (DVar.RefExpr == nullptr)
9135 DVar.CKind = PredeterminedCKind;
9136 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9137 } else if (LoopDeclRefExpr) {
9138 // Make the loop iteration variable private (for worksharing
9139 // constructs), linear (for simd directives with the only one
9140 // associated loop) or lastprivate (for simd directives with several
9141 // collapsed or ordered loops).
9142 if (DVar.CKind == OMPC_unknown)
9143 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9144 }
9145 }
9146 }
9147 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9148}
9149
9150namespace {
9151// Utility for OpenMP doacross clause kind
9152class OMPDoacrossKind {
9153public:
9154 bool isSource(const OMPDoacrossClause *C) {
9155 return C->getDependenceType() == OMPC_DOACROSS_source ||
9156 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9157 }
9158 bool isSink(const OMPDoacrossClause *C) {
9159 return C->getDependenceType() == OMPC_DOACROSS_sink;
9160 }
9161 bool isSinkIter(const OMPDoacrossClause *C) {
9162 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9163 }
9164};
9165} // namespace
9166/// Called on a for stmt to check and extract its iteration space
9167/// for further processing (such as collapsing).
9169 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9170 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9171 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9172 Expr *OrderedLoopCountExpr,
9173 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9175 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9176 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9177 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9178 // OpenMP [2.9.1, Canonical Loop Form]
9179 // for (init-expr; test-expr; incr-expr) structured-block
9180 // for (range-decl: range-expr) structured-block
9181 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9182 S = CanonLoop->getLoopStmt();
9183 auto *For = dyn_cast_or_null<ForStmt>(S);
9184 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9185 // Ranged for is supported only in OpenMP 5.0.
9186 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9187 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9188 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9189 << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
9190 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9191 if (TotalNestedLoopCount > 1) {
9192 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9193 SemaRef.Diag(DSA.getConstructLoc(),
9194 diag::note_omp_collapse_ordered_expr)
9195 << 2 << CollapseLoopCountExpr->getSourceRange()
9196 << OrderedLoopCountExpr->getSourceRange();
9197 else if (CollapseLoopCountExpr)
9198 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9199 diag::note_omp_collapse_ordered_expr)
9200 << 0 << CollapseLoopCountExpr->getSourceRange();
9201 else
9202 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9203 diag::note_omp_collapse_ordered_expr)
9204 << 1 << OrderedLoopCountExpr->getSourceRange();
9205 }
9206 return true;
9207 }
9208 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9209 "No loop body.");
9210 // Postpone analysis in dependent contexts for ranged for loops.
9211 if (CXXFor && SemaRef.CurContext->isDependentContext())
9212 return false;
9213
9214 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9215 For ? For->getForLoc() : CXXFor->getForLoc(),
9216 CollapsedLoopVarDecls);
9217
9218 // Check init.
9219 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9220 if (ISC.checkAndSetInit(Init))
9221 return true;
9222
9223 bool HasErrors = false;
9224
9225 // Check loop variable's type.
9226 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9227 // OpenMP [2.6, Canonical Loop Form]
9228 // Var is one of the following:
9229 // A variable of signed or unsigned integer type.
9230 // For C++, a variable of a random access iterator type.
9231 // For C, a variable of a pointer type.
9232 QualType VarType = LCDecl->getType().getNonReferenceType();
9233 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9234 !VarType->isPointerType() &&
9235 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9236 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9237 << SemaRef.getLangOpts().CPlusPlus;
9238 HasErrors = true;
9239 }
9240
9241 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9242 // a Construct
9243 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9244 // parallel for construct is (are) private.
9245 // The loop iteration variable in the associated for-loop of a simd
9246 // construct with just one associated for-loop is linear with a
9247 // constant-linear-step that is the increment of the associated for-loop.
9248 // Exclude loop var from the list of variables with implicitly defined data
9249 // sharing attributes.
9250 VarsWithImplicitDSA.erase(LCDecl);
9251
9252 assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
9253
9254 // Check test-expr.
9255 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9256
9257 // Check incr-expr.
9258 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9259 }
9260
9261 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9262 return HasErrors;
9263
9264 // Build the loop's iteration space representation.
9265 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9266 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9267 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9268 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9274 Captures);
9275 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9276 ISC.buildCounterVar(Captures, DSA);
9277 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9278 ISC.buildPrivateCounterVar();
9279 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9280 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9281 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9282 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9283 ISC.getConditionSrcRange();
9284 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9285 ISC.getIncrementSrcRange();
9286 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9287 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9288 ISC.isStrictTestOp();
9289 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9290 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9291 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9292 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9293 ISC.buildFinalCondition(DSA.getCurScope());
9294 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9295 ISC.doesInitDependOnLC();
9296 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9297 ISC.doesCondDependOnLC();
9298 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9299 ISC.getLoopDependentIdx();
9300
9301 HasErrors |=
9302 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9303 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9304 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9305 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9306 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9307 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9308 if (!HasErrors && DSA.isOrderedRegion()) {
9309 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9310 if (CurrentNestedLoopCount <
9311 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9312 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9313 CurrentNestedLoopCount,
9314 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9315 DSA.getOrderedRegionParam().second->setLoopCounter(
9316 CurrentNestedLoopCount,
9317 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9318 }
9319 }
9320 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9321 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9322 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9323 unsigned NumLoops =
9324 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9325 if (CurrentNestedLoopCount >= NumLoops) {
9326 // Erroneous case - clause has some problems.
9327 continue;
9328 }
9329 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9330 Pair.second.size() <= CurrentNestedLoopCount) {
9331 // Erroneous case - clause has some problems.
9332 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9333 continue;
9334 }
9335 OMPDoacrossKind ODK;
9336 if (DoacrossC && ODK.isSink(DoacrossC) &&
9337 Pair.second.size() <= CurrentNestedLoopCount) {
9338 // Erroneous case - clause has some problems.
9339 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9340 continue;
9341 }
9342 Expr *CntValue;
9343 SourceLocation DepLoc =
9344 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9345 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9346 (DoacrossC && ODK.isSource(DoacrossC)))
9347 CntValue = ISC.buildOrderedLoopData(
9348 DSA.getCurScope(),
9349 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9350 DepLoc);
9351 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9352 Expr *Cnt = SemaRef
9354 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9355 .get();
9356 if (!Cnt)
9357 continue;
9358 // build CounterVar - 1
9359 Expr *Inc =
9360 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9361 .get();
9362 CntValue = ISC.buildOrderedLoopData(
9363 DSA.getCurScope(),
9364 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9365 DepLoc, Inc, clang::OO_Minus);
9366 } else
9367 CntValue = ISC.buildOrderedLoopData(
9368 DSA.getCurScope(),
9369 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9370 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9371 Pair.second[CurrentNestedLoopCount].second);
9372 if (DependC)
9373 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9374 else
9375 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9376 }
9377 }
9378
9379 return HasErrors;
9380}
9381
9382/// Build 'VarRef = Start.
9383static ExprResult
9385 ExprResult Start, bool IsNonRectangularLB,
9386 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9387 // Build 'VarRef = Start.
9388 ExprResult NewStart = IsNonRectangularLB
9389 ? Start.get()
9390 : tryBuildCapture(SemaRef, Start.get(), Captures);
9391 if (!NewStart.isUsable())
9392 return ExprError();
9393 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9394 VarRef.get()->getType())) {
9395 NewStart = SemaRef.PerformImplicitConversion(
9396 NewStart.get(), VarRef.get()->getType(), Sema::AA_Converting,
9397 /*AllowExplicit=*/true);
9398 if (!NewStart.isUsable())
9399 return ExprError();
9400 }
9401
9403 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9404 return Init;
9405}
9406
9407/// Build 'VarRef = Start + Iter * Step'.
9409 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9410 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9411 bool IsNonRectangularLB,
9412 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9413 // Add parentheses (for debugging purposes only).
9414 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9415 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9416 !Step.isUsable())
9417 return ExprError();
9418
9419 ExprResult NewStep = Step;
9420 if (Captures)
9421 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9422 if (NewStep.isInvalid())
9423 return ExprError();
9425 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9426 if (!Update.isUsable())
9427 return ExprError();
9428
9429 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9430 // 'VarRef = Start (+|-) Iter * Step'.
9431 if (!Start.isUsable())
9432 return ExprError();
9433 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9434 if (!NewStart.isUsable())
9435 return ExprError();
9436 if (Captures && !IsNonRectangularLB)
9437 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9438 if (NewStart.isInvalid())
9439 return ExprError();
9440
9441 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9442 ExprResult SavedUpdate = Update;
9443 ExprResult UpdateVal;
9444 if (VarRef.get()->getType()->isOverloadableType() ||
9445 NewStart.get()->getType()->isOverloadableType() ||
9446 Update.get()->getType()->isOverloadableType()) {
9447 Sema::TentativeAnalysisScope Trap(SemaRef);
9448
9449 Update =
9450 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9451 if (Update.isUsable()) {
9452 UpdateVal =
9453 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9454 VarRef.get(), SavedUpdate.get());
9455 if (UpdateVal.isUsable()) {
9456 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9457 UpdateVal.get());
9458 }
9459 }
9460 }
9461
9462 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9463 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9464 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9465 NewStart.get(), SavedUpdate.get());
9466 if (!Update.isUsable())
9467 return ExprError();
9468
9469 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9470 VarRef.get()->getType())) {
9472 Update.get(), VarRef.get()->getType(), Sema::AA_Converting, true);
9473 if (!Update.isUsable())
9474 return ExprError();
9475 }
9476
9477 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9478 }
9479 return Update;
9480}
9481
9482/// Convert integer expression \a E to make it have at least \a Bits
9483/// bits.
9484static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9485 if (E == nullptr)
9486 return ExprError();
9487 ASTContext &C = SemaRef.Context;
9488 QualType OldType = E->getType();
9489 unsigned HasBits = C.getTypeSize(OldType);
9490 if (HasBits >= Bits)
9491 return ExprResult(E);
9492 // OK to convert to signed, because new type has more bits than old.
9493 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9494 return SemaRef.PerformImplicitConversion(E, NewType, Sema::AA_Converting,
9495 true);
9496}
9497
9498/// Check if the given expression \a E is a constant integer that fits
9499/// into \a Bits bits.
9500static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9501 if (E == nullptr)
9502 return false;
9503 if (std::optional<llvm::APSInt> Result =
9505 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9506 return false;
9507}
9508
9509/// Build preinits statement for the given declarations.
9511 MutableArrayRef<Decl *> PreInits) {
9512 if (!PreInits.empty()) {
9513 return new (Context) DeclStmt(
9514 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9516 }
9517 return nullptr;
9518}
9519
9520/// Append the \p Item or the content of a CompoundStmt to the list \p
9521/// TargetList.
9522///
9523/// A CompoundStmt is used as container in case multiple statements need to be
9524/// stored in lieu of using an explicit list. Flattening is necessary because
9525/// contained DeclStmts need to be visible after the execution of the list. Used
9526/// for OpenMP pre-init declarations/statements.
9528 Stmt *Item) {
9529 // nullptr represents an empty list.
9530 if (!Item)
9531 return;
9532
9533 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9534 llvm::append_range(TargetList, CS->body());
9535 else
9536 TargetList.push_back(Item);
9537}
9538
9539/// Build preinits statement for the given declarations.
9540static Stmt *
9542 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9543 if (!Captures.empty()) {
9544 SmallVector<Decl *, 16> PreInits;
9545 for (const auto &Pair : Captures)
9546 PreInits.push_back(Pair.second->getDecl());
9547 return buildPreInits(Context, PreInits);
9548 }
9549 return nullptr;
9550}
9551
9552/// Build pre-init statement for the given statements.
9553static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9554 if (PreInits.empty())
9555 return nullptr;
9556
9557 SmallVector<Stmt *> Stmts;
9558 for (Stmt *S : PreInits)
9559 appendFlattenedStmtList(Stmts, S);
9560 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9561}
9562
9563/// Build postupdate expression for the given list of postupdates expressions.
9564static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9565 Expr *PostUpdate = nullptr;
9566 if (!PostUpdates.empty()) {
9567 for (Expr *E : PostUpdates) {
9568 Expr *ConvE = S.BuildCStyleCastExpr(
9569 E->getExprLoc(),
9571 E->getExprLoc(), E)
9572 .get();
9573 PostUpdate = PostUpdate
9574 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9575 PostUpdate, ConvE)
9576 .get()
9577 : ConvE;
9578 }
9579 }
9580 return PostUpdate;
9581}
9582
9583/// Look for variables declared in the body parts of a for-loop nest. Used
9584/// for verifying loop nest structure before performing a loop collapse
9585/// operation.
9586class ForVarDeclFinder final : public RecursiveASTVisitor<ForVarDeclFinder> {
9587 int NestingDepth = 0;
9588 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9589
9590public:
9591 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9592 : VarDecls(VD) {}
9593
9595 ++NestingDepth;
9596 TraverseStmt(F->getBody());
9597 --NestingDepth;
9598 return false;
9599 }
9600
9602 ++NestingDepth;
9603 TraverseStmt(RF->getBody());
9604 --NestingDepth;
9605 return false;
9606 }
9607
9609 Decl *C = D->getCanonicalDecl();
9610 if (NestingDepth > 0)
9611 VarDecls.insert(C);
9612 return true;
9613 }
9614};
9615
9616/// Called on a for stmt to check itself and nested loops (if any).
9617/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9618/// number of collapsed loops otherwise.
9619static unsigned
9620checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9621 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9622 DSAStackTy &DSA,
9623 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9625 unsigned NestedLoopCount = 1;
9626 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9628 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9629
9630 if (CollapseLoopCountExpr) {
9631 // Found 'collapse' clause - calculate collapse number.
9633 if (!CollapseLoopCountExpr->isValueDependent() &&
9634 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9635 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9636
9637 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9638 FVDF.TraverseStmt(AStmt);
9639 } else {
9640 Built.clear(/*Size=*/1);
9641 return 1;
9642 }
9643 }
9644 unsigned OrderedLoopCount = 1;
9645 if (OrderedLoopCountExpr) {
9646 // Found 'ordered' clause - calculate collapse number.
9647 Expr::EvalResult EVResult;
9648 if (!OrderedLoopCountExpr->isValueDependent() &&
9649 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9650 SemaRef.getASTContext())) {
9651 llvm::APSInt Result = EVResult.Val.getInt();
9652 if (Result.getLimitedValue() < NestedLoopCount) {
9653 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9654 diag::err_omp_wrong_ordered_loop_count)
9655 << OrderedLoopCountExpr->getSourceRange();
9656 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9657 diag::note_collapse_loop_count)
9658 << CollapseLoopCountExpr->getSourceRange();
9659 }
9660 OrderedLoopCount = Result.getLimitedValue();
9661 } else {
9662 Built.clear(/*Size=*/1);
9663 return 1;
9664 }
9665 }
9666 // This is helper routine for loop directives (e.g., 'for', 'simd',
9667 // 'for simd', etc.).
9668 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9669 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9670 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9673 SupportsNonPerfectlyNested, NumLoops,
9674 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9675 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9676 &IterSpaces, &Captures,
9677 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9679 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9680 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9681 VarsWithImplicitDSA, IterSpaces, Captures,
9682 CollapsedLoopVarDecls))
9683 return true;
9684 if (Cnt > 0 && Cnt >= NestedLoopCount &&
9685 IterSpaces[Cnt].CounterVar) {
9686 // Handle initialization of captured loop iterator variables.
9687 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
9688 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
9689 Captures[DRE] = DRE;
9690 }
9691 }
9692 return false;
9693 },
9694 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
9695 Stmt *DependentPreInits = Transform->getPreInits();
9696 if (!DependentPreInits)
9697 return;
9698
9699 // Search for pre-init declared variables that need to be captured
9700 // to be referenceable inside the directive.
9701 SmallVector<Stmt *> Constituents;
9702 appendFlattenedStmtList(Constituents, DependentPreInits);
9703 for (Stmt *S : Constituents) {
9704 if (auto *DC = dyn_cast<DeclStmt>(S)) {
9705 for (Decl *C : DC->decls()) {
9706 auto *D = cast<VarDecl>(C);
9708 SemaRef, D, D->getType().getNonReferenceType(),
9709 Transform->getBeginLoc());
9710 Captures[Ref] = Ref;
9711 }
9712 }
9713 }
9714 }))
9715 return 0;
9716
9717 Built.clear(/*size=*/NestedLoopCount);
9718
9719 if (SemaRef.CurContext->isDependentContext())
9720 return NestedLoopCount;
9721
9722 // An example of what is generated for the following code:
9723 //
9724 // #pragma omp simd collapse(2) ordered(2)
9725 // for (i = 0; i < NI; ++i)
9726 // for (k = 0; k < NK; ++k)
9727 // for (j = J0; j < NJ; j+=2) {
9728 // <loop body>
9729 // }
9730 //
9731 // We generate the code below.
9732 // Note: the loop body may be outlined in CodeGen.
9733 // Note: some counters may be C++ classes, operator- is used to find number of
9734 // iterations and operator+= to calculate counter value.
9735 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
9736 // or i64 is currently supported).
9737 //
9738 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
9739 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
9740 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
9741 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
9742 // // similar updates for vars in clauses (e.g. 'linear')
9743 // <loop body (using local i and j)>
9744 // }
9745 // i = NI; // assign final values of counters
9746 // j = NJ;
9747 //
9748
9749 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
9750 // the iteration counts of the collapsed for loops.
9751 // Precondition tests if there is at least one iteration (all conditions are
9752 // true).
9753 auto PreCond = ExprResult(IterSpaces[0].PreCond);
9754 Expr *N0 = IterSpaces[0].NumIterations;
9755 ExprResult LastIteration32 =
9756 widenIterationCount(/*Bits=*/32,
9757 SemaRef
9758 .PerformImplicitConversion(
9759 N0->IgnoreImpCasts(), N0->getType(),
9760 Sema::AA_Converting, /*AllowExplicit=*/true)
9761 .get(),
9762 SemaRef);
9763 ExprResult LastIteration64 = widenIterationCount(
9764 /*Bits=*/64,
9765 SemaRef
9766 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
9768 /*AllowExplicit=*/true)
9769 .get(),
9770 SemaRef);
9771
9772 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
9773 return NestedLoopCount;
9774
9775 ASTContext &C = SemaRef.Context;
9776 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
9777
9778 Scope *CurScope = DSA.getCurScope();
9779 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
9780 if (PreCond.isUsable()) {
9781 PreCond =
9782 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
9783 PreCond.get(), IterSpaces[Cnt].PreCond);
9784 }
9785 Expr *N = IterSpaces[Cnt].NumIterations;
9787 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
9788 if (LastIteration32.isUsable())
9789 LastIteration32 = SemaRef.BuildBinOp(
9790 CurScope, Loc, BO_Mul, LastIteration32.get(),
9791 SemaRef
9794 /*AllowExplicit=*/true)
9795 .get());
9796 if (LastIteration64.isUsable())
9797 LastIteration64 = SemaRef.BuildBinOp(
9798 CurScope, Loc, BO_Mul, LastIteration64.get(),
9799 SemaRef
9802 /*AllowExplicit=*/true)
9803 .get());
9804 }
9805
9806 // Choose either the 32-bit or 64-bit version.
9807 ExprResult LastIteration = LastIteration64;
9808 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
9809 (LastIteration32.isUsable() &&
9810 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
9811 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
9812 fitsInto(
9813 /*Bits=*/32,
9814 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
9815 LastIteration64.get(), SemaRef))))
9816 LastIteration = LastIteration32;
9817 QualType VType = LastIteration.get()->getType();
9818 QualType RealVType = VType;
9819 QualType StrideVType = VType;
9820 if (isOpenMPTaskLoopDirective(DKind)) {
9821 VType =
9822 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
9823 StrideVType =
9824 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
9825 }
9826
9827 if (!LastIteration.isUsable())
9828 return 0;
9829
9830 // Save the number of iterations.
9831 ExprResult NumIterations = LastIteration;
9832 {
9833 LastIteration = SemaRef.BuildBinOp(
9834 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
9835 LastIteration.get(),
9836 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9837 if (!LastIteration.isUsable())
9838 return 0;
9839 }
9840
9841 // Calculate the last iteration number beforehand instead of doing this on
9842 // each iteration. Do not do this if the number of iterations may be kfold-ed.
9843 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
9844 ExprResult CalcLastIteration;
9845 if (!IsConstant) {
9846 ExprResult SaveRef =
9847 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
9848 LastIteration = SaveRef;
9849
9850 // Prepare SaveRef + 1.
9851 NumIterations = SemaRef.BuildBinOp(
9852 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
9853 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9854 if (!NumIterations.isUsable())
9855 return 0;
9856 }
9857
9858 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
9859
9860 // Build variables passed into runtime, necessary for worksharing directives.
9861 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
9866 // Lower bound variable, initialized with zero.
9867 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
9868 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
9869 SemaRef.AddInitializerToDecl(LBDecl,
9870 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9871 /*DirectInit=*/false);
9872
9873 // Upper bound variable, initialized with last iteration number.
9874 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
9875 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
9876 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
9877 /*DirectInit=*/false);
9878
9879 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
9880 // This will be used to implement clause 'lastprivate'.
9881 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
9882 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
9883 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
9884 SemaRef.AddInitializerToDecl(ILDecl,
9885 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9886 /*DirectInit=*/false);
9887
9888 // Stride variable returned by runtime (we initialize it to 1 by default).
9889 VarDecl *STDecl =
9890 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
9891 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
9892 SemaRef.AddInitializerToDecl(STDecl,
9893 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
9894 /*DirectInit=*/false);
9895
9896 // Build expression: UB = min(UB, LastIteration)
9897 // It is necessary for CodeGen of directives with static scheduling.
9898 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
9899 UB.get(), LastIteration.get());
9900 ExprResult CondOp = SemaRef.ActOnConditionalOp(
9901 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
9902 LastIteration.get(), UB.get());
9903 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
9904 CondOp.get());
9905 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
9906
9907 // If we have a combined directive that combines 'distribute', 'for' or
9908 // 'simd' we need to be able to access the bounds of the schedule of the
9909 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
9910 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
9912 // Lower bound variable, initialized with zero.
9913 VarDecl *CombLBDecl =
9914 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
9915 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
9916 SemaRef.AddInitializerToDecl(
9917 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
9918 /*DirectInit=*/false);
9919
9920 // Upper bound variable, initialized with last iteration number.
9921 VarDecl *CombUBDecl =
9922 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
9923 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
9924 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
9925 /*DirectInit=*/false);
9926
9927 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
9928 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
9929 ExprResult CombCondOp =
9930 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
9931 LastIteration.get(), CombUB.get());
9932 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
9933 CombCondOp.get());
9934 CombEUB =
9935 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
9936
9937 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
9938 // We expect to have at least 2 more parameters than the 'parallel'
9939 // directive does - the lower and upper bounds of the previous schedule.
9940 assert(CD->getNumParams() >= 4 &&
9941 "Unexpected number of parameters in loop combined directive");
9942
9943 // Set the proper type for the bounds given what we learned from the
9944 // enclosed loops.
9945 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
9946 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
9947
9948 // Previous lower and upper bounds are obtained from the region
9949 // parameters.
9950 PrevLB =
9951 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
9952 PrevUB =
9953 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
9954 }
9955 }
9956
9957 // Build the iteration variable and its initialization before loop.
9958 ExprResult IV;
9959 ExprResult Init, CombInit;
9960 {
9961 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
9962 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
9963 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
9968 ? LB.get()
9969 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9970 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
9971 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
9972
9974 Expr *CombRHS =
9979 ? CombLB.get()
9980 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
9981 CombInit =
9982 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
9983 CombInit =
9984 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
9985 }
9986 }
9987
9988 bool UseStrictCompare =
9989 RealVType->hasUnsignedIntegerRepresentation() &&
9990 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
9991 return LIS.IsStrictCompare;
9992 });
9993 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
9994 // unsigned IV)) for worksharing loops.
9995 SourceLocation CondLoc = AStmt->getBeginLoc();
9996 Expr *BoundUB = UB.get();
9997 if (UseStrictCompare) {
9998 BoundUB =
9999 SemaRef
10000 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10001 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10002 .get();
10003 BoundUB =
10004 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10005 }
10006 ExprResult Cond =
10011 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10012 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10013 BoundUB)
10014 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10015 NumIterations.get());
10016 ExprResult CombDistCond;
10018 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10019 NumIterations.get());
10020 }
10021
10022 ExprResult CombCond;
10024 Expr *BoundCombUB = CombUB.get();
10025 if (UseStrictCompare) {
10026 BoundCombUB =
10027 SemaRef
10028 .BuildBinOp(
10029 CurScope, CondLoc, BO_Add, BoundCombUB,
10030 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10031 .get();
10032 BoundCombUB =
10033 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10034 .get();
10035 }
10036 CombCond =
10037 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10038 IV.get(), BoundCombUB);
10039 }
10040 // Loop increment (IV = IV + 1)
10041 SourceLocation IncLoc = AStmt->getBeginLoc();
10042 ExprResult Inc =
10043 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10044 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10045 if (!Inc.isUsable())
10046 return 0;
10047 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10048 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10049 if (!Inc.isUsable())
10050 return 0;
10051
10052 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10053 // Used for directives with static scheduling.
10054 // In combined construct, add combined version that use CombLB and CombUB
10055 // base variables for the update
10056 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10061 // LB + ST
10062 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10063 if (!NextLB.isUsable())
10064 return 0;
10065 // LB = LB + ST
10066 NextLB =
10067 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10068 NextLB =
10069 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10070 if (!NextLB.isUsable())
10071 return 0;
10072 // UB + ST
10073 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10074 if (!NextUB.isUsable())
10075 return 0;
10076 // UB = UB + ST
10077 NextUB =
10078 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10079 NextUB =
10080 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10081 if (!NextUB.isUsable())
10082 return 0;
10084 CombNextLB =
10085 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10086 if (!NextLB.isUsable())
10087 return 0;
10088 // LB = LB + ST
10089 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10090 CombNextLB.get());
10091 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10092 /*DiscardedValue=*/false);
10093 if (!CombNextLB.isUsable())
10094 return 0;
10095 // UB + ST
10096 CombNextUB =
10097 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10098 if (!CombNextUB.isUsable())
10099 return 0;
10100 // UB = UB + ST
10101 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10102 CombNextUB.get());
10103 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10104 /*DiscardedValue=*/false);
10105 if (!CombNextUB.isUsable())
10106 return 0;
10107 }
10108 }
10109
10110 // Create increment expression for distribute loop when combined in a same
10111 // directive with for as IV = IV + ST; ensure upper bound expression based
10112 // on PrevUB instead of NumIterations - used to implement 'for' when found
10113 // in combination with 'distribute', like in 'distribute parallel for'
10114 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10115 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10117 DistCond = SemaRef.BuildBinOp(
10118 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10119 assert(DistCond.isUsable() && "distribute cond expr was not built");
10120
10121 DistInc =
10122 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10123 assert(DistInc.isUsable() && "distribute inc expr was not built");
10124 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10125 DistInc.get());
10126 DistInc =
10127 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10128 assert(DistInc.isUsable() && "distribute inc expr was not built");
10129
10130 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10131 // construct
10132 ExprResult NewPrevUB = PrevUB;
10133 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10134 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10135 PrevUB.get()->getType())) {
10136 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10137 DistEUBLoc,
10139 DistEUBLoc, NewPrevUB.get());
10140 if (!NewPrevUB.isUsable())
10141 return 0;
10142 }
10143 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10144 UB.get(), NewPrevUB.get());
10145 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10146 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10147 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10148 CondOp.get());
10149 PrevEUB =
10150 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10151
10152 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10153 // parallel for is in combination with a distribute directive with
10154 // schedule(static, 1)
10155 Expr *BoundPrevUB = PrevUB.get();
10156 if (UseStrictCompare) {
10157 BoundPrevUB =
10158 SemaRef
10159 .BuildBinOp(
10160 CurScope, CondLoc, BO_Add, BoundPrevUB,
10161 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10162 .get();
10163 BoundPrevUB =
10164 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10165 .get();
10166 }
10167 ParForInDistCond =
10168 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10169 IV.get(), BoundPrevUB);
10170 }
10171
10172 // Build updates and final values of the loop counters.
10173 bool HasErrors = false;
10174 Built.Counters.resize(NestedLoopCount);
10175 Built.Inits.resize(NestedLoopCount);
10176 Built.Updates.resize(NestedLoopCount);
10177 Built.Finals.resize(NestedLoopCount);
10178 Built.DependentCounters.resize(NestedLoopCount);
10179 Built.DependentInits.resize(NestedLoopCount);
10180 Built.FinalsConditions.resize(NestedLoopCount);
10181 {
10182 // We implement the following algorithm for obtaining the
10183 // original loop iteration variable values based on the
10184 // value of the collapsed loop iteration variable IV.
10185 //
10186 // Let n+1 be the number of collapsed loops in the nest.
10187 // Iteration variables (I0, I1, .... In)
10188 // Iteration counts (N0, N1, ... Nn)
10189 //
10190 // Acc = IV;
10191 //
10192 // To compute Ik for loop k, 0 <= k <= n, generate:
10193 // Prod = N(k+1) * N(k+2) * ... * Nn;
10194 // Ik = Acc / Prod;
10195 // Acc -= Ik * Prod;
10196 //
10197 ExprResult Acc = IV;
10198 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10199 LoopIterationSpace &IS = IterSpaces[Cnt];
10200 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10202
10203 // Compute prod
10204 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10205 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10206 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10207 IterSpaces[K].NumIterations);
10208
10209 // Iter = Acc / Prod
10210 // If there is at least one more inner loop to avoid
10211 // multiplication by 1.
10212 if (Cnt + 1 < NestedLoopCount)
10213 Iter =
10214 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10215 else
10216 Iter = Acc;
10217 if (!Iter.isUsable()) {
10218 HasErrors = true;
10219 break;
10220 }
10221
10222 // Update Acc:
10223 // Acc -= Iter * Prod
10224 // Check if there is at least one more inner loop to avoid
10225 // multiplication by 1.
10226 if (Cnt + 1 < NestedLoopCount)
10227 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10228 Prod.get());
10229 else
10230 Prod = Iter;
10231 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10232
10233 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10234 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10235 DeclRefExpr *CounterVar = buildDeclRefExpr(
10236 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10237 /*RefersToCapture=*/true);
10239 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10240 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10241 if (!Init.isUsable()) {
10242 HasErrors = true;
10243 break;
10244 }
10246 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10247 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10248 if (!Update.isUsable()) {
10249 HasErrors = true;
10250 break;
10251 }
10252
10253 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10254 ExprResult Final =
10255 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10256 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10257 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10258 if (!Final.isUsable()) {
10259 HasErrors = true;
10260 break;
10261 }
10262
10263 if (!Update.isUsable() || !Final.isUsable()) {
10264 HasErrors = true;
10265 break;
10266 }
10267 // Save results
10268 Built.Counters[Cnt] = IS.CounterVar;
10269 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10270 Built.Inits[Cnt] = Init.get();
10271 Built.Updates[Cnt] = Update.get();
10272 Built.Finals[Cnt] = Final.get();
10273 Built.DependentCounters[Cnt] = nullptr;
10274 Built.DependentInits[Cnt] = nullptr;
10275 Built.FinalsConditions[Cnt] = nullptr;
10276 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10277 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10278 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10279 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10280 }
10281 }
10282 }
10283
10284 if (HasErrors)
10285 return 0;
10286
10287 // Save results
10288 Built.IterationVarRef = IV.get();
10289 Built.LastIteration = LastIteration.get();
10290 Built.NumIterations = NumIterations.get();
10291 Built.CalcLastIteration = SemaRef
10292 .ActOnFinishFullExpr(CalcLastIteration.get(),
10293 /*DiscardedValue=*/false)
10294 .get();
10295 Built.PreCond = PreCond.get();
10296 Built.PreInits = buildPreInits(C, Captures);
10297 Built.Cond = Cond.get();
10298 Built.Init = Init.get();
10299 Built.Inc = Inc.get();
10300 Built.LB = LB.get();
10301 Built.UB = UB.get();
10302 Built.IL = IL.get();
10303 Built.ST = ST.get();
10304 Built.EUB = EUB.get();
10305 Built.NLB = NextLB.get();
10306 Built.NUB = NextUB.get();
10307 Built.PrevLB = PrevLB.get();
10308 Built.PrevUB = PrevUB.get();
10309 Built.DistInc = DistInc.get();
10310 Built.PrevEUB = PrevEUB.get();
10311 Built.DistCombinedFields.LB = CombLB.get();
10312 Built.DistCombinedFields.UB = CombUB.get();
10313 Built.DistCombinedFields.EUB = CombEUB.get();
10314 Built.DistCombinedFields.Init = CombInit.get();
10315 Built.DistCombinedFields.Cond = CombCond.get();
10316 Built.DistCombinedFields.NLB = CombNextLB.get();
10317 Built.DistCombinedFields.NUB = CombNextUB.get();
10318 Built.DistCombinedFields.DistCond = CombDistCond.get();
10319 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10320
10321 return NestedLoopCount;
10322}
10323
10325 auto CollapseClauses =
10326 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10327 if (CollapseClauses.begin() != CollapseClauses.end())
10328 return (*CollapseClauses.begin())->getNumForLoops();
10329 return nullptr;
10330}
10331
10333 auto OrderedClauses =
10334 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10335 if (OrderedClauses.begin() != OrderedClauses.end())
10336 return (*OrderedClauses.begin())->getNumForLoops();
10337 return nullptr;
10338}
10339
10341 const ArrayRef<OMPClause *> Clauses) {
10342 const OMPSafelenClause *Safelen = nullptr;
10343 const OMPSimdlenClause *Simdlen = nullptr;
10344
10345 for (const OMPClause *Clause : Clauses) {
10346 if (Clause->getClauseKind() == OMPC_safelen)
10347 Safelen = cast<OMPSafelenClause>(Clause);
10348 else if (Clause->getClauseKind() == OMPC_simdlen)
10349 Simdlen = cast<OMPSimdlenClause>(Clause);
10350 if (Safelen && Simdlen)
10351 break;
10352 }
10353
10354 if (Simdlen && Safelen) {
10355 const Expr *SimdlenLength = Simdlen->getSimdlen();
10356 const Expr *SafelenLength = Safelen->getSafelen();
10357 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10358 SimdlenLength->isInstantiationDependent() ||
10359 SimdlenLength->containsUnexpandedParameterPack())
10360 return false;
10361 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10362 SafelenLength->isInstantiationDependent() ||
10363 SafelenLength->containsUnexpandedParameterPack())
10364 return false;
10365 Expr::EvalResult SimdlenResult, SafelenResult;
10366 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10367 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10368 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10369 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10370 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10371 // If both simdlen and safelen clauses are specified, the value of the
10372 // simdlen parameter must be less than or equal to the value of the safelen
10373 // parameter.
10374 if (SimdlenRes > SafelenRes) {
10375 S.Diag(SimdlenLength->getExprLoc(),
10376 diag::err_omp_wrong_simdlen_safelen_values)
10377 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10378 return true;
10379 }
10380 }
10381 return false;
10382}
10383
10385 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10386 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10387 if (!AStmt)
10388 return StmtError();
10389
10390 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10391
10392 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10394 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10395 // define the nested loops number.
10396 unsigned NestedLoopCount = checkOpenMPLoop(
10397 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10398 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10399 if (NestedLoopCount == 0)
10400 return StmtError();
10401
10402 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10403 return StmtError();
10404
10406 return StmtError();
10407
10408 auto *SimdDirective = OMPSimdDirective::Create(
10409 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10410 return SimdDirective;
10411}
10412
10414 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10415 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10416 if (!AStmt)
10417 return StmtError();
10418
10419 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10421 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10422 // define the nested loops number.
10423 unsigned NestedLoopCount = checkOpenMPLoop(
10424 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10425 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10426 if (NestedLoopCount == 0)
10427 return StmtError();
10428
10429 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10430 return StmtError();
10431
10432 auto *ForDirective = OMPForDirective::Create(
10433 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10434 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10435 return ForDirective;
10436}
10437
10439 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10440 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10441 if (!AStmt)
10442 return StmtError();
10443
10444 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10445
10446 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10448 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10449 // define the nested loops number.
10450 unsigned NestedLoopCount =
10451 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10452 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10453 VarsWithImplicitDSA, B);
10454 if (NestedLoopCount == 0)
10455 return StmtError();
10456
10457 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10458 return StmtError();
10459
10461 return StmtError();
10462
10463 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10464 NestedLoopCount, Clauses, AStmt, B);
10465}
10466
10468 Stmt *AStmt, DSAStackTy *Stack) {
10469 if (!AStmt)
10470 return true;
10471
10472 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10473 auto BaseStmt = AStmt;
10474 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10475 BaseStmt = CS->getCapturedStmt();
10476 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10477 auto S = C->children();
10478 if (S.begin() == S.end())
10479 return true;
10480 // All associated statements must be '#pragma omp section' except for
10481 // the first one.
10482 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10483 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10484 if (SectionStmt)
10485 SemaRef.Diag(SectionStmt->getBeginLoc(),
10486 diag::err_omp_sections_substmt_not_section)
10487 << getOpenMPDirectiveName(DKind);
10488 return true;
10489 }
10490 cast<OMPSectionDirective>(SectionStmt)
10491 ->setHasCancel(Stack->isCancelRegion());
10492 }
10493 } else {
10494 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10495 << getOpenMPDirectiveName(DKind);
10496 return true;
10497 }
10498 return false;
10499}
10500
10503 Stmt *AStmt, SourceLocation StartLoc,
10504 SourceLocation EndLoc) {
10505 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10506 return StmtError();
10507
10509
10511 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10512 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10513}
10514
10516 SourceLocation StartLoc,
10517 SourceLocation EndLoc) {
10518 if (!AStmt)
10519 return StmtError();
10520
10522 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10523
10524 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10525 DSAStack->isCancelRegion());
10526}
10527
10530 if (auto *CE = dyn_cast<CallExpr>(E))
10531 if (CE->getDirectCallee())
10532 return E;
10533 return nullptr;
10534}
10535
10538 Stmt *AStmt, SourceLocation StartLoc,
10539 SourceLocation EndLoc) {
10540 if (!AStmt)
10541 return StmtError();
10542
10543 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10544
10545 // 5.1 OpenMP
10546 // expression-stmt : an expression statement with one of the following forms:
10547 // expression = target-call ( [expression-list] );
10548 // target-call ( [expression-list] );
10549
10550 SourceLocation TargetCallLoc;
10551
10553 Expr *TargetCall = nullptr;
10554
10555 auto *E = dyn_cast<Expr>(S);
10556 if (!E) {
10557 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10558 return StmtError();
10559 }
10560
10562
10563 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10564 if (BO->getOpcode() == BO_Assign)
10565 TargetCall = getDirectCallExpr(BO->getRHS());
10566 } else {
10567 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10568 if (COCE->getOperator() == OO_Equal)
10569 TargetCall = getDirectCallExpr(COCE->getArg(1));
10570 if (!TargetCall)
10571 TargetCall = getDirectCallExpr(E);
10572 }
10573 if (!TargetCall) {
10574 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10575 return StmtError();
10576 }
10577 TargetCallLoc = TargetCall->getExprLoc();
10578 }
10579
10581
10582 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10583 Clauses, AStmt, TargetCallLoc);
10584}
10585
10588 DSAStackTy *Stack) {
10589 bool ErrorFound = false;
10590 for (OMPClause *C : Clauses) {
10591 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10592 for (Expr *RefExpr : LPC->varlist()) {
10593 SourceLocation ELoc;
10594 SourceRange ERange;
10595 Expr *SimpleRefExpr = RefExpr;
10596 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10597 if (ValueDecl *D = Res.first) {
10598 auto &&Info = Stack->isLoopControlVariable(D);
10599 if (!Info.first) {
10600 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10601 << getOpenMPDirectiveName(K);
10602 ErrorFound = true;
10603 }
10604 }
10605 }
10606 }
10607 }
10608 return ErrorFound;
10609}
10610
10612 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10613 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10614 if (!AStmt)
10615 return StmtError();
10616
10617 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10618 // A list item may not appear in a lastprivate clause unless it is the
10619 // loop iteration variable of a loop that is associated with the construct.
10620 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10621 return StmtError();
10622
10623 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10624
10626 // In presence of clause 'collapse', it will define the nested loops number.
10627 unsigned NestedLoopCount = checkOpenMPLoop(
10628 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10629 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10630 if (NestedLoopCount == 0)
10631 return StmtError();
10632
10633 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10634 "omp loop exprs were not built");
10635
10636 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10637 NestedLoopCount, Clauses, AStmt, B);
10638}
10639
10641 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10642 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10643 if (!AStmt)
10644 return StmtError();
10645
10646 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10647 // A list item may not appear in a lastprivate clause unless it is the
10648 // loop iteration variable of a loop that is associated with the construct.
10649 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10650 return StmtError();
10651
10652 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10653
10655 // In presence of clause 'collapse', it will define the nested loops number.
10656 unsigned NestedLoopCount =
10657 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10658 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10659 VarsWithImplicitDSA, B);
10660 if (NestedLoopCount == 0)
10661 return StmtError();
10662
10663 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10664 "omp loop exprs were not built");
10665
10666 DSAStack->setParentTeamsRegionLoc(StartLoc);
10667
10669 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10670}
10671
10673 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10674 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10675 if (!AStmt)
10676 return StmtError();
10677
10678 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10679 // A list item may not appear in a lastprivate clause unless it is the
10680 // loop iteration variable of a loop that is associated with the construct.
10681 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
10682 DSAStack))
10683 return StmtError();
10684
10685 CapturedStmt *CS =
10686 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
10687
10689 // In presence of clause 'collapse', it will define the nested loops number.
10690 unsigned NestedLoopCount =
10691 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
10692 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10693 VarsWithImplicitDSA, B);
10694 if (NestedLoopCount == 0)
10695 return StmtError();
10696
10697 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10698 "omp loop exprs were not built");
10699
10701 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10703}
10704
10706 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10707 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10708 if (!AStmt)
10709 return StmtError();
10710
10711 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10712 // A list item may not appear in a lastprivate clause unless it is the
10713 // loop iteration variable of a loop that is associated with the construct.
10714 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
10715 DSAStack))
10716 return StmtError();
10717
10718 CapturedStmt *CS =
10719 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
10720
10722 // In presence of clause 'collapse', it will define the nested loops number.
10723 unsigned NestedLoopCount =
10724 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
10725 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10726 VarsWithImplicitDSA, B);
10727 if (NestedLoopCount == 0)
10728 return StmtError();
10729
10730 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10731 "omp loop exprs were not built");
10732
10734 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10735}
10736
10738 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10739 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10740 if (!AStmt)
10741 return StmtError();
10742
10743 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10744 // A list item may not appear in a lastprivate clause unless it is the
10745 // loop iteration variable of a loop that is associated with the construct.
10746 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
10747 DSAStack))
10748 return StmtError();
10749
10750 CapturedStmt *CS =
10751 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
10752
10754 // In presence of clause 'collapse', it will define the nested loops number.
10755 unsigned NestedLoopCount =
10756 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
10757 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10758 VarsWithImplicitDSA, B);
10759 if (NestedLoopCount == 0)
10760 return StmtError();
10761
10762 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10763 "omp loop exprs were not built");
10764
10766 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10767}
10768
10770 Stmt *AStmt,
10771 SourceLocation StartLoc,
10772 SourceLocation EndLoc) {
10773 if (!AStmt)
10774 return StmtError();
10775
10776 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10777
10779
10780 // OpenMP [2.7.3, single Construct, Restrictions]
10781 // The copyprivate clause must not be used with the nowait clause.
10782 const OMPClause *Nowait = nullptr;
10783 const OMPClause *Copyprivate = nullptr;
10784 for (const OMPClause *Clause : Clauses) {
10785 if (Clause->getClauseKind() == OMPC_nowait)
10786 Nowait = Clause;
10787 else if (Clause->getClauseKind() == OMPC_copyprivate)
10788 Copyprivate = Clause;
10789 if (Copyprivate && Nowait) {
10790 Diag(Copyprivate->getBeginLoc(),
10791 diag::err_omp_single_copyprivate_with_nowait);
10792 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
10793 return StmtError();
10794 }
10795 }
10796
10797 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10798 AStmt);
10799}
10800
10802 SourceLocation StartLoc,
10803 SourceLocation EndLoc) {
10804 if (!AStmt)
10805 return StmtError();
10806
10808
10809 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
10810}
10811
10813 Stmt *AStmt,
10814 SourceLocation StartLoc,
10815 SourceLocation EndLoc) {
10816 if (!AStmt)
10817 return StmtError();
10818
10820
10821 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
10822 AStmt);
10823}
10824
10826 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
10827 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
10828 if (!AStmt)
10829 return StmtError();
10830
10831 bool ErrorFound = false;
10832 llvm::APSInt Hint;
10833 SourceLocation HintLoc;
10834 bool DependentHint = false;
10835 for (const OMPClause *C : Clauses) {
10836 if (C->getClauseKind() == OMPC_hint) {
10837 if (!DirName.getName()) {
10838 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
10839 ErrorFound = true;
10840 }
10841 Expr *E = cast<OMPHintClause>(C)->getHint();
10842 if (E->isTypeDependent() || E->isValueDependent() ||
10844 DependentHint = true;
10845 } else {
10847 HintLoc = C->getBeginLoc();
10848 }
10849 }
10850 }
10851 if (ErrorFound)
10852 return StmtError();
10853 const auto Pair = DSAStack->getCriticalWithHint(DirName);
10854 if (Pair.first && DirName.getName() && !DependentHint) {
10855 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
10856 Diag(StartLoc, diag::err_omp_critical_with_hint);
10857 if (HintLoc.isValid())
10858 Diag(HintLoc, diag::note_omp_critical_hint_here)
10859 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
10860 else
10861 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
10862 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
10863 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
10864 << 1
10865 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
10866 /*Radix=*/10, /*Signed=*/false);
10867 } else {
10868 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
10869 }
10870 }
10871 }
10872
10874
10875 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
10876 EndLoc, Clauses, AStmt);
10877 if (!Pair.first && DirName.getName() && !DependentHint)
10878 DSAStack->addCriticalWithHint(Dir, Hint);
10879 return Dir;
10880}
10881
10883 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10884 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10885 if (!AStmt)
10886 return StmtError();
10887
10888 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
10889
10891 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10892 // define the nested loops number.
10893 unsigned NestedLoopCount =
10894 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
10895 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
10896 VarsWithImplicitDSA, B);
10897 if (NestedLoopCount == 0)
10898 return StmtError();
10899
10900 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10901 return StmtError();
10902
10904 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10905 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10906}
10907
10909 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10910 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10911 if (!AStmt)
10912 return StmtError();
10913
10914 CapturedStmt *CS =
10915 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
10916
10918 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10919 // define the nested loops number.
10920 unsigned NestedLoopCount =
10921 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
10922 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10923 VarsWithImplicitDSA, B);
10924 if (NestedLoopCount == 0)
10925 return StmtError();
10926
10927 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10928 return StmtError();
10929
10931 return StmtError();
10932
10934 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10935}
10936
10938 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10939 SourceLocation EndLoc) {
10940 if (!AStmt)
10941 return StmtError();
10942
10943 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
10944
10946 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10947 DSAStack->getTaskgroupReductionRef());
10948}
10949
10951 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10952 SourceLocation EndLoc) {
10953 if (!AStmt)
10954 return StmtError();
10955
10956 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
10957
10959 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10960 DSAStack->getTaskgroupReductionRef());
10961}
10962
10964 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10965 SourceLocation EndLoc) {
10966 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
10967 return StmtError();
10968
10970
10972 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10973 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10974}
10975
10976/// Find and diagnose mutually exclusive clause kinds.
10978 Sema &S, ArrayRef<OMPClause *> Clauses,
10979 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
10980 const OMPClause *PrevClause = nullptr;
10981 bool ErrorFound = false;
10982 for (const OMPClause *C : Clauses) {
10983 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
10984 if (!PrevClause) {
10985 PrevClause = C;
10986 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
10987 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
10988 << getOpenMPClauseName(C->getClauseKind())
10989 << getOpenMPClauseName(PrevClause->getClauseKind());
10990 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
10991 << getOpenMPClauseName(PrevClause->getClauseKind());
10992 ErrorFound = true;
10993 }
10994 }
10995 }
10996 return ErrorFound;
10997}
10998
11000 Stmt *AStmt,
11001 SourceLocation StartLoc,
11002 SourceLocation EndLoc) {
11003 if (!AStmt)
11004 return StmtError();
11005
11006 // OpenMP 5.0, 2.10.1 task Construct
11007 // If a detach clause appears on the directive, then a mergeable clause cannot
11008 // appear on the same directive.
11010 {OMPC_detach, OMPC_mergeable}))
11011 return StmtError();
11012
11013 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11014
11015 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11016 AStmt, DSAStack->isCancelRegion());
11017}
11018
11020 SourceLocation EndLoc) {
11021 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11022}
11023
11025 SourceLocation EndLoc) {
11026 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11027}
11028
11030 SourceLocation StartLoc,
11031 SourceLocation EndLoc,
11032 bool InExContext) {
11033 const OMPAtClause *AtC =
11034 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11035
11036 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11037 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11038 return StmtError();
11039 }
11040
11041 const OMPSeverityClause *SeverityC =
11042 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11043 const OMPMessageClause *MessageC =
11044 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11045 Expr *ME = MessageC ? MessageC->getMessageString() : nullptr;
11046
11047 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11048 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11049 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11050 << (ME ? cast<StringLiteral>(ME)->getString() : "WARNING");
11051 else
11052 Diag(StartLoc, diag::err_diagnose_if_succeeded)
11053 << (ME ? cast<StringLiteral>(ME)->getString() : "ERROR");
11054 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11055 return StmtError();
11056 }
11057 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11058}
11059
11062 SourceLocation StartLoc,
11063 SourceLocation EndLoc) {
11064 const OMPNowaitClause *NowaitC =
11065 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11066 bool HasDependC =
11067 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11068 .empty();
11069 if (NowaitC && !HasDependC) {
11070 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11071 return StmtError();
11072 }
11073
11074 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11075 Clauses);
11076}
11077
11080 Stmt *AStmt, SourceLocation StartLoc,
11081 SourceLocation EndLoc) {
11082 if (!AStmt)
11083 return StmtError();
11084
11085 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11086
11088
11089 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11090 Clauses, AStmt,
11091 DSAStack->getTaskgroupReductionRef());
11092}
11093
11095 SourceLocation StartLoc,
11096 SourceLocation EndLoc) {
11097 OMPFlushClause *FC = nullptr;
11098 OMPClause *OrderClause = nullptr;
11099 for (OMPClause *C : Clauses) {
11100 if (C->getClauseKind() == OMPC_flush)
11101 FC = cast<OMPFlushClause>(C);
11102 else
11103 OrderClause = C;
11104 }
11105 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11106 SourceLocation MemOrderLoc;
11107 for (const OMPClause *C : Clauses) {
11108 if (C->getClauseKind() == OMPC_acq_rel ||
11109 C->getClauseKind() == OMPC_acquire ||
11110 C->getClauseKind() == OMPC_release) {
11111 if (MemOrderKind != OMPC_unknown) {
11112 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11113 << getOpenMPDirectiveName(OMPD_flush) << 1
11114 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11115 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11116 << getOpenMPClauseName(MemOrderKind);
11117 } else {
11118 MemOrderKind = C->getClauseKind();
11119 MemOrderLoc = C->getBeginLoc();
11120 }
11121 }
11122 }
11123 if (FC && OrderClause) {
11124 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11125 << getOpenMPClauseName(OrderClause->getClauseKind());
11126 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11127 << getOpenMPClauseName(OrderClause->getClauseKind());
11128 return StmtError();
11129 }
11130 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11131}
11132
11134 SourceLocation StartLoc,
11135 SourceLocation EndLoc) {
11136 if (Clauses.empty()) {
11137 Diag(StartLoc, diag::err_omp_depobj_expected);
11138 return StmtError();
11139 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11140 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11141 return StmtError();
11142 }
11143 // Only depobj expression and another single clause is allowed.
11144 if (Clauses.size() > 2) {
11145 Diag(Clauses[2]->getBeginLoc(),
11146 diag::err_omp_depobj_single_clause_expected);
11147 return StmtError();
11148 } else if (Clauses.size() < 1) {
11149 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11150 return StmtError();
11151 }
11152 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11153}
11154
11156 SourceLocation StartLoc,
11157 SourceLocation EndLoc) {
11158 // Check that exactly one clause is specified.
11159 if (Clauses.size() != 1) {
11160 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11161 diag::err_omp_scan_single_clause_expected);
11162 return StmtError();
11163 }
11164 // Check that scan directive is used in the scope of the OpenMP loop body.
11165 if (Scope *S = DSAStack->getCurScope()) {
11166 Scope *ParentS = S->getParent();
11167 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11168 !ParentS->getBreakParent()->isOpenMPLoopScope())
11169 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11170 << getOpenMPDirectiveName(OMPD_scan) << 5);
11171 }
11172 // Check that only one instance of scan directives is used in the same outer
11173 // region.
11174 if (DSAStack->doesParentHasScanDirective()) {
11175 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11176 Diag(DSAStack->getParentScanDirectiveLoc(),
11177 diag::note_omp_previous_directive)
11178 << "scan";
11179 return StmtError();
11180 }
11181 DSAStack->setParentHasScanDirective(StartLoc);
11182 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11183}
11184
11187 Stmt *AStmt, SourceLocation StartLoc,
11188 SourceLocation EndLoc) {
11189 const OMPClause *DependFound = nullptr;
11190 const OMPClause *DependSourceClause = nullptr;
11191 const OMPClause *DependSinkClause = nullptr;
11192 const OMPClause *DoacrossFound = nullptr;
11193 const OMPClause *DoacrossSourceClause = nullptr;
11194 const OMPClause *DoacrossSinkClause = nullptr;
11195 bool ErrorFound = false;
11196 const OMPThreadsClause *TC = nullptr;
11197 const OMPSIMDClause *SC = nullptr;
11198 for (const OMPClause *C : Clauses) {
11199 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11200 auto DC = dyn_cast<OMPDependClause>(C);
11201 if (DC || DOC) {
11202 DependFound = DC ? C : nullptr;
11203 DoacrossFound = DOC ? C : nullptr;
11204 OMPDoacrossKind ODK;
11205 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11206 (DOC && (ODK.isSource(DOC)))) {
11207 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11208 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11209 << getOpenMPDirectiveName(OMPD_ordered)
11210 << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
11211 ErrorFound = true;
11212 } else {
11213 if (DC)
11214 DependSourceClause = C;
11215 else
11216 DoacrossSourceClause = C;
11217 }
11218 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11219 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11220 << (DC ? "depend" : "doacross") << 0;
11221 ErrorFound = true;
11222 }
11223 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11224 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11225 if (DependSourceClause || DoacrossSourceClause) {
11226 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11227 << (DC ? "depend" : "doacross") << 1;
11228 ErrorFound = true;
11229 }
11230 if (DC)
11231 DependSinkClause = C;
11232 else
11233 DoacrossSinkClause = C;
11234 }
11235 } else if (C->getClauseKind() == OMPC_threads) {
11236 TC = cast<OMPThreadsClause>(C);
11237 } else if (C->getClauseKind() == OMPC_simd) {
11238 SC = cast<OMPSIMDClause>(C);
11239 }
11240 }
11241 if (!ErrorFound && !SC &&
11242 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11243 // OpenMP [2.8.1,simd Construct, Restrictions]
11244 // An ordered construct with the simd clause is the only OpenMP construct
11245 // that can appear in the simd region.
11246 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11247 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11248 ErrorFound = true;
11249 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11251 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11252 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11253 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
11254 << getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
11255 ErrorFound = true;
11256 } else if ((DependFound || DoacrossFound) &&
11257 !DSAStack->getParentOrderedRegionParam().first) {
11259 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11260 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11261 << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
11262 ErrorFound = true;
11263 } else if (TC || Clauses.empty()) {
11264 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11265 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11266 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11267 << (TC != nullptr);
11268 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11269 ErrorFound = true;
11270 }
11271 }
11272 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11273 return StmtError();
11274
11275 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11276 // During execution of an iteration of a worksharing-loop or a loop nest
11277 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11278 // must not execute more than one ordered region corresponding to an ordered
11279 // construct without a depend clause.
11280 if (!DependFound && !DoacrossFound) {
11281 if (DSAStack->doesParentHasOrderedDirective()) {
11282 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11283 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11284 diag::note_omp_previous_directive)
11285 << "ordered";
11286 return StmtError();
11287 }
11288 DSAStack->setParentHasOrderedDirective(StartLoc);
11289 }
11290
11291 if (AStmt) {
11292 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11293
11295 }
11296
11297 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11298 AStmt);
11299}
11300
11301namespace {
11302/// Helper class for checking expression in 'omp atomic [update]'
11303/// construct.
11304class OpenMPAtomicUpdateChecker {
11305 /// Error results for atomic update expressions.
11306 enum ExprAnalysisErrorCode {
11307 /// A statement is not an expression statement.
11308 NotAnExpression,
11309 /// Expression is not builtin binary or unary operation.
11310 NotABinaryOrUnaryExpression,
11311 /// Unary operation is not post-/pre- increment/decrement operation.
11312 NotAnUnaryIncDecExpression,
11313 /// An expression is not of scalar type.
11314 NotAScalarType,
11315 /// A binary operation is not an assignment operation.
11316 NotAnAssignmentOp,
11317 /// RHS part of the binary operation is not a binary expression.
11318 NotABinaryExpression,
11319 /// RHS part is not additive/multiplicative/shift/bitwise binary
11320 /// expression.
11321 NotABinaryOperator,
11322 /// RHS binary operation does not have reference to the updated LHS
11323 /// part.
11324 NotAnUpdateExpression,
11325 /// An expression contains semantical error not related to
11326 /// 'omp atomic [update]'
11327 NotAValidExpression,
11328 /// No errors is found.
11329 NoError
11330 };
11331 /// Reference to Sema.
11332 Sema &SemaRef;
11333 /// A location for note diagnostics (when error is found).
11334 SourceLocation NoteLoc;
11335 /// 'x' lvalue part of the source atomic expression.
11336 Expr *X;
11337 /// 'expr' rvalue part of the source atomic expression.
11338 Expr *E;
11339 /// Helper expression of the form
11340 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11341 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11342 Expr *UpdateExpr;
11343 /// Is 'x' a LHS in a RHS part of full update expression. It is
11344 /// important for non-associative operations.
11345 bool IsXLHSInRHSPart;
11347 SourceLocation OpLoc;
11348 /// true if the source expression is a postfix unary operation, false
11349 /// if it is a prefix unary operation.
11350 bool IsPostfixUpdate;
11351
11352public:
11353 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11354 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11355 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11356 /// Check specified statement that it is suitable for 'atomic update'
11357 /// constructs and extract 'x', 'expr' and Operation from the original
11358 /// expression. If DiagId and NoteId == 0, then only check is performed
11359 /// without error notification.
11360 /// \param DiagId Diagnostic which should be emitted if error is found.
11361 /// \param NoteId Diagnostic note for the main error message.
11362 /// \return true if statement is not an update expression, false otherwise.
11363 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11364 /// Return the 'x' lvalue part of the source atomic expression.
11365 Expr *getX() const { return X; }
11366 /// Return the 'expr' rvalue part of the source atomic expression.
11367 Expr *getExpr() const { return E; }
11368 /// Return the update expression used in calculation of the updated
11369 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11370 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11371 Expr *getUpdateExpr() const { return UpdateExpr; }
11372 /// Return true if 'x' is LHS in RHS part of full update expression,
11373 /// false otherwise.
11374 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11375
11376 /// true if the source expression is a postfix unary operation, false
11377 /// if it is a prefix unary operation.
11378 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11379
11380private:
11381 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11382 unsigned NoteId = 0);
11383};
11384
11385bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11386 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11387 ExprAnalysisErrorCode ErrorFound = NoError;
11388 SourceLocation ErrorLoc, NoteLoc;
11389 SourceRange ErrorRange, NoteRange;
11390 // Allowed constructs are:
11391 // x = x binop expr;
11392 // x = expr binop x;
11393 if (AtomicBinOp->getOpcode() == BO_Assign) {
11394 X = AtomicBinOp->getLHS();
11395 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11396 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11397 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11398 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11399 AtomicInnerBinOp->isBitwiseOp()) {
11400 Op = AtomicInnerBinOp->getOpcode();
11401 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11402 Expr *LHS = AtomicInnerBinOp->getLHS();
11403 Expr *RHS = AtomicInnerBinOp->getRHS();
11404 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11405 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11406 /*Canonical=*/true);
11407 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11408 /*Canonical=*/true);
11409 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11410 /*Canonical=*/true);
11411 if (XId == LHSId) {
11412 E = RHS;
11413 IsXLHSInRHSPart = true;
11414 } else if (XId == RHSId) {
11415 E = LHS;
11416 IsXLHSInRHSPart = false;
11417 } else {
11418 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11419 ErrorRange = AtomicInnerBinOp->getSourceRange();
11420 NoteLoc = X->getExprLoc();
11421 NoteRange = X->getSourceRange();
11422 ErrorFound = NotAnUpdateExpression;
11423 }
11424 } else {
11425 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11426 ErrorRange = AtomicInnerBinOp->getSourceRange();
11427 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11428 NoteRange = SourceRange(NoteLoc, NoteLoc);
11429 ErrorFound = NotABinaryOperator;
11430 }
11431 } else {
11432 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11433 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11434 ErrorFound = NotABinaryExpression;
11435 }
11436 } else {
11437 ErrorLoc = AtomicBinOp->getExprLoc();
11438 ErrorRange = AtomicBinOp->getSourceRange();
11439 NoteLoc = AtomicBinOp->getOperatorLoc();
11440 NoteRange = SourceRange(NoteLoc, NoteLoc);
11441 ErrorFound = NotAnAssignmentOp;
11442 }
11443 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11444 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11445 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11446 return true;
11447 }
11448 if (SemaRef.CurContext->isDependentContext())
11449 E = X = UpdateExpr = nullptr;
11450 return ErrorFound != NoError;
11451}
11452
11453bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11454 unsigned NoteId) {
11455 ExprAnalysisErrorCode ErrorFound = NoError;
11456 SourceLocation ErrorLoc, NoteLoc;
11457 SourceRange ErrorRange, NoteRange;
11458 // Allowed constructs are:
11459 // x++;
11460 // x--;
11461 // ++x;
11462 // --x;
11463 // x binop= expr;
11464 // x = x binop expr;
11465 // x = expr binop x;
11466 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11467 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11468 if (AtomicBody->getType()->isScalarType() ||
11469 AtomicBody->isInstantiationDependent()) {
11470 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11471 AtomicBody->IgnoreParenImpCasts())) {
11472 // Check for Compound Assignment Operation
11474 AtomicCompAssignOp->getOpcode());
11475 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11476 E = AtomicCompAssignOp->getRHS();
11477 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11478 IsXLHSInRHSPart = true;
11479 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11480 AtomicBody->IgnoreParenImpCasts())) {
11481 // Check for Binary Operation
11482 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11483 return true;
11484 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11485 AtomicBody->IgnoreParenImpCasts())) {
11486 // Check for Unary Operation
11487 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11488 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11489 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11490 OpLoc = AtomicUnaryOp->getOperatorLoc();
11491 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11492 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11493 IsXLHSInRHSPart = true;
11494 } else {
11495 ErrorFound = NotAnUnaryIncDecExpression;
11496 ErrorLoc = AtomicUnaryOp->getExprLoc();
11497 ErrorRange = AtomicUnaryOp->getSourceRange();
11498 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11499 NoteRange = SourceRange(NoteLoc, NoteLoc);
11500 }
11501 } else if (!AtomicBody->isInstantiationDependent()) {
11502 ErrorFound = NotABinaryOrUnaryExpression;
11503 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11504 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11505 } else if (AtomicBody->containsErrors()) {
11506 ErrorFound = NotAValidExpression;
11507 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11508 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11509 }
11510 } else {
11511 ErrorFound = NotAScalarType;
11512 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11513 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11514 }
11515 } else {
11516 ErrorFound = NotAnExpression;
11517 NoteLoc = ErrorLoc = S->getBeginLoc();
11518 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11519 }
11520 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11521 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11522 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11523 return true;
11524 }
11525 if (SemaRef.CurContext->isDependentContext())
11526 E = X = UpdateExpr = nullptr;
11527 if (ErrorFound == NoError && E && X) {
11528 // Build an update expression of form 'OpaqueValueExpr(x) binop
11529 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11530 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11531 auto *OVEX = new (SemaRef.getASTContext())
11532 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11533 auto *OVEExpr = new (SemaRef.getASTContext())
11536 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11537 IsXLHSInRHSPart ? OVEExpr : OVEX);
11538 if (Update.isInvalid())
11539 return true;
11540 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11542 if (Update.isInvalid())
11543 return true;
11544 UpdateExpr = Update.get();
11545 }
11546 return ErrorFound != NoError;
11547}
11548
11549/// Get the node id of the fixed point of an expression \a S.
11550llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11551 llvm::FoldingSetNodeID Id;
11552 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11553 return Id;
11554}
11555
11556/// Check if two expressions are same.
11557bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11558 const Expr *RHS) {
11559 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11560}
11561
11562class OpenMPAtomicCompareChecker {
11563public:
11564 /// All kinds of errors that can occur in `atomic compare`
11565 enum ErrorTy {
11566 /// Empty compound statement.
11567 NoStmt = 0,
11568 /// More than one statement in a compound statement.
11569 MoreThanOneStmt,
11570 /// Not an assignment binary operator.
11571 NotAnAssignment,
11572 /// Not a conditional operator.
11573 NotCondOp,
11574 /// Wrong false expr. According to the spec, 'x' should be at the false
11575 /// expression of a conditional expression.
11576 WrongFalseExpr,
11577 /// The condition of a conditional expression is not a binary operator.
11578 NotABinaryOp,
11579 /// Invalid binary operator (not <, >, or ==).
11580 InvalidBinaryOp,
11581 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11582 InvalidComparison,
11583 /// X is not a lvalue.
11584 XNotLValue,
11585 /// Not a scalar.
11586 NotScalar,
11587 /// Not an integer.
11588 NotInteger,
11589 /// 'else' statement is not expected.
11590 UnexpectedElse,
11591 /// Not an equality operator.
11592 NotEQ,
11593 /// Invalid assignment (not v == x).
11594 InvalidAssignment,
11595 /// Not if statement
11596 NotIfStmt,
11597 /// More than two statements in a compound statement.
11598 MoreThanTwoStmts,
11599 /// Not a compound statement.
11600 NotCompoundStmt,
11601 /// No else statement.
11602 NoElse,
11603 /// Not 'if (r)'.
11604 InvalidCondition,
11605 /// No error.
11606 NoError,
11607 };
11608
11609 struct ErrorInfoTy {
11610 ErrorTy Error;
11611 SourceLocation ErrorLoc;
11612 SourceRange ErrorRange;
11613 SourceLocation NoteLoc;
11614 SourceRange NoteRange;
11615 };
11616
11617 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11618
11619 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11620 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11621
11622 Expr *getX() const { return X; }
11623 Expr *getE() const { return E; }
11624 Expr *getD() const { return D; }
11625 Expr *getCond() const { return C; }
11626 bool isXBinopExpr() const { return IsXBinopExpr; }
11627
11628protected:
11629 /// Reference to ASTContext
11630 ASTContext &ContextRef;
11631 /// 'x' lvalue part of the source atomic expression.
11632 Expr *X = nullptr;
11633 /// 'expr' or 'e' rvalue part of the source atomic expression.
11634 Expr *E = nullptr;
11635 /// 'd' rvalue part of the source atomic expression.
11636 Expr *D = nullptr;
11637 /// 'cond' part of the source atomic expression. It is in one of the following
11638 /// forms:
11639 /// expr ordop x
11640 /// x ordop expr
11641 /// x == e
11642 /// e == x
11643 Expr *C = nullptr;
11644 /// True if the cond expr is in the form of 'x ordop expr'.
11645 bool IsXBinopExpr = true;
11646
11647 /// Check if it is a valid conditional update statement (cond-update-stmt).
11648 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11649
11650 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11651 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11652
11653 /// Check if all captured values have right type.
11654 bool checkType(ErrorInfoTy &ErrorInfo) const;
11655
11656 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11657 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11659 return true;
11660
11661 if (ShouldBeLValue && !E->isLValue()) {
11662 ErrorInfo.Error = ErrorTy::XNotLValue;
11663 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11664 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11665 return false;
11666 }
11667
11668 QualType QTy = E->getType();
11669 if (!QTy->isScalarType()) {
11670 ErrorInfo.Error = ErrorTy::NotScalar;
11671 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11672 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11673 return false;
11674 }
11675 if (ShouldBeInteger && !QTy->isIntegerType()) {
11676 ErrorInfo.Error = ErrorTy::NotInteger;
11677 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
11678 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
11679 return false;
11680 }
11681
11682 return true;
11683 }
11684};
11685
11686bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
11687 ErrorInfoTy &ErrorInfo) {
11688 auto *Then = S->getThen();
11689 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11690 if (CS->body_empty()) {
11691 ErrorInfo.Error = ErrorTy::NoStmt;
11692 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11693 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11694 return false;
11695 }
11696 if (CS->size() > 1) {
11697 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11698 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11699 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11700 return false;
11701 }
11702 Then = CS->body_front();
11703 }
11704
11705 auto *BO = dyn_cast<BinaryOperator>(Then);
11706 if (!BO) {
11707 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11708 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
11709 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
11710 return false;
11711 }
11712 if (BO->getOpcode() != BO_Assign) {
11713 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11714 ErrorInfo.ErrorLoc = BO->getExprLoc();
11715 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11716 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11717 return false;
11718 }
11719
11720 X = BO->getLHS();
11721
11722 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
11723 if (!Cond) {
11724 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11725 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
11726 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
11727 return false;
11728 }
11729
11730 switch (Cond->getOpcode()) {
11731 case BO_EQ: {
11732 C = Cond;
11733 D = BO->getRHS();
11734 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11735 E = Cond->getRHS();
11736 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11737 E = Cond->getLHS();
11738 } else {
11739 ErrorInfo.Error = ErrorTy::InvalidComparison;
11740 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11741 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11742 return false;
11743 }
11744 break;
11745 }
11746 case BO_LT:
11747 case BO_GT: {
11748 E = BO->getRHS();
11749 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11750 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11751 C = Cond;
11752 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11753 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11754 C = Cond;
11755 IsXBinopExpr = false;
11756 } else {
11757 ErrorInfo.Error = ErrorTy::InvalidComparison;
11758 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11759 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11760 return false;
11761 }
11762 break;
11763 }
11764 default:
11765 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11766 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11767 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11768 return false;
11769 }
11770
11771 if (S->getElse()) {
11772 ErrorInfo.Error = ErrorTy::UnexpectedElse;
11773 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
11774 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
11775 return false;
11776 }
11777
11778 return true;
11779}
11780
11781bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
11782 ErrorInfoTy &ErrorInfo) {
11783 auto *BO = dyn_cast<BinaryOperator>(S);
11784 if (!BO) {
11785 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11786 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
11787 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
11788 return false;
11789 }
11790 if (BO->getOpcode() != BO_Assign) {
11791 ErrorInfo.Error = ErrorTy::NotAnAssignment;
11792 ErrorInfo.ErrorLoc = BO->getExprLoc();
11793 ErrorInfo.NoteLoc = BO->getOperatorLoc();
11794 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
11795 return false;
11796 }
11797
11798 X = BO->getLHS();
11799
11800 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
11801 if (!CO) {
11802 ErrorInfo.Error = ErrorTy::NotCondOp;
11803 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
11804 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
11805 return false;
11806 }
11807
11808 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
11809 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
11810 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
11811 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11812 CO->getFalseExpr()->getSourceRange();
11813 return false;
11814 }
11815
11816 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
11817 if (!Cond) {
11818 ErrorInfo.Error = ErrorTy::NotABinaryOp;
11819 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
11820 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
11821 CO->getCond()->getSourceRange();
11822 return false;
11823 }
11824
11825 switch (Cond->getOpcode()) {
11826 case BO_EQ: {
11827 C = Cond;
11828 D = CO->getTrueExpr();
11829 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
11830 E = Cond->getRHS();
11831 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11832 E = Cond->getLHS();
11833 } else {
11834 ErrorInfo.Error = ErrorTy::InvalidComparison;
11835 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11836 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11837 return false;
11838 }
11839 break;
11840 }
11841 case BO_LT:
11842 case BO_GT: {
11843 E = CO->getTrueExpr();
11844 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS()) &&
11845 checkIfTwoExprsAreSame(ContextRef, E, Cond->getRHS())) {
11846 C = Cond;
11847 } else if (checkIfTwoExprsAreSame(ContextRef, E, Cond->getLHS()) &&
11848 checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
11849 C = Cond;
11850 IsXBinopExpr = false;
11851 } else {
11852 ErrorInfo.Error = ErrorTy::InvalidComparison;
11853 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11854 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11855 return false;
11856 }
11857 break;
11858 }
11859 default:
11860 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
11861 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
11862 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
11863 return false;
11864 }
11865
11866 return true;
11867}
11868
11869bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
11870 // 'x' and 'e' cannot be nullptr
11871 assert(X && E && "X and E cannot be nullptr");
11872
11873 if (!CheckValue(X, ErrorInfo, true))
11874 return false;
11875
11876 if (!CheckValue(E, ErrorInfo, false))
11877 return false;
11878
11879 if (D && !CheckValue(D, ErrorInfo, false))
11880 return false;
11881
11882 return true;
11883}
11884
11885bool OpenMPAtomicCompareChecker::checkStmt(
11886 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
11887 auto *CS = dyn_cast<CompoundStmt>(S);
11888 if (CS) {
11889 if (CS->body_empty()) {
11890 ErrorInfo.Error = ErrorTy::NoStmt;
11891 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11892 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11893 return false;
11894 }
11895
11896 if (CS->size() != 1) {
11897 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11898 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11899 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11900 return false;
11901 }
11902 S = CS->body_front();
11903 }
11904
11905 auto Res = false;
11906
11907 if (auto *IS = dyn_cast<IfStmt>(S)) {
11908 // Check if the statement is in one of the following forms
11909 // (cond-update-stmt):
11910 // if (expr ordop x) { x = expr; }
11911 // if (x ordop expr) { x = expr; }
11912 // if (x == e) { x = d; }
11913 Res = checkCondUpdateStmt(IS, ErrorInfo);
11914 } else {
11915 // Check if the statement is in one of the following forms (cond-expr-stmt):
11916 // x = expr ordop x ? expr : x;
11917 // x = x ordop expr ? expr : x;
11918 // x = x == e ? d : x;
11919 Res = checkCondExprStmt(S, ErrorInfo);
11920 }
11921
11922 if (!Res)
11923 return false;
11924
11925 return checkType(ErrorInfo);
11926}
11927
11928class OpenMPAtomicCompareCaptureChecker final
11929 : public OpenMPAtomicCompareChecker {
11930public:
11931 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
11932
11933 Expr *getV() const { return V; }
11934 Expr *getR() const { return R; }
11935 bool isFailOnly() const { return IsFailOnly; }
11936 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11937
11938 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
11939 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11940
11941private:
11942 bool checkType(ErrorInfoTy &ErrorInfo);
11943
11944 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
11945 // form of 'conditional-update-capture-atomic' structured block on the v5.2
11946 // spec p.p. 82:
11947 // (1) { v = x; cond-update-stmt }
11948 // (2) { cond-update-stmt v = x; }
11949 // (3) if(x == e) { x = d; } else { v = x; }
11950 // (4) { r = x == e; if(r) { x = d; } }
11951 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
11952
11953 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
11954 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
11955
11956 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
11957 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
11958 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
11959
11960 /// 'v' lvalue part of the source atomic expression.
11961 Expr *V = nullptr;
11962 /// 'r' lvalue part of the source atomic expression.
11963 Expr *R = nullptr;
11964 /// If 'v' is only updated when the comparison fails.
11965 bool IsFailOnly = false;
11966 /// If original value of 'x' must be stored in 'v', not an updated one.
11967 bool IsPostfixUpdate = false;
11968};
11969
11970bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
11971 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
11972 return false;
11973
11974 if (V && !CheckValue(V, ErrorInfo, true))
11975 return false;
11976
11977 if (R && !CheckValue(R, ErrorInfo, true, true))
11978 return false;
11979
11980 return true;
11981}
11982
11983bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
11984 ErrorInfoTy &ErrorInfo) {
11985 IsFailOnly = true;
11986
11987 auto *Then = S->getThen();
11988 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
11989 if (CS->body_empty()) {
11990 ErrorInfo.Error = ErrorTy::NoStmt;
11991 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11992 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11993 return false;
11994 }
11995 if (CS->size() > 1) {
11996 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
11997 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
11998 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
11999 return false;
12000 }
12001 Then = CS->body_front();
12002 }
12003
12004 auto *BO = dyn_cast<BinaryOperator>(Then);
12005 if (!BO) {
12006 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12007 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12008 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12009 return false;
12010 }
12011 if (BO->getOpcode() != BO_Assign) {
12012 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12013 ErrorInfo.ErrorLoc = BO->getExprLoc();
12014 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12015 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12016 return false;
12017 }
12018
12019 X = BO->getLHS();
12020 D = BO->getRHS();
12021
12022 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12023 if (!Cond) {
12024 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12025 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12026 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12027 return false;
12028 }
12029 if (Cond->getOpcode() != BO_EQ) {
12030 ErrorInfo.Error = ErrorTy::NotEQ;
12031 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12032 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12033 return false;
12034 }
12035
12036 if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getLHS())) {
12037 E = Cond->getRHS();
12038 } else if (checkIfTwoExprsAreSame(ContextRef, X, Cond->getRHS())) {
12039 E = Cond->getLHS();
12040 } else {
12041 ErrorInfo.Error = ErrorTy::InvalidComparison;
12042 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Cond->getExprLoc();
12043 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12044 return false;
12045 }
12046
12047 C = Cond;
12048
12049 if (!S->getElse()) {
12050 ErrorInfo.Error = ErrorTy::NoElse;
12051 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12052 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12053 return false;
12054 }
12055
12056 auto *Else = S->getElse();
12057 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12058 if (CS->body_empty()) {
12059 ErrorInfo.Error = ErrorTy::NoStmt;
12060 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12061 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12062 return false;
12063 }
12064 if (CS->size() > 1) {
12065 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12066 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12067 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12068 return false;
12069 }
12070 Else = CS->body_front();
12071 }
12072
12073 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12074 if (!ElseBO) {
12075 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12078 return false;
12079 }
12080 if (ElseBO->getOpcode() != BO_Assign) {
12081 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12082 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12083 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12084 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12085 return false;
12086 }
12087
12088 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12089 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12090 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12092 ElseBO->getRHS()->getSourceRange();
12093 return false;
12094 }
12095
12096 V = ElseBO->getLHS();
12097
12098 return checkType(ErrorInfo);
12099}
12100
12101bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12102 ErrorInfoTy &ErrorInfo) {
12103 // We don't check here as they should be already done before call this
12104 // function.
12105 auto *CS = cast<CompoundStmt>(S);
12106 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12107 auto *S1 = cast<BinaryOperator>(CS->body_front());
12108 auto *S2 = cast<IfStmt>(CS->body_back());
12109 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12110
12111 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12112 ErrorInfo.Error = ErrorTy::InvalidCondition;
12113 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12114 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12115 return false;
12116 }
12117
12118 R = S1->getLHS();
12119
12120 auto *Then = S2->getThen();
12121 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12122 if (ThenCS->body_empty()) {
12123 ErrorInfo.Error = ErrorTy::NoStmt;
12124 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12125 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12126 return false;
12127 }
12128 if (ThenCS->size() > 1) {
12129 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12130 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12131 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12132 return false;
12133 }
12134 Then = ThenCS->body_front();
12135 }
12136
12137 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12138 if (!ThenBO) {
12139 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12140 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12141 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12142 return false;
12143 }
12144 if (ThenBO->getOpcode() != BO_Assign) {
12145 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12146 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12147 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12148 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12149 return false;
12150 }
12151
12152 X = ThenBO->getLHS();
12153 D = ThenBO->getRHS();
12154
12155 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12156 if (BO->getOpcode() != BO_EQ) {
12157 ErrorInfo.Error = ErrorTy::NotEQ;
12158 ErrorInfo.ErrorLoc = BO->getExprLoc();
12159 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12160 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12161 return false;
12162 }
12163
12164 C = BO;
12165
12166 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12167 E = BO->getRHS();
12168 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12169 E = BO->getLHS();
12170 } else {
12171 ErrorInfo.Error = ErrorTy::InvalidComparison;
12172 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12173 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12174 return false;
12175 }
12176
12177 if (S2->getElse()) {
12178 IsFailOnly = true;
12179
12180 auto *Else = S2->getElse();
12181 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12182 if (ElseCS->body_empty()) {
12183 ErrorInfo.Error = ErrorTy::NoStmt;
12184 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12185 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12186 return false;
12187 }
12188 if (ElseCS->size() > 1) {
12189 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12190 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12191 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12192 return false;
12193 }
12194 Else = ElseCS->body_front();
12195 }
12196
12197 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12198 if (!ElseBO) {
12199 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12200 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12201 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12202 return false;
12203 }
12204 if (ElseBO->getOpcode() != BO_Assign) {
12205 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12206 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12207 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12208 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12209 return false;
12210 }
12211 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12212 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12213 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12214 ErrorInfo.NoteLoc = X->getExprLoc();
12215 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12216 ErrorInfo.NoteRange = X->getSourceRange();
12217 return false;
12218 }
12219
12220 V = ElseBO->getLHS();
12221 }
12222
12223 return checkType(ErrorInfo);
12224}
12225
12226bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12227 ErrorInfoTy &ErrorInfo) {
12228 // if(x == e) { x = d; } else { v = x; }
12229 if (auto *IS = dyn_cast<IfStmt>(S))
12230 return checkForm3(IS, ErrorInfo);
12231
12232 auto *CS = dyn_cast<CompoundStmt>(S);
12233 if (!CS) {
12234 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12235 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12236 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12237 return false;
12238 }
12239 if (CS->body_empty()) {
12240 ErrorInfo.Error = ErrorTy::NoStmt;
12241 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12242 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12243 return false;
12244 }
12245
12246 // { if(x == e) { x = d; } else { v = x; } }
12247 if (CS->size() == 1) {
12248 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12249 if (!IS) {
12250 ErrorInfo.Error = ErrorTy::NotIfStmt;
12251 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12252 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12253 CS->body_front()->getSourceRange();
12254 return false;
12255 }
12256
12257 return checkForm3(IS, ErrorInfo);
12258 } else if (CS->size() == 2) {
12259 auto *S1 = CS->body_front();
12260 auto *S2 = CS->body_back();
12261
12262 Stmt *UpdateStmt = nullptr;
12263 Stmt *CondUpdateStmt = nullptr;
12264 Stmt *CondExprStmt = nullptr;
12265
12266 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12267 // It could be one of the following cases:
12268 // { v = x; cond-update-stmt }
12269 // { v = x; cond-expr-stmt }
12270 // { cond-expr-stmt; v = x; }
12271 // form 45
12272 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12273 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12274 // check if form 45
12275 if (isa<IfStmt>(S2))
12276 return checkForm45(CS, ErrorInfo);
12277 // { cond-expr-stmt; v = x; }
12278 CondExprStmt = S1;
12279 UpdateStmt = S2;
12280 } else {
12281 IsPostfixUpdate = true;
12282 UpdateStmt = S1;
12283 if (isa<IfStmt>(S2)) {
12284 // { v = x; cond-update-stmt }
12285 CondUpdateStmt = S2;
12286 } else {
12287 // { v = x; cond-expr-stmt }
12288 CondExprStmt = S2;
12289 }
12290 }
12291 } else {
12292 // { cond-update-stmt v = x; }
12293 UpdateStmt = S2;
12294 CondUpdateStmt = S1;
12295 }
12296
12297 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12298 auto *IS = dyn_cast<IfStmt>(CUS);
12299 if (!IS) {
12300 ErrorInfo.Error = ErrorTy::NotIfStmt;
12301 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12302 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12303 return false;
12304 }
12305
12306 return checkCondUpdateStmt(IS, ErrorInfo);
12307 };
12308
12309 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12310 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12311 auto *BO = dyn_cast<BinaryOperator>(US);
12312 if (!BO) {
12313 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12314 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12315 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12316 return false;
12317 }
12318 if (BO->getOpcode() != BO_Assign) {
12319 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12320 ErrorInfo.ErrorLoc = BO->getExprLoc();
12321 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12322 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12323 return false;
12324 }
12325 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12326 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12327 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12328 ErrorInfo.NoteLoc = this->X->getExprLoc();
12329 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12330 ErrorInfo.NoteRange = this->X->getSourceRange();
12331 return false;
12332 }
12333
12334 this->V = BO->getLHS();
12335
12336 return true;
12337 };
12338
12339 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12340 return false;
12341 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12342 return false;
12343 if (!CheckUpdateStmt(UpdateStmt))
12344 return false;
12345 } else {
12346 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12347 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12348 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12349 return false;
12350 }
12351
12352 return checkType(ErrorInfo);
12353}
12354} // namespace
12355
12357 Stmt *AStmt,
12358 SourceLocation StartLoc,
12359 SourceLocation EndLoc) {
12360 ASTContext &Context = getASTContext();
12361 // Register location of the first atomic directive.
12362 DSAStack->addAtomicDirectiveLoc(StartLoc);
12363 if (!AStmt)
12364 return StmtError();
12365
12366 // 1.2.2 OpenMP Language Terminology
12367 // Structured block - An executable statement with a single entry at the
12368 // top and a single exit at the bottom.
12369 // The point of exit cannot be a branch out of the structured block.
12370 // longjmp() and throw() must not violate the entry/exit criteria.
12371 OpenMPClauseKind AtomicKind = OMPC_unknown;
12372 SourceLocation AtomicKindLoc;
12373 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12374 SourceLocation MemOrderLoc;
12375 bool MutexClauseEncountered = false;
12376 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12377 for (const OMPClause *C : Clauses) {
12378 switch (C->getClauseKind()) {
12379 case OMPC_read:
12380 case OMPC_write:
12381 case OMPC_update:
12382 MutexClauseEncountered = true;
12383 [[fallthrough]];
12384 case OMPC_capture:
12385 case OMPC_compare: {
12386 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12387 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12388 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12389 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12390 << getOpenMPClauseName(AtomicKind);
12391 } else {
12392 AtomicKind = C->getClauseKind();
12393 AtomicKindLoc = C->getBeginLoc();
12394 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12395 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12396 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12397 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12398 << getOpenMPClauseName(AtomicKind);
12399 }
12400 }
12401 break;
12402 }
12403 case OMPC_weak:
12404 case OMPC_fail: {
12405 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12406 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12407 << getOpenMPClauseName(C->getClauseKind())
12408 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12409 return StmtError();
12410 }
12411 break;
12412 }
12413 case OMPC_seq_cst:
12414 case OMPC_acq_rel:
12415 case OMPC_acquire:
12416 case OMPC_release:
12417 case OMPC_relaxed: {
12418 if (MemOrderKind != OMPC_unknown) {
12419 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12420 << getOpenMPDirectiveName(OMPD_atomic) << 0
12421 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12422 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12423 << getOpenMPClauseName(MemOrderKind);
12424 } else {
12425 MemOrderKind = C->getClauseKind();
12426 MemOrderLoc = C->getBeginLoc();
12427 }
12428 break;
12429 }
12430 // The following clauses are allowed, but we don't need to do anything here.
12431 case OMPC_hint:
12432 break;
12433 default:
12434 llvm_unreachable("unknown clause is encountered");
12435 }
12436 }
12437 bool IsCompareCapture = false;
12438 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12439 EncounteredAtomicKinds.contains(OMPC_capture)) {
12440 IsCompareCapture = true;
12441 AtomicKind = OMPC_compare;
12442 }
12443 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12444 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12445 // release.
12446 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12447 // acquire.
12448 // If atomic-clause is update or not present then memory-order-clause must not
12449 // be acq_rel or acquire.
12450 if ((AtomicKind == OMPC_read &&
12451 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12452 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12453 AtomicKind == OMPC_unknown) &&
12454 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12455 SourceLocation Loc = AtomicKindLoc;
12456 if (AtomicKind == OMPC_unknown)
12457 Loc = StartLoc;
12458 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12459 << getOpenMPClauseName(AtomicKind)
12460 << (AtomicKind == OMPC_unknown ? 1 : 0)
12461 << getOpenMPClauseName(MemOrderKind);
12462 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12463 << getOpenMPClauseName(MemOrderKind);
12464 }
12465
12466 Stmt *Body = AStmt;
12467 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12468 Body = EWC->getSubExpr();
12469
12470 Expr *X = nullptr;
12471 Expr *V = nullptr;
12472 Expr *E = nullptr;
12473 Expr *UE = nullptr;
12474 Expr *D = nullptr;
12475 Expr *CE = nullptr;
12476 Expr *R = nullptr;
12477 bool IsXLHSInRHSPart = false;
12478 bool IsPostfixUpdate = false;
12479 bool IsFailOnly = false;
12480 // OpenMP [2.12.6, atomic Construct]
12481 // In the next expressions:
12482 // * x and v (as applicable) are both l-value expressions with scalar type.
12483 // * During the execution of an atomic region, multiple syntactic
12484 // occurrences of x must designate the same storage location.
12485 // * Neither of v and expr (as applicable) may access the storage location
12486 // designated by x.
12487 // * Neither of x and expr (as applicable) may access the storage location
12488 // designated by v.
12489 // * expr is an expression with scalar type.
12490 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12491 // * binop, binop=, ++, and -- are not overloaded operators.
12492 // * The expression x binop expr must be numerically equivalent to x binop
12493 // (expr). This requirement is satisfied if the operators in expr have
12494 // precedence greater than binop, or by using parentheses around expr or
12495 // subexpressions of expr.
12496 // * The expression expr binop x must be numerically equivalent to (expr)
12497 // binop x. This requirement is satisfied if the operators in expr have
12498 // precedence equal to or greater than binop, or by using parentheses around
12499 // expr or subexpressions of expr.
12500 // * For forms that allow multiple occurrences of x, the number of times
12501 // that x is evaluated is unspecified.
12502 if (AtomicKind == OMPC_read) {
12503 enum {
12504 NotAnExpression,
12505 NotAnAssignmentOp,
12506 NotAScalarType,
12507 NotAnLValue,
12508 NoError
12509 } ErrorFound = NoError;
12510 SourceLocation ErrorLoc, NoteLoc;
12511 SourceRange ErrorRange, NoteRange;
12512 // If clause is read:
12513 // v = x;
12514 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12515 const auto *AtomicBinOp =
12516 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12517 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12518 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12519 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12520 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12521 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12522 if (!X->isLValue() || !V->isLValue()) {
12523 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12524 ErrorFound = NotAnLValue;
12525 ErrorLoc = AtomicBinOp->getExprLoc();
12526 ErrorRange = AtomicBinOp->getSourceRange();
12527 NoteLoc = NotLValueExpr->getExprLoc();
12528 NoteRange = NotLValueExpr->getSourceRange();
12529 }
12530 } else if (!X->isInstantiationDependent() ||
12531 !V->isInstantiationDependent()) {
12532 const Expr *NotScalarExpr =
12533 (X->isInstantiationDependent() || X->getType()->isScalarType())
12534 ? V
12535 : X;
12536 ErrorFound = NotAScalarType;
12537 ErrorLoc = AtomicBinOp->getExprLoc();
12538 ErrorRange = AtomicBinOp->getSourceRange();
12539 NoteLoc = NotScalarExpr->getExprLoc();
12540 NoteRange = NotScalarExpr->getSourceRange();
12541 }
12542 } else if (!AtomicBody->isInstantiationDependent()) {
12543 ErrorFound = NotAnAssignmentOp;
12544 ErrorLoc = AtomicBody->getExprLoc();
12545 ErrorRange = AtomicBody->getSourceRange();
12546 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12547 : AtomicBody->getExprLoc();
12548 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12549 : AtomicBody->getSourceRange();
12550 }
12551 } else {
12552 ErrorFound = NotAnExpression;
12553 NoteLoc = ErrorLoc = Body->getBeginLoc();
12554 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12555 }
12556 if (ErrorFound != NoError) {
12557 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12558 << ErrorRange;
12559 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12560 << ErrorFound << NoteRange;
12561 return StmtError();
12562 }
12564 V = X = nullptr;
12565 } else if (AtomicKind == OMPC_write) {
12566 enum {
12567 NotAnExpression,
12568 NotAnAssignmentOp,
12569 NotAScalarType,
12570 NotAnLValue,
12571 NoError
12572 } ErrorFound = NoError;
12573 SourceLocation ErrorLoc, NoteLoc;
12574 SourceRange ErrorRange, NoteRange;
12575 // If clause is write:
12576 // x = expr;
12577 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12578 const auto *AtomicBinOp =
12579 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12580 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12581 X = AtomicBinOp->getLHS();
12582 E = AtomicBinOp->getRHS();
12583 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12585 if (!X->isLValue()) {
12586 ErrorFound = NotAnLValue;
12587 ErrorLoc = AtomicBinOp->getExprLoc();
12588 ErrorRange = AtomicBinOp->getSourceRange();
12589 NoteLoc = X->getExprLoc();
12590 NoteRange = X->getSourceRange();
12591 }
12592 } else if (!X->isInstantiationDependent() ||
12594 const Expr *NotScalarExpr =
12595 (X->isInstantiationDependent() || X->getType()->isScalarType())
12596 ? E
12597 : X;
12598 ErrorFound = NotAScalarType;
12599 ErrorLoc = AtomicBinOp->getExprLoc();
12600 ErrorRange = AtomicBinOp->getSourceRange();
12601 NoteLoc = NotScalarExpr->getExprLoc();
12602 NoteRange = NotScalarExpr->getSourceRange();
12603 }
12604 } else if (!AtomicBody->isInstantiationDependent()) {
12605 ErrorFound = NotAnAssignmentOp;
12606 ErrorLoc = AtomicBody->getExprLoc();
12607 ErrorRange = AtomicBody->getSourceRange();
12608 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12609 : AtomicBody->getExprLoc();
12610 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12611 : AtomicBody->getSourceRange();
12612 }
12613 } else {
12614 ErrorFound = NotAnExpression;
12615 NoteLoc = ErrorLoc = Body->getBeginLoc();
12616 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12617 }
12618 if (ErrorFound != NoError) {
12619 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12620 << ErrorRange;
12621 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12622 << ErrorFound << NoteRange;
12623 return StmtError();
12624 }
12626 E = X = nullptr;
12627 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
12628 // If clause is update:
12629 // x++;
12630 // x--;
12631 // ++x;
12632 // --x;
12633 // x binop= expr;
12634 // x = x binop expr;
12635 // x = expr binop x;
12636 OpenMPAtomicUpdateChecker Checker(SemaRef);
12637 if (Checker.checkStatement(
12638 Body,
12639 (AtomicKind == OMPC_update)
12640 ? diag::err_omp_atomic_update_not_expression_statement
12641 : diag::err_omp_atomic_not_expression_statement,
12642 diag::note_omp_atomic_update))
12643 return StmtError();
12645 E = Checker.getExpr();
12646 X = Checker.getX();
12647 UE = Checker.getUpdateExpr();
12648 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12649 }
12650 } else if (AtomicKind == OMPC_capture) {
12651 enum {
12652 NotAnAssignmentOp,
12653 NotACompoundStatement,
12654 NotTwoSubstatements,
12655 NotASpecificExpression,
12656 NoError
12657 } ErrorFound = NoError;
12658 SourceLocation ErrorLoc, NoteLoc;
12659 SourceRange ErrorRange, NoteRange;
12660 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12661 // If clause is a capture:
12662 // v = x++;
12663 // v = x--;
12664 // v = ++x;
12665 // v = --x;
12666 // v = x binop= expr;
12667 // v = x = x binop expr;
12668 // v = x = expr binop x;
12669 const auto *AtomicBinOp =
12670 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12671 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12672 V = AtomicBinOp->getLHS();
12673 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12674 OpenMPAtomicUpdateChecker Checker(SemaRef);
12675 if (Checker.checkStatement(
12676 Body, diag::err_omp_atomic_capture_not_expression_statement,
12677 diag::note_omp_atomic_update))
12678 return StmtError();
12679 E = Checker.getExpr();
12680 X = Checker.getX();
12681 UE = Checker.getUpdateExpr();
12682 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12683 IsPostfixUpdate = Checker.isPostfixUpdate();
12684 } else if (!AtomicBody->isInstantiationDependent()) {
12685 ErrorLoc = AtomicBody->getExprLoc();
12686 ErrorRange = AtomicBody->getSourceRange();
12687 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12688 : AtomicBody->getExprLoc();
12689 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12690 : AtomicBody->getSourceRange();
12691 ErrorFound = NotAnAssignmentOp;
12692 }
12693 if (ErrorFound != NoError) {
12694 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
12695 << ErrorRange;
12696 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12697 return StmtError();
12698 }
12700 UE = V = E = X = nullptr;
12701 } else {
12702 // If clause is a capture:
12703 // { v = x; x = expr; }
12704 // { v = x; x++; }
12705 // { v = x; x--; }
12706 // { v = x; ++x; }
12707 // { v = x; --x; }
12708 // { v = x; x binop= expr; }
12709 // { v = x; x = x binop expr; }
12710 // { v = x; x = expr binop x; }
12711 // { x++; v = x; }
12712 // { x--; v = x; }
12713 // { ++x; v = x; }
12714 // { --x; v = x; }
12715 // { x binop= expr; v = x; }
12716 // { x = x binop expr; v = x; }
12717 // { x = expr binop x; v = x; }
12718 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
12719 // Check that this is { expr1; expr2; }
12720 if (CS->size() == 2) {
12721 Stmt *First = CS->body_front();
12722 Stmt *Second = CS->body_back();
12723 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
12724 First = EWC->getSubExpr()->IgnoreParenImpCasts();
12725 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
12726 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
12727 // Need to find what subexpression is 'v' and what is 'x'.
12728 OpenMPAtomicUpdateChecker Checker(SemaRef);
12729 bool IsUpdateExprFound = !Checker.checkStatement(Second);
12730 BinaryOperator *BinOp = nullptr;
12731 if (IsUpdateExprFound) {
12732 BinOp = dyn_cast<BinaryOperator>(First);
12733 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12734 }
12735 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
12736 // { v = x; x++; }
12737 // { v = x; x--; }
12738 // { v = x; ++x; }
12739 // { v = x; --x; }
12740 // { v = x; x binop= expr; }
12741 // { v = x; x = x binop expr; }
12742 // { v = x; x = expr binop x; }
12743 // Check that the first expression has form v = x.
12744 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12745 llvm::FoldingSetNodeID XId, PossibleXId;
12746 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12747 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12748 IsUpdateExprFound = XId == PossibleXId;
12749 if (IsUpdateExprFound) {
12750 V = BinOp->getLHS();
12751 X = Checker.getX();
12752 E = Checker.getExpr();
12753 UE = Checker.getUpdateExpr();
12754 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12755 IsPostfixUpdate = true;
12756 }
12757 }
12758 if (!IsUpdateExprFound) {
12759 IsUpdateExprFound = !Checker.checkStatement(First);
12760 BinOp = nullptr;
12761 if (IsUpdateExprFound) {
12762 BinOp = dyn_cast<BinaryOperator>(Second);
12763 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
12764 }
12765 if (IsUpdateExprFound &&
12767 // { x++; v = x; }
12768 // { x--; v = x; }
12769 // { ++x; v = x; }
12770 // { --x; v = x; }
12771 // { x binop= expr; v = x; }
12772 // { x = x binop expr; v = x; }
12773 // { x = expr binop x; v = x; }
12774 // Check that the second expression has form v = x.
12775 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
12776 llvm::FoldingSetNodeID XId, PossibleXId;
12777 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
12778 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
12779 IsUpdateExprFound = XId == PossibleXId;
12780 if (IsUpdateExprFound) {
12781 V = BinOp->getLHS();
12782 X = Checker.getX();
12783 E = Checker.getExpr();
12784 UE = Checker.getUpdateExpr();
12785 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
12786 IsPostfixUpdate = false;
12787 }
12788 }
12789 }
12790 if (!IsUpdateExprFound) {
12791 // { v = x; x = expr; }
12792 auto *FirstExpr = dyn_cast<Expr>(First);
12793 auto *SecondExpr = dyn_cast<Expr>(Second);
12794 if (!FirstExpr || !SecondExpr ||
12795 !(FirstExpr->isInstantiationDependent() ||
12796 SecondExpr->isInstantiationDependent())) {
12797 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
12798 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
12799 ErrorFound = NotAnAssignmentOp;
12800 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
12801 : First->getBeginLoc();
12802 NoteRange = ErrorRange = FirstBinOp
12803 ? FirstBinOp->getSourceRange()
12804 : SourceRange(ErrorLoc, ErrorLoc);
12805 } else {
12806 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
12807 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
12808 ErrorFound = NotAnAssignmentOp;
12809 NoteLoc = ErrorLoc = SecondBinOp
12810 ? SecondBinOp->getOperatorLoc()
12811 : Second->getBeginLoc();
12812 NoteRange = ErrorRange =
12813 SecondBinOp ? SecondBinOp->getSourceRange()
12814 : SourceRange(ErrorLoc, ErrorLoc);
12815 } else {
12816 Expr *PossibleXRHSInFirst =
12817 FirstBinOp->getRHS()->IgnoreParenImpCasts();
12818 Expr *PossibleXLHSInSecond =
12819 SecondBinOp->getLHS()->IgnoreParenImpCasts();
12820 llvm::FoldingSetNodeID X1Id, X2Id;
12821 PossibleXRHSInFirst->Profile(X1Id, Context,
12822 /*Canonical=*/true);
12823 PossibleXLHSInSecond->Profile(X2Id, Context,
12824 /*Canonical=*/true);
12825 IsUpdateExprFound = X1Id == X2Id;
12826 if (IsUpdateExprFound) {
12827 V = FirstBinOp->getLHS();
12828 X = SecondBinOp->getLHS();
12829 E = SecondBinOp->getRHS();
12830 UE = nullptr;
12831 IsXLHSInRHSPart = false;
12832 IsPostfixUpdate = true;
12833 } else {
12834 ErrorFound = NotASpecificExpression;
12835 ErrorLoc = FirstBinOp->getExprLoc();
12836 ErrorRange = FirstBinOp->getSourceRange();
12837 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
12838 NoteRange = SecondBinOp->getRHS()->getSourceRange();
12839 }
12840 }
12841 }
12842 }
12843 }
12844 } else {
12845 NoteLoc = ErrorLoc = Body->getBeginLoc();
12846 NoteRange = ErrorRange =
12847 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12848 ErrorFound = NotTwoSubstatements;
12849 }
12850 } else {
12851 NoteLoc = ErrorLoc = Body->getBeginLoc();
12852 NoteRange = ErrorRange =
12853 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
12854 ErrorFound = NotACompoundStatement;
12855 }
12856 }
12857 if (ErrorFound != NoError) {
12858 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
12859 << ErrorRange;
12860 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
12861 return StmtError();
12862 }
12864 UE = V = E = X = nullptr;
12865 } else if (AtomicKind == OMPC_compare) {
12866 if (IsCompareCapture) {
12867 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
12868 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
12869 if (!Checker.checkStmt(Body, ErrorInfo)) {
12870 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
12871 << ErrorInfo.ErrorRange;
12872 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12873 << ErrorInfo.Error << ErrorInfo.NoteRange;
12874 return StmtError();
12875 }
12876 X = Checker.getX();
12877 E = Checker.getE();
12878 D = Checker.getD();
12879 CE = Checker.getCond();
12880 V = Checker.getV();
12881 R = Checker.getR();
12882 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12883 IsXLHSInRHSPart = Checker.isXBinopExpr();
12884 IsFailOnly = Checker.isFailOnly();
12885 IsPostfixUpdate = Checker.isPostfixUpdate();
12886 } else {
12887 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
12888 OpenMPAtomicCompareChecker Checker(SemaRef);
12889 if (!Checker.checkStmt(Body, ErrorInfo)) {
12890 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
12891 << ErrorInfo.ErrorRange;
12892 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
12893 << ErrorInfo.Error << ErrorInfo.NoteRange;
12894 return StmtError();
12895 }
12896 X = Checker.getX();
12897 E = Checker.getE();
12898 D = Checker.getD();
12899 CE = Checker.getCond();
12900 // The weak clause may only appear if the resulting atomic operation is
12901 // an atomic conditional update for which the comparison tests for
12902 // equality. It was not possible to do this check in
12903 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
12904 // could not be performed (Clauses are not available).
12905 auto *It = find_if(Clauses, [](OMPClause *C) {
12906 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
12907 });
12908 if (It != Clauses.end()) {
12909 auto *Cond = dyn_cast<BinaryOperator>(CE);
12910 if (Cond->getOpcode() != BO_EQ) {
12911 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
12912 ErrorInfo.ErrorLoc = Cond->getExprLoc();
12913 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
12914 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
12915
12916 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
12917 << ErrorInfo.ErrorRange;
12918 return StmtError();
12919 }
12920 }
12921 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
12922 IsXLHSInRHSPart = Checker.isXBinopExpr();
12923 }
12924 }
12925
12927
12929 Context, StartLoc, EndLoc, Clauses, AStmt,
12930 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
12931}
12932
12934 Stmt *AStmt,
12935 SourceLocation StartLoc,
12936 SourceLocation EndLoc) {
12937 if (!AStmt)
12938 return StmtError();
12939
12940 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
12941
12942 // OpenMP [2.16, Nesting of Regions]
12943 // If specified, a teams construct must be contained within a target
12944 // construct. That target construct must contain no statements or directives
12945 // outside of the teams construct.
12946 if (DSAStack->hasInnerTeamsRegion()) {
12947 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
12948 bool OMPTeamsFound = true;
12949 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
12950 auto I = CS->body_begin();
12951 while (I != CS->body_end()) {
12952 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
12953 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12954 if (!IsTeams || I != CS->body_begin()) {
12955 OMPTeamsFound = false;
12956 if (IsTeams && I != CS->body_begin()) {
12957 // This is the two teams case. Since the InnerTeamsRegionLoc will
12958 // point to this second one reset the iterator to the other teams.
12959 --I;
12960 }
12961 break;
12962 }
12963 ++I;
12964 }
12965 assert(I != CS->body_end() && "Not found statement");
12966 S = *I;
12967 } else {
12968 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
12969 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
12970 }
12971 if (!OMPTeamsFound) {
12972 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
12973 Diag(DSAStack->getInnerTeamsRegionLoc(),
12974 diag::note_omp_nested_teams_construct_here);
12975 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
12976 << isa<OMPExecutableDirective>(S);
12977 return StmtError();
12978 }
12979 }
12980
12981 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12982 AStmt);
12983}
12984
12986 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12987 SourceLocation EndLoc) {
12988 if (!AStmt)
12989 return StmtError();
12990
12991 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
12992
12994 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12995 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12996}
12997
12999 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13000 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13001 if (!AStmt)
13002 return StmtError();
13003
13004 CapturedStmt *CS =
13005 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13006
13008 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13009 // define the nested loops number.
13010 unsigned NestedLoopCount =
13011 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13012 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13013 VarsWithImplicitDSA, B);
13014 if (NestedLoopCount == 0)
13015 return StmtError();
13016
13017 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13018 return StmtError();
13019
13021 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13022 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13023}
13024
13025/// Check for existence of a map clause in the list of clauses.
13027 const OpenMPClauseKind K) {
13028 return llvm::any_of(
13029 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13030}
13031
13032template <typename... Params>
13034 const Params... ClauseTypes) {
13035 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13036}
13037
13038/// Check if the variables in the mapping clause are externally visible.
13040 for (const OMPClause *C : Clauses) {
13041 if (auto *TC = dyn_cast<OMPToClause>(C))
13042 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13043 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13044 (VD->isExternallyVisible() &&
13045 VD->getVisibility() != HiddenVisibility);
13046 });
13047 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13048 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13049 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13050 (VD->isExternallyVisible() &&
13051 VD->getVisibility() != HiddenVisibility);
13052 });
13053 }
13054
13055 return true;
13056}
13057
13060 Stmt *AStmt, SourceLocation StartLoc,
13061 SourceLocation EndLoc) {
13062 if (!AStmt)
13063 return StmtError();
13064
13065 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13066
13067 // OpenMP [2.12.2, target data Construct, Restrictions]
13068 // At least one map, use_device_addr or use_device_ptr clause must appear on
13069 // the directive.
13070 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13071 (getLangOpts().OpenMP < 50 ||
13072 !hasClauses(Clauses, OMPC_use_device_addr))) {
13073 StringRef Expected;
13074 if (getLangOpts().OpenMP < 50)
13075 Expected = "'map' or 'use_device_ptr'";
13076 else
13077 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13078 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13079 << Expected << getOpenMPDirectiveName(OMPD_target_data);
13080 return StmtError();
13081 }
13082
13084
13085 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13086 Clauses, AStmt);
13087}
13088
13090 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13091 SourceLocation EndLoc, Stmt *AStmt) {
13092 if (!AStmt)
13093 return StmtError();
13094
13095 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13096
13097 // OpenMP [2.10.2, Restrictions, p. 99]
13098 // At least one map clause must appear on the directive.
13099 if (!hasClauses(Clauses, OMPC_map)) {
13100 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13101 << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
13102 return StmtError();
13103 }
13104
13105 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13106 Clauses, AStmt);
13107}
13108
13110 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13111 SourceLocation EndLoc, Stmt *AStmt) {
13112 if (!AStmt)
13113 return StmtError();
13114
13115 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13116
13117 // OpenMP [2.10.3, Restrictions, p. 102]
13118 // At least one map clause must appear on the directive.
13119 if (!hasClauses(Clauses, OMPC_map)) {
13120 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13121 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
13122 return StmtError();
13123 }
13124
13125 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13126 Clauses, AStmt);
13127}
13128
13130 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13131 SourceLocation EndLoc, Stmt *AStmt) {
13132 if (!AStmt)
13133 return StmtError();
13134
13135 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13136
13137 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13138 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13139 return StmtError();
13140 }
13141
13142 if (!isClauseMappable(Clauses)) {
13143 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13144 return StmtError();
13145 }
13146
13147 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13148 Clauses, AStmt);
13149}
13150
13151/// This checks whether a \p ClauseType clause \p C has at most \p Max
13152/// expression. If not, a diag of number \p Diag will be emitted.
13153template <typename ClauseType>
13154static bool checkNumExprsInClause(SemaBase &SemaRef,
13155 ArrayRef<OMPClause *> Clauses,
13156 unsigned MaxNum, unsigned Diag) {
13157 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13158 if (ClauseItr == Clauses.end())
13159 return true;
13160 const auto *C = cast<ClauseType>(*ClauseItr);
13161 auto VarList = C->getVarRefs();
13162 if (VarList.size() > MaxNum) {
13163 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13164 << getOpenMPClauseName(C->getClauseKind());
13165 return false;
13166 }
13167 return true;
13168}
13169
13171 Stmt *AStmt,
13172 SourceLocation StartLoc,
13173 SourceLocation EndLoc) {
13174 if (!AStmt)
13175 return StmtError();
13176
13177 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13178 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13179 !checkNumExprsInClause<OMPThreadLimitClause>(
13180 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13181 return StmtError();
13182
13183 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13184 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13185 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13186
13187 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13188
13189 DSAStack->setParentTeamsRegionLoc(StartLoc);
13190
13191 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13192 AStmt);
13193}
13194
13196 SourceLocation StartLoc, SourceLocation EndLoc,
13197 OpenMPDirectiveKind CancelRegion) {
13198 if (DSAStack->isParentNowaitRegion()) {
13199 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13200 return StmtError();
13201 }
13202 if (DSAStack->isParentOrderedRegion()) {
13203 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13204 return StmtError();
13205 }
13207 EndLoc, CancelRegion);
13208}
13209
13211 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13212 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13213 if (DSAStack->isParentNowaitRegion()) {
13214 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13215 return StmtError();
13216 }
13217 if (DSAStack->isParentOrderedRegion()) {
13218 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13219 return StmtError();
13220 }
13221 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13222 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13223 CancelRegion);
13224}
13225
13227 ArrayRef<OMPClause *> Clauses) {
13228 const OMPClause *ReductionClause = nullptr;
13229 const OMPClause *NogroupClause = nullptr;
13230 for (const OMPClause *C : Clauses) {
13231 if (C->getClauseKind() == OMPC_reduction) {
13232 ReductionClause = C;
13233 if (NogroupClause)
13234 break;
13235 continue;
13236 }
13237 if (C->getClauseKind() == OMPC_nogroup) {
13238 NogroupClause = C;
13239 if (ReductionClause)
13240 break;
13241 continue;
13242 }
13243 }
13244 if (ReductionClause && NogroupClause) {
13245 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13246 << SourceRange(NogroupClause->getBeginLoc(),
13247 NogroupClause->getEndLoc());
13248 return true;
13249 }
13250 return false;
13251}
13252
13254 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13255 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13256 if (!AStmt)
13257 return StmtError();
13258
13259 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13261 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13262 // define the nested loops number.
13263 unsigned NestedLoopCount =
13264 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13265 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13266 *DSAStack, VarsWithImplicitDSA, B);
13267 if (NestedLoopCount == 0)
13268 return StmtError();
13269
13270 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13271 "omp for loop exprs were not built");
13272
13273 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13274 // The grainsize clause and num_tasks clause are mutually exclusive and may
13275 // not appear on the same taskloop directive.
13277 {OMPC_grainsize, OMPC_num_tasks}))
13278 return StmtError();
13279 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13280 // If a reduction clause is present on the taskloop directive, the nogroup
13281 // clause must not be specified.
13283 return StmtError();
13284
13286 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13287 NestedLoopCount, Clauses, AStmt, B,
13288 DSAStack->isCancelRegion());
13289}
13290
13292 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13293 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13294 if (!AStmt)
13295 return StmtError();
13296
13297 CapturedStmt *CS =
13298 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13299
13300 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13302 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13303 // define the nested loops number.
13304 unsigned NestedLoopCount =
13305 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13306 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13307 VarsWithImplicitDSA, B);
13308 if (NestedLoopCount == 0)
13309 return StmtError();
13310
13311 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13312 return StmtError();
13313
13314 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13315 // The grainsize clause and num_tasks clause are mutually exclusive and may
13316 // not appear on the same taskloop directive.
13318 {OMPC_grainsize, OMPC_num_tasks}))
13319 return StmtError();
13320 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13321 // If a reduction clause is present on the taskloop directive, the nogroup
13322 // clause must not be specified.
13324 return StmtError();
13326 return StmtError();
13327
13328 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13329 NestedLoopCount, Clauses, AStmt, B);
13330}
13331
13333 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13334 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13335 if (!AStmt)
13336 return StmtError();
13337
13338 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13340 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13341 // define the nested loops number.
13342 unsigned NestedLoopCount =
13343 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13344 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13345 *DSAStack, VarsWithImplicitDSA, B);
13346 if (NestedLoopCount == 0)
13347 return StmtError();
13348
13349 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13350 "omp for loop exprs were not built");
13351
13352 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13353 // The grainsize clause and num_tasks clause are mutually exclusive and may
13354 // not appear on the same taskloop directive.
13356 {OMPC_grainsize, OMPC_num_tasks}))
13357 return StmtError();
13358 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13359 // If a reduction clause is present on the taskloop directive, the nogroup
13360 // clause must not be specified.
13362 return StmtError();
13363
13365 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13366 NestedLoopCount, Clauses, AStmt, B,
13367 DSAStack->isCancelRegion());
13368}
13369
13371 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13372 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13373 if (!AStmt)
13374 return StmtError();
13375
13376 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13378 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13379 // define the nested loops number.
13380 unsigned NestedLoopCount =
13381 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13382 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13383 *DSAStack, VarsWithImplicitDSA, B);
13384 if (NestedLoopCount == 0)
13385 return StmtError();
13386
13387 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13388 "omp for loop exprs were not built");
13389
13390 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13391 // The grainsize clause and num_tasks clause are mutually exclusive and may
13392 // not appear on the same taskloop directive.
13394 {OMPC_grainsize, OMPC_num_tasks}))
13395 return StmtError();
13396 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13397 // If a reduction clause is present on the taskloop directive, the nogroup
13398 // clause must not be specified.
13400 return StmtError();
13401
13403 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13404 NestedLoopCount, Clauses, AStmt, B,
13405 DSAStack->isCancelRegion());
13406}
13407
13409 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13410 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13411 if (!AStmt)
13412 return StmtError();
13413
13414 CapturedStmt *CS =
13415 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13416
13417 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13419 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13420 // define the nested loops number.
13421 unsigned NestedLoopCount =
13422 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13423 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13424 VarsWithImplicitDSA, B);
13425 if (NestedLoopCount == 0)
13426 return StmtError();
13427
13428 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13429 return StmtError();
13430
13431 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13432 // The grainsize clause and num_tasks clause are mutually exclusive and may
13433 // not appear on the same taskloop directive.
13435 {OMPC_grainsize, OMPC_num_tasks}))
13436 return StmtError();
13437 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13438 // If a reduction clause is present on the taskloop directive, the nogroup
13439 // clause must not be specified.
13441 return StmtError();
13443 return StmtError();
13444
13446 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13447}
13448
13450 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13451 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13452 if (!AStmt)
13453 return StmtError();
13454
13455 CapturedStmt *CS =
13456 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13457
13458 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13460 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13461 // define the nested loops number.
13462 unsigned NestedLoopCount =
13463 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13464 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13465 VarsWithImplicitDSA, B);
13466 if (NestedLoopCount == 0)
13467 return StmtError();
13468
13469 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13470 return StmtError();
13471
13472 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13473 // The grainsize clause and num_tasks clause are mutually exclusive and may
13474 // not appear on the same taskloop directive.
13476 {OMPC_grainsize, OMPC_num_tasks}))
13477 return StmtError();
13478 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13479 // If a reduction clause is present on the taskloop directive, the nogroup
13480 // clause must not be specified.
13482 return StmtError();
13484 return StmtError();
13485
13487 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13488}
13489
13491 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13492 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13493 if (!AStmt)
13494 return StmtError();
13495
13496 CapturedStmt *CS =
13497 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13498
13500 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13501 // define the nested loops number.
13502 unsigned NestedLoopCount = checkOpenMPLoop(
13503 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13504 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13505 VarsWithImplicitDSA, B);
13506 if (NestedLoopCount == 0)
13507 return StmtError();
13508
13509 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13510 "omp for loop exprs were not built");
13511
13512 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13513 // The grainsize clause and num_tasks clause are mutually exclusive and may
13514 // not appear on the same taskloop directive.
13516 {OMPC_grainsize, OMPC_num_tasks}))
13517 return StmtError();
13518 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13519 // If a reduction clause is present on the taskloop directive, the nogroup
13520 // clause must not be specified.
13522 return StmtError();
13523
13525 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13526 DSAStack->isCancelRegion());
13527}
13528
13530 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13531 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13532 if (!AStmt)
13533 return StmtError();
13534
13535 CapturedStmt *CS =
13536 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13537
13539 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13540 // define the nested loops number.
13541 unsigned NestedLoopCount = checkOpenMPLoop(
13542 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13543 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13544 VarsWithImplicitDSA, B);
13545 if (NestedLoopCount == 0)
13546 return StmtError();
13547
13548 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13549 "omp for loop exprs were not built");
13550
13551 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13552 // The grainsize clause and num_tasks clause are mutually exclusive and may
13553 // not appear on the same taskloop directive.
13555 {OMPC_grainsize, OMPC_num_tasks}))
13556 return StmtError();
13557 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13558 // If a reduction clause is present on the taskloop directive, the nogroup
13559 // clause must not be specified.
13561 return StmtError();
13562
13564 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13565 DSAStack->isCancelRegion());
13566}
13567
13569 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13570 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13571 if (!AStmt)
13572 return StmtError();
13573
13575 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13576
13578 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13579 // define the nested loops number.
13580 unsigned NestedLoopCount = checkOpenMPLoop(
13581 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13582 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13583 VarsWithImplicitDSA, B);
13584 if (NestedLoopCount == 0)
13585 return StmtError();
13586
13587 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13588 return StmtError();
13589
13590 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13591 // The grainsize clause and num_tasks clause are mutually exclusive and may
13592 // not appear on the same taskloop directive.
13594 {OMPC_grainsize, OMPC_num_tasks}))
13595 return StmtError();
13596 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13597 // If a reduction clause is present on the taskloop directive, the nogroup
13598 // clause must not be specified.
13600 return StmtError();
13602 return StmtError();
13603
13605 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13606}
13607
13609 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13610 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13611 if (!AStmt)
13612 return StmtError();
13613
13615 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13616
13618 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13619 // define the nested loops number.
13620 unsigned NestedLoopCount = checkOpenMPLoop(
13621 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13622 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13623 VarsWithImplicitDSA, B);
13624 if (NestedLoopCount == 0)
13625 return StmtError();
13626
13627 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13628 return StmtError();
13629
13630 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13631 // The grainsize clause and num_tasks clause are mutually exclusive and may
13632 // not appear on the same taskloop directive.
13634 {OMPC_grainsize, OMPC_num_tasks}))
13635 return StmtError();
13636 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13637 // If a reduction clause is present on the taskloop directive, the nogroup
13638 // clause must not be specified.
13640 return StmtError();
13642 return StmtError();
13643
13645 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13646}
13647
13649 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13650 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13651 if (!AStmt)
13652 return StmtError();
13653
13654 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13656 // In presence of clause 'collapse' with number of loops, it will
13657 // define the nested loops number.
13658 unsigned NestedLoopCount =
13659 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
13660 nullptr /*ordered not a clause on distribute*/, AStmt,
13661 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13662 if (NestedLoopCount == 0)
13663 return StmtError();
13664
13665 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13666 "omp for loop exprs were not built");
13667
13669 auto *DistributeDirective = OMPDistributeDirective::Create(
13670 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13671 return DistributeDirective;
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_distribute_parallel_for, 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_distribute_parallel_for, 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 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13694 "omp for loop exprs were not built");
13695
13697 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13698 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13699}
13700
13702 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13703 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13704 if (!AStmt)
13705 return StmtError();
13706
13708 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
13709
13711 // In presence of clause 'collapse' with number of loops, it will
13712 // define the nested loops number.
13713 unsigned NestedLoopCount = checkOpenMPLoop(
13714 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13715 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13716 VarsWithImplicitDSA, B);
13717 if (NestedLoopCount == 0)
13718 return StmtError();
13719
13720 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13721 return StmtError();
13722
13724 return StmtError();
13725
13727 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13728}
13729
13731 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13732 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13733 if (!AStmt)
13734 return StmtError();
13735
13736 CapturedStmt *CS =
13737 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
13738
13740 // In presence of clause 'collapse' with number of loops, it will
13741 // define the nested loops number.
13742 unsigned NestedLoopCount =
13743 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
13744 nullptr /*ordered not a clause on distribute*/, CS,
13745 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13746 if (NestedLoopCount == 0)
13747 return StmtError();
13748
13749 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13750 return StmtError();
13751
13753 return StmtError();
13754
13755 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13756 NestedLoopCount, Clauses, AStmt, B);
13757}
13758
13760 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13761 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13762 if (!AStmt)
13763 return StmtError();
13764
13765 CapturedStmt *CS =
13766 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
13767
13769 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13770 // define the nested loops number.
13771 unsigned NestedLoopCount = checkOpenMPLoop(
13772 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
13773 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13774 VarsWithImplicitDSA, B);
13775 if (NestedLoopCount == 0)
13776 return StmtError();
13777
13778 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13779 return StmtError();
13780
13782 return StmtError();
13783
13785 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13786}
13787
13789 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13790 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13791 if (!AStmt)
13792 return StmtError();
13793
13794 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
13795
13797 // In presence of clause 'collapse' with number of loops, it will define the
13798 // nested loops number.
13799 unsigned NestedLoopCount =
13800 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
13801 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13802 VarsWithImplicitDSA, B);
13803 if (NestedLoopCount == 0)
13804 return StmtError();
13805
13806 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13807 return StmtError();
13808
13810 return StmtError();
13811
13812 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13813 NestedLoopCount, Clauses, AStmt, B);
13814}
13815
13817 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13818 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13819 if (!AStmt)
13820 return StmtError();
13821
13822 CapturedStmt *CS =
13823 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
13824
13826 // In presence of clause 'collapse' with number of loops, it will
13827 // define the nested loops number.
13828 unsigned NestedLoopCount =
13829 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
13830 nullptr /*ordered not a clause on distribute*/, CS,
13831 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
13832 if (NestedLoopCount == 0)
13833 return StmtError();
13834
13835 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13836 "omp teams distribute loop exprs were not built");
13837
13838 DSAStack->setParentTeamsRegionLoc(StartLoc);
13839
13841 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13842}
13843
13845 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13846 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13847 if (!AStmt)
13848 return StmtError();
13849
13850 CapturedStmt *CS =
13851 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
13852
13854 // In presence of clause 'collapse' with number of loops, it will
13855 // define the nested loops number.
13856 unsigned NestedLoopCount = checkOpenMPLoop(
13857 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
13858 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13859 VarsWithImplicitDSA, B);
13860 if (NestedLoopCount == 0)
13861 return StmtError();
13862
13863 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13864 return StmtError();
13865
13867 return StmtError();
13868
13869 DSAStack->setParentTeamsRegionLoc(StartLoc);
13870
13872 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13873}
13874
13876 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13877 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13878 if (!AStmt)
13879 return StmtError();
13880
13882 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
13883
13885 // In presence of clause 'collapse' with number of loops, it will
13886 // define the nested loops number.
13887 unsigned NestedLoopCount = checkOpenMPLoop(
13888 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
13889 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13890 VarsWithImplicitDSA, B);
13891 if (NestedLoopCount == 0)
13892 return StmtError();
13893
13894 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13895 return StmtError();
13896
13898 return StmtError();
13899
13900 DSAStack->setParentTeamsRegionLoc(StartLoc);
13901
13903 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13904}
13905
13907 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13908 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13909 if (!AStmt)
13910 return StmtError();
13911
13913 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
13914
13916 // In presence of clause 'collapse' with number of loops, it will
13917 // define the nested loops number.
13918 unsigned NestedLoopCount = checkOpenMPLoop(
13919 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
13920 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13921 VarsWithImplicitDSA, B);
13922
13923 if (NestedLoopCount == 0)
13924 return StmtError();
13925
13926 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13927 "omp for loop exprs were not built");
13928
13929 DSAStack->setParentTeamsRegionLoc(StartLoc);
13930
13932 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13933 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13934}
13935
13937 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13938 SourceLocation EndLoc) {
13939 if (!AStmt)
13940 return StmtError();
13941
13942 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
13943
13944 const OMPClause *BareClause = nullptr;
13945 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
13946 hasClauses(Clauses, OMPC_thread_limit);
13947 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
13948 BareClause = C;
13949 return C->getClauseKind() == OMPC_ompx_bare;
13950 });
13951
13952 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
13953 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
13954 return StmtError();
13955 }
13956
13957 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
13958 unsigned DiagNo = HasBareClause
13959 ? diag::err_ompx_more_than_three_expr_not_allowed
13960 : diag::err_omp_multi_expr_not_allowed;
13961 if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
13962 ClauseMaxNumExprs, DiagNo) ||
13963 !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses,
13964 ClauseMaxNumExprs, DiagNo))
13965 return StmtError();
13966
13967 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
13968 Clauses, AStmt);
13969}
13970
13972 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13973 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13974 if (!AStmt)
13975 return StmtError();
13976
13977 if (!checkNumExprsInClause<OMPNumTeamsClause>(
13978 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
13979 !checkNumExprsInClause<OMPThreadLimitClause>(
13980 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13981 return StmtError();
13982
13983 CapturedStmt *CS =
13984 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
13985
13987 // In presence of clause 'collapse' with number of loops, it will
13988 // define the nested loops number.
13989 unsigned NestedLoopCount = checkOpenMPLoop(
13990 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
13991 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
13992 VarsWithImplicitDSA, B);
13993 if (NestedLoopCount == 0)
13994 return StmtError();
13995
13996 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13997 "omp target teams distribute loop exprs were not built");
13998
14000 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14001}
14002
14004 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14005 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14006 if (!AStmt)
14007 return StmtError();
14008
14009 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14010 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14011 !checkNumExprsInClause<OMPThreadLimitClause>(
14012 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14013 return StmtError();
14014
14016 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14017
14019 // In presence of clause 'collapse' with number of loops, it will
14020 // define the nested loops number.
14021 unsigned NestedLoopCount = checkOpenMPLoop(
14022 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14023 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14024 VarsWithImplicitDSA, B);
14025 if (NestedLoopCount == 0)
14026 return StmtError();
14027
14028 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14029 return StmtError();
14030
14032 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14033 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14034}
14035
14037 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14038 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14039 if (!AStmt)
14040 return StmtError();
14041
14042 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14043 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14044 !checkNumExprsInClause<OMPThreadLimitClause>(
14045 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14046 return StmtError();
14047
14049 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14050
14052 // In presence of clause 'collapse' with number of loops, it will
14053 // define the nested loops number.
14054 unsigned NestedLoopCount =
14055 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14056 getCollapseNumberExpr(Clauses),
14057 nullptr /*ordered not a clause on distribute*/, CS,
14058 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14059 if (NestedLoopCount == 0)
14060 return StmtError();
14061
14062 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14063 return StmtError();
14064
14066 return StmtError();
14067
14069 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14070}
14071
14073 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14074 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14075 if (!AStmt)
14076 return StmtError();
14077
14078 if (!checkNumExprsInClause<OMPNumTeamsClause>(
14079 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
14080 !checkNumExprsInClause<OMPThreadLimitClause>(
14081 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14082 return StmtError();
14083
14085 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14086
14088 // In presence of clause 'collapse' with number of loops, it will
14089 // define the nested loops number.
14090 unsigned NestedLoopCount = checkOpenMPLoop(
14091 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14092 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14093 VarsWithImplicitDSA, B);
14094 if (NestedLoopCount == 0)
14095 return StmtError();
14096
14097 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14098 return StmtError();
14099
14101 return StmtError();
14102
14104 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14105}
14106
14107bool SemaOpenMP::checkTransformableLoopNest(
14108 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14110 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits) {
14111 OriginalInits.emplace_back();
14113 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14114 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14115 Stmt *CurStmt) {
14116 VarsWithInheritedDSAType TmpDSA;
14117 unsigned SingleNumLoops =
14118 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14119 TmpDSA, LoopHelpers[Cnt]);
14120 if (SingleNumLoops == 0)
14121 return true;
14122 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14123 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14124 OriginalInits.back().push_back(For->getInit());
14125 Body = For->getBody();
14126 } else {
14127 assert(isa<CXXForRangeStmt>(CurStmt) &&
14128 "Expected canonical for or range-based for loops.");
14129 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14130 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14131 Body = CXXFor->getBody();
14132 }
14133 OriginalInits.emplace_back();
14134 return false;
14135 },
14136 [&OriginalInits](OMPLoopBasedDirective *Transform) {
14137 Stmt *DependentPreInits;
14138 if (auto *Dir = dyn_cast<OMPTileDirective>(Transform))
14139 DependentPreInits = Dir->getPreInits();
14140 else if (auto *Dir = dyn_cast<OMPUnrollDirective>(Transform))
14141 DependentPreInits = Dir->getPreInits();
14142 else if (auto *Dir = dyn_cast<OMPReverseDirective>(Transform))
14143 DependentPreInits = Dir->getPreInits();
14144 else if (auto *Dir = dyn_cast<OMPInterchangeDirective>(Transform))
14145 DependentPreInits = Dir->getPreInits();
14146 else
14147 llvm_unreachable("Unhandled loop transformation");
14148
14149 appendFlattenedStmtList(OriginalInits.back(), DependentPreInits);
14150 });
14151 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14152 OriginalInits.pop_back();
14153 return Result;
14154}
14155
14156/// Add preinit statements that need to be propageted from the selected loop.
14157static void addLoopPreInits(ASTContext &Context,
14159 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14160 SmallVectorImpl<Stmt *> &PreInits) {
14161
14162 // For range-based for-statements, ensure that their syntactic sugar is
14163 // executed by adding them as pre-init statements.
14164 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14165 Stmt *RangeInit = CXXRangeFor->getInit();
14166 if (RangeInit)
14167 PreInits.push_back(RangeInit);
14168
14169 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14170 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14171 RangeStmt->getBeginLoc(),
14172 RangeStmt->getEndLoc()));
14173
14174 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14175 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14176 RangeEnd->getBeginLoc(),
14177 RangeEnd->getEndLoc()));
14178 }
14179
14180 llvm::append_range(PreInits, OriginalInit);
14181
14182 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14183 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14184 PreInits.push_back(new (Context) DeclStmt(
14185 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14186 }
14187
14188 // Gather declarations for the data members used as counters.
14189 for (Expr *CounterRef : LoopHelper.Counters) {
14190 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14191 if (isa<OMPCapturedExprDecl>(CounterDecl))
14192 PreInits.push_back(new (Context) DeclStmt(
14193 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14194 }
14195}
14196
14197/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14198/// loop of a construct.
14199static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14200 size_t NumLoops = LoopStmts.size();
14202 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14203 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14204 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14205 LoopStmts[Cnt] = CurStmt;
14206 return false;
14207 });
14208 assert(!is_contained(LoopStmts, nullptr) &&
14209 "Expecting a loop statement for each affected loop");
14210}
14211
14213 Stmt *AStmt,
14214 SourceLocation StartLoc,
14215 SourceLocation EndLoc) {
14216 ASTContext &Context = getASTContext();
14217 Scope *CurScope = SemaRef.getCurScope();
14218
14219 const auto *SizesClause =
14220 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14221 if (!SizesClause ||
14222 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14223 return StmtError();
14224 unsigned NumLoops = SizesClause->getNumSizes();
14225
14226 // Empty statement should only be possible if there already was an error.
14227 if (!AStmt)
14228 return StmtError();
14229
14230 // Verify and diagnose loop nest.
14232 Stmt *Body = nullptr;
14233 SmallVector<SmallVector<Stmt *, 0>, 4> OriginalInits;
14234 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14235 OriginalInits))
14236 return StmtError();
14237
14238 // Delay tiling to when template is completely instantiated.
14240 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14241 NumLoops, AStmt, nullptr, nullptr);
14242
14243 assert(LoopHelpers.size() == NumLoops &&
14244 "Expecting loop iteration space dimensionality to match number of "
14245 "affected loops");
14246 assert(OriginalInits.size() == NumLoops &&
14247 "Expecting loop iteration space dimensionality to match number of "
14248 "affected loops");
14249
14250 // Collect all affected loop statements.
14251 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14252 collectLoopStmts(AStmt, LoopStmts);
14253
14254 SmallVector<Stmt *, 4> PreInits;
14255 CaptureVars CopyTransformer(SemaRef);
14256
14257 // Create iteration variables for the generated loops.
14258 SmallVector<VarDecl *, 4> FloorIndVars;
14259 SmallVector<VarDecl *, 4> TileIndVars;
14260 FloorIndVars.resize(NumLoops);
14261 TileIndVars.resize(NumLoops);
14262 for (unsigned I = 0; I < NumLoops; ++I) {
14263 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14264
14265 assert(LoopHelper.Counters.size() == 1 &&
14266 "Expect single-dimensional loop iteration space");
14267 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14268 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14269 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14270 QualType CntTy = IterVarRef->getType();
14271
14272 // Iteration variable for the floor (i.e. outer) loop.
14273 {
14274 std::string FloorCntName =
14275 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14276 VarDecl *FloorCntDecl =
14277 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14278 FloorIndVars[I] = FloorCntDecl;
14279 }
14280
14281 // Iteration variable for the tile (i.e. inner) loop.
14282 {
14283 std::string TileCntName =
14284 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14285
14286 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14287 // used by the expressions to derive the original iteration variable's
14288 // value from the logical iteration number.
14289 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14290 TileCntDecl->setDeclName(
14291 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14292 TileIndVars[I] = TileCntDecl;
14293 }
14294
14295 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14296 PreInits);
14297 }
14298
14299 // Once the original iteration values are set, append the innermost body.
14300 Stmt *Inner = Body;
14301
14302 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14303 SizesClause, CurScope](int I) -> Expr * {
14304 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14305 if (isa<ConstantExpr>(DimTileSizeExpr))
14306 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14307
14308 // When the tile size is not a constant but a variable, it is possible to
14309 // pass non-positive numbers. For instance:
14310 // \code{c}
14311 // int a = 0;
14312 // #pragma omp tile sizes(a)
14313 // for (int i = 0; i < 42; ++i)
14314 // body(i);
14315 // \endcode
14316 // Although there is no meaningful interpretation of the tile size, the body
14317 // should still be executed 42 times to avoid surprises. To preserve the
14318 // invariant that every loop iteration is executed exactly once and not
14319 // cause an infinite loop, apply a minimum tile size of one.
14320 // Build expr:
14321 // \code{c}
14322 // (TS <= 0) ? 1 : TS
14323 // \endcode
14324 QualType DimTy = DimTileSizeExpr->getType();
14325 uint64_t DimWidth = Context.getTypeSize(DimTy);
14327 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14328 IntegerLiteral *One =
14329 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14331 CurScope, {}, BO_LE,
14332 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14333 Expr *MinOne = new (Context) ConditionalOperator(
14334 Cond, {}, One, {},
14335 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
14337 return MinOne;
14338 };
14339
14340 // Create tile loops from the inside to the outside.
14341 for (int I = NumLoops - 1; I >= 0; --I) {
14342 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14343 Expr *NumIterations = LoopHelper.NumIterations;
14344 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14345 QualType IVTy = NumIterations->getType();
14346 Stmt *LoopStmt = LoopStmts[I];
14347
14348 // Commonly used variables. One of the constraints of an AST is that every
14349 // node object must appear at most once, hence we define lamdas that create
14350 // a new AST node at every use.
14351 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
14352 OrigCntVar]() {
14353 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
14354 OrigCntVar->getExprLoc());
14355 };
14356 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14357 OrigCntVar]() {
14358 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14359 OrigCntVar->getExprLoc());
14360 };
14361
14362 // For init-statement: auto .tile.iv = .floor.iv
14364 TileIndVars[I], SemaRef.DefaultLvalueConversion(MakeFloorIVRef()).get(),
14365 /*DirectInit=*/false);
14366 Decl *CounterDecl = TileIndVars[I];
14367 StmtResult InitStmt = new (Context)
14368 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14369 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14370 if (!InitStmt.isUsable())
14371 return StmtError();
14372
14373 // For cond-expression:
14374 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
14375 ExprResult EndOfTile =
14376 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14377 MakeFloorIVRef(), MakeDimTileSize(I));
14378 if (!EndOfTile.isUsable())
14379 return StmtError();
14380 ExprResult IsPartialTile =
14381 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14382 NumIterations, EndOfTile.get());
14383 if (!IsPartialTile.isUsable())
14384 return StmtError();
14385 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
14386 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
14387 IsPartialTile.get(), NumIterations, EndOfTile.get());
14388 if (!MinTileAndIterSpace.isUsable())
14389 return StmtError();
14390 ExprResult CondExpr =
14391 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14392 MakeTileIVRef(), MinTileAndIterSpace.get());
14393 if (!CondExpr.isUsable())
14394 return StmtError();
14395
14396 // For incr-statement: ++.tile.iv
14397 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
14398 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
14399 if (!IncrStmt.isUsable())
14400 return StmtError();
14401
14402 // Statements to set the original iteration variable's value from the
14403 // logical iteration number.
14404 // Generated for loop is:
14405 // \code
14406 // Original_for_init;
14407 // for (auto .tile.iv = .floor.iv;
14408 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
14409 // ++.tile.iv) {
14410 // Original_Body;
14411 // Original_counter_update;
14412 // }
14413 // \endcode
14414 // FIXME: If the innermost body is an loop itself, inserting these
14415 // statements stops it being recognized as a perfectly nested loop (e.g.
14416 // for applying tiling again). If this is the case, sink the expressions
14417 // further into the inner loop.
14418 SmallVector<Stmt *, 4> BodyParts;
14419 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14420 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14421 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
14422 BodyParts.push_back(Inner);
14423 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
14424 Inner->getBeginLoc(), Inner->getEndLoc());
14425 Inner = new (Context)
14426 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14427 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14428 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14429 }
14430
14431 // Create floor loops from the inside to the outside.
14432 for (int I = NumLoops - 1; I >= 0; --I) {
14433 auto &LoopHelper = LoopHelpers[I];
14434 Expr *NumIterations = LoopHelper.NumIterations;
14435 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
14436 QualType IVTy = NumIterations->getType();
14437
14438 // Commonly used variables. One of the constraints of an AST is that every
14439 // node object must appear at most once, hence we define lamdas that create
14440 // a new AST node at every use.
14441 auto MakeFloorIVRef = [&SemaRef = this->SemaRef, &FloorIndVars, I, IVTy,
14442 OrigCntVar]() {
14443 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14444 OrigCntVar->getExprLoc());
14445 };
14446
14447 // For init-statement: auto .floor.iv = 0
14449 FloorIndVars[I],
14450 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14451 /*DirectInit=*/false);
14452 Decl *CounterDecl = FloorIndVars[I];
14453 StmtResult InitStmt = new (Context)
14454 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
14455 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
14456 if (!InitStmt.isUsable())
14457 return StmtError();
14458
14459 // For cond-expression: .floor.iv < NumIterations
14460 ExprResult CondExpr =
14461 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14462 MakeFloorIVRef(), NumIterations);
14463 if (!CondExpr.isUsable())
14464 return StmtError();
14465
14466 // For incr-statement: .floor.iv += DimTileSize
14467 ExprResult IncrStmt =
14468 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14469 MakeFloorIVRef(), MakeDimTileSize(I));
14470 if (!IncrStmt.isUsable())
14471 return StmtError();
14472
14473 Inner = new (Context)
14474 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
14475 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
14476 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14477 }
14478
14479 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
14480 AStmt, Inner,
14481 buildPreInits(Context, PreInits));
14482}
14483
14485 Stmt *AStmt,
14486 SourceLocation StartLoc,
14487 SourceLocation EndLoc) {
14488 ASTContext &Context = getASTContext();
14489 Scope *CurScope = SemaRef.getCurScope();
14490 // Empty statement should only be possible if there already was an error.
14491 if (!AStmt)
14492 return StmtError();
14493
14495 {OMPC_partial, OMPC_full}))
14496 return StmtError();
14497
14498 const OMPFullClause *FullClause =
14499 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
14500 const OMPPartialClause *PartialClause =
14501 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
14502 assert(!(FullClause && PartialClause) &&
14503 "mutual exclusivity must have been checked before");
14504
14505 constexpr unsigned NumLoops = 1;
14506 Stmt *Body = nullptr;
14508 NumLoops);
14509 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14510 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
14511 Body, OriginalInits))
14512 return StmtError();
14513
14514 unsigned NumGeneratedLoops = PartialClause ? 1 : 0;
14515
14516 // Delay unrolling to when template is completely instantiated.
14518 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14519 NumGeneratedLoops, nullptr, nullptr);
14520
14521 assert(LoopHelpers.size() == NumLoops &&
14522 "Expecting a single-dimensional loop iteration space");
14523 assert(OriginalInits.size() == NumLoops &&
14524 "Expecting a single-dimensional loop iteration space");
14525 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14526
14527 if (FullClause) {
14529 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
14530 /*SuppressExprDiags=*/true)
14531 .isUsable()) {
14532 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
14533 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
14534 << "#pragma omp unroll full";
14535 return StmtError();
14536 }
14537 }
14538
14539 // The generated loop may only be passed to other loop-associated directive
14540 // when a partial clause is specified. Without the requirement it is
14541 // sufficient to generate loop unroll metadata at code-generation.
14542 if (NumGeneratedLoops == 0)
14543 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14544 NumGeneratedLoops, nullptr, nullptr);
14545
14546 // Otherwise, we need to provide a de-sugared/transformed AST that can be
14547 // associated with another loop directive.
14548 //
14549 // The canonical loop analysis return by checkTransformableLoopNest assumes
14550 // the following structure to be the same loop without transformations or
14551 // directives applied: \code OriginalInits; LoopHelper.PreInits;
14552 // LoopHelper.Counters;
14553 // for (; IV < LoopHelper.NumIterations; ++IV) {
14554 // LoopHelper.Updates;
14555 // Body;
14556 // }
14557 // \endcode
14558 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
14559 // and referenced by LoopHelper.IterationVarRef.
14560 //
14561 // The unrolling directive transforms this into the following loop:
14562 // \code
14563 // OriginalInits; \
14564 // LoopHelper.PreInits; > NewPreInits
14565 // LoopHelper.Counters; /
14566 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
14567 // #pragma clang loop unroll_count(Factor)
14568 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
14569 // {
14570 // LoopHelper.Updates;
14571 // Body;
14572 // }
14573 // }
14574 // \endcode
14575 // where UIV is a new logical iteration counter. IV must be the same VarDecl
14576 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
14577 // references it. If the partially unrolled loop is associated with another
14578 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
14579 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
14580 // OpenMP canonical loop. The inner loop is not an associable canonical loop
14581 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
14582 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
14583 // property of the OMPLoopBasedDirective instead of statements in
14584 // CompoundStatement. This is to allow the loop to become a non-outermost loop
14585 // of a canonical loop nest where these PreInits are emitted before the
14586 // outermost directive.
14587
14588 // Find the loop statement.
14589 Stmt *LoopStmt = nullptr;
14590 collectLoopStmts(AStmt, {LoopStmt});
14591
14592 // Determine the PreInit declarations.
14593 SmallVector<Stmt *, 4> PreInits;
14594 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14595
14596 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14597 QualType IVTy = IterationVarRef->getType();
14598 assert(LoopHelper.Counters.size() == 1 &&
14599 "Expecting a single-dimensional loop iteration space");
14600 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14601
14602 // Determine the unroll factor.
14603 uint64_t Factor;
14604 SourceLocation FactorLoc;
14605 if (Expr *FactorVal = PartialClause->getFactor()) {
14606 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
14607 FactorLoc = FactorVal->getExprLoc();
14608 } else {
14609 // TODO: Use a better profitability model.
14610 Factor = 2;
14611 }
14612 assert(Factor > 0 && "Expected positive unroll factor");
14613 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
14615 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
14616 IVTy, FactorLoc);
14617 };
14618
14619 // Iteration variable SourceLocations.
14620 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14621 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14622 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14623
14624 // Internal variable names.
14625 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14626 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
14627 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
14628 std::string InnerTripCountName =
14629 (Twine(".unroll_inner.tripcount.") + OrigVarName).str();
14630
14631 // Create the iteration variable for the unrolled loop.
14632 VarDecl *OuterIVDecl =
14633 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
14634 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
14635 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
14636 };
14637
14638 // Iteration variable for the inner loop: Reuse the iteration variable created
14639 // by checkOpenMPLoop.
14640 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14641 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
14642 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
14643 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
14644 };
14645
14646 // Make a copy of the NumIterations expression for each use: By the AST
14647 // constraints, every expression object in a DeclContext must be unique.
14648 CaptureVars CopyTransformer(SemaRef);
14649 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14650 return AssertSuccess(
14651 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14652 };
14653
14654 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
14655 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
14656 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
14657 /*DirectInit=*/false);
14658 StmtResult InnerInit = new (Context)
14659 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14660 if (!InnerInit.isUsable())
14661 return StmtError();
14662
14663 // Inner For cond-expression:
14664 // \code
14665 // .unroll_inner.iv < .unrolled.iv + Factor &&
14666 // .unroll_inner.iv < NumIterations
14667 // \endcode
14668 // This conjunction of two conditions allows ScalarEvolution to derive the
14669 // maximum trip count of the inner loop.
14670 ExprResult EndOfTile =
14671 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
14672 MakeOuterRef(), MakeFactorExpr());
14673 if (!EndOfTile.isUsable())
14674 return StmtError();
14675 ExprResult InnerCond1 =
14676 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14677 MakeInnerRef(), EndOfTile.get());
14678 if (!InnerCond1.isUsable())
14679 return StmtError();
14680 ExprResult InnerCond2 =
14681 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14682 MakeInnerRef(), MakeNumIterations());
14683 if (!InnerCond2.isUsable())
14684 return StmtError();
14685 ExprResult InnerCond =
14686 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
14687 InnerCond1.get(), InnerCond2.get());
14688 if (!InnerCond.isUsable())
14689 return StmtError();
14690
14691 // Inner For incr-statement: ++.unroll_inner.iv
14692 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
14693 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
14694 if (!InnerIncr.isUsable())
14695 return StmtError();
14696
14697 // Inner For statement.
14698 SmallVector<Stmt *> InnerBodyStmts;
14699 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
14700 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14701 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14702 InnerBodyStmts.push_back(Body);
14703 CompoundStmt *InnerBody =
14705 Body->getBeginLoc(), Body->getEndLoc());
14706 ForStmt *InnerFor = new (Context)
14707 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
14708 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
14709 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14710
14711 // Unroll metadata for the inner loop.
14712 // This needs to take into account the remainder portion of the unrolled loop,
14713 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
14714 // supports multiple loop exits. Instead, unroll using a factor equivalent to
14715 // the maximum trip count, which will also generate a remainder loop. Just
14716 // `unroll(enable)` (which could have been useful if the user has not
14717 // specified a concrete factor; even though the outer loop cannot be
14718 // influenced anymore, would avoid more code bloat than necessary) will refuse
14719 // the loop because "Won't unroll; remainder loop could not be generated when
14720 // assuming runtime trip count". Even if it did work, it must not choose a
14721 // larger unroll factor than the maximum loop length, or it would always just
14722 // execute the remainder loop.
14723 LoopHintAttr *UnrollHintAttr =
14724 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
14725 LoopHintAttr::Numeric, MakeFactorExpr());
14726 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
14727 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
14728
14729 // Outer For init-statement: auto .unrolled.iv = 0
14731 OuterIVDecl,
14732 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
14733 /*DirectInit=*/false);
14734 StmtResult OuterInit = new (Context)
14735 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14736 if (!OuterInit.isUsable())
14737 return StmtError();
14738
14739 // Outer For cond-expression: .unrolled.iv < NumIterations
14740 ExprResult OuterConde =
14741 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14742 MakeOuterRef(), MakeNumIterations());
14743 if (!OuterConde.isUsable())
14744 return StmtError();
14745
14746 // Outer For incr-statement: .unrolled.iv += Factor
14747 ExprResult OuterIncr =
14748 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
14749 MakeOuterRef(), MakeFactorExpr());
14750 if (!OuterIncr.isUsable())
14751 return StmtError();
14752
14753 // Outer For statement.
14754 ForStmt *OuterFor = new (Context)
14755 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
14756 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
14757 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14758
14759 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
14760 NumGeneratedLoops, OuterFor,
14761 buildPreInits(Context, PreInits));
14762}
14763
14765 SourceLocation StartLoc,
14766 SourceLocation EndLoc) {
14767 ASTContext &Context = getASTContext();
14768 Scope *CurScope = SemaRef.getCurScope();
14769
14770 // Empty statement should only be possible if there already was an error.
14771 if (!AStmt)
14772 return StmtError();
14773
14774 constexpr unsigned NumLoops = 1;
14775 Stmt *Body = nullptr;
14777 NumLoops);
14778 SmallVector<SmallVector<Stmt *, 0>, NumLoops + 1> OriginalInits;
14779 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
14780 Body, OriginalInits))
14781 return StmtError();
14782
14783 // Delay applying the transformation to when template is completely
14784 // instantiated.
14786 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14787 nullptr, nullptr);
14788
14789 assert(LoopHelpers.size() == NumLoops &&
14790 "Expecting a single-dimensional loop iteration space");
14791 assert(OriginalInits.size() == NumLoops &&
14792 "Expecting a single-dimensional loop iteration space");
14793 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
14794
14795 // Find the loop statement.
14796 Stmt *LoopStmt = nullptr;
14797 collectLoopStmts(AStmt, {LoopStmt});
14798
14799 // Determine the PreInit declarations.
14800 SmallVector<Stmt *> PreInits;
14801 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
14802
14803 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14804 QualType IVTy = IterationVarRef->getType();
14805 uint64_t IVWidth = Context.getTypeSize(IVTy);
14806 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14807
14808 // Iteration variable SourceLocations.
14809 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
14810 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
14811 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
14812
14813 // Locations pointing to the transformation.
14814 SourceLocation TransformLoc = StartLoc;
14815 SourceLocation TransformLocBegin = StartLoc;
14816 SourceLocation TransformLocEnd = EndLoc;
14817
14818 // Internal variable names.
14819 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
14820 SmallString<64> ForwardIVName(".forward.iv.");
14821 ForwardIVName += OrigVarName;
14822 SmallString<64> ReversedIVName(".reversed.iv.");
14823 ReversedIVName += OrigVarName;
14824
14825 // LoopHelper.Updates will read the logical iteration number from
14826 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
14827 // that logical iteration from it, then assign it to the user loop counter
14828 // variable. We cannot directly use LoopHelper.IterationVarRef as the
14829 // induction variable of the generated loop because it may cause an underflow:
14830 // \code{.c}
14831 // for (unsigned i = 0; i < n; ++i)
14832 // body(i);
14833 // \endcode
14834 //
14835 // Naive reversal:
14836 // \code{.c}
14837 // for (unsigned i = n-1; i >= 0; --i)
14838 // body(i);
14839 // \endcode
14840 //
14841 // Instead, we introduce a new iteration variable representing the logical
14842 // iteration counter of the original loop, convert it to the logical iteration
14843 // number of the reversed loop, then let LoopHelper.Updates compute the user's
14844 // loop iteration variable from it.
14845 // \code{.cpp}
14846 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
14847 // auto .reversed.iv = n - .forward.iv - 1;
14848 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
14849 // body(i); // Body
14850 // }
14851 // \endcode
14852
14853 // Subexpressions with more than one use. One of the constraints of an AST is
14854 // that every node object must appear at most once, hence we define a lambda
14855 // that creates a new AST node at every use.
14856 CaptureVars CopyTransformer(SemaRef);
14857 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
14858 return AssertSuccess(
14859 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
14860 };
14861
14862 // Create the iteration variable for the forward loop (from 0 to n-1).
14863 VarDecl *ForwardIVDecl =
14864 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
14865 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
14866 OrigVarLoc]() {
14867 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
14868 };
14869
14870 // Iteration variable for the reversed induction variable (from n-1 downto 0):
14871 // Reuse the iteration variable created by checkOpenMPLoop.
14872 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
14873 ReversedIVDecl->setDeclName(
14874 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
14875
14876 // For init-statement:
14877 // \code{.cpp}
14878 // auto .forward.iv = 0;
14879 // \endcode
14880 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
14881 ForwardIVDecl->getType(), OrigVarLoc);
14882 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
14883 StmtResult Init = new (Context)
14884 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
14885 if (!Init.isUsable())
14886 return StmtError();
14887
14888 // Forward iv cond-expression:
14889 // \code{.cpp}
14890 // .forward.iv < MakeNumIterations()
14891 // \endcode
14892 ExprResult Cond =
14893 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
14894 MakeForwardRef(), MakeNumIterations());
14895 if (!Cond.isUsable())
14896 return StmtError();
14897
14898 // Forward incr-statement:
14899 // \code{.c}
14900 // ++.forward.iv
14901 // \endcode
14902 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
14903 UO_PreInc, MakeForwardRef());
14904 if (!Incr.isUsable())
14905 return StmtError();
14906
14907 // Reverse the forward-iv:
14908 // \code{.cpp}
14909 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
14910 // \endcode
14911 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
14912 TransformLoc);
14913 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
14914 MakeNumIterations(), One);
14915 if (!Minus.isUsable())
14916 return StmtError();
14917 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
14918 MakeForwardRef());
14919 if (!Minus.isUsable())
14920 return StmtError();
14921 StmtResult InitReversed = new (Context) DeclStmt(
14922 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
14923 if (!InitReversed.isUsable())
14924 return StmtError();
14925 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
14926 /*DirectInit=*/false);
14927
14928 // The new loop body.
14929 SmallVector<Stmt *, 4> BodyStmts;
14930 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
14931 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
14932 BodyStmts.push_back(InitReversed.get());
14933 llvm::append_range(BodyStmts, LoopHelper.Updates);
14934 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
14935 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
14936 BodyStmts.push_back(Body);
14937 auto *ReversedBody =
14938 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
14939 Body->getBeginLoc(), Body->getEndLoc());
14940
14941 // Finally create the reversed For-statement.
14942 auto *ReversedFor = new (Context)
14943 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
14944 ReversedBody, LoopHelper.Init->getBeginLoc(),
14945 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
14946 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
14947 ReversedFor,
14948 buildPreInits(Context, PreInits));
14949}
14950
14952 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14953 SourceLocation EndLoc) {
14954 ASTContext &Context = getASTContext();
14955 DeclContext *CurContext = SemaRef.CurContext;
14956 Scope *CurScope = SemaRef.getCurScope();
14957
14958 // Empty statement should only be possible if there already was an error.
14959 if (!AStmt)
14960 return StmtError();
14961
14962 // interchange without permutation clause swaps two loops.
14963 constexpr size_t NumLoops = 2;
14964
14965 // Verify and diagnose loop nest.
14967 Stmt *Body = nullptr;
14968 SmallVector<SmallVector<Stmt *, 0>, 2> OriginalInits;
14969 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
14970 LoopHelpers, Body, OriginalInits))
14971 return StmtError();
14972
14973 // Delay interchange to when template is completely instantiated.
14974 if (CurContext->isDependentContext())
14975 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
14976 NumLoops, AStmt, nullptr, nullptr);
14977
14978 assert(LoopHelpers.size() == NumLoops &&
14979 "Expecting loop iteration space dimensionaly to match number of "
14980 "affected loops");
14981 assert(OriginalInits.size() == NumLoops &&
14982 "Expecting loop iteration space dimensionaly to match number of "
14983 "affected loops");
14984
14985 // Decode the permutation clause.
14986 constexpr uint64_t Permutation[] = {1, 0};
14987
14988 // Find the affected loops.
14989 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14990 collectLoopStmts(AStmt, LoopStmts);
14991
14992 // Collect pre-init statements on the order before the permuation.
14993 SmallVector<Stmt *> PreInits;
14994 for (auto I : llvm::seq<int>(NumLoops)) {
14995 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14996
14997 assert(LoopHelper.Counters.size() == 1 &&
14998 "Single-dimensional loop iteration space expected");
14999 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15000
15001 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15002 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15003 PreInits);
15004 }
15005
15006 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15007 CaptureVars CopyTransformer(SemaRef);
15008
15009 // Create the permuted loops from the inside to the outside of the
15010 // interchanged loop nest. Body of the innermost new loop is the original
15011 // innermost body.
15012 Stmt *Inner = Body;
15013 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15014 // Get the original loop that belongs to this new position.
15015 uint64_t SourceIdx = Permutation[TargetIdx];
15016 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15017 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15018 assert(SourceHelper.Counters.size() == 1 &&
15019 "Single-dimensional loop iteration space expected");
15020 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15021
15022 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15023 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15024 QualType IVTy = IterVarRef->getType();
15025 assert(IVTy->isIntegerType() &&
15026 "Expected the logical iteration counter to be an integer");
15027
15028 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15029 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15030
15031 // Make a copy of the NumIterations expression for each use: By the AST
15032 // constraints, every expression object in a DeclContext must be unique.
15033 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
15034 return AssertSuccess(
15035 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
15036 };
15037
15038 // Iteration variable for the permuted loop. Reuse the one from
15039 // checkOpenMPLoop which will also be used to update the original loop
15040 // variable.
15041 SmallString<64> PermutedCntName(".permuted_");
15042 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
15043 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15044 PermutedCntDecl->setDeclName(
15045 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
15046 PermutedIndVars[TargetIdx] = PermutedCntDecl;
15047 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
15048 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
15049 };
15050
15051 // For init-statement:
15052 // \code
15053 // auto .permuted_{target}.iv = 0
15054 // \endcode
15055 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
15056 if (!Zero.isUsable())
15057 return StmtError();
15058 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
15059 /*DirectInit=*/false);
15060 StmtResult InitStmt = new (Context)
15061 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
15062 OrigCntVar->getEndLoc());
15063 if (!InitStmt.isUsable())
15064 return StmtError();
15065
15066 // For cond-expression:
15067 // \code
15068 // .permuted_{target}.iv < MakeNumIterations()
15069 // \endcode
15070 ExprResult CondExpr =
15071 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
15072 MakePermutedRef(), MakeNumIterations());
15073 if (!CondExpr.isUsable())
15074 return StmtError();
15075
15076 // For incr-statement:
15077 // \code
15078 // ++.tile.iv
15079 // \endcode
15080 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15081 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
15082 if (!IncrStmt.isUsable())
15083 return StmtError();
15084
15085 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
15086 SourceHelper.Updates.end());
15087 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
15088 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15089 BodyParts.push_back(Inner);
15090 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15091 Inner->getBeginLoc(), Inner->getEndLoc());
15092 Inner = new (Context) ForStmt(
15093 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
15094 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
15095 SourceHelper.Inc->getEndLoc());
15096 }
15097
15098 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15099 NumLoops, AStmt, Inner,
15100 buildPreInits(Context, PreInits));
15101}
15102
15104 Expr *Expr,
15105 SourceLocation StartLoc,
15106 SourceLocation LParenLoc,
15107 SourceLocation EndLoc) {
15108 OMPClause *Res = nullptr;
15109 switch (Kind) {
15110 case OMPC_final:
15111 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
15112 break;
15113 case OMPC_num_threads:
15114 Res = ActOnOpenMPNumThreadsClause(Expr, StartLoc, LParenLoc, EndLoc);
15115 break;
15116 case OMPC_safelen:
15117 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
15118 break;
15119 case OMPC_simdlen:
15120 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
15121 break;
15122 case OMPC_allocator:
15123 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
15124 break;
15125 case OMPC_collapse:
15126 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
15127 break;
15128 case OMPC_ordered:
15129 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
15130 break;
15131 case OMPC_priority:
15132 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
15133 break;
15134 case OMPC_hint:
15135 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
15136 break;
15137 case OMPC_depobj:
15138 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
15139 break;
15140 case OMPC_detach:
15141 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
15142 break;
15143 case OMPC_novariants:
15144 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
15145 break;
15146 case OMPC_nocontext:
15147 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
15148 break;
15149 case OMPC_filter:
15150 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
15151 break;
15152 case OMPC_partial:
15153 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
15154 break;
15155 case OMPC_message:
15156 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
15157 break;
15158 case OMPC_align:
15159 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
15160 break;
15161 case OMPC_ompx_dyn_cgroup_mem:
15162 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
15163 break;
15164 case OMPC_holds:
15165 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
15166 break;
15167 case OMPC_grainsize:
15168 case OMPC_num_tasks:
15169 case OMPC_device:
15170 case OMPC_if:
15171 case OMPC_default:
15172 case OMPC_proc_bind:
15173 case OMPC_schedule:
15174 case OMPC_private:
15175 case OMPC_firstprivate:
15176 case OMPC_lastprivate:
15177 case OMPC_shared:
15178 case OMPC_reduction:
15179 case OMPC_task_reduction:
15180 case OMPC_in_reduction:
15181 case OMPC_linear:
15182 case OMPC_aligned:
15183 case OMPC_copyin:
15184 case OMPC_copyprivate:
15185 case OMPC_nowait:
15186 case OMPC_untied:
15187 case OMPC_mergeable:
15188 case OMPC_threadprivate:
15189 case OMPC_sizes:
15190 case OMPC_allocate:
15191 case OMPC_flush:
15192 case OMPC_read:
15193 case OMPC_write:
15194 case OMPC_update:
15195 case OMPC_capture:
15196 case OMPC_compare:
15197 case OMPC_seq_cst:
15198 case OMPC_acq_rel:
15199 case OMPC_acquire:
15200 case OMPC_release:
15201 case OMPC_relaxed:
15202 case OMPC_depend:
15203 case OMPC_threads:
15204 case OMPC_simd:
15205 case OMPC_map:
15206 case OMPC_nogroup:
15207 case OMPC_dist_schedule:
15208 case OMPC_defaultmap:
15209 case OMPC_unknown:
15210 case OMPC_uniform:
15211 case OMPC_to:
15212 case OMPC_from:
15213 case OMPC_use_device_ptr:
15214 case OMPC_use_device_addr:
15215 case OMPC_is_device_ptr:
15216 case OMPC_unified_address:
15217 case OMPC_unified_shared_memory:
15218 case OMPC_reverse_offload:
15219 case OMPC_dynamic_allocators:
15220 case OMPC_atomic_default_mem_order:
15221 case OMPC_device_type:
15222 case OMPC_match:
15223 case OMPC_nontemporal:
15224 case OMPC_order:
15225 case OMPC_at:
15226 case OMPC_severity:
15227 case OMPC_destroy:
15228 case OMPC_inclusive:
15229 case OMPC_exclusive:
15230 case OMPC_uses_allocators:
15231 case OMPC_affinity:
15232 case OMPC_when:
15233 case OMPC_bind:
15234 case OMPC_num_teams:
15235 case OMPC_thread_limit:
15236 default:
15237 llvm_unreachable("Clause is not allowed.");
15238 }
15239 return Res;
15240}
15241
15242// An OpenMP directive such as 'target parallel' has two captured regions:
15243// for the 'target' and 'parallel' respectively. This function returns
15244// the region in which to capture expressions associated with a clause.
15245// A return value of OMPD_unknown signifies that the expression should not
15246// be captured.
15248 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
15249 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
15250 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
15251 "Invalid directive with CKind-clause");
15252
15253 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
15254 if (NameModifier != OMPD_unknown &&
15255 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
15256 return OMPD_unknown;
15257
15258 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
15259
15260 // [5.2:341:24-30]
15261 // If the clauses have expressions on them, such as for various clauses where
15262 // the argument of the clause is an expression, or lower-bound, length, or
15263 // stride expressions inside array sections (or subscript and stride
15264 // expressions in subscript-triplet for Fortran), or linear-step or alignment
15265 // expressions, the expressions are evaluated immediately before the construct
15266 // to which the clause has been split or duplicated per the above rules
15267 // (therefore inside of the outer leaf constructs). However, the expressions
15268 // inside the num_teams and thread_limit clauses are always evaluated before
15269 // the outermost leaf construct.
15270
15271 // Process special cases first.
15272 switch (CKind) {
15273 case OMPC_if:
15274 switch (DKind) {
15275 case OMPD_teams_loop:
15276 case OMPD_target_teams_loop:
15277 // For [target] teams loop, assume capture region is 'teams' so it's
15278 // available for codegen later to use if/when necessary.
15279 return OMPD_teams;
15280 case OMPD_target_update:
15281 case OMPD_target_enter_data:
15282 case OMPD_target_exit_data:
15283 return OMPD_task;
15284 default:
15285 break;
15286 }
15287 break;
15288 case OMPC_num_teams:
15289 case OMPC_thread_limit:
15290 case OMPC_ompx_dyn_cgroup_mem:
15291 if (Leafs[0] == OMPD_target)
15292 return OMPD_target;
15293 break;
15294 case OMPC_device:
15295 if (Leafs[0] == OMPD_target ||
15296 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
15297 OMPD_target_enter_data, OMPD_target_exit_data},
15298 DKind))
15299 return OMPD_task;
15300 break;
15301 case OMPC_novariants:
15302 case OMPC_nocontext:
15303 if (DKind == OMPD_dispatch)
15304 return OMPD_task;
15305 break;
15306 case OMPC_when:
15307 if (DKind == OMPD_metadirective)
15308 return OMPD_metadirective;
15309 break;
15310 case OMPC_filter:
15311 return OMPD_unknown;
15312 default:
15313 break;
15314 }
15315
15316 // If none of the special cases above applied, and DKind is a capturing
15317 // directive, find the innermost enclosing leaf construct that allows the
15318 // clause, and returns the corresponding capture region.
15319
15320 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
15321 // Find the index in "Leafs" of the last leaf that allows the given
15322 // clause. The search will only include indexes [0, EndIdx).
15323 // EndIdx may be set to the index of the NameModifier, if present.
15324 int InnermostIdx = [&]() {
15325 for (int I = EndIdx - 1; I >= 0; --I) {
15326 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
15327 return I;
15328 }
15329 return -1;
15330 }();
15331
15332 // Find the nearest enclosing capture region.
15334 for (int I = InnermostIdx - 1; I >= 0; --I) {
15335 if (!isOpenMPCapturingDirective(Leafs[I]))
15336 continue;
15337 Regions.clear();
15338 getOpenMPCaptureRegions(Regions, Leafs[I]);
15339 if (Regions[0] != OMPD_unknown)
15340 return Regions.back();
15341 }
15342 return OMPD_unknown;
15343 };
15344
15345 if (isOpenMPCapturingDirective(DKind)) {
15346 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
15347 for (int I = 0, E = Leafs.size(); I != E; ++I) {
15348 if (Leafs[I] == Dir)
15349 return I + 1;
15350 }
15351 return 0;
15352 };
15353
15354 int End = NameModifier == OMPD_unknown ? Leafs.size()
15355 : GetLeafIndex(NameModifier);
15356 return GetEnclosingRegion(End, CKind);
15357 }
15358
15359 return OMPD_unknown;
15360}
15361
15363 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
15364 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
15365 SourceLocation ColonLoc, SourceLocation EndLoc) {
15366 Expr *ValExpr = Condition;
15367 Stmt *HelperValStmt = nullptr;
15368 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15369 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15370 !Condition->isInstantiationDependent() &&
15371 !Condition->containsUnexpandedParameterPack()) {
15373 if (Val.isInvalid())
15374 return nullptr;
15375
15376 ValExpr = Val.get();
15377
15378 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15379 CaptureRegion = getOpenMPCaptureRegionForClause(
15380 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
15381 if (CaptureRegion != OMPD_unknown &&
15383 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15384 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15385 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15386 HelperValStmt = buildPreInits(getASTContext(), Captures);
15387 }
15388 }
15389
15390 return new (getASTContext())
15391 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
15392 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
15393}
15394
15396 SourceLocation StartLoc,
15397 SourceLocation LParenLoc,
15398 SourceLocation EndLoc) {
15399 Expr *ValExpr = Condition;
15400 Stmt *HelperValStmt = nullptr;
15401 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
15402 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
15403 !Condition->isInstantiationDependent() &&
15404 !Condition->containsUnexpandedParameterPack()) {
15406 if (Val.isInvalid())
15407 return nullptr;
15408
15409 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
15410
15411 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15412 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
15413 getLangOpts().OpenMP);
15414 if (CaptureRegion != OMPD_unknown &&
15416 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15417 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15418 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15419 HelperValStmt = buildPreInits(getASTContext(), Captures);
15420 }
15421 }
15422
15423 return new (getASTContext()) OMPFinalClause(
15424 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15425}
15426
15429 Expr *Op) {
15430 if (!Op)
15431 return ExprError();
15432
15433 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
15434 public:
15435 IntConvertDiagnoser()
15436 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
15437 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
15438 QualType T) override {
15439 return S.Diag(Loc, diag::err_omp_not_integral) << T;
15440 }
15441 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
15442 QualType T) override {
15443 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
15444 }
15445 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
15446 QualType T,
15447 QualType ConvTy) override {
15448 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
15449 }
15450 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
15451 QualType ConvTy) override {
15452 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15453 << ConvTy->isEnumeralType() << ConvTy;
15454 }
15455 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
15456 QualType T) override {
15457 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
15458 }
15459 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
15460 QualType ConvTy) override {
15461 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
15462 << ConvTy->isEnumeralType() << ConvTy;
15463 }
15464 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
15465 QualType) override {
15466 llvm_unreachable("conversion functions are permitted");
15467 }
15468 } ConvertDiagnoser;
15469 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
15470}
15471
15472static bool
15474 bool StrictlyPositive, bool BuildCapture = false,
15475 OpenMPDirectiveKind DKind = OMPD_unknown,
15476 OpenMPDirectiveKind *CaptureRegion = nullptr,
15477 Stmt **HelperValStmt = nullptr) {
15478 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
15479 !ValExpr->isInstantiationDependent()) {
15480 SourceLocation Loc = ValExpr->getExprLoc();
15483 if (Value.isInvalid())
15484 return false;
15485
15486 ValExpr = Value.get();
15487 // The expression must evaluate to a non-negative integer value.
15488 if (std::optional<llvm::APSInt> Result =
15489 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
15490 if (Result->isSigned() &&
15491 !((!StrictlyPositive && Result->isNonNegative()) ||
15492 (StrictlyPositive && Result->isStrictlyPositive()))) {
15493 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
15494 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15495 << ValExpr->getSourceRange();
15496 return false;
15497 }
15498 }
15499 if (!BuildCapture)
15500 return true;
15501 *CaptureRegion =
15502 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
15503 if (*CaptureRegion != OMPD_unknown &&
15504 !SemaRef.CurContext->isDependentContext()) {
15505 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15506 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15507 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15508 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
15509 }
15510 }
15511 return true;
15512}
15513
15515 SourceLocation StartLoc,
15516 SourceLocation LParenLoc,
15517 SourceLocation EndLoc) {
15518 Expr *ValExpr = NumThreads;
15519 Stmt *HelperValStmt = nullptr;
15520
15521 // OpenMP [2.5, Restrictions]
15522 // The num_threads expression must evaluate to a positive integer value.
15523 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
15524 /*StrictlyPositive=*/true))
15525 return nullptr;
15526
15527 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
15529 DKind, OMPC_num_threads, getLangOpts().OpenMP);
15530 if (CaptureRegion != OMPD_unknown &&
15532 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
15533 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
15534 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
15535 HelperValStmt = buildPreInits(getASTContext(), Captures);
15536 }
15537
15538 return new (getASTContext()) OMPNumThreadsClause(
15539 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
15540}
15541
15543 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
15544 bool SuppressExprDiags) {
15545 if (!E)
15546 return ExprError();
15547 if (E->isValueDependent() || E->isTypeDependent() ||
15549 return E;
15550
15551 llvm::APSInt Result;
15552 ExprResult ICE;
15553 if (SuppressExprDiags) {
15554 // Use a custom diagnoser that suppresses 'note' diagnostics about the
15555 // expression.
15556 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
15557 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
15559 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
15560 llvm_unreachable("Diagnostic suppressed");
15561 }
15562 } Diagnoser;
15565 } else {
15567 /*FIXME*/ Sema::AllowFold);
15568 }
15569 if (ICE.isInvalid())
15570 return ExprError();
15571
15572 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
15573 (!StrictlyPositive && !Result.isNonNegative())) {
15574 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
15575 << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
15576 << E->getSourceRange();
15577 return ExprError();
15578 }
15579 if ((CKind == OMPC_aligned || CKind == OMPC_align) && !Result.isPowerOf2()) {
15580 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
15581 << E->getSourceRange();
15582 return ExprError();
15583 }
15584 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
15585 DSAStack->setAssociatedLoops(Result.getExtValue());
15586 else if (CKind == OMPC_ordered)
15587 DSAStack->setAssociatedLoops(Result.getExtValue());
15588 return ICE;
15589}
15590
15592 SourceLocation StartLoc,
15593 SourceLocation LParenLoc,
15594 SourceLocation EndLoc) {
15595 // OpenMP [2.8.1, simd construct, Description]
15596 // The parameter of the safelen clause must be a constant
15597 // positive integer expression.
15598 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
15599 if (Safelen.isInvalid())
15600 return nullptr;
15601 return new (getASTContext())
15602 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
15603}
15604
15606 SourceLocation StartLoc,
15607 SourceLocation LParenLoc,
15608 SourceLocation EndLoc) {
15609 // OpenMP [2.8.1, simd construct, Description]
15610 // The parameter of the simdlen clause must be a constant
15611 // positive integer expression.
15612 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
15613 if (Simdlen.isInvalid())
15614 return nullptr;
15615 return new (getASTContext())
15616 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
15617}
15618
15619/// Tries to find omp_allocator_handle_t type.
15621 DSAStackTy *Stack) {
15622 if (!Stack->getOMPAllocatorHandleT().isNull())
15623 return true;
15624
15625 // Set the allocator handle type.
15626 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
15627 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
15628 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
15629 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15630 << "omp_allocator_handle_t";
15631 return false;
15632 }
15633 QualType AllocatorHandleEnumTy = PT.get();
15634 AllocatorHandleEnumTy.addConst();
15635 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
15636
15637 // Fill the predefined allocator map.
15638 bool ErrorFound = false;
15639 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
15640 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
15641 StringRef Allocator =
15642 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
15643 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
15644 auto *VD = dyn_cast_or_null<ValueDecl>(
15645 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
15646 if (!VD) {
15647 ErrorFound = true;
15648 break;
15649 }
15650 QualType AllocatorType =
15652 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
15653 if (!Res.isUsable()) {
15654 ErrorFound = true;
15655 break;
15656 }
15657 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
15659 /*AllowExplicit=*/true);
15660 if (!Res.isUsable()) {
15661 ErrorFound = true;
15662 break;
15663 }
15664 Stack->setAllocator(AllocatorKind, Res.get());
15665 }
15666 if (ErrorFound) {
15667 S.Diag(Loc, diag::err_omp_implied_type_not_found)
15668 << "omp_allocator_handle_t";
15669 return false;
15670 }
15671
15672 return true;
15673}
15674
15676 SourceLocation StartLoc,
15677 SourceLocation LParenLoc,
15678 SourceLocation EndLoc) {
15679 // OpenMP [2.11.3, allocate Directive, Description]
15680 // allocator is an expression of omp_allocator_handle_t type.
15682 return nullptr;
15683
15685 if (Allocator.isInvalid())
15686 return nullptr;
15688 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
15690 /*AllowExplicit=*/true);
15691 if (Allocator.isInvalid())
15692 return nullptr;
15693 return new (getASTContext())
15694 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
15695}
15696
15698 SourceLocation StartLoc,
15699 SourceLocation LParenLoc,
15700 SourceLocation EndLoc) {
15701 // OpenMP [2.7.1, loop construct, Description]
15702 // OpenMP [2.8.1, simd construct, Description]
15703 // OpenMP [2.9.6, distribute construct, Description]
15704 // The parameter of the collapse clause must be a constant
15705 // positive integer expression.
15706 ExprResult NumForLoopsResult =
15707 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
15708 if (NumForLoopsResult.isInvalid())
15709 return nullptr;
15710 return new (getASTContext())
15711 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
15712}
15713
15715 SourceLocation EndLoc,
15716 SourceLocation LParenLoc,
15717 Expr *NumForLoops) {
15718 // OpenMP [2.7.1, loop construct, Description]
15719 // OpenMP [2.8.1, simd construct, Description]
15720 // OpenMP [2.9.6, distribute construct, Description]
15721 // The parameter of the ordered clause must be a constant
15722 // positive integer expression if any.
15723 if (NumForLoops && LParenLoc.isValid()) {
15724 ExprResult NumForLoopsResult =
15725 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
15726 if (NumForLoopsResult.isInvalid())
15727 return nullptr;
15728 NumForLoops = NumForLoopsResult.get();
15729 } else {
15730 NumForLoops = nullptr;
15731 }
15732 auto *Clause =
15734 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
15735 StartLoc, LParenLoc, EndLoc);
15736 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
15737 return Clause;
15738}
15739
15741 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
15742 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15743 OMPClause *Res = nullptr;
15744 switch (Kind) {
15745 case OMPC_default:
15746 Res = ActOnOpenMPDefaultClause(static_cast<DefaultKind>(Argument),
15747 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15748 break;
15749 case OMPC_proc_bind:
15750 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
15751 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15752 break;
15753 case OMPC_atomic_default_mem_order:
15755 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
15756 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15757 break;
15758 case OMPC_fail:
15759 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
15760 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15761 break;
15762 case OMPC_update:
15763 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
15764 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15765 break;
15766 case OMPC_bind:
15767 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
15768 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15769 break;
15770 case OMPC_at:
15771 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
15772 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
15773 break;
15774 case OMPC_severity:
15776 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
15777 LParenLoc, EndLoc);
15778 break;
15779 case OMPC_if:
15780 case OMPC_final:
15781 case OMPC_num_threads:
15782 case OMPC_safelen:
15783 case OMPC_simdlen:
15784 case OMPC_sizes:
15785 case OMPC_allocator:
15786 case OMPC_collapse:
15787 case OMPC_schedule:
15788 case OMPC_private:
15789 case OMPC_firstprivate:
15790 case OMPC_lastprivate:
15791 case OMPC_shared:
15792 case OMPC_reduction:
15793 case OMPC_task_reduction:
15794 case OMPC_in_reduction:
15795 case OMPC_linear:
15796 case OMPC_aligned:
15797 case OMPC_copyin:
15798 case OMPC_copyprivate:
15799 case OMPC_ordered:
15800 case OMPC_nowait:
15801 case OMPC_untied:
15802 case OMPC_mergeable:
15803 case OMPC_threadprivate:
15804 case OMPC_allocate:
15805 case OMPC_flush:
15806 case OMPC_depobj:
15807 case OMPC_read:
15808 case OMPC_write:
15809 case OMPC_capture:
15810 case OMPC_compare:
15811 case OMPC_seq_cst:
15812 case OMPC_acq_rel:
15813 case OMPC_acquire:
15814 case OMPC_release:
15815 case OMPC_relaxed:
15816 case OMPC_depend:
15817 case OMPC_device:
15818 case OMPC_threads:
15819 case OMPC_simd:
15820 case OMPC_map:
15821 case OMPC_num_teams:
15822 case OMPC_thread_limit:
15823 case OMPC_priority:
15824 case OMPC_grainsize:
15825 case OMPC_nogroup:
15826 case OMPC_num_tasks:
15827 case OMPC_hint:
15828 case OMPC_dist_schedule:
15829 case OMPC_defaultmap:
15830 case OMPC_unknown:
15831 case OMPC_uniform:
15832 case OMPC_to:
15833 case OMPC_from:
15834 case OMPC_use_device_ptr:
15835 case OMPC_use_device_addr:
15836 case OMPC_is_device_ptr:
15837 case OMPC_has_device_addr:
15838 case OMPC_unified_address:
15839 case OMPC_unified_shared_memory:
15840 case OMPC_reverse_offload:
15841 case OMPC_dynamic_allocators:
15842 case OMPC_device_type:
15843 case OMPC_match:
15844 case OMPC_nontemporal:
15845 case OMPC_destroy:
15846 case OMPC_novariants:
15847 case OMPC_nocontext:
15848 case OMPC_detach:
15849 case OMPC_inclusive:
15850 case OMPC_exclusive:
15851 case OMPC_uses_allocators:
15852 case OMPC_affinity:
15853 case OMPC_when:
15854 case OMPC_message:
15855 default:
15856 llvm_unreachable("Clause is not allowed.");
15857 }
15858 return Res;
15859}
15860
15861static std::string
15863 ArrayRef<unsigned> Exclude = std::nullopt) {
15864 SmallString<256> Buffer;
15865 llvm::raw_svector_ostream Out(Buffer);
15866 unsigned Skipped = Exclude.size();
15867 for (unsigned I = First; I < Last; ++I) {
15868 if (llvm::is_contained(Exclude, I)) {
15869 --Skipped;
15870 continue;
15871 }
15872 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
15873 if (I + Skipped + 2 == Last)
15874 Out << " or ";
15875 else if (I + Skipped + 1 != Last)
15876 Out << ", ";
15877 }
15878 return std::string(Out.str());
15879}
15880
15882 SourceLocation KindKwLoc,
15883 SourceLocation StartLoc,
15884 SourceLocation LParenLoc,
15885 SourceLocation EndLoc) {
15886 if (Kind == OMP_DEFAULT_unknown) {
15887 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15888 << getListOfPossibleValues(OMPC_default, /*First=*/0,
15889 /*Last=*/unsigned(OMP_DEFAULT_unknown))
15890 << getOpenMPClauseName(OMPC_default);
15891 return nullptr;
15892 }
15893
15894 switch (Kind) {
15895 case OMP_DEFAULT_none:
15896 DSAStack->setDefaultDSANone(KindKwLoc);
15897 break;
15898 case OMP_DEFAULT_shared:
15899 DSAStack->setDefaultDSAShared(KindKwLoc);
15900 break;
15901 case OMP_DEFAULT_firstprivate:
15902 DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
15903 break;
15904 case OMP_DEFAULT_private:
15905 DSAStack->setDefaultDSAPrivate(KindKwLoc);
15906 break;
15907 default:
15908 llvm_unreachable("DSA unexpected in OpenMP default clause");
15909 }
15910
15911 return new (getASTContext())
15912 OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15913}
15914
15916 SourceLocation KindKwLoc,
15917 SourceLocation StartLoc,
15918 SourceLocation LParenLoc,
15919 SourceLocation EndLoc) {
15920 if (Kind == OMP_PROC_BIND_unknown) {
15921 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15922 << getListOfPossibleValues(OMPC_proc_bind,
15923 /*First=*/unsigned(OMP_PROC_BIND_master),
15924 /*Last=*/
15925 unsigned(getLangOpts().OpenMP > 50
15926 ? OMP_PROC_BIND_primary
15927 : OMP_PROC_BIND_spread) +
15928 1)
15929 << getOpenMPClauseName(OMPC_proc_bind);
15930 return nullptr;
15931 }
15932 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
15933 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15934 << getListOfPossibleValues(OMPC_proc_bind,
15935 /*First=*/unsigned(OMP_PROC_BIND_master),
15936 /*Last=*/
15937 unsigned(OMP_PROC_BIND_spread) + 1)
15938 << getOpenMPClauseName(OMPC_proc_bind);
15939 return new (getASTContext())
15940 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15941}
15942
15945 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
15947 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15949 OMPC_atomic_default_mem_order, /*First=*/0,
15951 << getOpenMPClauseName(OMPC_atomic_default_mem_order);
15952 return nullptr;
15953 }
15955 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15956}
15957
15959 SourceLocation KindKwLoc,
15960 SourceLocation StartLoc,
15961 SourceLocation LParenLoc,
15962 SourceLocation EndLoc) {
15963 if (Kind == OMPC_AT_unknown) {
15964 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15965 << getListOfPossibleValues(OMPC_at, /*First=*/0,
15966 /*Last=*/OMPC_AT_unknown)
15967 << getOpenMPClauseName(OMPC_at);
15968 return nullptr;
15969 }
15970 return new (getASTContext())
15971 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15972}
15973
15975 SourceLocation KindKwLoc,
15976 SourceLocation StartLoc,
15977 SourceLocation LParenLoc,
15978 SourceLocation EndLoc) {
15979 if (Kind == OMPC_SEVERITY_unknown) {
15980 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
15981 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
15982 /*Last=*/OMPC_SEVERITY_unknown)
15983 << getOpenMPClauseName(OMPC_severity);
15984 return nullptr;
15985 }
15986 return new (getASTContext())
15987 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
15988}
15989
15991 SourceLocation StartLoc,
15992 SourceLocation LParenLoc,
15993 SourceLocation EndLoc) {
15994 assert(ME && "NULL expr in Message clause");
15995 if (!isa<StringLiteral>(ME)) {
15996 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
15997 << getOpenMPClauseName(OMPC_message);
15998 return nullptr;
15999 }
16000 return new (getASTContext())
16001 OMPMessageClause(ME, StartLoc, LParenLoc, EndLoc);
16002}
16003
16006 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
16007 SourceLocation KindLoc, SourceLocation EndLoc) {
16008 if (Kind != OMPC_ORDER_concurrent ||
16009 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
16010 // Kind should be concurrent,
16011 // Modifiers introduced in OpenMP 5.1
16012 static_assert(OMPC_ORDER_unknown > 0,
16013 "OMPC_ORDER_unknown not greater than 0");
16014
16015 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16016 << getListOfPossibleValues(OMPC_order,
16017 /*First=*/0,
16018 /*Last=*/OMPC_ORDER_unknown)
16019 << getOpenMPClauseName(OMPC_order);
16020 return nullptr;
16021 }
16022 if (getLangOpts().OpenMP >= 51) {
16023 if (Modifier == OMPC_ORDER_MODIFIER_unknown && MLoc.isValid()) {
16024 Diag(MLoc, diag::err_omp_unexpected_clause_value)
16025 << getListOfPossibleValues(OMPC_order,
16026 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
16027 /*Last=*/OMPC_ORDER_MODIFIER_last)
16028 << getOpenMPClauseName(OMPC_order);
16029 } else {
16030 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
16031 if (DSAStack->getCurScope()) {
16032 // mark the current scope with 'order' flag
16033 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
16034 DSAStack->getCurScope()->setFlags(existingFlags |
16036 }
16037 }
16038 }
16039 return new (getASTContext()) OMPOrderClause(
16040 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
16041}
16042
16044 SourceLocation KindKwLoc,
16045 SourceLocation StartLoc,
16046 SourceLocation LParenLoc,
16047 SourceLocation EndLoc) {
16048 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
16049 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
16050 SmallVector<unsigned> Except = {
16051 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
16052 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
16053 if (getLangOpts().OpenMP < 51)
16054 Except.push_back(OMPC_DEPEND_inoutset);
16055 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
16056 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
16057 /*Last=*/OMPC_DEPEND_unknown, Except)
16058 << getOpenMPClauseName(OMPC_update);
16059 return nullptr;
16060 }
16061 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
16062 KindKwLoc, Kind, EndLoc);
16063}
16064
16066 SourceLocation StartLoc,
16067 SourceLocation LParenLoc,
16068 SourceLocation EndLoc) {
16069 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
16070
16071 for (Expr *&SizeExpr : SanitizedSizeExprs) {
16072 // Skip if already sanitized, e.g. during a partial template instantiation.
16073 if (!SizeExpr)
16074 continue;
16075
16076 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
16077 /*StrictlyPositive=*/true);
16078
16079 // isNonNegativeIntegerValue returns true for non-integral types (but still
16080 // emits error diagnostic), so check for the expected type explicitly.
16081 QualType SizeTy = SizeExpr->getType();
16082 if (!SizeTy->isIntegerType())
16083 IsValid = false;
16084
16085 // Handling in templates is tricky. There are four possibilities to
16086 // consider:
16087 //
16088 // 1a. The expression is valid and we are in a instantiated template or not
16089 // in a template:
16090 // Pass valid expression to be further analysed later in Sema.
16091 // 1b. The expression is valid and we are in a template (including partial
16092 // instantiation):
16093 // isNonNegativeIntegerValue skipped any checks so there is no
16094 // guarantee it will be correct after instantiation.
16095 // ActOnOpenMPSizesClause will be called again at instantiation when
16096 // it is not in a dependent context anymore. This may cause warnings
16097 // to be emitted multiple times.
16098 // 2a. The expression is invalid and we are in an instantiated template or
16099 // not in a template:
16100 // Invalidate the expression with a clearly wrong value (nullptr) so
16101 // later in Sema we do not have to do the same validity analysis again
16102 // or crash from unexpected data. Error diagnostics have already been
16103 // emitted.
16104 // 2b. The expression is invalid and we are in a template (including partial
16105 // instantiation):
16106 // Pass the invalid expression as-is, template instantiation may
16107 // replace unexpected types/values with valid ones. The directives
16108 // with this clause must not try to use these expressions in dependent
16109 // contexts, but delay analysis until full instantiation.
16110 if (!SizeExpr->isInstantiationDependent() && !IsValid)
16111 SizeExpr = nullptr;
16112 }
16113
16114 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16115 SanitizedSizeExprs);
16116}
16117
16119 SourceLocation EndLoc) {
16120 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
16121}
16122
16124 SourceLocation StartLoc,
16125 SourceLocation LParenLoc,
16126 SourceLocation EndLoc) {
16127 if (FactorExpr) {
16128 // If an argument is specified, it must be a constant (or an unevaluated
16129 // template expression).
16131 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
16132 if (FactorResult.isInvalid())
16133 return nullptr;
16134 FactorExpr = FactorResult.get();
16135 }
16136
16137 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
16138 FactorExpr);
16139}
16140
16142 SourceLocation LParenLoc,
16143 SourceLocation EndLoc) {
16144 ExprResult AlignVal;
16145 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
16146 if (AlignVal.isInvalid())
16147 return nullptr;
16148 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
16149 LParenLoc, EndLoc);
16150}
16151
16154 SourceLocation StartLoc, SourceLocation LParenLoc,
16155 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
16156 SourceLocation EndLoc) {
16157 OMPClause *Res = nullptr;
16158 switch (Kind) {
16159 case OMPC_schedule:
16160 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
16161 assert(Argument.size() == NumberOfElements &&
16162 ArgumentLoc.size() == NumberOfElements);
16164 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
16165 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
16166 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
16167 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
16168 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
16169 break;
16170 case OMPC_if:
16171 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16172 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
16173 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
16174 DelimLoc, EndLoc);
16175 break;
16176 case OMPC_dist_schedule:
16178 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
16179 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
16180 break;
16181 case OMPC_defaultmap:
16182 enum { Modifier, DefaultmapKind };
16184 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
16185 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
16186 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
16187 EndLoc);
16188 break;
16189 case OMPC_order:
16190 enum { OrderModifier, OrderKind };
16192 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
16193 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
16194 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
16195 break;
16196 case OMPC_device:
16197 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
16199 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
16200 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16201 break;
16202 case OMPC_grainsize:
16203 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16204 "Modifier for grainsize clause and its location are expected.");
16206 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
16207 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16208 break;
16209 case OMPC_num_tasks:
16210 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
16211 "Modifier for num_tasks clause and its location are expected.");
16213 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
16214 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
16215 break;
16216 case OMPC_final:
16217 case OMPC_num_threads:
16218 case OMPC_safelen:
16219 case OMPC_simdlen:
16220 case OMPC_sizes:
16221 case OMPC_allocator:
16222 case OMPC_collapse:
16223 case OMPC_default:
16224 case OMPC_proc_bind:
16225 case OMPC_private:
16226 case OMPC_firstprivate:
16227 case OMPC_lastprivate:
16228 case OMPC_shared:
16229 case OMPC_reduction:
16230 case OMPC_task_reduction:
16231 case OMPC_in_reduction:
16232 case OMPC_linear:
16233 case OMPC_aligned:
16234 case OMPC_copyin:
16235 case OMPC_copyprivate:
16236 case OMPC_ordered:
16237 case OMPC_nowait:
16238 case OMPC_untied:
16239 case OMPC_mergeable:
16240 case OMPC_threadprivate:
16241 case OMPC_allocate:
16242 case OMPC_flush:
16243 case OMPC_depobj:
16244 case OMPC_read:
16245 case OMPC_write:
16246 case OMPC_update:
16247 case OMPC_capture:
16248 case OMPC_compare:
16249 case OMPC_seq_cst:
16250 case OMPC_acq_rel:
16251 case OMPC_acquire:
16252 case OMPC_release:
16253 case OMPC_relaxed:
16254 case OMPC_depend:
16255 case OMPC_threads:
16256 case OMPC_simd:
16257 case OMPC_map:
16258 case OMPC_num_teams:
16259 case OMPC_thread_limit:
16260 case OMPC_priority:
16261 case OMPC_nogroup:
16262 case OMPC_hint:
16263 case OMPC_unknown:
16264 case OMPC_uniform:
16265 case OMPC_to:
16266 case OMPC_from:
16267 case OMPC_use_device_ptr:
16268 case OMPC_use_device_addr:
16269 case OMPC_is_device_ptr:
16270 case OMPC_has_device_addr:
16271 case OMPC_unified_address:
16272 case OMPC_unified_shared_memory:
16273 case OMPC_reverse_offload:
16274 case OMPC_dynamic_allocators:
16275 case OMPC_atomic_default_mem_order:
16276 case OMPC_device_type:
16277 case OMPC_match:
16278 case OMPC_nontemporal:
16279 case OMPC_at:
16280 case OMPC_severity:
16281 case OMPC_message:
16282 case OMPC_destroy:
16283 case OMPC_novariants:
16284 case OMPC_nocontext:
16285 case OMPC_detach:
16286 case OMPC_inclusive:
16287 case OMPC_exclusive:
16288 case OMPC_uses_allocators:
16289 case OMPC_affinity:
16290 case OMPC_when:
16291 case OMPC_bind:
16292 default:
16293 llvm_unreachable("Clause is not allowed.");
16294 }
16295 return Res;
16296}
16297
16300 SourceLocation M1Loc, SourceLocation M2Loc) {
16301 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
16302 SmallVector<unsigned, 2> Excluded;
16304 Excluded.push_back(M2);
16305 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
16306 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
16307 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
16308 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
16309 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
16310 << getListOfPossibleValues(OMPC_schedule,
16311 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
16313 Excluded)
16314 << getOpenMPClauseName(OMPC_schedule);
16315 return true;
16316 }
16317 return false;
16318}
16319
16322 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
16323 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
16324 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
16325 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
16326 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
16327 return nullptr;
16328 // OpenMP, 2.7.1, Loop Construct, Restrictions
16329 // Either the monotonic modifier or the nonmonotonic modifier can be specified
16330 // but not both.
16331 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
16332 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
16333 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
16334 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
16335 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
16336 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
16337 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
16338 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
16339 return nullptr;
16340 }
16341 if (Kind == OMPC_SCHEDULE_unknown) {
16342 std::string Values;
16343 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
16344 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
16345 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16347 Exclude);
16348 } else {
16349 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
16350 /*Last=*/OMPC_SCHEDULE_unknown);
16351 }
16352 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
16353 << Values << getOpenMPClauseName(OMPC_schedule);
16354 return nullptr;
16355 }
16356 // OpenMP, 2.7.1, Loop Construct, Restrictions
16357 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
16358 // schedule(guided).
16359 // OpenMP 5.0 does not have this restriction.
16360 if (getLangOpts().OpenMP < 50 &&
16361 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
16362 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
16363 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
16364 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
16365 diag::err_omp_schedule_nonmonotonic_static);
16366 return nullptr;
16367 }
16368 Expr *ValExpr = ChunkSize;
16369 Stmt *HelperValStmt = nullptr;
16370 if (ChunkSize) {
16371 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
16372 !ChunkSize->isInstantiationDependent() &&
16373 !ChunkSize->containsUnexpandedParameterPack()) {
16374 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
16375 ExprResult Val =
16376 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
16377 if (Val.isInvalid())
16378 return nullptr;
16379
16380 ValExpr = Val.get();
16381
16382 // OpenMP [2.7.1, Restrictions]
16383 // chunk_size must be a loop invariant integer expression with a positive
16384 // value.
16385 if (std::optional<llvm::APSInt> Result =
16387 if (Result->isSigned() && !Result->isStrictlyPositive()) {
16388 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
16389 << "schedule" << 1 << ChunkSize->getSourceRange();
16390 return nullptr;
16391 }
16393 DSAStack->getCurrentDirective(), OMPC_schedule,
16394 getLangOpts().OpenMP) != OMPD_unknown &&
16396 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16397 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16398 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16399 HelperValStmt = buildPreInits(getASTContext(), Captures);
16400 }
16401 }
16402 }
16403
16404 return new (getASTContext())
16405 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
16406 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
16407}
16408
16410 SourceLocation StartLoc,
16411 SourceLocation EndLoc) {
16412 OMPClause *Res = nullptr;
16413 switch (Kind) {
16414 case OMPC_ordered:
16415 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
16416 break;
16417 case OMPC_nowait:
16418 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc);
16419 break;
16420 case OMPC_untied:
16421 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
16422 break;
16423 case OMPC_mergeable:
16424 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
16425 break;
16426 case OMPC_read:
16427 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
16428 break;
16429 case OMPC_write:
16430 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
16431 break;
16432 case OMPC_update:
16433 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
16434 break;
16435 case OMPC_capture:
16436 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
16437 break;
16438 case OMPC_compare:
16439 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
16440 break;
16441 case OMPC_fail:
16442 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
16443 break;
16444 case OMPC_seq_cst:
16445 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
16446 break;
16447 case OMPC_acq_rel:
16448 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
16449 break;
16450 case OMPC_acquire:
16451 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
16452 break;
16453 case OMPC_release:
16454 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
16455 break;
16456 case OMPC_relaxed:
16457 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
16458 break;
16459 case OMPC_weak:
16460 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
16461 break;
16462 case OMPC_threads:
16463 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
16464 break;
16465 case OMPC_simd:
16466 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
16467 break;
16468 case OMPC_nogroup:
16469 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
16470 break;
16471 case OMPC_unified_address:
16472 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
16473 break;
16474 case OMPC_unified_shared_memory:
16475 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16476 break;
16477 case OMPC_reverse_offload:
16478 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
16479 break;
16480 case OMPC_dynamic_allocators:
16481 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
16482 break;
16483 case OMPC_destroy:
16484 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
16485 /*LParenLoc=*/SourceLocation(),
16486 /*VarLoc=*/SourceLocation(), EndLoc);
16487 break;
16488 case OMPC_full:
16489 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
16490 break;
16491 case OMPC_partial:
16492 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
16493 break;
16494 case OMPC_ompx_bare:
16495 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
16496 break;
16497 case OMPC_if:
16498 case OMPC_final:
16499 case OMPC_num_threads:
16500 case OMPC_safelen:
16501 case OMPC_simdlen:
16502 case OMPC_sizes:
16503 case OMPC_allocator:
16504 case OMPC_collapse:
16505 case OMPC_schedule:
16506 case OMPC_private:
16507 case OMPC_firstprivate:
16508 case OMPC_lastprivate:
16509 case OMPC_shared:
16510 case OMPC_reduction:
16511 case OMPC_task_reduction:
16512 case OMPC_in_reduction:
16513 case OMPC_linear:
16514 case OMPC_aligned:
16515 case OMPC_copyin:
16516 case OMPC_copyprivate:
16517 case OMPC_default:
16518 case OMPC_proc_bind:
16519 case OMPC_threadprivate:
16520 case OMPC_allocate:
16521 case OMPC_flush:
16522 case OMPC_depobj:
16523 case OMPC_depend:
16524 case OMPC_device:
16525 case OMPC_map:
16526 case OMPC_num_teams:
16527 case OMPC_thread_limit:
16528 case OMPC_priority:
16529 case OMPC_grainsize:
16530 case OMPC_num_tasks:
16531 case OMPC_hint:
16532 case OMPC_dist_schedule:
16533 case OMPC_defaultmap:
16534 case OMPC_unknown:
16535 case OMPC_uniform:
16536 case OMPC_to:
16537 case OMPC_from:
16538 case OMPC_use_device_ptr:
16539 case OMPC_use_device_addr:
16540 case OMPC_is_device_ptr:
16541 case OMPC_has_device_addr:
16542 case OMPC_atomic_default_mem_order:
16543 case OMPC_device_type:
16544 case OMPC_match:
16545 case OMPC_nontemporal:
16546 case OMPC_order:
16547 case OMPC_at:
16548 case OMPC_severity:
16549 case OMPC_message:
16550 case OMPC_novariants:
16551 case OMPC_nocontext:
16552 case OMPC_detach:
16553 case OMPC_inclusive:
16554 case OMPC_exclusive:
16555 case OMPC_uses_allocators:
16556 case OMPC_affinity:
16557 case OMPC_when:
16558 case OMPC_ompx_dyn_cgroup_mem:
16559 default:
16560 llvm_unreachable("Clause is not allowed.");
16561 }
16562 return Res;
16563}
16564
16566 SourceLocation EndLoc) {
16567 DSAStack->setNowaitRegion();
16568 return new (getASTContext()) OMPNowaitClause(StartLoc, EndLoc);
16569}
16570
16572 SourceLocation EndLoc) {
16573 DSAStack->setUntiedRegion();
16574 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
16575}
16576
16578 SourceLocation EndLoc) {
16579 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
16580}
16581
16583 SourceLocation EndLoc) {
16584 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
16585}
16586
16588 SourceLocation EndLoc) {
16589 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
16590}
16591
16593 SourceLocation EndLoc) {
16594 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
16595}
16596
16598 SourceLocation EndLoc) {
16599 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
16600}
16601
16603 SourceLocation EndLoc) {
16604 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
16605}
16606
16608 SourceLocation EndLoc) {
16609 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
16610}
16611
16613 SourceLocation KindLoc,
16614 SourceLocation StartLoc,
16615 SourceLocation LParenLoc,
16616 SourceLocation EndLoc) {
16617
16619 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
16620 return nullptr;
16621 }
16622 return new (getASTContext())
16623 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
16624}
16625
16627 SourceLocation EndLoc) {
16628 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
16629}
16630
16632 SourceLocation EndLoc) {
16633 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
16634}
16635
16637 SourceLocation EndLoc) {
16638 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
16639}
16640
16642 SourceLocation EndLoc) {
16643 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
16644}
16645
16647 SourceLocation EndLoc) {
16648 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
16649}
16650
16652 SourceLocation EndLoc) {
16653 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
16654}
16655
16657 SourceLocation EndLoc) {
16658 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
16659}
16660
16662 SourceLocation EndLoc) {
16663 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
16664}
16665
16667 SourceLocation EndLoc) {
16668 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
16669}
16670
16672 SourceLocation EndLoc) {
16673 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
16674}
16675
16676OMPClause *
16678 SourceLocation EndLoc) {
16679 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
16680}
16681
16683 SourceLocation EndLoc) {
16684 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
16685}
16686
16687OMPClause *
16689 SourceLocation EndLoc) {
16690 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
16691}
16692
16695 SourceLocation StartLoc,
16696 SourceLocation EndLoc) {
16697
16698 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16699 // At least one action-clause must appear on a directive.
16700 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
16701 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
16702 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
16703 << Expected << getOpenMPDirectiveName(OMPD_interop);
16704 return StmtError();
16705 }
16706
16707 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16708 // A depend clause can only appear on the directive if a targetsync
16709 // interop-type is present or the interop-var was initialized with
16710 // the targetsync interop-type.
16711
16712 // If there is any 'init' clause diagnose if there is no 'init' clause with
16713 // interop-type of 'targetsync'. Cases involving other directives cannot be
16714 // diagnosed.
16715 const OMPDependClause *DependClause = nullptr;
16716 bool HasInitClause = false;
16717 bool IsTargetSync = false;
16718 for (const OMPClause *C : Clauses) {
16719 if (IsTargetSync)
16720 break;
16721 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
16722 HasInitClause = true;
16723 if (InitClause->getIsTargetSync())
16724 IsTargetSync = true;
16725 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
16726 DependClause = DC;
16727 }
16728 }
16729 if (DependClause && HasInitClause && !IsTargetSync) {
16730 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
16731 return StmtError();
16732 }
16733
16734 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16735 // Each interop-var may be specified for at most one action-clause of each
16736 // interop construct.
16738 for (OMPClause *C : Clauses) {
16739 OpenMPClauseKind ClauseKind = C->getClauseKind();
16740 std::pair<ValueDecl *, bool> DeclResult;
16741 SourceLocation ELoc;
16742 SourceRange ERange;
16743
16744 if (ClauseKind == OMPC_init) {
16745 auto *E = cast<OMPInitClause>(C)->getInteropVar();
16746 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16747 } else if (ClauseKind == OMPC_use) {
16748 auto *E = cast<OMPUseClause>(C)->getInteropVar();
16749 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16750 } else if (ClauseKind == OMPC_destroy) {
16751 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
16752 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
16753 }
16754
16755 if (DeclResult.first) {
16756 if (!InteropVars.insert(DeclResult.first).second) {
16757 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
16758 << DeclResult.first;
16759 return StmtError();
16760 }
16761 }
16762 }
16763
16764 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
16765 Clauses);
16766}
16767
16768static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
16769 SourceLocation VarLoc,
16770 OpenMPClauseKind Kind) {
16771 SourceLocation ELoc;
16772 SourceRange ERange;
16773 Expr *RefExpr = InteropVarExpr;
16774 auto Res =
16775 getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
16776 /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
16777
16778 if (Res.second) {
16779 // It will be analyzed later.
16780 return true;
16781 }
16782
16783 if (!Res.first)
16784 return false;
16785
16786 // Interop variable should be of type omp_interop_t.
16787 bool HasError = false;
16788 QualType InteropType;
16789 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
16790 VarLoc, Sema::LookupOrdinaryName);
16791 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
16792 NamedDecl *ND = Result.getFoundDecl();
16793 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
16794 InteropType = QualType(TD->getTypeForDecl(), 0);
16795 } else {
16796 HasError = true;
16797 }
16798 } else {
16799 HasError = true;
16800 }
16801
16802 if (HasError) {
16803 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
16804 << "omp_interop_t";
16805 return false;
16806 }
16807
16808 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
16809 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
16810 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
16811 return false;
16812 }
16813
16814 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
16815 // The interop-var passed to init or destroy must be non-const.
16816 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
16817 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
16818 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
16819 << /*non-const*/ 1;
16820 return false;
16821 }
16822 return true;
16823}
16824
16826 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
16827 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
16828
16829 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
16830 return nullptr;
16831
16832 // Check prefer_type values. These foreign-runtime-id values are either
16833 // string literals or constant integral expressions.
16834 for (const Expr *E : InteropInfo.PreferTypes) {
16835 if (E->isValueDependent() || E->isTypeDependent() ||
16837 continue;
16839 continue;
16840 if (isa<StringLiteral>(E))
16841 continue;
16842 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
16843 return nullptr;
16844 }
16845
16846 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
16847 StartLoc, LParenLoc, VarLoc, EndLoc);
16848}
16849
16851 SourceLocation StartLoc,
16852 SourceLocation LParenLoc,
16853 SourceLocation VarLoc,
16854 SourceLocation EndLoc) {
16855
16856 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
16857 return nullptr;
16858
16859 return new (getASTContext())
16860 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16861}
16862
16864 SourceLocation StartLoc,
16865 SourceLocation LParenLoc,
16866 SourceLocation VarLoc,
16867 SourceLocation EndLoc) {
16868 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
16869 DSAStack->getCurrentDirective() == OMPD_depobj) {
16870 Diag(StartLoc, diag::err_omp_expected_clause_argument)
16871 << getOpenMPClauseName(OMPC_destroy)
16872 << getOpenMPDirectiveName(OMPD_depobj);
16873 return nullptr;
16874 }
16875 if (InteropVar &&
16876 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
16877 return nullptr;
16878
16879 return new (getASTContext())
16880 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
16881}
16882
16884 SourceLocation StartLoc,
16885 SourceLocation LParenLoc,
16886 SourceLocation EndLoc) {
16887 Expr *ValExpr = Condition;
16888 Stmt *HelperValStmt = nullptr;
16889 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16890 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16891 !Condition->isInstantiationDependent() &&
16892 !Condition->containsUnexpandedParameterPack()) {
16894 if (Val.isInvalid())
16895 return nullptr;
16896
16897 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16898
16899 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16900 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
16901 getLangOpts().OpenMP);
16902 if (CaptureRegion != OMPD_unknown &&
16904 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16905 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16906 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16907 HelperValStmt = buildPreInits(getASTContext(), Captures);
16908 }
16909 }
16910
16911 return new (getASTContext()) OMPNovariantsClause(
16912 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16913}
16914
16916 SourceLocation StartLoc,
16917 SourceLocation LParenLoc,
16918 SourceLocation EndLoc) {
16919 Expr *ValExpr = Condition;
16920 Stmt *HelperValStmt = nullptr;
16921 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16922 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16923 !Condition->isInstantiationDependent() &&
16924 !Condition->containsUnexpandedParameterPack()) {
16926 if (Val.isInvalid())
16927 return nullptr;
16928
16929 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16930
16931 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16932 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
16933 getLangOpts().OpenMP);
16934 if (CaptureRegion != OMPD_unknown &&
16936 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16937 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16938 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16939 HelperValStmt = buildPreInits(getASTContext(), Captures);
16940 }
16941 }
16942
16943 return new (getASTContext()) OMPNocontextClause(
16944 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16945}
16946
16948 SourceLocation StartLoc,
16949 SourceLocation LParenLoc,
16950 SourceLocation EndLoc) {
16951 Expr *ValExpr = ThreadID;
16952 Stmt *HelperValStmt = nullptr;
16953
16954 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16955 OpenMPDirectiveKind CaptureRegion =
16956 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
16957 if (CaptureRegion != OMPD_unknown &&
16959 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16960 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16961 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16962 HelperValStmt = buildPreInits(getASTContext(), Captures);
16963 }
16964
16965 return new (getASTContext()) OMPFilterClause(
16966 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16967}
16968
16970 ArrayRef<Expr *> VarList,
16971 const OMPVarListLocTy &Locs,
16973 SourceLocation StartLoc = Locs.StartLoc;
16974 SourceLocation LParenLoc = Locs.LParenLoc;
16975 SourceLocation EndLoc = Locs.EndLoc;
16976 OMPClause *Res = nullptr;
16977 int ExtraModifier = Data.ExtraModifier;
16978 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
16979 SourceLocation ColonLoc = Data.ColonLoc;
16980 switch (Kind) {
16981 case OMPC_private:
16982 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16983 break;
16984 case OMPC_firstprivate:
16985 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
16986 break;
16987 case OMPC_lastprivate:
16988 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
16989 "Unexpected lastprivate modifier.");
16991 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
16992 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
16993 break;
16994 case OMPC_shared:
16995 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
16996 break;
16997 case OMPC_reduction:
16998 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
16999 "Unexpected lastprivate modifier.");
17001 VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
17002 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
17003 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17004 break;
17005 case OMPC_task_reduction:
17007 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17008 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17009 break;
17010 case OMPC_in_reduction:
17012 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
17013 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
17014 break;
17015 case OMPC_linear:
17016 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
17017 "Unexpected linear modifier.");
17019 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
17020 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
17021 ColonLoc, Data.StepModifierLoc, EndLoc);
17022 break;
17023 case OMPC_aligned:
17024 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
17025 LParenLoc, ColonLoc, EndLoc);
17026 break;
17027 case OMPC_copyin:
17028 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
17029 break;
17030 case OMPC_copyprivate:
17031 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
17032 break;
17033 case OMPC_flush:
17034 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
17035 break;
17036 case OMPC_depend:
17037 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
17038 "Unexpected depend modifier.");
17040 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
17041 ColonLoc, Data.OmpAllMemoryLoc},
17042 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
17043 break;
17044 case OMPC_map:
17045 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
17046 "Unexpected map modifier.");
17048 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
17049 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
17050 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
17051 ExtraModifierLoc, ColonLoc, VarList, Locs);
17052 break;
17053 case OMPC_to:
17054 Res =
17055 ActOnOpenMPToClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17056 Data.ReductionOrMapperIdScopeSpec,
17057 Data.ReductionOrMapperId, ColonLoc, VarList, Locs);
17058 break;
17059 case OMPC_from:
17060 Res = ActOnOpenMPFromClause(Data.MotionModifiers, Data.MotionModifiersLoc,
17061 Data.ReductionOrMapperIdScopeSpec,
17062 Data.ReductionOrMapperId, ColonLoc, VarList,
17063 Locs);
17064 break;
17065 case OMPC_use_device_ptr:
17066 Res = ActOnOpenMPUseDevicePtrClause(VarList, Locs);
17067 break;
17068 case OMPC_use_device_addr:
17069 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
17070 break;
17071 case OMPC_is_device_ptr:
17072 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
17073 break;
17074 case OMPC_has_device_addr:
17075 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
17076 break;
17077 case OMPC_allocate:
17078 Res = ActOnOpenMPAllocateClause(Data.DepModOrTailExpr, VarList, StartLoc,
17079 LParenLoc, ColonLoc, EndLoc);
17080 break;
17081 case OMPC_nontemporal:
17082 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
17083 break;
17084 case OMPC_inclusive:
17085 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17086 break;
17087 case OMPC_exclusive:
17088 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
17089 break;
17090 case OMPC_affinity:
17091 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
17092 Data.DepModOrTailExpr, VarList);
17093 break;
17094 case OMPC_doacross:
17096 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
17097 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
17098 break;
17099 case OMPC_num_teams:
17100 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
17101 break;
17102 case OMPC_thread_limit:
17103 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
17104 break;
17105 case OMPC_if:
17106 case OMPC_depobj:
17107 case OMPC_final:
17108 case OMPC_num_threads:
17109 case OMPC_safelen:
17110 case OMPC_simdlen:
17111 case OMPC_sizes:
17112 case OMPC_allocator:
17113 case OMPC_collapse:
17114 case OMPC_default:
17115 case OMPC_proc_bind:
17116 case OMPC_schedule:
17117 case OMPC_ordered:
17118 case OMPC_nowait:
17119 case OMPC_untied:
17120 case OMPC_mergeable:
17121 case OMPC_threadprivate:
17122 case OMPC_read:
17123 case OMPC_write:
17124 case OMPC_update:
17125 case OMPC_capture:
17126 case OMPC_compare:
17127 case OMPC_seq_cst:
17128 case OMPC_acq_rel:
17129 case OMPC_acquire:
17130 case OMPC_release:
17131 case OMPC_relaxed:
17132 case OMPC_device:
17133 case OMPC_threads:
17134 case OMPC_simd:
17135 case OMPC_priority:
17136 case OMPC_grainsize:
17137 case OMPC_nogroup:
17138 case OMPC_num_tasks:
17139 case OMPC_hint:
17140 case OMPC_dist_schedule:
17141 case OMPC_defaultmap:
17142 case OMPC_unknown:
17143 case OMPC_uniform:
17144 case OMPC_unified_address:
17145 case OMPC_unified_shared_memory:
17146 case OMPC_reverse_offload:
17147 case OMPC_dynamic_allocators:
17148 case OMPC_atomic_default_mem_order:
17149 case OMPC_device_type:
17150 case OMPC_match:
17151 case OMPC_order:
17152 case OMPC_at:
17153 case OMPC_severity:
17154 case OMPC_message:
17155 case OMPC_destroy:
17156 case OMPC_novariants:
17157 case OMPC_nocontext:
17158 case OMPC_detach:
17159 case OMPC_uses_allocators:
17160 case OMPC_when:
17161 case OMPC_bind:
17162 default:
17163 llvm_unreachable("Clause is not allowed.");
17164 }
17165 return Res;
17166}
17167
17169 ExprObjectKind OK,
17172 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
17173 if (!Res.isUsable())
17174 return ExprError();
17175 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
17176 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
17177 if (!Res.isUsable())
17178 return ExprError();
17179 }
17180 if (VK != VK_LValue && Res.get()->isGLValue()) {
17181 Res = SemaRef.DefaultLvalueConversion(Res.get());
17182 if (!Res.isUsable())
17183 return ExprError();
17184 }
17185 return Res;
17186}
17187
17189 SourceLocation StartLoc,
17190 SourceLocation LParenLoc,
17191 SourceLocation EndLoc) {
17193 SmallVector<Expr *, 8> PrivateCopies;
17194 bool IsImplicitClause =
17195 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17196 for (Expr *RefExpr : VarList) {
17197 assert(RefExpr && "NULL expr in OpenMP private clause.");
17198 SourceLocation ELoc;
17199 SourceRange ERange;
17200 Expr *SimpleRefExpr = RefExpr;
17201 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17202 if (Res.second) {
17203 // It will be analyzed later.
17204 Vars.push_back(RefExpr);
17205 PrivateCopies.push_back(nullptr);
17206 }
17207 ValueDecl *D = Res.first;
17208 if (!D)
17209 continue;
17210
17211 QualType Type = D->getType();
17212 auto *VD = dyn_cast<VarDecl>(D);
17213
17214 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17215 // A variable that appears in a private clause must not have an incomplete
17216 // type or a reference type.
17218 diag::err_omp_private_incomplete_type))
17219 continue;
17220 Type = Type.getNonReferenceType();
17221
17222 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17223 // A variable that is privatized must not have a const-qualified type
17224 // unless it is of class type with a mutable member. This restriction does
17225 // not apply to the firstprivate clause.
17226 //
17227 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
17228 // A variable that appears in a private clause must not have a
17229 // const-qualified type unless it is of class type with a mutable member.
17230 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
17231 continue;
17232
17233 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17234 // in a Construct]
17235 // Variables with the predetermined data-sharing attributes may not be
17236 // listed in data-sharing attributes clauses, except for the cases
17237 // listed below. For these exceptions only, listing a predetermined
17238 // variable in a data-sharing attribute clause is allowed and overrides
17239 // the variable's predetermined data-sharing attributes.
17240 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17241 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
17242 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17243 << getOpenMPClauseName(OMPC_private);
17245 continue;
17246 }
17247
17248 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17249 // Variably modified types are not supported for tasks.
17251 isOpenMPTaskingDirective(CurrDir)) {
17252 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17253 << getOpenMPClauseName(OMPC_private) << Type
17254 << getOpenMPDirectiveName(CurrDir);
17255 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17257 Diag(D->getLocation(),
17258 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17259 << D;
17260 continue;
17261 }
17262
17263 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17264 // A list item cannot appear in both a map clause and a data-sharing
17265 // attribute clause on the same construct
17266 //
17267 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17268 // A list item cannot appear in both a map clause and a data-sharing
17269 // attribute clause on the same construct unless the construct is a
17270 // combined construct.
17271 if ((getLangOpts().OpenMP <= 45 &&
17273 CurrDir == OMPD_target) {
17274 OpenMPClauseKind ConflictKind;
17275 if (DSAStack->checkMappableExprComponentListsForDecl(
17276 VD, /*CurrentRegionOnly=*/true,
17278 OpenMPClauseKind WhereFoundClauseKind) -> bool {
17279 ConflictKind = WhereFoundClauseKind;
17280 return true;
17281 })) {
17282 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17283 << getOpenMPClauseName(OMPC_private)
17284 << getOpenMPClauseName(ConflictKind)
17285 << getOpenMPDirectiveName(CurrDir);
17287 continue;
17288 }
17289 }
17290
17291 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
17292 // A variable of class type (or array thereof) that appears in a private
17293 // clause requires an accessible, unambiguous default constructor for the
17294 // class type.
17295 // Generate helper private variable and initialize it with the default
17296 // value. The address of the original variable is replaced by the address of
17297 // the new private variable in CodeGen. This new variable is not added to
17298 // IdResolver, so the code in the OpenMP region uses original variable for
17299 // proper diagnostics.
17300 Type = Type.getUnqualifiedType();
17301 VarDecl *VDPrivate =
17302 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17303 D->hasAttrs() ? &D->getAttrs() : nullptr,
17304 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17306 if (VDPrivate->isInvalidDecl())
17307 continue;
17308 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17309 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
17310
17311 DeclRefExpr *Ref = nullptr;
17312 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17313 auto *FD = dyn_cast<FieldDecl>(D);
17314 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17315 if (VD)
17317 RefExpr->getExprLoc());
17318 else
17319 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17320 }
17321 if (!IsImplicitClause)
17322 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
17323 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17324 ? RefExpr->IgnoreParens()
17325 : Ref);
17326 PrivateCopies.push_back(VDPrivateRefExpr);
17327 }
17328
17329 if (Vars.empty())
17330 return nullptr;
17331
17332 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17333 Vars, PrivateCopies);
17334}
17335
17337 SourceLocation StartLoc,
17338 SourceLocation LParenLoc,
17339 SourceLocation EndLoc) {
17341 SmallVector<Expr *, 8> PrivateCopies;
17343 SmallVector<Decl *, 4> ExprCaptures;
17344 bool IsImplicitClause =
17345 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
17346 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
17347
17348 for (Expr *RefExpr : VarList) {
17349 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
17350 SourceLocation ELoc;
17351 SourceRange ERange;
17352 Expr *SimpleRefExpr = RefExpr;
17353 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17354 if (Res.second) {
17355 // It will be analyzed later.
17356 Vars.push_back(RefExpr);
17357 PrivateCopies.push_back(nullptr);
17358 Inits.push_back(nullptr);
17359 }
17360 ValueDecl *D = Res.first;
17361 if (!D)
17362 continue;
17363
17364 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
17365 QualType Type = D->getType();
17366 auto *VD = dyn_cast<VarDecl>(D);
17367
17368 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
17369 // A variable that appears in a private clause must not have an incomplete
17370 // type or a reference type.
17372 diag::err_omp_firstprivate_incomplete_type))
17373 continue;
17374 Type = Type.getNonReferenceType();
17375
17376 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
17377 // A variable of class type (or array thereof) that appears in a private
17378 // clause requires an accessible, unambiguous copy constructor for the
17379 // class type.
17380 QualType ElemType =
17382
17383 // If an implicit firstprivate variable found it was checked already.
17384 DSAStackTy::DSAVarData TopDVar;
17385 if (!IsImplicitClause) {
17386 DSAStackTy::DSAVarData DVar =
17387 DSAStack->getTopDSA(D, /*FromParent=*/false);
17388 TopDVar = DVar;
17389 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17390 bool IsConstant = ElemType.isConstant(getASTContext());
17391 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
17392 // A list item that specifies a given variable may not appear in more
17393 // than one clause on the same directive, except that a variable may be
17394 // specified in both firstprivate and lastprivate clauses.
17395 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17396 // A list item may appear in a firstprivate or lastprivate clause but not
17397 // both.
17398 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
17399 (isOpenMPDistributeDirective(CurrDir) ||
17400 DVar.CKind != OMPC_lastprivate) &&
17401 DVar.RefExpr) {
17402 Diag(ELoc, diag::err_omp_wrong_dsa)
17403 << getOpenMPClauseName(DVar.CKind)
17404 << getOpenMPClauseName(OMPC_firstprivate);
17406 continue;
17407 }
17408
17409 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17410 // in a Construct]
17411 // Variables with the predetermined data-sharing attributes may not be
17412 // listed in data-sharing attributes clauses, except for the cases
17413 // listed below. For these exceptions only, listing a predetermined
17414 // variable in a data-sharing attribute clause is allowed and overrides
17415 // the variable's predetermined data-sharing attributes.
17416 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17417 // in a Construct, C/C++, p.2]
17418 // Variables with const-qualified type having no mutable member may be
17419 // listed in a firstprivate clause, even if they are static data members.
17420 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
17421 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
17422 Diag(ELoc, diag::err_omp_wrong_dsa)
17423 << getOpenMPClauseName(DVar.CKind)
17424 << getOpenMPClauseName(OMPC_firstprivate);
17426 continue;
17427 }
17428
17429 // OpenMP [2.9.3.4, Restrictions, p.2]
17430 // A list item that is private within a parallel region must not appear
17431 // in a firstprivate clause on a worksharing construct if any of the
17432 // worksharing regions arising from the worksharing construct ever bind
17433 // to any of the parallel regions arising from the parallel construct.
17434 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17435 // A list item that is private within a teams region must not appear in a
17436 // firstprivate clause on a distribute construct if any of the distribute
17437 // regions arising from the distribute construct ever bind to any of the
17438 // teams regions arising from the teams construct.
17439 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
17440 // A list item that appears in a reduction clause of a teams construct
17441 // must not appear in a firstprivate clause on a distribute construct if
17442 // any of the distribute regions arising from the distribute construct
17443 // ever bind to any of the teams regions arising from the teams construct.
17444 if ((isOpenMPWorksharingDirective(CurrDir) ||
17445 isOpenMPDistributeDirective(CurrDir)) &&
17446 !isOpenMPParallelDirective(CurrDir) &&
17447 !isOpenMPTeamsDirective(CurrDir)) {
17448 DVar = DSAStack->getImplicitDSA(D, true);
17449 if (DVar.CKind != OMPC_shared &&
17450 (isOpenMPParallelDirective(DVar.DKind) ||
17451 isOpenMPTeamsDirective(DVar.DKind) ||
17452 DVar.DKind == OMPD_unknown)) {
17453 Diag(ELoc, diag::err_omp_required_access)
17454 << getOpenMPClauseName(OMPC_firstprivate)
17455 << getOpenMPClauseName(OMPC_shared);
17457 continue;
17458 }
17459 }
17460 // OpenMP [2.9.3.4, Restrictions, p.3]
17461 // A list item that appears in a reduction clause of a parallel construct
17462 // must not appear in a firstprivate clause on a worksharing or task
17463 // construct if any of the worksharing or task regions arising from the
17464 // worksharing or task construct ever bind to any of the parallel regions
17465 // arising from the parallel construct.
17466 // OpenMP [2.9.3.4, Restrictions, p.4]
17467 // A list item that appears in a reduction clause in worksharing
17468 // construct must not appear in a firstprivate clause in a task construct
17469 // encountered during execution of any of the worksharing regions arising
17470 // from the worksharing construct.
17471 if (isOpenMPTaskingDirective(CurrDir)) {
17472 DVar = DSAStack->hasInnermostDSA(
17473 D,
17474 [](OpenMPClauseKind C, bool AppliedToPointee) {
17475 return C == OMPC_reduction && !AppliedToPointee;
17476 },
17477 [](OpenMPDirectiveKind K) {
17478 return isOpenMPParallelDirective(K) ||
17481 },
17482 /*FromParent=*/true);
17483 if (DVar.CKind == OMPC_reduction &&
17484 (isOpenMPParallelDirective(DVar.DKind) ||
17485 isOpenMPWorksharingDirective(DVar.DKind) ||
17486 isOpenMPTeamsDirective(DVar.DKind))) {
17487 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
17488 << getOpenMPDirectiveName(DVar.DKind);
17490 continue;
17491 }
17492 }
17493
17494 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
17495 // A list item cannot appear in both a map clause and a data-sharing
17496 // attribute clause on the same construct
17497 //
17498 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
17499 // A list item cannot appear in both a map clause and a data-sharing
17500 // attribute clause on the same construct unless the construct is a
17501 // combined construct.
17502 if ((getLangOpts().OpenMP <= 45 &&
17504 CurrDir == OMPD_target) {
17505 OpenMPClauseKind ConflictKind;
17506 if (DSAStack->checkMappableExprComponentListsForDecl(
17507 VD, /*CurrentRegionOnly=*/true,
17508 [&ConflictKind](
17510 OpenMPClauseKind WhereFoundClauseKind) {
17511 ConflictKind = WhereFoundClauseKind;
17512 return true;
17513 })) {
17514 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
17515 << getOpenMPClauseName(OMPC_firstprivate)
17516 << getOpenMPClauseName(ConflictKind)
17517 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17519 continue;
17520 }
17521 }
17522 }
17523
17524 // Variably modified types are not supported for tasks.
17526 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
17527 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
17528 << getOpenMPClauseName(OMPC_firstprivate) << Type
17529 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
17530 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17532 Diag(D->getLocation(),
17533 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17534 << D;
17535 continue;
17536 }
17537
17538 Type = Type.getUnqualifiedType();
17539 VarDecl *VDPrivate =
17540 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
17541 D->hasAttrs() ? &D->getAttrs() : nullptr,
17542 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
17543 // Generate helper private variable and initialize it with the value of the
17544 // original variable. The address of the original variable is replaced by
17545 // the address of the new private variable in the CodeGen. This new variable
17546 // is not added to IdResolver, so the code in the OpenMP region uses
17547 // original variable for proper diagnostics and variable capturing.
17548 Expr *VDInitRefExpr = nullptr;
17549 // For arrays generate initializer for single element and replace it by the
17550 // original array element in CodeGen.
17551 if (Type->isArrayType()) {
17552 VarDecl *VDInit =
17553 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
17554 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
17555 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
17556 ElemType = ElemType.getUnqualifiedType();
17557 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
17558 ElemType, ".firstprivate.temp");
17559 InitializedEntity Entity =
17562
17563 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
17564 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
17565 if (Result.isInvalid())
17566 VDPrivate->setInvalidDecl();
17567 else
17568 VDPrivate->setInit(Result.getAs<Expr>());
17569 // Remove temp variable declaration.
17570 getASTContext().Deallocate(VDInitTemp);
17571 } else {
17572 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
17573 ".firstprivate.temp");
17574 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
17575 RefExpr->getExprLoc());
17577 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
17578 /*DirectInit=*/false);
17579 }
17580 if (VDPrivate->isInvalidDecl()) {
17581 if (IsImplicitClause) {
17582 Diag(RefExpr->getExprLoc(),
17583 diag::note_omp_task_predetermined_firstprivate_here);
17584 }
17585 continue;
17586 }
17587 SemaRef.CurContext->addDecl(VDPrivate);
17588 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
17589 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
17590 RefExpr->getExprLoc());
17591 DeclRefExpr *Ref = nullptr;
17592 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17593 if (TopDVar.CKind == OMPC_lastprivate) {
17594 Ref = TopDVar.PrivateCopy;
17595 } else {
17596 auto *FD = dyn_cast<FieldDecl>(D);
17597 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
17598 if (VD)
17599 Ref =
17601 RefExpr->getExprLoc());
17602 else
17603 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17604 if (VD || !isOpenMPCapturedDecl(D))
17605 ExprCaptures.push_back(Ref->getDecl());
17606 }
17607 }
17608 if (!IsImplicitClause)
17609 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
17610 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17611 ? RefExpr->IgnoreParens()
17612 : Ref);
17613 PrivateCopies.push_back(VDPrivateRefExpr);
17614 Inits.push_back(VDInitRefExpr);
17615 }
17616
17617 if (Vars.empty())
17618 return nullptr;
17619
17621 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
17622 buildPreInits(getASTContext(), ExprCaptures));
17623}
17624
17627 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
17628 SourceLocation LParenLoc, SourceLocation EndLoc) {
17629 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
17630 assert(ColonLoc.isValid() && "Colon location must be valid.");
17631 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
17632 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
17633 /*Last=*/OMPC_LASTPRIVATE_unknown)
17634 << getOpenMPClauseName(OMPC_lastprivate);
17635 return nullptr;
17636 }
17637
17639 SmallVector<Expr *, 8> SrcExprs;
17640 SmallVector<Expr *, 8> DstExprs;
17641 SmallVector<Expr *, 8> AssignmentOps;
17642 SmallVector<Decl *, 4> ExprCaptures;
17643 SmallVector<Expr *, 4> ExprPostUpdates;
17644 for (Expr *RefExpr : VarList) {
17645 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17646 SourceLocation ELoc;
17647 SourceRange ERange;
17648 Expr *SimpleRefExpr = RefExpr;
17649 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17650 if (Res.second) {
17651 // It will be analyzed later.
17652 Vars.push_back(RefExpr);
17653 SrcExprs.push_back(nullptr);
17654 DstExprs.push_back(nullptr);
17655 AssignmentOps.push_back(nullptr);
17656 }
17657 ValueDecl *D = Res.first;
17658 if (!D)
17659 continue;
17660
17661 QualType Type = D->getType();
17662 auto *VD = dyn_cast<VarDecl>(D);
17663
17664 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
17665 // A variable that appears in a lastprivate clause must not have an
17666 // incomplete type or a reference type.
17668 diag::err_omp_lastprivate_incomplete_type))
17669 continue;
17670 Type = Type.getNonReferenceType();
17671
17672 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
17673 // A variable that is privatized must not have a const-qualified type
17674 // unless it is of class type with a mutable member. This restriction does
17675 // not apply to the firstprivate clause.
17676 //
17677 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
17678 // A variable that appears in a lastprivate clause must not have a
17679 // const-qualified type unless it is of class type with a mutable member.
17680 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
17681 continue;
17682
17683 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
17684 // A list item that appears in a lastprivate clause with the conditional
17685 // modifier must be a scalar variable.
17686 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
17687 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
17688 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
17690 Diag(D->getLocation(),
17691 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
17692 << D;
17693 continue;
17694 }
17695
17696 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
17697 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
17698 // in a Construct]
17699 // Variables with the predetermined data-sharing attributes may not be
17700 // listed in data-sharing attributes clauses, except for the cases
17701 // listed below.
17702 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
17703 // A list item may appear in a firstprivate or lastprivate clause but not
17704 // both.
17705 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17706 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
17707 (isOpenMPDistributeDirective(CurrDir) ||
17708 DVar.CKind != OMPC_firstprivate) &&
17709 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
17710 Diag(ELoc, diag::err_omp_wrong_dsa)
17711 << getOpenMPClauseName(DVar.CKind)
17712 << getOpenMPClauseName(OMPC_lastprivate);
17714 continue;
17715 }
17716
17717 // OpenMP [2.14.3.5, Restrictions, p.2]
17718 // A list item that is private within a parallel region, or that appears in
17719 // the reduction clause of a parallel construct, must not appear in a
17720 // lastprivate clause on a worksharing construct if any of the corresponding
17721 // worksharing regions ever binds to any of the corresponding parallel
17722 // regions.
17723 DSAStackTy::DSAVarData TopDVar = DVar;
17724 if (isOpenMPWorksharingDirective(CurrDir) &&
17725 !isOpenMPParallelDirective(CurrDir) &&
17726 !isOpenMPTeamsDirective(CurrDir)) {
17727 DVar = DSAStack->getImplicitDSA(D, true);
17728 if (DVar.CKind != OMPC_shared) {
17729 Diag(ELoc, diag::err_omp_required_access)
17730 << getOpenMPClauseName(OMPC_lastprivate)
17731 << getOpenMPClauseName(OMPC_shared);
17733 continue;
17734 }
17735 }
17736
17737 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
17738 // A variable of class type (or array thereof) that appears in a
17739 // lastprivate clause requires an accessible, unambiguous default
17740 // constructor for the class type, unless the list item is also specified
17741 // in a firstprivate clause.
17742 // A variable of class type (or array thereof) that appears in a
17743 // lastprivate clause requires an accessible, unambiguous copy assignment
17744 // operator for the class type.
17746 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
17747 Type.getUnqualifiedType(), ".lastprivate.src",
17748 D->hasAttrs() ? &D->getAttrs() : nullptr);
17749 DeclRefExpr *PseudoSrcExpr =
17750 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
17751 VarDecl *DstVD =
17752 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
17753 D->hasAttrs() ? &D->getAttrs() : nullptr);
17754 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
17755 // For arrays generate assignment operation for single element and replace
17756 // it by the original array element in CodeGen.
17757 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
17758 PseudoDstExpr, PseudoSrcExpr);
17759 if (AssignmentOp.isInvalid())
17760 continue;
17761 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
17762 /*DiscardedValue=*/false);
17763 if (AssignmentOp.isInvalid())
17764 continue;
17765
17766 DeclRefExpr *Ref = nullptr;
17767 if (!VD && !SemaRef.CurContext->isDependentContext()) {
17768 if (TopDVar.CKind == OMPC_firstprivate) {
17769 Ref = TopDVar.PrivateCopy;
17770 } else {
17771 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
17772 if (!isOpenMPCapturedDecl(D))
17773 ExprCaptures.push_back(Ref->getDecl());
17774 }
17775 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
17777 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
17779 if (!RefRes.isUsable())
17780 continue;
17781 ExprResult PostUpdateRes =
17782 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
17783 SimpleRefExpr, RefRes.get());
17784 if (!PostUpdateRes.isUsable())
17785 continue;
17786 ExprPostUpdates.push_back(
17787 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
17788 }
17789 }
17790 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
17791 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
17792 ? RefExpr->IgnoreParens()
17793 : Ref);
17794 SrcExprs.push_back(PseudoSrcExpr);
17795 DstExprs.push_back(PseudoDstExpr);
17796 AssignmentOps.push_back(AssignmentOp.get());
17797 }
17798
17799 if (Vars.empty())
17800 return nullptr;
17801
17803 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
17804 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
17805 buildPreInits(getASTContext(), ExprCaptures),
17806 buildPostUpdate(SemaRef, ExprPostUpdates));
17807}
17808
17810 SourceLocation StartLoc,
17811 SourceLocation LParenLoc,
17812 SourceLocation EndLoc) {
17814 for (Expr *RefExpr : VarList) {
17815 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
17816 SourceLocation ELoc;
17817 SourceRange ERange;
17818 Expr *SimpleRefExpr = RefExpr;
17819 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
17820 if (Res.second) {
17821 // It will be analyzed later.
17822 Vars.push_back(RefExpr);
17823 }
17824 ValueDecl *D = Res.first;
17825 if (!D)
17826 continue;
17827
17828 auto *VD = dyn_cast<VarDecl>(D);
17829 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
17830 // in a Construct]
17831 // Variables with the predetermined data-sharing attributes may not be
17832 // listed in data-sharing attributes clauses, except for the cases
17833 // listed below. For these exceptions only, listing a predetermined
17834 // variable in a data-sharing attribute clause is allowed and overrides
17835 // the variable's predetermined data-sharing attributes.
17836 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
17837 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
17838 DVar.RefExpr) {
17839 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
17840 << getOpenMPClauseName(OMPC_shared);
17842 continue;
17843 }
17844
17845 DeclRefExpr *Ref = nullptr;
17846 if (!VD && isOpenMPCapturedDecl(D) &&
17848 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
17849 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
17850 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
17851 ? RefExpr->IgnoreParens()
17852 : Ref);
17853 }
17854
17855 if (Vars.empty())
17856 return nullptr;
17857
17858 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17859 Vars);
17860}
17861
17862namespace {
17863class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
17864 DSAStackTy *Stack;
17865
17866public:
17867 bool VisitDeclRefExpr(DeclRefExpr *E) {
17868 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
17869 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
17870 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
17871 return false;
17872 if (DVar.CKind != OMPC_unknown)
17873 return true;
17874 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
17875 VD,
17876 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
17877 return isOpenMPPrivate(C) && !AppliedToPointee;
17878 },
17879 [](OpenMPDirectiveKind) { return true; },
17880 /*FromParent=*/true);
17881 return DVarPrivate.CKind != OMPC_unknown;
17882 }
17883 return false;
17884 }
17885 bool VisitStmt(Stmt *S) {
17886 for (Stmt *Child : S->children()) {
17887 if (Child && Visit(Child))
17888 return true;
17889 }
17890 return false;
17891 }
17892 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
17893};
17894} // namespace
17895
17896namespace {
17897// Transform MemberExpression for specified FieldDecl of current class to
17898// DeclRefExpr to specified OMPCapturedExprDecl.
17899class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
17900 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
17901 ValueDecl *Field = nullptr;
17902 DeclRefExpr *CapturedExpr = nullptr;
17903
17904public:
17905 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
17906 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
17907
17908 ExprResult TransformMemberExpr(MemberExpr *E) {
17909 if (isa<CXXThisExpr>(E->getBase()->IgnoreParenImpCasts()) &&
17910 E->getMemberDecl() == Field) {
17911 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
17912 return CapturedExpr;
17913 }
17914 return BaseTransform::TransformMemberExpr(E);
17915 }
17916 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
17917};
17918} // namespace
17919
17920template <typename T, typename U>
17922 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
17923 for (U &Set : Lookups) {
17924 for (auto *D : Set) {
17925 if (T Res = Gen(cast<ValueDecl>(D)))
17926 return Res;
17927 }
17928 }
17929 return T();
17930}
17931
17933 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
17934
17935 for (auto *RD : D->redecls()) {
17936 // Don't bother with extra checks if we already know this one isn't visible.
17937 if (RD == D)
17938 continue;
17939
17940 auto ND = cast<NamedDecl>(RD);
17941 if (LookupResult::isVisible(SemaRef, ND))
17942 return ND;
17943 }
17944
17945 return nullptr;
17946}
17947
17948static void
17952 // Find all of the associated namespaces and classes based on the
17953 // arguments we have.
17954 Sema::AssociatedNamespaceSet AssociatedNamespaces;
17955 Sema::AssociatedClassSet AssociatedClasses;
17956 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
17957 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
17958 AssociatedClasses);
17959
17960 // C++ [basic.lookup.argdep]p3:
17961 // Let X be the lookup set produced by unqualified lookup (3.4.1)
17962 // and let Y be the lookup set produced by argument dependent
17963 // lookup (defined as follows). If X contains [...] then Y is
17964 // empty. Otherwise Y is the set of declarations found in the
17965 // namespaces associated with the argument types as described
17966 // below. The set of declarations found by the lookup of the name
17967 // is the union of X and Y.
17968 //
17969 // Here, we compute Y and add its members to the overloaded
17970 // candidate set.
17971 for (auto *NS : AssociatedNamespaces) {
17972 // When considering an associated namespace, the lookup is the
17973 // same as the lookup performed when the associated namespace is
17974 // used as a qualifier (3.4.3.2) except that:
17975 //
17976 // -- Any using-directives in the associated namespace are
17977 // ignored.
17978 //
17979 // -- Any namespace-scope friend functions declared in
17980 // associated classes are visible within their respective
17981 // namespaces even if they are not visible during an ordinary
17982 // lookup (11.4).
17983 DeclContext::lookup_result R = NS->lookup(Id.getName());
17984 for (auto *D : R) {
17985 auto *Underlying = D;
17986 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
17987 Underlying = USD->getTargetDecl();
17988
17989 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
17990 !isa<OMPDeclareMapperDecl>(Underlying))
17991 continue;
17992
17993 if (!SemaRef.isVisible(D)) {
17994 D = findAcceptableDecl(SemaRef, D);
17995 if (!D)
17996 continue;
17997 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
17998 Underlying = USD->getTargetDecl();
17999 }
18000 Lookups.emplace_back();
18001 Lookups.back().addDecl(Underlying);
18002 }
18003 }
18004}
18005
18006static ExprResult
18008 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
18009 const DeclarationNameInfo &ReductionId, QualType Ty,
18010 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
18011 if (ReductionIdScopeSpec.isInvalid())
18012 return ExprError();
18013 SmallVector<UnresolvedSet<8>, 4> Lookups;
18014 if (S) {
18015 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18016 Lookup.suppressDiagnostics();
18017 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
18018 /*ObjectType=*/QualType())) {
18019 NamedDecl *D = Lookup.getRepresentativeDecl();
18020 do {
18021 S = S->getParent();
18022 } while (S && !S->isDeclScope(D));
18023 if (S)
18024 S = S->getParent();
18025 Lookups.emplace_back();
18026 Lookups.back().append(Lookup.begin(), Lookup.end());
18027 Lookup.clear();
18028 }
18029 } else if (auto *ULE =
18030 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
18031 Lookups.push_back(UnresolvedSet<8>());
18032 Decl *PrevD = nullptr;
18033 for (NamedDecl *D : ULE->decls()) {
18034 if (D == PrevD)
18035 Lookups.push_back(UnresolvedSet<8>());
18036 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
18037 Lookups.back().addDecl(DRD);
18038 PrevD = D;
18039 }
18040 }
18041 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
18044 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
18045 return !D->isInvalidDecl() &&
18046 (D->getType()->isDependentType() ||
18047 D->getType()->isInstantiationDependentType() ||
18048 D->getType()->containsUnexpandedParameterPack());
18049 })) {
18050 UnresolvedSet<8> ResSet;
18051 for (const UnresolvedSet<8> &Set : Lookups) {
18052 if (Set.empty())
18053 continue;
18054 ResSet.append(Set.begin(), Set.end());
18055 // The last item marks the end of all declarations at the specified scope.
18056 ResSet.addDecl(Set[Set.size() - 1]);
18057 }
18059 SemaRef.Context, /*NamingClass=*/nullptr,
18060 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
18061 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
18062 /*KnownInstantiationDependent=*/false);
18063 }
18064 // Lookup inside the classes.
18065 // C++ [over.match.oper]p3:
18066 // For a unary operator @ with an operand of a type whose
18067 // cv-unqualified version is T1, and for a binary operator @ with
18068 // a left operand of a type whose cv-unqualified version is T1 and
18069 // a right operand of a type whose cv-unqualified version is T2,
18070 // three sets of candidate functions, designated member
18071 // candidates, non-member candidates and built-in candidates, are
18072 // constructed as follows:
18073 // -- If T1 is a complete class type or a class currently being
18074 // defined, the set of member candidates is the result of the
18075 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
18076 // the set of member candidates is empty.
18077 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
18078 Lookup.suppressDiagnostics();
18079 if (const auto *TyRec = Ty->getAs<RecordType>()) {
18080 // Complete the type if it can be completed.
18081 // If the type is neither complete nor being defined, bail out now.
18082 if (SemaRef.isCompleteType(Loc, Ty) || TyRec->isBeingDefined() ||
18083 TyRec->getDecl()->getDefinition()) {
18084 Lookup.clear();
18085 SemaRef.LookupQualifiedName(Lookup, TyRec->getDecl());
18086 if (Lookup.empty()) {
18087 Lookups.emplace_back();
18088 Lookups.back().append(Lookup.begin(), Lookup.end());
18089 }
18090 }
18091 }
18092 // Perform ADL.
18093 if (SemaRef.getLangOpts().CPlusPlus)
18094 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
18095 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18096 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
18097 if (!D->isInvalidDecl() &&
18098 SemaRef.Context.hasSameType(D->getType(), Ty))
18099 return D;
18100 return nullptr;
18101 }))
18102 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
18103 VK_LValue, Loc);
18104 if (SemaRef.getLangOpts().CPlusPlus) {
18105 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
18106 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
18107 if (!D->isInvalidDecl() &&
18108 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
18109 !Ty.isMoreQualifiedThan(D->getType()))
18110 return D;
18111 return nullptr;
18112 })) {
18113 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
18114 /*DetectVirtual=*/false);
18115 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
18116 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
18117 VD->getType().getUnqualifiedType()))) {
18118 if (SemaRef.CheckBaseClassAccess(
18119 Loc, VD->getType(), Ty, Paths.front(),
18120 /*DiagID=*/0) != Sema::AR_inaccessible) {
18121 SemaRef.BuildBasePathArray(Paths, BasePath);
18122 return SemaRef.BuildDeclRefExpr(
18124 }
18125 }
18126 }
18127 }
18128 }
18129 if (ReductionIdScopeSpec.isSet()) {
18130 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
18131 << Ty << Range;
18132 return ExprError();
18133 }
18134 return ExprEmpty();
18135}
18136
18137namespace {
18138/// Data for the reduction-based clauses.
18139struct ReductionData {
18140 /// List of original reduction items.
18142 /// List of private copies of the reduction items.
18143 SmallVector<Expr *, 8> Privates;
18144 /// LHS expressions for the reduction_op expressions.
18146 /// RHS expressions for the reduction_op expressions.
18148 /// Reduction operation expression.
18149 SmallVector<Expr *, 8> ReductionOps;
18150 /// inscan copy operation expressions.
18151 SmallVector<Expr *, 8> InscanCopyOps;
18152 /// inscan copy temp array expressions for prefix sums.
18153 SmallVector<Expr *, 8> InscanCopyArrayTemps;
18154 /// inscan copy temp array element expressions for prefix sums.
18155 SmallVector<Expr *, 8> InscanCopyArrayElems;
18156 /// Taskgroup descriptors for the corresponding reduction items in
18157 /// in_reduction clauses.
18158 SmallVector<Expr *, 8> TaskgroupDescriptors;
18159 /// List of captures for clause.
18160 SmallVector<Decl *, 4> ExprCaptures;
18161 /// List of postupdate expressions.
18162 SmallVector<Expr *, 4> ExprPostUpdates;
18163 /// Reduction modifier.
18164 unsigned RedModifier = 0;
18165 ReductionData() = delete;
18166 /// Reserves required memory for the reduction data.
18167 ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
18168 Vars.reserve(Size);
18169 Privates.reserve(Size);
18170 LHSs.reserve(Size);
18171 RHSs.reserve(Size);
18172 ReductionOps.reserve(Size);
18173 if (RedModifier == OMPC_REDUCTION_inscan) {
18174 InscanCopyOps.reserve(Size);
18175 InscanCopyArrayTemps.reserve(Size);
18176 InscanCopyArrayElems.reserve(Size);
18177 }
18178 TaskgroupDescriptors.reserve(Size);
18179 ExprCaptures.reserve(Size);
18180 ExprPostUpdates.reserve(Size);
18181 }
18182 /// Stores reduction item and reduction operation only (required for dependent
18183 /// reduction item).
18184 void push(Expr *Item, Expr *ReductionOp) {
18185 Vars.emplace_back(Item);
18186 Privates.emplace_back(nullptr);
18187 LHSs.emplace_back(nullptr);
18188 RHSs.emplace_back(nullptr);
18189 ReductionOps.emplace_back(ReductionOp);
18190 TaskgroupDescriptors.emplace_back(nullptr);
18191 if (RedModifier == OMPC_REDUCTION_inscan) {
18192 InscanCopyOps.push_back(nullptr);
18193 InscanCopyArrayTemps.push_back(nullptr);
18194 InscanCopyArrayElems.push_back(nullptr);
18195 }
18196 }
18197 /// Stores reduction data.
18198 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
18199 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
18200 Expr *CopyArrayElem) {
18201 Vars.emplace_back(Item);
18202 Privates.emplace_back(Private);
18203 LHSs.emplace_back(LHS);
18204 RHSs.emplace_back(RHS);
18205 ReductionOps.emplace_back(ReductionOp);
18206 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
18207 if (RedModifier == OMPC_REDUCTION_inscan) {
18208 InscanCopyOps.push_back(CopyOp);
18209 InscanCopyArrayTemps.push_back(CopyArrayTemp);
18210 InscanCopyArrayElems.push_back(CopyArrayElem);
18211 } else {
18212 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
18213 CopyArrayElem == nullptr &&
18214 "Copy operation must be used for inscan reductions only.");
18215 }
18216 }
18217};
18218} // namespace
18219
18221 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
18222 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
18223 const Expr *Length = OASE->getLength();
18224 if (Length == nullptr) {
18225 // For array sections of the form [1:] or [:], we would need to analyze
18226 // the lower bound...
18227 if (OASE->getColonLocFirst().isValid())
18228 return false;
18229
18230 // This is an array subscript which has implicit length 1!
18231 SingleElement = true;
18232 ArraySizes.push_back(llvm::APSInt::get(1));
18233 } else {
18235 if (!Length->EvaluateAsInt(Result, Context))
18236 return false;
18237
18238 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18239 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
18240 ArraySizes.push_back(ConstantLengthValue);
18241 }
18242
18243 // Get the base of this array section and walk up from there.
18244 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
18245
18246 // We require length = 1 for all array sections except the right-most to
18247 // guarantee that the memory region is contiguous and has no holes in it.
18248 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
18249 Length = TempOASE->getLength();
18250 if (Length == nullptr) {
18251 // For array sections of the form [1:] or [:], we would need to analyze
18252 // the lower bound...
18253 if (OASE->getColonLocFirst().isValid())
18254 return false;
18255
18256 // This is an array subscript which has implicit length 1!
18257 ArraySizes.push_back(llvm::APSInt::get(1));
18258 } else {
18260 if (!Length->EvaluateAsInt(Result, Context))
18261 return false;
18262
18263 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
18264 if (ConstantLengthValue.getSExtValue() != 1)
18265 return false;
18266
18267 ArraySizes.push_back(ConstantLengthValue);
18268 }
18269 Base = TempOASE->getBase()->IgnoreParenImpCasts();
18270 }
18271
18272 // If we have a single element, we don't need to add the implicit lengths.
18273 if (!SingleElement) {
18274 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
18275 // Has implicit length 1!
18276 ArraySizes.push_back(llvm::APSInt::get(1));
18277 Base = TempASE->getBase()->IgnoreParenImpCasts();
18278 }
18279 }
18280
18281 // This array section can be privatized as a single value or as a constant
18282 // sized array.
18283 return true;
18284}
18285
18286static BinaryOperatorKind
18288 if (BOK == BO_Add)
18289 return BO_AddAssign;
18290 if (BOK == BO_Mul)
18291 return BO_MulAssign;
18292 if (BOK == BO_And)
18293 return BO_AndAssign;
18294 if (BOK == BO_Or)
18295 return BO_OrAssign;
18296 if (BOK == BO_Xor)
18297 return BO_XorAssign;
18298 return BOK;
18299}
18300
18302 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
18303 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
18304 SourceLocation ColonLoc, SourceLocation EndLoc,
18305 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
18306 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
18307 DeclarationName DN = ReductionId.getName();
18309 BinaryOperatorKind BOK = BO_Comma;
18310
18311 ASTContext &Context = S.Context;
18312 // OpenMP [2.14.3.6, reduction clause]
18313 // C
18314 // reduction-identifier is either an identifier or one of the following
18315 // operators: +, -, *, &, |, ^, && and ||
18316 // C++
18317 // reduction-identifier is either an id-expression or one of the following
18318 // operators: +, -, *, &, |, ^, && and ||
18319 switch (OOK) {
18320 case OO_Plus:
18321 BOK = BO_Add;
18322 break;
18323 case OO_Minus:
18324 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
18325 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
18326 // reduction identifier.
18327 if (S.LangOpts.OpenMP > 52)
18328 BOK = BO_Comma;
18329 else
18330 BOK = BO_Add;
18331 break;
18332 case OO_Star:
18333 BOK = BO_Mul;
18334 break;
18335 case OO_Amp:
18336 BOK = BO_And;
18337 break;
18338 case OO_Pipe:
18339 BOK = BO_Or;
18340 break;
18341 case OO_Caret:
18342 BOK = BO_Xor;
18343 break;
18344 case OO_AmpAmp:
18345 BOK = BO_LAnd;
18346 break;
18347 case OO_PipePipe:
18348 BOK = BO_LOr;
18349 break;
18350 case OO_New:
18351 case OO_Delete:
18352 case OO_Array_New:
18353 case OO_Array_Delete:
18354 case OO_Slash:
18355 case OO_Percent:
18356 case OO_Tilde:
18357 case OO_Exclaim:
18358 case OO_Equal:
18359 case OO_Less:
18360 case OO_Greater:
18361 case OO_LessEqual:
18362 case OO_GreaterEqual:
18363 case OO_PlusEqual:
18364 case OO_MinusEqual:
18365 case OO_StarEqual:
18366 case OO_SlashEqual:
18367 case OO_PercentEqual:
18368 case OO_CaretEqual:
18369 case OO_AmpEqual:
18370 case OO_PipeEqual:
18371 case OO_LessLess:
18372 case OO_GreaterGreater:
18373 case OO_LessLessEqual:
18374 case OO_GreaterGreaterEqual:
18375 case OO_EqualEqual:
18376 case OO_ExclaimEqual:
18377 case OO_Spaceship:
18378 case OO_PlusPlus:
18379 case OO_MinusMinus:
18380 case OO_Comma:
18381 case OO_ArrowStar:
18382 case OO_Arrow:
18383 case OO_Call:
18384 case OO_Subscript:
18385 case OO_Conditional:
18386 case OO_Coawait:
18388 llvm_unreachable("Unexpected reduction identifier");
18389 case OO_None:
18390 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
18391 if (II->isStr("max"))
18392 BOK = BO_GT;
18393 else if (II->isStr("min"))
18394 BOK = BO_LT;
18395 }
18396 break;
18397 }
18398
18399 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
18400 // A reduction clause with the minus (-) operator was deprecated
18401 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
18402 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
18403
18404 SourceRange ReductionIdRange;
18405 if (ReductionIdScopeSpec.isValid())
18406 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
18407 else
18408 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
18409 ReductionIdRange.setEnd(ReductionId.getEndLoc());
18410
18411 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
18412 bool FirstIter = true;
18413 for (Expr *RefExpr : VarList) {
18414 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
18415 // OpenMP [2.1, C/C++]
18416 // A list item is a variable or array section, subject to the restrictions
18417 // specified in Section 2.4 on page 42 and in each of the sections
18418 // describing clauses and directives for which a list appears.
18419 // OpenMP [2.14.3.3, Restrictions, p.1]
18420 // A variable that is part of another variable (as an array or
18421 // structure element) cannot appear in a private clause.
18422 if (!FirstIter && IR != ER)
18423 ++IR;
18424 FirstIter = false;
18425 SourceLocation ELoc;
18426 SourceRange ERange;
18427 Expr *SimpleRefExpr = RefExpr;
18428 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
18429 /*AllowArraySection=*/true);
18430 if (Res.second) {
18431 // Try to find 'declare reduction' corresponding construct before using
18432 // builtin/overloaded operators.
18433 QualType Type = Context.DependentTy;
18434 CXXCastPath BasePath;
18435 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18436 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18437 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18438 Expr *ReductionOp = nullptr;
18439 if (S.CurContext->isDependentContext() &&
18440 (DeclareReductionRef.isUnset() ||
18441 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
18442 ReductionOp = DeclareReductionRef.get();
18443 // It will be analyzed later.
18444 RD.push(RefExpr, ReductionOp);
18445 }
18446 ValueDecl *D = Res.first;
18447 if (!D)
18448 continue;
18449
18450 Expr *TaskgroupDescriptor = nullptr;
18451 QualType Type;
18452 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
18453 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
18454 if (ASE) {
18455 Type = ASE->getType().getNonReferenceType();
18456 } else if (OASE) {
18457 QualType BaseType =
18459 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
18460 Type = ATy->getElementType();
18461 else
18462 Type = BaseType->getPointeeType();
18463 Type = Type.getNonReferenceType();
18464 } else {
18465 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
18466 }
18467 auto *VD = dyn_cast<VarDecl>(D);
18468
18469 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
18470 // A variable that appears in a private clause must not have an incomplete
18471 // type or a reference type.
18472 if (S.RequireCompleteType(ELoc, D->getType(),
18473 diag::err_omp_reduction_incomplete_type))
18474 continue;
18475 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18476 // A list item that appears in a reduction clause must not be
18477 // const-qualified.
18478 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
18479 /*AcceptIfMutable=*/false, ASE || OASE))
18480 continue;
18481
18482 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
18483 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
18484 // If a list-item is a reference type then it must bind to the same object
18485 // for all threads of the team.
18486 if (!ASE && !OASE) {
18487 if (VD) {
18488 VarDecl *VDDef = VD->getDefinition();
18489 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
18490 DSARefChecker Check(Stack);
18491 if (Check.Visit(VDDef->getInit())) {
18492 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
18493 << getOpenMPClauseName(ClauseKind) << ERange;
18494 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
18495 continue;
18496 }
18497 }
18498 }
18499
18500 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
18501 // in a Construct]
18502 // Variables with the predetermined data-sharing attributes may not be
18503 // listed in data-sharing attributes clauses, except for the cases
18504 // listed below. For these exceptions only, listing a predetermined
18505 // variable in a data-sharing attribute clause is allowed and overrides
18506 // the variable's predetermined data-sharing attributes.
18507 // OpenMP [2.14.3.6, Restrictions, p.3]
18508 // Any number of reduction clauses can be specified on the directive,
18509 // but a list item can appear only once in the reduction clauses for that
18510 // directive.
18511 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18512 if (DVar.CKind == OMPC_reduction) {
18513 S.Diag(ELoc, diag::err_omp_once_referenced)
18514 << getOpenMPClauseName(ClauseKind);
18515 if (DVar.RefExpr)
18516 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
18517 continue;
18518 }
18519 if (DVar.CKind != OMPC_unknown) {
18520 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18521 << getOpenMPClauseName(DVar.CKind)
18522 << getOpenMPClauseName(OMPC_reduction);
18523 reportOriginalDsa(S, Stack, D, DVar);
18524 continue;
18525 }
18526
18527 // OpenMP [2.14.3.6, Restrictions, p.1]
18528 // A list item that appears in a reduction clause of a worksharing
18529 // construct must be shared in the parallel regions to which any of the
18530 // worksharing regions arising from the worksharing construct bind.
18531 if (isOpenMPWorksharingDirective(CurrDir) &&
18532 !isOpenMPParallelDirective(CurrDir) &&
18533 !isOpenMPTeamsDirective(CurrDir)) {
18534 DVar = Stack->getImplicitDSA(D, true);
18535 if (DVar.CKind != OMPC_shared) {
18536 S.Diag(ELoc, diag::err_omp_required_access)
18537 << getOpenMPClauseName(OMPC_reduction)
18538 << getOpenMPClauseName(OMPC_shared);
18539 reportOriginalDsa(S, Stack, D, DVar);
18540 continue;
18541 }
18542 }
18543 } else {
18544 // Threadprivates cannot be shared between threads, so dignose if the base
18545 // is a threadprivate variable.
18546 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
18547 if (DVar.CKind == OMPC_threadprivate) {
18548 S.Diag(ELoc, diag::err_omp_wrong_dsa)
18549 << getOpenMPClauseName(DVar.CKind)
18550 << getOpenMPClauseName(OMPC_reduction);
18551 reportOriginalDsa(S, Stack, D, DVar);
18552 continue;
18553 }
18554 }
18555
18556 // Try to find 'declare reduction' corresponding construct before using
18557 // builtin/overloaded operators.
18558 CXXCastPath BasePath;
18559 ExprResult DeclareReductionRef = buildDeclareReductionRef(
18560 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
18561 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
18562 if (DeclareReductionRef.isInvalid())
18563 continue;
18564 if (S.CurContext->isDependentContext() &&
18565 (DeclareReductionRef.isUnset() ||
18566 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
18567 RD.push(RefExpr, DeclareReductionRef.get());
18568 continue;
18569 }
18570 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
18571 // Not allowed reduction identifier is found.
18572 if (S.LangOpts.OpenMP > 52)
18573 S.Diag(ReductionId.getBeginLoc(),
18574 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
18575 << Type << ReductionIdRange;
18576 else
18577 S.Diag(ReductionId.getBeginLoc(),
18578 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
18579 << Type << ReductionIdRange;
18580 continue;
18581 }
18582
18583 // OpenMP [2.14.3.6, reduction clause, Restrictions]
18584 // The type of a list item that appears in a reduction clause must be valid
18585 // for the reduction-identifier. For a max or min reduction in C, the type
18586 // of the list item must be an allowed arithmetic data type: char, int,
18587 // float, double, or _Bool, possibly modified with long, short, signed, or
18588 // unsigned. For a max or min reduction in C++, the type of the list item
18589 // must be an allowed arithmetic data type: char, wchar_t, int, float,
18590 // double, or bool, possibly modified with long, short, signed, or unsigned.
18591 if (DeclareReductionRef.isUnset()) {
18592 if ((BOK == BO_GT || BOK == BO_LT) &&
18593 !(Type->isScalarType() ||
18594 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
18595 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
18596 << getOpenMPClauseName(ClauseKind) << S.getLangOpts().CPlusPlus;
18597 if (!ASE && !OASE) {
18598 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18600 S.Diag(D->getLocation(),
18601 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18602 << D;
18603 }
18604 continue;
18605 }
18606 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
18607 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
18608 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
18609 << getOpenMPClauseName(ClauseKind);
18610 if (!ASE && !OASE) {
18611 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18613 S.Diag(D->getLocation(),
18614 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18615 << D;
18616 }
18617 continue;
18618 }
18619 }
18620
18621 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
18622 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
18623 D->hasAttrs() ? &D->getAttrs() : nullptr);
18624 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
18625 D->hasAttrs() ? &D->getAttrs() : nullptr);
18626 QualType PrivateTy = Type;
18627
18628 // Try if we can determine constant lengths for all array sections and avoid
18629 // the VLA.
18630 bool ConstantLengthOASE = false;
18631 if (OASE) {
18632 bool SingleElement;
18634 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
18635 Context, OASE, SingleElement, ArraySizes);
18636
18637 // If we don't have a single element, we must emit a constant array type.
18638 if (ConstantLengthOASE && !SingleElement) {
18639 for (llvm::APSInt &Size : ArraySizes)
18640 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
18642 /*IndexTypeQuals=*/0);
18643 }
18644 }
18645
18646 if ((OASE && !ConstantLengthOASE) ||
18647 (!OASE && !ASE &&
18648 D->getType().getNonReferenceType()->isVariablyModifiedType())) {
18649 if (!Context.getTargetInfo().isVLASupported()) {
18650 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
18651 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18652 S.Diag(ELoc, diag::note_vla_unsupported);
18653 continue;
18654 } else {
18655 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
18656 S.targetDiag(ELoc, diag::note_vla_unsupported);
18657 }
18658 }
18659 // For arrays/array sections only:
18660 // Create pseudo array type for private copy. The size for this array will
18661 // be generated during codegen.
18662 // For array subscripts or single variables Private Ty is the same as Type
18663 // (type of the variable or single array element).
18664 PrivateTy = Context.getVariableArrayType(
18665 Type,
18666 new (Context)
18667 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
18668 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0, SourceRange());
18669 } else if (!ASE && !OASE &&
18670 Context.getAsArrayType(D->getType().getNonReferenceType())) {
18671 PrivateTy = D->getType().getNonReferenceType();
18672 }
18673 // Private copy.
18674 VarDecl *PrivateVD =
18675 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18676 D->hasAttrs() ? &D->getAttrs() : nullptr,
18677 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
18678 // Add initializer for private variable.
18679 Expr *Init = nullptr;
18680 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
18681 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
18682 if (DeclareReductionRef.isUsable()) {
18683 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
18684 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
18685 if (DRD->getInitializer()) {
18686 Init = DRDRef;
18687 RHSVD->setInit(DRDRef);
18689 }
18690 } else {
18691 switch (BOK) {
18692 case BO_Add:
18693 case BO_Xor:
18694 case BO_Or:
18695 case BO_LOr:
18696 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
18698 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
18699 break;
18700 case BO_Mul:
18701 case BO_LAnd:
18702 if (Type->isScalarType() || Type->isAnyComplexType()) {
18703 // '*' and '&&' reduction ops - initializer is '1'.
18704 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
18705 }
18706 break;
18707 case BO_And: {
18708 // '&' reduction op - initializer is '~0'.
18709 QualType OrigType = Type;
18710 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
18711 Type = ComplexTy->getElementType();
18712 if (Type->isRealFloatingType()) {
18713 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
18714 Context.getFloatTypeSemantics(Type));
18715 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18716 Type, ELoc);
18717 } else if (Type->isScalarType()) {
18718 uint64_t Size = Context.getTypeSize(Type);
18719 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
18720 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
18721 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18722 }
18723 if (Init && OrigType->isAnyComplexType()) {
18724 // Init = 0xFFFF + 0xFFFFi;
18725 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
18726 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
18727 }
18728 Type = OrigType;
18729 break;
18730 }
18731 case BO_LT:
18732 case BO_GT: {
18733 // 'min' reduction op - initializer is 'Largest representable number in
18734 // the reduction list item type'.
18735 // 'max' reduction op - initializer is 'Least representable number in
18736 // the reduction list item type'.
18737 if (Type->isIntegerType() || Type->isPointerType()) {
18738 bool IsSigned = Type->hasSignedIntegerRepresentation();
18739 uint64_t Size = Context.getTypeSize(Type);
18740 QualType IntTy =
18741 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
18742 llvm::APInt InitValue =
18743 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
18744 : llvm::APInt::getMinValue(Size)
18745 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
18746 : llvm::APInt::getMaxValue(Size);
18747 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
18748 if (Type->isPointerType()) {
18749 // Cast to pointer type.
18751 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
18752 if (CastExpr.isInvalid())
18753 continue;
18754 Init = CastExpr.get();
18755 }
18756 } else if (Type->isRealFloatingType()) {
18757 llvm::APFloat InitValue = llvm::APFloat::getLargest(
18758 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
18759 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
18760 Type, ELoc);
18761 }
18762 break;
18763 }
18764 case BO_PtrMemD:
18765 case BO_PtrMemI:
18766 case BO_MulAssign:
18767 case BO_Div:
18768 case BO_Rem:
18769 case BO_Sub:
18770 case BO_Shl:
18771 case BO_Shr:
18772 case BO_LE:
18773 case BO_GE:
18774 case BO_EQ:
18775 case BO_NE:
18776 case BO_Cmp:
18777 case BO_AndAssign:
18778 case BO_XorAssign:
18779 case BO_OrAssign:
18780 case BO_Assign:
18781 case BO_AddAssign:
18782 case BO_SubAssign:
18783 case BO_DivAssign:
18784 case BO_RemAssign:
18785 case BO_ShlAssign:
18786 case BO_ShrAssign:
18787 case BO_Comma:
18788 llvm_unreachable("Unexpected reduction operation");
18789 }
18790 }
18791 if (Init && DeclareReductionRef.isUnset()) {
18792 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
18793 // Store initializer for single element in private copy. Will be used
18794 // during codegen.
18795 PrivateVD->setInit(RHSVD->getInit());
18796 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18797 } else if (!Init) {
18798 S.ActOnUninitializedDecl(RHSVD);
18799 // Store initializer for single element in private copy. Will be used
18800 // during codegen.
18801 PrivateVD->setInit(RHSVD->getInit());
18802 PrivateVD->setInitStyle(RHSVD->getInitStyle());
18803 }
18804 if (RHSVD->isInvalidDecl())
18805 continue;
18806 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
18807 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
18808 << Type << ReductionIdRange;
18809 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
18811 S.Diag(D->getLocation(),
18812 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
18813 << D;
18814 continue;
18815 }
18816 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
18817 ExprResult ReductionOp;
18818 if (DeclareReductionRef.isUsable()) {
18819 QualType RedTy = DeclareReductionRef.get()->getType();
18820 QualType PtrRedTy = Context.getPointerType(RedTy);
18821 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
18822 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
18823 if (!BasePath.empty()) {
18824 LHS = S.DefaultLvalueConversion(LHS.get());
18825 RHS = S.DefaultLvalueConversion(RHS.get());
18827 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
18828 LHS.get()->getValueKind(), FPOptionsOverride());
18830 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
18831 RHS.get()->getValueKind(), FPOptionsOverride());
18832 }
18834 QualType Params[] = {PtrRedTy, PtrRedTy};
18835 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
18836 auto *OVE = new (Context) OpaqueValueExpr(
18837 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
18838 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
18839 Expr *Args[] = {LHS.get(), RHS.get()};
18840 ReductionOp =
18841 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
18843 } else {
18845 if (Type->isRecordType() && CombBOK != BOK) {
18847 ReductionOp =
18848 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18849 CombBOK, LHSDRE, RHSDRE);
18850 }
18851 if (!ReductionOp.isUsable()) {
18852 ReductionOp =
18853 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
18854 LHSDRE, RHSDRE);
18855 if (ReductionOp.isUsable()) {
18856 if (BOK != BO_LT && BOK != BO_GT) {
18857 ReductionOp =
18858 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18859 BO_Assign, LHSDRE, ReductionOp.get());
18860 } else {
18861 auto *ConditionalOp = new (Context)
18862 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
18863 RHSDRE, Type, VK_LValue, OK_Ordinary);
18864 ReductionOp =
18865 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
18866 BO_Assign, LHSDRE, ConditionalOp);
18867 }
18868 }
18869 }
18870 if (ReductionOp.isUsable())
18871 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
18872 /*DiscardedValue=*/false);
18873 if (!ReductionOp.isUsable())
18874 continue;
18875 }
18876
18877 // Add copy operations for inscan reductions.
18878 // LHS = RHS;
18879 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
18880 if (ClauseKind == OMPC_reduction &&
18881 RD.RedModifier == OMPC_REDUCTION_inscan) {
18882 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
18883 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
18884 RHS.get());
18885 if (!CopyOpRes.isUsable())
18886 continue;
18887 CopyOpRes =
18888 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
18889 if (!CopyOpRes.isUsable())
18890 continue;
18891 // For simd directive and simd-based directives in simd mode no need to
18892 // construct temp array, need just a single temp element.
18893 if (Stack->getCurrentDirective() == OMPD_simd ||
18894 (S.getLangOpts().OpenMPSimd &&
18895 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
18896 VarDecl *TempArrayVD =
18897 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
18898 D->hasAttrs() ? &D->getAttrs() : nullptr);
18899 // Add a constructor to the temp decl.
18900 S.ActOnUninitializedDecl(TempArrayVD);
18901 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
18902 } else {
18903 // Build temp array for prefix sum.
18904 auto *Dim = new (S.Context)
18907 PrivateTy, Dim, ArraySizeModifier::Normal,
18908 /*IndexTypeQuals=*/0, {ELoc, ELoc});
18909 VarDecl *TempArrayVD =
18910 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
18911 D->hasAttrs() ? &D->getAttrs() : nullptr);
18912 // Add a constructor to the temp decl.
18913 S.ActOnUninitializedDecl(TempArrayVD);
18914 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
18915 TempArrayElem =
18916 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
18917 auto *Idx = new (S.Context)
18919 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
18920 ELoc, Idx, ELoc);
18921 }
18922 }
18923
18924 // OpenMP [2.15.4.6, Restrictions, p.2]
18925 // A list item that appears in an in_reduction clause of a task construct
18926 // must appear in a task_reduction clause of a construct associated with a
18927 // taskgroup region that includes the participating task in its taskgroup
18928 // set. The construct associated with the innermost region that meets this
18929 // condition must specify the same reduction-identifier as the in_reduction
18930 // clause.
18931 if (ClauseKind == OMPC_in_reduction) {
18932 SourceRange ParentSR;
18933 BinaryOperatorKind ParentBOK;
18934 const Expr *ParentReductionOp = nullptr;
18935 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
18936 DSAStackTy::DSAVarData ParentBOKDSA =
18937 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
18938 ParentBOKTD);
18939 DSAStackTy::DSAVarData ParentReductionOpDSA =
18940 Stack->getTopMostTaskgroupReductionData(
18941 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
18942 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
18943 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
18944 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
18945 (DeclareReductionRef.isUsable() && IsParentBOK) ||
18946 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
18947 bool EmitError = true;
18948 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
18949 llvm::FoldingSetNodeID RedId, ParentRedId;
18950 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
18951 DeclareReductionRef.get()->Profile(RedId, Context,
18952 /*Canonical=*/true);
18953 EmitError = RedId != ParentRedId;
18954 }
18955 if (EmitError) {
18956 S.Diag(ReductionId.getBeginLoc(),
18957 diag::err_omp_reduction_identifier_mismatch)
18958 << ReductionIdRange << RefExpr->getSourceRange();
18959 S.Diag(ParentSR.getBegin(),
18960 diag::note_omp_previous_reduction_identifier)
18961 << ParentSR
18962 << (IsParentBOK ? ParentBOKDSA.RefExpr
18963 : ParentReductionOpDSA.RefExpr)
18964 ->getSourceRange();
18965 continue;
18966 }
18967 }
18968 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
18969 }
18970
18971 DeclRefExpr *Ref = nullptr;
18972 Expr *VarsExpr = RefExpr->IgnoreParens();
18973 if (!VD && !S.CurContext->isDependentContext()) {
18974 if (ASE || OASE) {
18975 TransformExprToCaptures RebuildToCapture(S, D);
18976 VarsExpr =
18977 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
18978 Ref = RebuildToCapture.getCapturedExpr();
18979 } else {
18980 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
18981 }
18982 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
18983 RD.ExprCaptures.emplace_back(Ref->getDecl());
18984 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
18985 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
18986 if (!RefRes.isUsable())
18987 continue;
18988 ExprResult PostUpdateRes =
18989 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
18990 RefRes.get());
18991 if (!PostUpdateRes.isUsable())
18992 continue;
18993 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
18994 Stack->getCurrentDirective() == OMPD_taskgroup) {
18995 S.Diag(RefExpr->getExprLoc(),
18996 diag::err_omp_reduction_non_addressable_expression)
18997 << RefExpr->getSourceRange();
18998 continue;
18999 }
19000 RD.ExprPostUpdates.emplace_back(
19001 S.IgnoredValueConversions(PostUpdateRes.get()).get());
19002 }
19003 }
19004 }
19005 // All reduction items are still marked as reduction (to do not increase
19006 // code base size).
19007 unsigned Modifier = RD.RedModifier;
19008 // Consider task_reductions as reductions with task modifier. Required for
19009 // correct analysis of in_reduction clauses.
19010 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
19011 Modifier = OMPC_REDUCTION_task;
19012 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
19013 ASE || OASE);
19014 if (Modifier == OMPC_REDUCTION_task &&
19015 (CurrDir == OMPD_taskgroup ||
19016 ((isOpenMPParallelDirective(CurrDir) ||
19017 isOpenMPWorksharingDirective(CurrDir)) &&
19018 !isOpenMPSimdDirective(CurrDir)))) {
19019 if (DeclareReductionRef.isUsable())
19020 Stack->addTaskgroupReductionData(D, ReductionIdRange,
19021 DeclareReductionRef.get());
19022 else
19023 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
19024 }
19025 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
19026 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
19027 TempArrayElem.get());
19028 }
19029 return RD.Vars.empty();
19030}
19031
19034 SourceLocation StartLoc, SourceLocation LParenLoc,
19035 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
19036 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19037 ArrayRef<Expr *> UnresolvedReductions) {
19038 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
19039 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
19040 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
19041 /*Last=*/OMPC_REDUCTION_unknown)
19042 << getOpenMPClauseName(OMPC_reduction);
19043 return nullptr;
19044 }
19045 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
19046 // A reduction clause with the inscan reduction-modifier may only appear on a
19047 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
19048 // construct, a parallel worksharing-loop construct or a parallel
19049 // worksharing-loop SIMD construct.
19050 if (Modifier == OMPC_REDUCTION_inscan &&
19051 (DSAStack->getCurrentDirective() != OMPD_for &&
19052 DSAStack->getCurrentDirective() != OMPD_for_simd &&
19053 DSAStack->getCurrentDirective() != OMPD_simd &&
19054 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
19055 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
19056 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
19057 return nullptr;
19058 }
19059
19060 ReductionData RD(VarList.size(), Modifier);
19061 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
19062 StartLoc, LParenLoc, ColonLoc, EndLoc,
19063 ReductionIdScopeSpec, ReductionId,
19064 UnresolvedReductions, RD))
19065 return nullptr;
19066
19068 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
19069 Modifier, RD.Vars,
19070 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19071 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
19072 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
19073 buildPreInits(getASTContext(), RD.ExprCaptures),
19074 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19075}
19076
19078 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19079 SourceLocation ColonLoc, SourceLocation EndLoc,
19080 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19081 ArrayRef<Expr *> UnresolvedReductions) {
19082 ReductionData RD(VarList.size());
19083 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
19084 VarList, StartLoc, LParenLoc, ColonLoc,
19085 EndLoc, ReductionIdScopeSpec, ReductionId,
19086 UnresolvedReductions, RD))
19087 return nullptr;
19088
19090 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19091 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19092 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
19093 buildPreInits(getASTContext(), RD.ExprCaptures),
19094 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19095}
19096
19098 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19099 SourceLocation ColonLoc, SourceLocation EndLoc,
19100 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
19101 ArrayRef<Expr *> UnresolvedReductions) {
19102 ReductionData RD(VarList.size());
19103 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
19104 StartLoc, LParenLoc, ColonLoc, EndLoc,
19105 ReductionIdScopeSpec, ReductionId,
19106 UnresolvedReductions, RD))
19107 return nullptr;
19108
19110 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
19111 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
19112 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
19113 buildPreInits(getASTContext(), RD.ExprCaptures),
19114 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
19115}
19116
19118 SourceLocation LinLoc) {
19119 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
19120 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
19121 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
19122 << getLangOpts().CPlusPlus;
19123 return true;
19124 }
19125 return false;
19126}
19127
19129 OpenMPLinearClauseKind LinKind,
19130 QualType Type, bool IsDeclareSimd) {
19131 const auto *VD = dyn_cast_or_null<VarDecl>(D);
19132 // A variable must not have an incomplete type or a reference type.
19134 diag::err_omp_linear_incomplete_type))
19135 return true;
19136 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
19137 !Type->isReferenceType()) {
19138 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
19139 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
19140 return true;
19141 }
19142 Type = Type.getNonReferenceType();
19143
19144 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19145 // A variable that is privatized must not have a const-qualified type
19146 // unless it is of class type with a mutable member. This restriction does
19147 // not apply to the firstprivate clause, nor to the linear clause on
19148 // declarative directives (like declare simd).
19149 if (!IsDeclareSimd &&
19150 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
19151 return true;
19152
19153 // A list item must be of integral or pointer type.
19154 Type = Type.getUnqualifiedType().getCanonicalType();
19155 const auto *Ty = Type.getTypePtrOrNull();
19156 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
19157 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
19158 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
19159 if (D) {
19160 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19162 Diag(D->getLocation(),
19163 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19164 << D;
19165 }
19166 return true;
19167 }
19168 return false;
19169}
19170
19172 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
19173 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
19174 SourceLocation LinLoc, SourceLocation ColonLoc,
19175 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
19177 SmallVector<Expr *, 8> Privates;
19179 SmallVector<Decl *, 4> ExprCaptures;
19180 SmallVector<Expr *, 4> ExprPostUpdates;
19181 // OpenMP 5.2 [Section 5.4.6, linear clause]
19182 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
19183 // 'ref'
19184 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
19185 getLangOpts().OpenMP >= 52)
19186 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
19187 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
19188 LinKind = OMPC_LINEAR_val;
19189 for (Expr *RefExpr : VarList) {
19190 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19191 SourceLocation ELoc;
19192 SourceRange ERange;
19193 Expr *SimpleRefExpr = RefExpr;
19194 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19195 if (Res.second) {
19196 // It will be analyzed later.
19197 Vars.push_back(RefExpr);
19198 Privates.push_back(nullptr);
19199 Inits.push_back(nullptr);
19200 }
19201 ValueDecl *D = Res.first;
19202 if (!D)
19203 continue;
19204
19205 QualType Type = D->getType();
19206 auto *VD = dyn_cast<VarDecl>(D);
19207
19208 // OpenMP [2.14.3.7, linear clause]
19209 // A list-item cannot appear in more than one linear clause.
19210 // A list-item that appears in a linear clause cannot appear in any
19211 // other data-sharing attribute clause.
19212 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19213 if (DVar.RefExpr) {
19214 Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind)
19215 << getOpenMPClauseName(OMPC_linear);
19217 continue;
19218 }
19219
19220 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
19221 continue;
19222 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
19223
19224 // Build private copy of original var.
19225 VarDecl *Private =
19226 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19227 D->hasAttrs() ? &D->getAttrs() : nullptr,
19228 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19229 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
19230 // Build var to save initial value.
19231 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
19232 Expr *InitExpr;
19233 DeclRefExpr *Ref = nullptr;
19234 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19235 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19236 if (!isOpenMPCapturedDecl(D)) {
19237 ExprCaptures.push_back(Ref->getDecl());
19238 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
19240 if (!RefRes.isUsable())
19241 continue;
19242 ExprResult PostUpdateRes =
19243 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19244 SimpleRefExpr, RefRes.get());
19245 if (!PostUpdateRes.isUsable())
19246 continue;
19247 ExprPostUpdates.push_back(
19248 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19249 }
19250 }
19251 }
19252 if (LinKind == OMPC_LINEAR_uval)
19253 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
19254 else
19255 InitExpr = VD ? SimpleRefExpr : Ref;
19258 /*DirectInit=*/false);
19259 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
19260
19261 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
19262 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19263 ? RefExpr->IgnoreParens()
19264 : Ref);
19265 Privates.push_back(PrivateRef);
19266 Inits.push_back(InitRef);
19267 }
19268
19269 if (Vars.empty())
19270 return nullptr;
19271
19272 Expr *StepExpr = Step;
19273 Expr *CalcStepExpr = nullptr;
19274 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
19275 !Step->isInstantiationDependent() &&
19277 SourceLocation StepLoc = Step->getBeginLoc();
19279 if (Val.isInvalid())
19280 return nullptr;
19281 StepExpr = Val.get();
19282
19283 // Build var to save the step value.
19284 VarDecl *SaveVar =
19285 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
19286 ExprResult SaveRef =
19287 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
19288 ExprResult CalcStep = SemaRef.BuildBinOp(
19289 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
19290 CalcStep =
19291 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
19292
19293 // Warn about zero linear step (it would be probably better specified as
19294 // making corresponding variables 'const').
19295 if (std::optional<llvm::APSInt> Result =
19297 if (!Result->isNegative() && !Result->isStrictlyPositive())
19298 Diag(StepLoc, diag::warn_omp_linear_step_zero)
19299 << Vars[0] << (Vars.size() > 1);
19300 } else if (CalcStep.isUsable()) {
19301 // Calculate the step beforehand instead of doing this on each iteration.
19302 // (This is not used if the number of iterations may be kfold-ed).
19303 CalcStepExpr = CalcStep.get();
19304 }
19305 }
19306
19307 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
19308 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
19309 Vars, Privates, Inits, StepExpr, CalcStepExpr,
19310 buildPreInits(getASTContext(), ExprCaptures),
19311 buildPostUpdate(SemaRef, ExprPostUpdates));
19312}
19313
19315 Expr *NumIterations, Sema &SemaRef,
19316 Scope *S, DSAStackTy *Stack) {
19317 // Walk the vars and build update/final expressions for the CodeGen.
19318 SmallVector<Expr *, 8> Updates;
19320 SmallVector<Expr *, 8> UsedExprs;
19321 Expr *Step = Clause.getStep();
19322 Expr *CalcStep = Clause.getCalcStep();
19323 // OpenMP [2.14.3.7, linear clause]
19324 // If linear-step is not specified it is assumed to be 1.
19325 if (!Step)
19326 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
19327 else if (CalcStep)
19328 Step = cast<BinaryOperator>(CalcStep)->getLHS();
19329 bool HasErrors = false;
19330 auto CurInit = Clause.inits().begin();
19331 auto CurPrivate = Clause.privates().begin();
19332 OpenMPLinearClauseKind LinKind = Clause.getModifier();
19333 for (Expr *RefExpr : Clause.varlist()) {
19334 SourceLocation ELoc;
19335 SourceRange ERange;
19336 Expr *SimpleRefExpr = RefExpr;
19337 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19338 ValueDecl *D = Res.first;
19339 if (Res.second || !D) {
19340 Updates.push_back(nullptr);
19341 Finals.push_back(nullptr);
19342 HasErrors = true;
19343 continue;
19344 }
19345 auto &&Info = Stack->isLoopControlVariable(D);
19346 // OpenMP [2.15.11, distribute simd Construct]
19347 // A list item may not appear in a linear clause, unless it is the loop
19348 // iteration variable.
19349 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
19350 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
19351 SemaRef.Diag(ELoc,
19352 diag::err_omp_linear_distribute_var_non_loop_iteration);
19353 Updates.push_back(nullptr);
19354 Finals.push_back(nullptr);
19355 HasErrors = true;
19356 continue;
19357 }
19358 Expr *InitExpr = *CurInit;
19359
19360 // Build privatized reference to the current linear var.
19361 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
19362 Expr *CapturedRef;
19363 if (LinKind == OMPC_LINEAR_uval)
19364 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
19365 else
19366 CapturedRef =
19367 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
19368 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
19369 /*RefersToCapture=*/true);
19370
19371 // Build update: Var = InitExpr + IV * Step
19373 if (!Info.first)
19375 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
19376 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
19377 else
19378 Update = *CurPrivate;
19379 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
19380 /*DiscardedValue=*/false);
19381
19382 // Build final: Var = PrivCopy;
19383 ExprResult Final;
19384 if (!Info.first)
19385 Final = SemaRef.BuildBinOp(
19386 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
19387 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
19388 else
19389 Final = *CurPrivate;
19390 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
19391 /*DiscardedValue=*/false);
19392
19393 if (!Update.isUsable() || !Final.isUsable()) {
19394 Updates.push_back(nullptr);
19395 Finals.push_back(nullptr);
19396 UsedExprs.push_back(nullptr);
19397 HasErrors = true;
19398 } else {
19399 Updates.push_back(Update.get());
19400 Finals.push_back(Final.get());
19401 if (!Info.first)
19402 UsedExprs.push_back(SimpleRefExpr);
19403 }
19404 ++CurInit;
19405 ++CurPrivate;
19406 }
19407 if (Expr *S = Clause.getStep())
19408 UsedExprs.push_back(S);
19409 // Fill the remaining part with the nullptr.
19410 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
19411 Clause.setUpdates(Updates);
19412 Clause.setFinals(Finals);
19413 Clause.setUsedExprs(UsedExprs);
19414 return HasErrors;
19415}
19416
19418 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
19419 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
19421 for (Expr *RefExpr : VarList) {
19422 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19423 SourceLocation ELoc;
19424 SourceRange ERange;
19425 Expr *SimpleRefExpr = RefExpr;
19426 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19427 if (Res.second) {
19428 // It will be analyzed later.
19429 Vars.push_back(RefExpr);
19430 }
19431 ValueDecl *D = Res.first;
19432 if (!D)
19433 continue;
19434
19435 QualType QType = D->getType();
19436 auto *VD = dyn_cast<VarDecl>(D);
19437
19438 // OpenMP [2.8.1, simd construct, Restrictions]
19439 // The type of list items appearing in the aligned clause must be
19440 // array, pointer, reference to array, or reference to pointer.
19442 const Type *Ty = QType.getTypePtrOrNull();
19443 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
19444 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
19445 << QType << getLangOpts().CPlusPlus << ERange;
19446 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19448 Diag(D->getLocation(),
19449 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19450 << D;
19451 continue;
19452 }
19453
19454 // OpenMP [2.8.1, simd construct, Restrictions]
19455 // A list-item cannot appear in more than one aligned clause.
19456 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
19457 Diag(ELoc, diag::err_omp_used_in_clause_twice)
19458 << 0 << getOpenMPClauseName(OMPC_aligned) << ERange;
19459 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
19460 << getOpenMPClauseName(OMPC_aligned);
19461 continue;
19462 }
19463
19464 DeclRefExpr *Ref = nullptr;
19465 if (!VD && isOpenMPCapturedDecl(D))
19466 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19467 Vars.push_back(SemaRef
19468 .DefaultFunctionArrayConversion(
19469 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
19470 .get());
19471 }
19472
19473 // OpenMP [2.8.1, simd construct, Description]
19474 // The parameter of the aligned clause, alignment, must be a constant
19475 // positive integer expression.
19476 // If no optional parameter is specified, implementation-defined default
19477 // alignments for SIMD instructions on the target platforms are assumed.
19478 if (Alignment != nullptr) {
19479 ExprResult AlignResult =
19480 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
19481 if (AlignResult.isInvalid())
19482 return nullptr;
19483 Alignment = AlignResult.get();
19484 }
19485 if (Vars.empty())
19486 return nullptr;
19487
19488 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
19489 ColonLoc, EndLoc, Vars, Alignment);
19490}
19491
19493 SourceLocation StartLoc,
19494 SourceLocation LParenLoc,
19495 SourceLocation EndLoc) {
19497 SmallVector<Expr *, 8> SrcExprs;
19498 SmallVector<Expr *, 8> DstExprs;
19499 SmallVector<Expr *, 8> AssignmentOps;
19500 for (Expr *RefExpr : VarList) {
19501 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
19502 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19503 // It will be analyzed later.
19504 Vars.push_back(RefExpr);
19505 SrcExprs.push_back(nullptr);
19506 DstExprs.push_back(nullptr);
19507 AssignmentOps.push_back(nullptr);
19508 continue;
19509 }
19510
19511 SourceLocation ELoc = RefExpr->getExprLoc();
19512 // OpenMP [2.1, C/C++]
19513 // A list item is a variable name.
19514 // OpenMP [2.14.4.1, Restrictions, p.1]
19515 // A list item that appears in a copyin clause must be threadprivate.
19516 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
19517 if (!DE || !isa<VarDecl>(DE->getDecl())) {
19518 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
19519 << 0 << RefExpr->getSourceRange();
19520 continue;
19521 }
19522
19523 Decl *D = DE->getDecl();
19524 auto *VD = cast<VarDecl>(D);
19525
19526 QualType Type = VD->getType();
19528 // It will be analyzed later.
19529 Vars.push_back(DE);
19530 SrcExprs.push_back(nullptr);
19531 DstExprs.push_back(nullptr);
19532 AssignmentOps.push_back(nullptr);
19533 continue;
19534 }
19535
19536 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
19537 // A list item that appears in a copyin clause must be threadprivate.
19538 if (!DSAStack->isThreadPrivate(VD)) {
19539 Diag(ELoc, diag::err_omp_required_access)
19540 << getOpenMPClauseName(OMPC_copyin)
19541 << getOpenMPDirectiveName(OMPD_threadprivate);
19542 continue;
19543 }
19544
19545 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19546 // A variable of class type (or array thereof) that appears in a
19547 // copyin clause requires an accessible, unambiguous copy assignment
19548 // operator for the class type.
19549 QualType ElemType =
19551 VarDecl *SrcVD =
19552 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
19553 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19554 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
19555 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
19556 VarDecl *DstVD =
19557 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
19558 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
19559 DeclRefExpr *PseudoDstExpr =
19560 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
19561 // For arrays generate assignment operation for single element and replace
19562 // it by the original array element in CodeGen.
19563 ExprResult AssignmentOp =
19564 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
19565 PseudoDstExpr, PseudoSrcExpr);
19566 if (AssignmentOp.isInvalid())
19567 continue;
19568 AssignmentOp =
19569 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
19570 /*DiscardedValue=*/false);
19571 if (AssignmentOp.isInvalid())
19572 continue;
19573
19574 DSAStack->addDSA(VD, DE, OMPC_copyin);
19575 Vars.push_back(DE);
19576 SrcExprs.push_back(PseudoSrcExpr);
19577 DstExprs.push_back(PseudoDstExpr);
19578 AssignmentOps.push_back(AssignmentOp.get());
19579 }
19580
19581 if (Vars.empty())
19582 return nullptr;
19583
19584 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19585 Vars, SrcExprs, DstExprs, AssignmentOps);
19586}
19587
19589 SourceLocation StartLoc,
19590 SourceLocation LParenLoc,
19591 SourceLocation EndLoc) {
19593 SmallVector<Expr *, 8> SrcExprs;
19594 SmallVector<Expr *, 8> DstExprs;
19595 SmallVector<Expr *, 8> AssignmentOps;
19596 for (Expr *RefExpr : VarList) {
19597 assert(RefExpr && "NULL expr in OpenMP linear clause.");
19598 SourceLocation ELoc;
19599 SourceRange ERange;
19600 Expr *SimpleRefExpr = RefExpr;
19601 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19602 if (Res.second) {
19603 // It will be analyzed later.
19604 Vars.push_back(RefExpr);
19605 SrcExprs.push_back(nullptr);
19606 DstExprs.push_back(nullptr);
19607 AssignmentOps.push_back(nullptr);
19608 }
19609 ValueDecl *D = Res.first;
19610 if (!D)
19611 continue;
19612
19613 QualType Type = D->getType();
19614 auto *VD = dyn_cast<VarDecl>(D);
19615
19616 // OpenMP [2.14.4.2, Restrictions, p.2]
19617 // A list item that appears in a copyprivate clause may not appear in a
19618 // private or firstprivate clause on the single construct.
19619 if (!VD || !DSAStack->isThreadPrivate(VD)) {
19620 DSAStackTy::DSAVarData DVar =
19621 DSAStack->getTopDSA(D, /*FromParent=*/false);
19622 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
19623 DVar.RefExpr) {
19624 Diag(ELoc, diag::err_omp_wrong_dsa)
19625 << getOpenMPClauseName(DVar.CKind)
19626 << getOpenMPClauseName(OMPC_copyprivate);
19628 continue;
19629 }
19630
19631 // OpenMP [2.11.4.2, Restrictions, p.1]
19632 // All list items that appear in a copyprivate clause must be either
19633 // threadprivate or private in the enclosing context.
19634 if (DVar.CKind == OMPC_unknown) {
19635 DVar = DSAStack->getImplicitDSA(D, false);
19636 if (DVar.CKind == OMPC_shared) {
19637 Diag(ELoc, diag::err_omp_required_access)
19638 << getOpenMPClauseName(OMPC_copyprivate)
19639 << "threadprivate or private in the enclosing context";
19641 continue;
19642 }
19643 }
19644 }
19645
19646 // Variably modified types are not supported.
19648 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19649 << getOpenMPClauseName(OMPC_copyprivate) << Type
19650 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
19651 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19653 Diag(D->getLocation(),
19654 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19655 << D;
19656 continue;
19657 }
19658
19659 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
19660 // A variable of class type (or array thereof) that appears in a
19661 // copyin clause requires an accessible, unambiguous copy assignment
19662 // operator for the class type.
19664 .getBaseElementType(Type.getNonReferenceType())
19666 VarDecl *SrcVD =
19667 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
19668 D->hasAttrs() ? &D->getAttrs() : nullptr);
19669 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
19670 VarDecl *DstVD =
19671 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
19672 D->hasAttrs() ? &D->getAttrs() : nullptr);
19673 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19674 ExprResult AssignmentOp = SemaRef.BuildBinOp(
19675 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
19676 if (AssignmentOp.isInvalid())
19677 continue;
19678 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19679 /*DiscardedValue=*/false);
19680 if (AssignmentOp.isInvalid())
19681 continue;
19682
19683 // No need to mark vars as copyprivate, they are already threadprivate or
19684 // implicitly private.
19685 assert(VD || isOpenMPCapturedDecl(D));
19686 Vars.push_back(
19687 VD ? RefExpr->IgnoreParens()
19688 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
19689 SrcExprs.push_back(PseudoSrcExpr);
19690 DstExprs.push_back(PseudoDstExpr);
19691 AssignmentOps.push_back(AssignmentOp.get());
19692 }
19693
19694 if (Vars.empty())
19695 return nullptr;
19696
19697 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
19698 EndLoc, Vars, SrcExprs, DstExprs,
19699 AssignmentOps);
19700}
19701
19703 SourceLocation StartLoc,
19704 SourceLocation LParenLoc,
19705 SourceLocation EndLoc) {
19706 if (VarList.empty())
19707 return nullptr;
19708
19709 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19710 VarList);
19711}
19712
19713/// Tries to find omp_depend_t. type.
19714static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
19715 bool Diagnose = true) {
19716 QualType OMPDependT = Stack->getOMPDependT();
19717 if (!OMPDependT.isNull())
19718 return true;
19719 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
19720 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
19721 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
19722 if (Diagnose)
19723 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
19724 return false;
19725 }
19726 Stack->setOMPDependT(PT.get());
19727 return true;
19728}
19729
19731 SourceLocation StartLoc,
19732 SourceLocation LParenLoc,
19733 SourceLocation EndLoc) {
19734 if (!Depobj)
19735 return nullptr;
19736
19737 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
19738
19739 // OpenMP 5.0, 2.17.10.1 depobj Construct
19740 // depobj is an lvalue expression of type omp_depend_t.
19741 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
19742 !Depobj->isInstantiationDependent() &&
19744 (OMPDependTFound && !getASTContext().typesAreCompatible(
19745 DSAStack->getOMPDependT(), Depobj->getType(),
19746 /*CompareUnqualified=*/true))) {
19747 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19748 << 0 << Depobj->getType() << Depobj->getSourceRange();
19749 }
19750
19751 if (!Depobj->isLValue()) {
19752 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
19753 << 1 << Depobj->getSourceRange();
19754 }
19755
19756 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19757 Depobj);
19758}
19759
19760namespace {
19761// Utility struct that gathers the related info for doacross clause.
19762struct DoacrossDataInfoTy {
19763 // The list of expressions.
19765 // The OperatorOffset for doacross loop.
19767 // The depended loop count.
19768 llvm::APSInt TotalDepCount;
19769};
19770} // namespace
19771static DoacrossDataInfoTy
19773 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
19774 SourceLocation EndLoc) {
19775
19778 llvm::APSInt DepCounter(/*BitWidth=*/32);
19779 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19780
19781 if (const Expr *OrderedCountExpr =
19782 Stack->getParentOrderedRegionParam().first) {
19783 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
19784 TotalDepCount.setIsUnsigned(/*Val=*/true);
19785 }
19786
19787 for (Expr *RefExpr : VarList) {
19788 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
19789 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19790 // It will be analyzed later.
19791 Vars.push_back(RefExpr);
19792 continue;
19793 }
19794
19795 SourceLocation ELoc = RefExpr->getExprLoc();
19796 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19797 if (!IsSource) {
19798 if (Stack->getParentOrderedRegionParam().first &&
19799 DepCounter >= TotalDepCount) {
19800 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
19801 continue;
19802 }
19803 ++DepCounter;
19804 // OpenMP [2.13.9, Summary]
19805 // depend(dependence-type : vec), where dependence-type is:
19806 // 'sink' and where vec is the iteration vector, which has the form:
19807 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
19808 // where n is the value specified by the ordered clause in the loop
19809 // directive, xi denotes the loop iteration variable of the i-th nested
19810 // loop associated with the loop directive, and di is a constant
19811 // non-negative integer.
19812 if (SemaRef.CurContext->isDependentContext()) {
19813 // It will be analyzed later.
19814 Vars.push_back(RefExpr);
19815 continue;
19816 }
19817 SimpleExpr = SimpleExpr->IgnoreImplicit();
19819 SourceLocation OOLoc;
19820 Expr *LHS = SimpleExpr;
19821 Expr *RHS = nullptr;
19822 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
19823 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
19824 OOLoc = BO->getOperatorLoc();
19825 LHS = BO->getLHS()->IgnoreParenImpCasts();
19826 RHS = BO->getRHS()->IgnoreParenImpCasts();
19827 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
19828 OOK = OCE->getOperator();
19829 OOLoc = OCE->getOperatorLoc();
19830 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19831 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
19832 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
19833 OOK = MCE->getMethodDecl()
19834 ->getNameInfo()
19835 .getName()
19836 .getCXXOverloadedOperator();
19837 OOLoc = MCE->getCallee()->getExprLoc();
19838 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
19839 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
19840 }
19841 SourceLocation ELoc;
19842 SourceRange ERange;
19843 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
19844 if (Res.second) {
19845 // It will be analyzed later.
19846 Vars.push_back(RefExpr);
19847 }
19848 ValueDecl *D = Res.first;
19849 if (!D)
19850 continue;
19851
19852 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
19853 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
19854 continue;
19855 }
19856 if (RHS) {
19857 ExprResult RHSRes =
19859 RHS, OMPC_depend, /*StrictlyPositive=*/false);
19860 if (RHSRes.isInvalid())
19861 continue;
19862 }
19863 if (!SemaRef.CurContext->isDependentContext() &&
19864 Stack->getParentOrderedRegionParam().first &&
19865 DepCounter != Stack->isParentLoopControlVariable(D).first) {
19866 const ValueDecl *VD =
19867 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
19868 if (VD)
19869 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19870 << 1 << VD;
19871 else
19872 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
19873 << 0;
19874 continue;
19875 }
19876 OpsOffs.emplace_back(RHS, OOK);
19877 }
19878 Vars.push_back(RefExpr->IgnoreParenImpCasts());
19879 }
19880 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
19881 TotalDepCount > VarList.size() &&
19882 Stack->getParentOrderedRegionParam().first &&
19883 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
19884 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
19885 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
19886 }
19887 return {Vars, OpsOffs, TotalDepCount};
19888}
19889
19891 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
19892 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
19893 SourceLocation EndLoc) {
19894 OpenMPDependClauseKind DepKind = Data.DepKind;
19895 SourceLocation DepLoc = Data.DepLoc;
19896 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
19897 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
19898 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19899 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
19900 return nullptr;
19901 }
19902 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
19903 DepKind == OMPC_DEPEND_mutexinoutset) {
19904 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
19905 return nullptr;
19906 }
19907 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
19908 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19909 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
19910 DepKind == OMPC_DEPEND_sink ||
19911 ((getLangOpts().OpenMP < 50 ||
19912 DSAStack->getCurrentDirective() == OMPD_depobj) &&
19913 DepKind == OMPC_DEPEND_depobj))) {
19914 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
19915 OMPC_DEPEND_outallmemory,
19916 OMPC_DEPEND_inoutallmemory};
19917 if (getLangOpts().OpenMP < 50 ||
19918 DSAStack->getCurrentDirective() == OMPD_depobj)
19919 Except.push_back(OMPC_DEPEND_depobj);
19920 if (getLangOpts().OpenMP < 51)
19921 Except.push_back(OMPC_DEPEND_inoutset);
19922 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
19923 ? "depend modifier(iterator) or "
19924 : "";
19925 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
19926 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
19927 /*Last=*/OMPC_DEPEND_unknown,
19928 Except)
19929 << getOpenMPClauseName(OMPC_depend);
19930 return nullptr;
19931 }
19932 if (DepModifier &&
19933 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
19934 Diag(DepModifier->getExprLoc(),
19935 diag::err_omp_depend_sink_source_with_modifier);
19936 return nullptr;
19937 }
19938 if (DepModifier &&
19939 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
19940 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
19941
19944 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
19945
19946 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
19947 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
19948 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
19949 Vars = VarOffset.Vars;
19950 OpsOffs = VarOffset.OpsOffs;
19951 TotalDepCount = VarOffset.TotalDepCount;
19952 } else {
19953 for (Expr *RefExpr : VarList) {
19954 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19955 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
19956 // It will be analyzed later.
19957 Vars.push_back(RefExpr);
19958 continue;
19959 }
19960
19961 SourceLocation ELoc = RefExpr->getExprLoc();
19962 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
19963 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
19964 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
19965 if (OMPDependTFound)
19966 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
19967 DepKind == OMPC_DEPEND_depobj);
19968 if (DepKind == OMPC_DEPEND_depobj) {
19969 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
19970 // List items used in depend clauses with the depobj dependence type
19971 // must be expressions of the omp_depend_t type.
19972 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
19973 !RefExpr->isInstantiationDependent() &&
19974 !RefExpr->containsUnexpandedParameterPack() &&
19975 (OMPDependTFound &&
19976 !getASTContext().hasSameUnqualifiedType(
19977 DSAStack->getOMPDependT(), RefExpr->getType()))) {
19978 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19979 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
19980 continue;
19981 }
19982 if (!RefExpr->isLValue()) {
19983 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
19984 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
19985 continue;
19986 }
19987 } else {
19988 // OpenMP 5.0 [2.17.11, Restrictions]
19989 // List items used in depend clauses cannot be zero-length array
19990 // sections.
19991 QualType ExprTy = RefExpr->getType().getNonReferenceType();
19992 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
19993 if (OASE) {
19994 QualType BaseType =
19996 if (BaseType.isNull())
19997 return nullptr;
19998 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
19999 ExprTy = ATy->getElementType();
20000 else
20001 ExprTy = BaseType->getPointeeType();
20002 if (BaseType.isNull() || ExprTy.isNull())
20003 return nullptr;
20004 ExprTy = ExprTy.getNonReferenceType();
20005 const Expr *Length = OASE->getLength();
20007 if (Length && !Length->isValueDependent() &&
20008 Length->EvaluateAsInt(Result, getASTContext()) &&
20009 Result.Val.getInt().isZero()) {
20010 Diag(ELoc,
20011 diag::err_omp_depend_zero_length_array_section_not_allowed)
20012 << SimpleExpr->getSourceRange();
20013 continue;
20014 }
20015 }
20016
20017 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
20018 // List items used in depend clauses with the in, out, inout,
20019 // inoutset, or mutexinoutset dependence types cannot be
20020 // expressions of the omp_depend_t type.
20021 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
20022 !RefExpr->isInstantiationDependent() &&
20023 !RefExpr->containsUnexpandedParameterPack() &&
20024 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
20025 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
20026 ExprTy.getTypePtr()))) {
20027 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20028 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20029 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20030 << RefExpr->getSourceRange();
20031 continue;
20032 }
20033
20034 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
20035 if (ASE && !ASE->getBase()->isTypeDependent() &&
20036 !ASE->getBase()
20037 ->getType()
20038 .getNonReferenceType()
20039 ->isPointerType() &&
20040 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
20041 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20042 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20043 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20044 << RefExpr->getSourceRange();
20045 continue;
20046 }
20047
20048 ExprResult Res;
20049 {
20051 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
20052 RefExpr->IgnoreParenImpCasts());
20053 }
20054 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
20055 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
20056 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
20057 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20058 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
20059 << RefExpr->getSourceRange();
20060 continue;
20061 }
20062 }
20063 }
20064 Vars.push_back(RefExpr->IgnoreParenImpCasts());
20065 }
20066 }
20067
20068 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
20069 DepKind != OMPC_DEPEND_outallmemory &&
20070 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
20071 return nullptr;
20072
20073 auto *C = OMPDependClause::Create(
20074 getASTContext(), StartLoc, LParenLoc, EndLoc,
20075 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
20076 TotalDepCount.getZExtValue());
20077 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
20078 DSAStack->isParentOrderedRegion())
20079 DSAStack->addDoacrossDependClause(C, OpsOffs);
20080 return C;
20081}
20082
20085 SourceLocation LParenLoc, SourceLocation ModifierLoc,
20086 SourceLocation EndLoc) {
20087 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
20088 "Unexpected device modifier in OpenMP < 50.");
20089
20090 bool ErrorFound = false;
20091 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
20092 std::string Values =
20093 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
20094 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
20095 << Values << getOpenMPClauseName(OMPC_device);
20096 ErrorFound = true;
20097 }
20098
20099 Expr *ValExpr = Device;
20100 Stmt *HelperValStmt = nullptr;
20101
20102 // OpenMP [2.9.1, Restrictions]
20103 // The device expression must evaluate to a non-negative integer value.
20104 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
20105 /*StrictlyPositive=*/false) ||
20106 ErrorFound;
20107 if (ErrorFound)
20108 return nullptr;
20109
20110 // OpenMP 5.0 [2.12.5, Restrictions]
20111 // In case of ancestor device-modifier, a requires directive with
20112 // the reverse_offload clause must be specified.
20113 if (Modifier == OMPC_DEVICE_ancestor) {
20114 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
20116 StartLoc,
20117 diag::err_omp_device_ancestor_without_requires_reverse_offload);
20118 ErrorFound = true;
20119 }
20120 }
20121
20122 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20123 OpenMPDirectiveKind CaptureRegion =
20124 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
20125 if (CaptureRegion != OMPD_unknown &&
20127 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20128 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20129 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20130 HelperValStmt = buildPreInits(getASTContext(), Captures);
20131 }
20132
20133 return new (getASTContext())
20134 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
20135 LParenLoc, ModifierLoc, EndLoc);
20136}
20137
20139 DSAStackTy *Stack, QualType QTy,
20140 bool FullCheck = true) {
20141 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
20142 return false;
20143 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
20144 !QTy.isTriviallyCopyableType(SemaRef.Context))
20145 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
20146 return true;
20147}
20148
20149/// Return true if it can be proven that the provided array expression
20150/// (array section or array subscript) does NOT specify the whole size of the
20151/// array whose base type is \a BaseQTy.
20153 const Expr *E,
20154 QualType BaseQTy) {
20155 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20156
20157 // If this is an array subscript, it refers to the whole size if the size of
20158 // the dimension is constant and equals 1. Also, an array section assumes the
20159 // format of an array subscript if no colon is used.
20160 if (isa<ArraySubscriptExpr>(E) ||
20161 (OASE && OASE->getColonLocFirst().isInvalid())) {
20162 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20163 return ATy->getSExtSize() != 1;
20164 // Size can't be evaluated statically.
20165 return false;
20166 }
20167
20168 assert(OASE && "Expecting array section if not an array subscript.");
20169 const Expr *LowerBound = OASE->getLowerBound();
20170 const Expr *Length = OASE->getLength();
20171
20172 // If there is a lower bound that does not evaluates to zero, we are not
20173 // covering the whole dimension.
20174 if (LowerBound) {
20176 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
20177 return false; // Can't get the integer value as a constant.
20178
20179 llvm::APSInt ConstLowerBound = Result.Val.getInt();
20180 if (ConstLowerBound.getSExtValue())
20181 return true;
20182 }
20183
20184 // If we don't have a length we covering the whole dimension.
20185 if (!Length)
20186 return false;
20187
20188 // If the base is a pointer, we don't have a way to get the size of the
20189 // pointee.
20190 if (BaseQTy->isPointerType())
20191 return false;
20192
20193 // We can only check if the length is the same as the size of the dimension
20194 // if we have a constant array.
20195 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
20196 if (!CATy)
20197 return false;
20198
20200 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20201 return false; // Can't get the integer value as a constant.
20202
20203 llvm::APSInt ConstLength = Result.Val.getInt();
20204 return CATy->getSExtSize() != ConstLength.getSExtValue();
20205}
20206
20207// Return true if it can be proven that the provided array expression (array
20208// section or array subscript) does NOT specify a single element of the array
20209// whose base type is \a BaseQTy.
20211 const Expr *E,
20212 QualType BaseQTy) {
20213 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
20214
20215 // An array subscript always refer to a single element. Also, an array section
20216 // assumes the format of an array subscript if no colon is used.
20217 if (isa<ArraySubscriptExpr>(E) ||
20218 (OASE && OASE->getColonLocFirst().isInvalid()))
20219 return false;
20220
20221 assert(OASE && "Expecting array section if not an array subscript.");
20222 const Expr *Length = OASE->getLength();
20223
20224 // If we don't have a length we have to check if the array has unitary size
20225 // for this dimension. Also, we should always expect a length if the base type
20226 // is pointer.
20227 if (!Length) {
20228 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
20229 return ATy->getSExtSize() != 1;
20230 // We cannot assume anything.
20231 return false;
20232 }
20233
20234 // Check if the length evaluates to 1.
20236 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
20237 return false; // Can't get the integer value as a constant.
20238
20239 llvm::APSInt ConstLength = Result.Val.getInt();
20240 return ConstLength.getSExtValue() != 1;
20241}
20242
20243// The base of elements of list in a map clause have to be either:
20244// - a reference to variable or field.
20245// - a member expression.
20246// - an array expression.
20247//
20248// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
20249// reference to 'r'.
20250//
20251// If we have:
20252//
20253// struct SS {
20254// Bla S;
20255// foo() {
20256// #pragma omp target map (S.Arr[:12]);
20257// }
20258// }
20259//
20260// We want to retrieve the member expression 'this->S';
20261
20262// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
20263// If a list item is an array section, it must specify contiguous storage.
20264//
20265// For this restriction it is sufficient that we make sure only references
20266// to variables or fields and array expressions, and that no array sections
20267// exist except in the rightmost expression (unless they cover the whole
20268// dimension of the array). E.g. these would be invalid:
20269//
20270// r.ArrS[3:5].Arr[6:7]
20271//
20272// r.ArrS[3:5].x
20273//
20274// but these would be valid:
20275// r.ArrS[3].Arr[6:7]
20276//
20277// r.ArrS[3].x
20278namespace {
20279class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
20280 Sema &SemaRef;
20281 OpenMPClauseKind CKind = OMPC_unknown;
20282 OpenMPDirectiveKind DKind = OMPD_unknown;
20284 bool IsNonContiguous = false;
20285 bool NoDiagnose = false;
20286 const Expr *RelevantExpr = nullptr;
20287 bool AllowUnitySizeArraySection = true;
20288 bool AllowWholeSizeArraySection = true;
20289 bool AllowAnotherPtr = true;
20290 SourceLocation ELoc;
20291 SourceRange ERange;
20292
20293 void emitErrorMsg() {
20294 // If nothing else worked, this is not a valid map clause expression.
20295 if (SemaRef.getLangOpts().OpenMP < 50) {
20296 SemaRef.Diag(ELoc,
20297 diag::err_omp_expected_named_var_member_or_array_expression)
20298 << ERange;
20299 } else {
20300 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
20301 << getOpenMPClauseName(CKind) << ERange;
20302 }
20303 }
20304
20305public:
20306 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
20307 if (!isa<VarDecl>(DRE->getDecl())) {
20308 emitErrorMsg();
20309 return false;
20310 }
20311 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20312 RelevantExpr = DRE;
20313 // Record the component.
20314 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
20315 return true;
20316 }
20317
20318 bool VisitMemberExpr(MemberExpr *ME) {
20319 Expr *E = ME;
20320 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
20321
20322 if (isa<CXXThisExpr>(BaseE)) {
20323 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20324 // We found a base expression: this->Val.
20325 RelevantExpr = ME;
20326 } else {
20327 E = BaseE;
20328 }
20329
20330 if (!isa<FieldDecl>(ME->getMemberDecl())) {
20331 if (!NoDiagnose) {
20332 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
20333 << ME->getSourceRange();
20334 return false;
20335 }
20336 if (RelevantExpr)
20337 return false;
20338 return Visit(E);
20339 }
20340
20341 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
20342
20343 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
20344 // A bit-field cannot appear in a map clause.
20345 //
20346 if (FD->isBitField()) {
20347 if (!NoDiagnose) {
20348 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
20349 << ME->getSourceRange() << getOpenMPClauseName(CKind);
20350 return false;
20351 }
20352 if (RelevantExpr)
20353 return false;
20354 return Visit(E);
20355 }
20356
20357 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20358 // If the type of a list item is a reference to a type T then the type
20359 // will be considered to be T for all purposes of this clause.
20360 QualType CurType = BaseE->getType().getNonReferenceType();
20361
20362 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
20363 // A list item cannot be a variable that is a member of a structure with
20364 // a union type.
20365 //
20366 if (CurType->isUnionType()) {
20367 if (!NoDiagnose) {
20368 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
20369 << ME->getSourceRange();
20370 return false;
20371 }
20372 return RelevantExpr || Visit(E);
20373 }
20374
20375 // If we got a member expression, we should not expect any array section
20376 // before that:
20377 //
20378 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
20379 // If a list item is an element of a structure, only the rightmost symbol
20380 // of the variable reference can be an array section.
20381 //
20382 AllowUnitySizeArraySection = false;
20383 AllowWholeSizeArraySection = false;
20384
20385 // Record the component.
20386 Components.emplace_back(ME, FD, IsNonContiguous);
20387 return RelevantExpr || Visit(E);
20388 }
20389
20390 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
20391 Expr *E = AE->getBase()->IgnoreParenImpCasts();
20392
20393 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
20394 if (!NoDiagnose) {
20395 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20396 << 0 << AE->getSourceRange();
20397 return false;
20398 }
20399 return RelevantExpr || Visit(E);
20400 }
20401
20402 // If we got an array subscript that express the whole dimension we
20403 // can have any array expressions before. If it only expressing part of
20404 // the dimension, we can only have unitary-size array expressions.
20406 AllowWholeSizeArraySection = false;
20407
20408 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
20409 Expr::EvalResult Result;
20410 if (!AE->getIdx()->isValueDependent() &&
20411 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
20412 !Result.Val.getInt().isZero()) {
20413 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20414 diag::err_omp_invalid_map_this_expr);
20415 SemaRef.Diag(AE->getIdx()->getExprLoc(),
20416 diag::note_omp_invalid_subscript_on_this_ptr_map);
20417 }
20418 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20419 RelevantExpr = TE;
20420 }
20421
20422 // Record the component - we don't have any declaration associated.
20423 Components.emplace_back(AE, nullptr, IsNonContiguous);
20424
20425 return RelevantExpr || Visit(E);
20426 }
20427
20428 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
20429 // After OMP 5.0 Array section in reduction clause will be implicitly
20430 // mapped
20431 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
20432 "Array sections cannot be implicitly mapped.");
20433 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20434 QualType CurType =
20436
20437 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20438 // If the type of a list item is a reference to a type T then the type
20439 // will be considered to be T for all purposes of this clause.
20440 if (CurType->isReferenceType())
20441 CurType = CurType->getPointeeType();
20442
20443 bool IsPointer = CurType->isAnyPointerType();
20444
20445 if (!IsPointer && !CurType->isArrayType()) {
20446 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
20447 << 0 << OASE->getSourceRange();
20448 return false;
20449 }
20450
20451 bool NotWhole =
20452 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
20453 bool NotUnity =
20454 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
20455
20456 if (AllowWholeSizeArraySection) {
20457 // Any array section is currently allowed. Allowing a whole size array
20458 // section implies allowing a unity array section as well.
20459 //
20460 // If this array section refers to the whole dimension we can still
20461 // accept other array sections before this one, except if the base is a
20462 // pointer. Otherwise, only unitary sections are accepted.
20463 if (NotWhole || IsPointer)
20464 AllowWholeSizeArraySection = false;
20465 } else if (DKind == OMPD_target_update &&
20466 SemaRef.getLangOpts().OpenMP >= 50) {
20467 if (IsPointer && !AllowAnotherPtr)
20468 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
20469 << /*array of unknown bound */ 1;
20470 else
20471 IsNonContiguous = true;
20472 } else if (AllowUnitySizeArraySection && NotUnity) {
20473 // A unity or whole array section is not allowed and that is not
20474 // compatible with the properties of the current array section.
20475 if (NoDiagnose)
20476 return false;
20477 SemaRef.Diag(ELoc,
20478 diag::err_array_section_does_not_specify_contiguous_storage)
20479 << OASE->getSourceRange();
20480 return false;
20481 }
20482
20483 if (IsPointer)
20484 AllowAnotherPtr = false;
20485
20486 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
20487 Expr::EvalResult ResultR;
20488 Expr::EvalResult ResultL;
20489 if (!OASE->getLength()->isValueDependent() &&
20490 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
20491 !ResultR.Val.getInt().isOne()) {
20492 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20493 diag::err_omp_invalid_map_this_expr);
20494 SemaRef.Diag(OASE->getLength()->getExprLoc(),
20495 diag::note_omp_invalid_length_on_this_ptr_mapping);
20496 }
20497 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
20498 OASE->getLowerBound()->EvaluateAsInt(ResultL,
20499 SemaRef.getASTContext()) &&
20500 !ResultL.Val.getInt().isZero()) {
20501 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20502 diag::err_omp_invalid_map_this_expr);
20503 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
20504 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
20505 }
20506 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20507 RelevantExpr = TE;
20508 }
20509
20510 // Record the component - we don't have any declaration associated.
20511 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
20512 return RelevantExpr || Visit(E);
20513 }
20514 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
20515 Expr *Base = E->getBase();
20516
20517 // Record the component - we don't have any declaration associated.
20518 Components.emplace_back(E, nullptr, IsNonContiguous);
20519
20520 return Visit(Base->IgnoreParenImpCasts());
20521 }
20522
20523 bool VisitUnaryOperator(UnaryOperator *UO) {
20524 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
20525 UO->getOpcode() != UO_Deref) {
20526 emitErrorMsg();
20527 return false;
20528 }
20529 if (!RelevantExpr) {
20530 // Record the component if haven't found base decl.
20531 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
20532 }
20533 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
20534 }
20535 bool VisitBinaryOperator(BinaryOperator *BO) {
20536 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
20537 emitErrorMsg();
20538 return false;
20539 }
20540
20541 // Pointer arithmetic is the only thing we expect to happen here so after we
20542 // make sure the binary operator is a pointer type, the only thing we need
20543 // to do is to visit the subtree that has the same type as root (so that we
20544 // know the other subtree is just an offset)
20545 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
20546 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
20547 Components.emplace_back(BO, nullptr, false);
20548 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
20549 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
20550 "Either LHS or RHS have base decl inside");
20551 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
20552 return RelevantExpr || Visit(LE);
20553 return RelevantExpr || Visit(RE);
20554 }
20555 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
20556 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20557 RelevantExpr = CTE;
20558 Components.emplace_back(CTE, nullptr, IsNonContiguous);
20559 return true;
20560 }
20561 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
20562 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
20563 Components.emplace_back(COCE, nullptr, IsNonContiguous);
20564 return true;
20565 }
20566 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
20567 Expr *Source = E->getSourceExpr();
20568 if (!Source) {
20569 emitErrorMsg();
20570 return false;
20571 }
20572 return Visit(Source);
20573 }
20574 bool VisitStmt(Stmt *) {
20575 emitErrorMsg();
20576 return false;
20577 }
20578 const Expr *getFoundBase() const { return RelevantExpr; }
20579 explicit MapBaseChecker(
20580 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
20582 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
20583 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
20584 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
20585};
20586} // namespace
20587
20588/// Return the expression of the base of the mappable expression or null if it
20589/// cannot be determined and do all the necessary checks to see if the
20590/// expression is valid as a standalone mappable expression. In the process,
20591/// record all the components of the expression.
20593 Sema &SemaRef, Expr *E,
20595 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
20596 SourceLocation ELoc = E->getExprLoc();
20597 SourceRange ERange = E->getSourceRange();
20598 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
20599 ERange);
20600 if (Checker.Visit(E->IgnoreParens())) {
20601 // Check if the highest dimension array section has length specified
20602 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
20603 (CKind == OMPC_to || CKind == OMPC_from)) {
20604 auto CI = CurComponents.rbegin();
20605 auto CE = CurComponents.rend();
20606 for (; CI != CE; ++CI) {
20607 const auto *OASE =
20608 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
20609 if (!OASE)
20610 continue;
20611 if (OASE && OASE->getLength())
20612 break;
20613 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
20614 << ERange;
20615 }
20616 }
20617 return Checker.getFoundBase();
20618 }
20619 return nullptr;
20620}
20621
20622// Return true if expression E associated with value VD has conflicts with other
20623// map information.
20625 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
20626 bool CurrentRegionOnly,
20628 OpenMPClauseKind CKind) {
20629 assert(VD && E);
20630 SourceLocation ELoc = E->getExprLoc();
20631 SourceRange ERange = E->getSourceRange();
20632
20633 // In order to easily check the conflicts we need to match each component of
20634 // the expression under test with the components of the expressions that are
20635 // already in the stack.
20636
20637 assert(!CurComponents.empty() && "Map clause expression with no components!");
20638 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
20639 "Map clause expression with unexpected base!");
20640
20641 // Variables to help detecting enclosing problems in data environment nests.
20642 bool IsEnclosedByDataEnvironmentExpr = false;
20643 const Expr *EnclosingExpr = nullptr;
20644
20645 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
20646 VD, CurrentRegionOnly,
20647 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
20648 ERange, CKind, &EnclosingExpr,
20650 StackComponents,
20651 OpenMPClauseKind Kind) {
20652 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
20653 return false;
20654 assert(!StackComponents.empty() &&
20655 "Map clause expression with no components!");
20656 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
20657 "Map clause expression with unexpected base!");
20658 (void)VD;
20659
20660 // The whole expression in the stack.
20661 const Expr *RE = StackComponents.front().getAssociatedExpression();
20662
20663 // Expressions must start from the same base. Here we detect at which
20664 // point both expressions diverge from each other and see if we can
20665 // detect if the memory referred to both expressions is contiguous and
20666 // do not overlap.
20667 auto CI = CurComponents.rbegin();
20668 auto CE = CurComponents.rend();
20669 auto SI = StackComponents.rbegin();
20670 auto SE = StackComponents.rend();
20671 for (; CI != CE && SI != SE; ++CI, ++SI) {
20672
20673 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
20674 // At most one list item can be an array item derived from a given
20675 // variable in map clauses of the same construct.
20676 if (CurrentRegionOnly &&
20677 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
20678 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
20679 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
20680 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
20681 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
20682 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
20683 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
20684 diag::err_omp_multiple_array_items_in_map_clause)
20685 << CI->getAssociatedExpression()->getSourceRange();
20686 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
20687 diag::note_used_here)
20688 << SI->getAssociatedExpression()->getSourceRange();
20689 return true;
20690 }
20691
20692 // Do both expressions have the same kind?
20693 if (CI->getAssociatedExpression()->getStmtClass() !=
20694 SI->getAssociatedExpression()->getStmtClass())
20695 break;
20696
20697 // Are we dealing with different variables/fields?
20698 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
20699 break;
20700 }
20701 // Check if the extra components of the expressions in the enclosing
20702 // data environment are redundant for the current base declaration.
20703 // If they are, the maps completely overlap, which is legal.
20704 for (; SI != SE; ++SI) {
20705 QualType Type;
20706 if (const auto *ASE =
20707 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
20708 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
20709 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
20710 SI->getAssociatedExpression())) {
20711 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
20712 Type = ArraySectionExpr::getBaseOriginalType(E).getCanonicalType();
20713 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
20714 SI->getAssociatedExpression())) {
20715 Type = OASE->getBase()->getType()->getPointeeType();
20716 }
20717 if (Type.isNull() || Type->isAnyPointerType() ||
20719 SemaRef, SI->getAssociatedExpression(), Type))
20720 break;
20721 }
20722
20723 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20724 // List items of map clauses in the same construct must not share
20725 // original storage.
20726 //
20727 // If the expressions are exactly the same or one is a subset of the
20728 // other, it means they are sharing storage.
20729 if (CI == CE && SI == SE) {
20730 if (CurrentRegionOnly) {
20731 if (CKind == OMPC_map) {
20732 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20733 } else {
20734 assert(CKind == OMPC_to || CKind == OMPC_from);
20735 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20736 << ERange;
20737 }
20738 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20739 << RE->getSourceRange();
20740 return true;
20741 }
20742 // If we find the same expression in the enclosing data environment,
20743 // that is legal.
20744 IsEnclosedByDataEnvironmentExpr = true;
20745 return false;
20746 }
20747
20748 QualType DerivedType =
20749 std::prev(CI)->getAssociatedDeclaration()->getType();
20750 SourceLocation DerivedLoc =
20751 std::prev(CI)->getAssociatedExpression()->getExprLoc();
20752
20753 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
20754 // If the type of a list item is a reference to a type T then the type
20755 // will be considered to be T for all purposes of this clause.
20756 DerivedType = DerivedType.getNonReferenceType();
20757
20758 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
20759 // A variable for which the type is pointer and an array section
20760 // derived from that variable must not appear as list items of map
20761 // clauses of the same construct.
20762 //
20763 // Also, cover one of the cases in:
20764 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20765 // If any part of the original storage of a list item has corresponding
20766 // storage in the device data environment, all of the original storage
20767 // must have corresponding storage in the device data environment.
20768 //
20769 if (DerivedType->isAnyPointerType()) {
20770 if (CI == CE || SI == SE) {
20771 SemaRef.Diag(
20772 DerivedLoc,
20773 diag::err_omp_pointer_mapped_along_with_derived_section)
20774 << DerivedLoc;
20775 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20776 << RE->getSourceRange();
20777 return true;
20778 }
20779 if (CI->getAssociatedExpression()->getStmtClass() !=
20780 SI->getAssociatedExpression()->getStmtClass() ||
20781 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
20782 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
20783 assert(CI != CE && SI != SE);
20784 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
20785 << DerivedLoc;
20786 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20787 << RE->getSourceRange();
20788 return true;
20789 }
20790 }
20791
20792 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
20793 // List items of map clauses in the same construct must not share
20794 // original storage.
20795 //
20796 // An expression is a subset of the other.
20797 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
20798 if (CKind == OMPC_map) {
20799 if (CI != CE || SI != SE) {
20800 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
20801 // a pointer.
20802 auto Begin =
20803 CI != CE ? CurComponents.begin() : StackComponents.begin();
20804 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
20805 auto It = Begin;
20806 while (It != End && !It->getAssociatedDeclaration())
20807 std::advance(It, 1);
20808 assert(It != End &&
20809 "Expected at least one component with the declaration.");
20810 if (It != Begin && It->getAssociatedDeclaration()
20811 ->getType()
20812 .getCanonicalType()
20813 ->isAnyPointerType()) {
20814 IsEnclosedByDataEnvironmentExpr = false;
20815 EnclosingExpr = nullptr;
20816 return false;
20817 }
20818 }
20819 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
20820 } else {
20821 assert(CKind == OMPC_to || CKind == OMPC_from);
20822 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
20823 << ERange;
20824 }
20825 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
20826 << RE->getSourceRange();
20827 return true;
20828 }
20829
20830 // The current expression uses the same base as other expression in the
20831 // data environment but does not contain it completely.
20832 if (!CurrentRegionOnly && SI != SE)
20833 EnclosingExpr = RE;
20834
20835 // The current expression is a subset of the expression in the data
20836 // environment.
20837 IsEnclosedByDataEnvironmentExpr |=
20838 (!CurrentRegionOnly && CI != CE && SI == SE);
20839
20840 return false;
20841 });
20842
20843 if (CurrentRegionOnly)
20844 return FoundError;
20845
20846 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
20847 // If any part of the original storage of a list item has corresponding
20848 // storage in the device data environment, all of the original storage must
20849 // have corresponding storage in the device data environment.
20850 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
20851 // If a list item is an element of a structure, and a different element of
20852 // the structure has a corresponding list item in the device data environment
20853 // prior to a task encountering the construct associated with the map clause,
20854 // then the list item must also have a corresponding list item in the device
20855 // data environment prior to the task encountering the construct.
20856 //
20857 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
20858 SemaRef.Diag(ELoc,
20859 diag::err_omp_original_storage_is_shared_and_does_not_contain)
20860 << ERange;
20861 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
20862 << EnclosingExpr->getSourceRange();
20863 return true;
20864 }
20865
20866 return FoundError;
20867}
20868
20869// Look up the user-defined mapper given the mapper name and mapped type, and
20870// build a reference to it.
20872 CXXScopeSpec &MapperIdScopeSpec,
20873 const DeclarationNameInfo &MapperId,
20874 QualType Type,
20875 Expr *UnresolvedMapper) {
20876 if (MapperIdScopeSpec.isInvalid())
20877 return ExprError();
20878 // Get the actual type for the array type.
20879 if (Type->isArrayType()) {
20880 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
20882 }
20883 // Find all user-defined mappers with the given MapperId.
20884 SmallVector<UnresolvedSet<8>, 4> Lookups;
20885 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
20886 Lookup.suppressDiagnostics();
20887 if (S) {
20888 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
20889 /*ObjectType=*/QualType())) {
20890 NamedDecl *D = Lookup.getRepresentativeDecl();
20891 while (S && !S->isDeclScope(D))
20892 S = S->getParent();
20893 if (S)
20894 S = S->getParent();
20895 Lookups.emplace_back();
20896 Lookups.back().append(Lookup.begin(), Lookup.end());
20897 Lookup.clear();
20898 }
20899 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
20900 // Extract the user-defined mappers with the given MapperId.
20901 Lookups.push_back(UnresolvedSet<8>());
20902 for (NamedDecl *D : ULE->decls()) {
20903 auto *DMD = cast<OMPDeclareMapperDecl>(D);
20904 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
20905 Lookups.back().addDecl(DMD);
20906 }
20907 }
20908 // Defer the lookup for dependent types. The results will be passed through
20909 // UnresolvedMapper on instantiation.
20910 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
20913 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
20914 return !D->isInvalidDecl() &&
20915 (D->getType()->isDependentType() ||
20916 D->getType()->isInstantiationDependentType() ||
20917 D->getType()->containsUnexpandedParameterPack());
20918 })) {
20919 UnresolvedSet<8> URS;
20920 for (const UnresolvedSet<8> &Set : Lookups) {
20921 if (Set.empty())
20922 continue;
20923 URS.append(Set.begin(), Set.end());
20924 }
20926 SemaRef.Context, /*NamingClass=*/nullptr,
20927 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
20928 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
20929 /*KnownInstantiationDependent=*/false);
20930 }
20931 SourceLocation Loc = MapperId.getLoc();
20932 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
20933 // The type must be of struct, union or class type in C and C++
20935 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
20936 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
20937 return ExprError();
20938 }
20939 // Perform argument dependent lookup.
20940 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
20941 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
20942 // Return the first user-defined mapper with the desired type.
20943 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20944 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
20945 if (!D->isInvalidDecl() &&
20946 SemaRef.Context.hasSameType(D->getType(), Type))
20947 return D;
20948 return nullptr;
20949 }))
20950 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
20951 // Find the first user-defined mapper with a type derived from the desired
20952 // type.
20953 if (auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
20954 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
20955 if (!D->isInvalidDecl() &&
20956 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
20957 !Type.isMoreQualifiedThan(D->getType()))
20958 return D;
20959 return nullptr;
20960 })) {
20961 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
20962 /*DetectVirtual=*/false);
20963 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
20964 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
20965 VD->getType().getUnqualifiedType()))) {
20966 if (SemaRef.CheckBaseClassAccess(
20967 Loc, VD->getType(), Type, Paths.front(),
20968 /*DiagID=*/0) != Sema::AR_inaccessible) {
20969 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
20970 }
20971 }
20972 }
20973 }
20974 // Report error if a mapper is specified, but cannot be found.
20975 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
20976 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
20977 << Type << MapperId.getName();
20978 return ExprError();
20979 }
20980 return ExprEmpty();
20981}
20982
20983namespace {
20984// Utility struct that gathers all the related lists associated with a mappable
20985// expression.
20986struct MappableVarListInfo {
20987 // The list of expressions.
20988 ArrayRef<Expr *> VarList;
20989 // The list of processed expressions.
20990 SmallVector<Expr *, 16> ProcessedVarList;
20991 // The mappble components for each expression.
20993 // The base declaration of the variable.
20994 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
20995 // The reference to the user-defined mapper associated with every expression.
20996 SmallVector<Expr *, 16> UDMapperList;
20997
20998 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
20999 // We have a list of components and base declarations for each entry in the
21000 // variable list.
21001 VarComponents.reserve(VarList.size());
21002 VarBaseDeclarations.reserve(VarList.size());
21003 }
21004};
21005} // namespace
21006
21008 DSAStackTy *Stack,
21010
21011 const RecordDecl *RD = BaseType->getAsRecordDecl();
21013 DeclarationNameInfo ImplicitName;
21014 // Dummy variable _s for Mapper.
21015 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
21016 DeclRefExpr *MapperVarRef =
21017 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
21018
21019 // Create implicit map clause for mapper.
21021 for (auto *FD : RD->fields()) {
21022 Expr *BE = S.BuildMemberExpr(
21023 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
21026 /*HadMultipleCandidates=*/false,
21028 FD->getType(), VK_LValue, OK_Ordinary);
21029 SExprs.push_back(BE);
21030 }
21031 CXXScopeSpec MapperIdScopeSpec;
21032 DeclarationNameInfo MapperId;
21033 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
21034
21035 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
21036 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
21037 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
21038 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
21039 OMPVarListLocTy());
21040 Maps.push_back(MapClause);
21041 return MapperVarRef;
21042}
21043
21045 DSAStackTy *Stack) {
21046
21047 // Build impilicit map for mapper
21049 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
21050
21051 const RecordDecl *RD = BaseType->getAsRecordDecl();
21052 // AST context is RD's ParentASTContext().
21053 ASTContext &Ctx = RD->getParentASTContext();
21054 // DeclContext is RD's DeclContext.
21055 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
21056
21057 // Create implicit default mapper for "RD".
21058 DeclarationName MapperId;
21059 auto &DeclNames = Ctx.DeclarationNames;
21060 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
21061 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
21062 BaseType, MapperId, Maps, nullptr);
21063 Scope *Scope = S.getScopeForContext(DCT);
21064 if (Scope)
21065 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
21066 DCT->addDecl(DMD);
21067 DMD->setAccess(clang::AS_none);
21068 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21069 VD->setDeclContext(DMD);
21070 VD->setLexicalDeclContext(DMD);
21071 DMD->addDecl(VD);
21072 DMD->setMapperVarRef(MapperVarRef);
21073 FieldDecl *FD = *RD->field_begin();
21074 // create mapper refence.
21076 DMD, false, SourceLocation(), BaseType, VK_LValue);
21077}
21078
21079// Look up the user-defined mapper given the mapper name and mapper type,
21080// return true if found one.
21081static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
21082 CXXScopeSpec &MapperIdScopeSpec,
21083 const DeclarationNameInfo &MapperId,
21084 QualType Type) {
21085 // Find all user-defined mappers with the given MapperId.
21086 SmallVector<UnresolvedSet<8>, 4> Lookups;
21087 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
21088 Lookup.suppressDiagnostics();
21089 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
21090 /*ObjectType=*/QualType())) {
21091 NamedDecl *D = Lookup.getRepresentativeDecl();
21092 while (S && !S->isDeclScope(D))
21093 S = S->getParent();
21094 if (S)
21095 S = S->getParent();
21096 Lookups.emplace_back();
21097 Lookups.back().append(Lookup.begin(), Lookup.end());
21098 Lookup.clear();
21099 }
21100 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
21103 filterLookupForUDReductionAndMapper<bool>(Lookups, [](ValueDecl *D) {
21104 return !D->isInvalidDecl() &&
21105 (D->getType()->isDependentType() ||
21106 D->getType()->isInstantiationDependentType() ||
21107 D->getType()->containsUnexpandedParameterPack());
21108 }))
21109 return false;
21110 // Perform argument dependent lookup.
21111 SourceLocation Loc = MapperId.getLoc();
21112 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
21113 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
21114 if (filterLookupForUDReductionAndMapper<ValueDecl *>(
21115 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
21116 if (!D->isInvalidDecl() &&
21117 SemaRef.Context.hasSameType(D->getType(), Type))
21118 return D;
21119 return nullptr;
21120 }))
21121 return true;
21122 // Find the first user-defined mapper with a type derived from the desired
21123 // type.
21124 auto *VD = filterLookupForUDReductionAndMapper<ValueDecl *>(
21125 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
21126 if (!D->isInvalidDecl() &&
21127 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
21128 !Type.isMoreQualifiedThan(D->getType()))
21129 return D;
21130 return nullptr;
21131 });
21132 if (!VD)
21133 return false;
21134 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
21135 /*DetectVirtual=*/false);
21136 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
21137 bool IsAmbiguous = !Paths.isAmbiguous(
21139 if (IsAmbiguous)
21140 return false;
21141 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
21142 /*DiagID=*/0) != Sema::AR_inaccessible)
21143 return true;
21144 }
21145 return false;
21146}
21147
21148static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
21149 QualType CanonType, const Expr *E) {
21150
21151 // DFS over data members in structures/classes.
21153 {CanonType, nullptr});
21154 llvm::DenseMap<const Type *, bool> Visited;
21155 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
21156 while (!Types.empty()) {
21157 auto [BaseType, CurFD] = Types.pop_back_val();
21158 while (ParentChain.back().second == 0)
21159 ParentChain.pop_back();
21160 --ParentChain.back().second;
21161 if (BaseType.isNull())
21162 continue;
21163 // Only structs/classes are allowed to have mappers.
21164 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
21165 if (!RD)
21166 continue;
21167 auto It = Visited.find(BaseType.getTypePtr());
21168 if (It == Visited.end()) {
21169 // Try to find the associated user-defined mapper.
21170 CXXScopeSpec MapperIdScopeSpec;
21171 DeclarationNameInfo DefaultMapperId;
21173 &S.Context.Idents.get("default")));
21174 DefaultMapperId.setLoc(E->getExprLoc());
21175 bool HasUDMapper =
21176 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
21177 DefaultMapperId, BaseType);
21178 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
21179 }
21180 // Found default mapper.
21181 if (It->second)
21182 return true;
21183 // Check for the "default" mapper for data members.
21184 bool FirstIter = true;
21185 for (FieldDecl *FD : RD->fields()) {
21186 if (!FD)
21187 continue;
21188 QualType FieldTy = FD->getType();
21189 if (FieldTy.isNull() ||
21190 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
21191 continue;
21192 if (FirstIter) {
21193 FirstIter = false;
21194 ParentChain.emplace_back(CurFD, 1);
21195 } else {
21196 ++ParentChain.back().second;
21197 }
21198 Types.emplace_back(FieldTy, FD);
21199 }
21200 }
21201 return false;
21202}
21203
21204// Check the validity of the provided variable list for the provided clause kind
21205// \a CKind. In the check process the valid expressions, mappable expression
21206// components, variables, and user-defined mappers are extracted and used to
21207// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
21208// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
21209// and \a MapperId are expected to be valid if the clause kind is 'map'.
21211 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
21212 MappableVarListInfo &MVLI, SourceLocation StartLoc,
21213 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
21214 ArrayRef<Expr *> UnresolvedMappers,
21216 ArrayRef<OpenMPMapModifierKind> Modifiers = std::nullopt,
21217 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
21218 // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
21219 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
21220 "Unexpected clause kind with mappable expressions!");
21221
21222 // If the identifier of user-defined mapper is not specified, it is "default".
21223 // We do not change the actual name in this clause to distinguish whether a
21224 // mapper is specified explicitly, i.e., it is not explicitly specified when
21225 // MapperId.getName() is empty.
21226 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
21227 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
21228 MapperId.setName(DeclNames.getIdentifier(
21229 &SemaRef.getASTContext().Idents.get("default")));
21230 MapperId.setLoc(StartLoc);
21231 }
21232
21233 // Iterators to find the current unresolved mapper expression.
21234 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
21235 bool UpdateUMIt = false;
21236 Expr *UnresolvedMapper = nullptr;
21237
21238 bool HasHoldModifier =
21239 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
21240
21241 // Keep track of the mappable components and base declarations in this clause.
21242 // Each entry in the list is going to have a list of components associated. We
21243 // record each set of the components so that we can build the clause later on.
21244 // In the end we should have the same amount of declarations and component
21245 // lists.
21246
21247 for (Expr *RE : MVLI.VarList) {
21248 assert(RE && "Null expr in omp to/from/map clause");
21249 SourceLocation ELoc = RE->getExprLoc();
21250
21251 // Find the current unresolved mapper expression.
21252 if (UpdateUMIt && UMIt != UMEnd) {
21253 UMIt++;
21254 assert(
21255 UMIt != UMEnd &&
21256 "Expect the size of UnresolvedMappers to match with that of VarList");
21257 }
21258 UpdateUMIt = true;
21259 if (UMIt != UMEnd)
21260 UnresolvedMapper = *UMIt;
21261
21262 const Expr *VE = RE->IgnoreParenLValueCasts();
21263
21264 if (VE->isValueDependent() || VE->isTypeDependent() ||
21267 // Try to find the associated user-defined mapper.
21269 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21270 VE->getType().getCanonicalType(), UnresolvedMapper);
21271 if (ER.isInvalid())
21272 continue;
21273 MVLI.UDMapperList.push_back(ER.get());
21274 // We can only analyze this information once the missing information is
21275 // resolved.
21276 MVLI.ProcessedVarList.push_back(RE);
21277 continue;
21278 }
21279
21280 Expr *SimpleExpr = RE->IgnoreParenCasts();
21281
21282 if (!RE->isLValue()) {
21283 if (SemaRef.getLangOpts().OpenMP < 50) {
21284 SemaRef.Diag(
21285 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
21286 << RE->getSourceRange();
21287 } else {
21288 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
21289 << getOpenMPClauseName(CKind) << RE->getSourceRange();
21290 }
21291 continue;
21292 }
21293
21295 ValueDecl *CurDeclaration = nullptr;
21296
21297 // Obtain the array or member expression bases if required. Also, fill the
21298 // components array with all the components identified in the process.
21299 const Expr *BE =
21300 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
21301 DSAS->getCurrentDirective(), NoDiagnose);
21302 if (!BE)
21303 continue;
21304
21305 assert(!CurComponents.empty() &&
21306 "Invalid mappable expression information.");
21307
21308 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
21309 // Add store "this" pointer to class in DSAStackTy for future checking
21310 DSAS->addMappedClassesQualTypes(TE->getType());
21311 // Try to find the associated user-defined mapper.
21313 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21314 VE->getType().getCanonicalType(), UnresolvedMapper);
21315 if (ER.isInvalid())
21316 continue;
21317 MVLI.UDMapperList.push_back(ER.get());
21318 // Skip restriction checking for variable or field declarations
21319 MVLI.ProcessedVarList.push_back(RE);
21320 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21321 MVLI.VarComponents.back().append(CurComponents.begin(),
21322 CurComponents.end());
21323 MVLI.VarBaseDeclarations.push_back(nullptr);
21324 continue;
21325 }
21326
21327 // For the following checks, we rely on the base declaration which is
21328 // expected to be associated with the last component. The declaration is
21329 // expected to be a variable or a field (if 'this' is being mapped).
21330 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
21331 assert(CurDeclaration && "Null decl on map clause.");
21332 assert(
21333 CurDeclaration->isCanonicalDecl() &&
21334 "Expecting components to have associated only canonical declarations.");
21335
21336 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
21337 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
21338
21339 assert((VD || FD) && "Only variables or fields are expected here!");
21340 (void)FD;
21341
21342 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
21343 // threadprivate variables cannot appear in a map clause.
21344 // OpenMP 4.5 [2.10.5, target update Construct]
21345 // threadprivate variables cannot appear in a from clause.
21346 if (VD && DSAS->isThreadPrivate(VD)) {
21347 if (NoDiagnose)
21348 continue;
21349 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21350 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
21351 << getOpenMPClauseName(CKind);
21352 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
21353 continue;
21354 }
21355
21356 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21357 // A list item cannot appear in both a map clause and a data-sharing
21358 // attribute clause on the same construct.
21359
21360 // Check conflicts with other map clause expressions. We check the conflicts
21361 // with the current construct separately from the enclosing data
21362 // environment, because the restrictions are different. We only have to
21363 // check conflicts across regions for the map clauses.
21364 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21365 /*CurrentRegionOnly=*/true, CurComponents, CKind))
21366 break;
21367 if (CKind == OMPC_map &&
21368 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
21369 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
21370 /*CurrentRegionOnly=*/false, CurComponents, CKind))
21371 break;
21372
21373 // OpenMP 4.5 [2.10.5, target update Construct]
21374 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
21375 // If the type of a list item is a reference to a type T then the type will
21376 // be considered to be T for all purposes of this clause.
21377 auto I = llvm::find_if(
21378 CurComponents,
21380 return MC.getAssociatedDeclaration();
21381 });
21382 assert(I != CurComponents.end() && "Null decl on map clause.");
21383 (void)I;
21384 QualType Type;
21385 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
21386 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
21387 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
21388 if (ASE) {
21389 Type = ASE->getType().getNonReferenceType();
21390 } else if (OASE) {
21391 QualType BaseType =
21393 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21394 Type = ATy->getElementType();
21395 else
21396 Type = BaseType->getPointeeType();
21397 Type = Type.getNonReferenceType();
21398 } else if (OAShE) {
21399 Type = OAShE->getBase()->getType()->getPointeeType();
21400 } else {
21401 Type = VE->getType();
21402 }
21403
21404 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
21405 // A list item in a to or from clause must have a mappable type.
21406 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
21407 // A list item must have a mappable type.
21408 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
21409 DSAS, Type, /*FullCheck=*/true))
21410 continue;
21411
21412 if (CKind == OMPC_map) {
21413 // target enter data
21414 // OpenMP [2.10.2, Restrictions, p. 99]
21415 // A map-type must be specified in all map clauses and must be either
21416 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
21417 // no map type is present.
21418 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
21419 if (DKind == OMPD_target_enter_data &&
21420 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
21421 SemaRef.getLangOpts().OpenMP >= 52)) {
21422 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21423 << (IsMapTypeImplicit ? 1 : 0)
21424 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21425 << getOpenMPDirectiveName(DKind);
21426 continue;
21427 }
21428
21429 // target exit_data
21430 // OpenMP [2.10.3, Restrictions, p. 102]
21431 // A map-type must be specified in all map clauses and must be either
21432 // from, release, or delete. Starting with OpenMP 5.2 the default map
21433 // type is `from` if no map type is present.
21434 if (DKind == OMPD_target_exit_data &&
21435 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
21436 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
21437 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21438 << (IsMapTypeImplicit ? 1 : 0)
21439 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21440 << getOpenMPDirectiveName(DKind);
21441 continue;
21442 }
21443
21444 // The 'ompx_hold' modifier is specifically intended to be used on a
21445 // 'target' or 'target data' directive to prevent data from being unmapped
21446 // during the associated statement. It is not permitted on a 'target
21447 // enter data' or 'target exit data' directive, which have no associated
21448 // statement.
21449 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
21450 HasHoldModifier) {
21451 SemaRef.Diag(StartLoc,
21452 diag::err_omp_invalid_map_type_modifier_for_directive)
21454 OMPC_MAP_MODIFIER_ompx_hold)
21455 << getOpenMPDirectiveName(DKind);
21456 continue;
21457 }
21458
21459 // target, target data
21460 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
21461 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
21462 // A map-type in a map clause must be to, from, tofrom or alloc
21463 if ((DKind == OMPD_target_data ||
21465 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
21466 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
21467 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
21468 << (IsMapTypeImplicit ? 1 : 0)
21469 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
21470 << getOpenMPDirectiveName(DKind);
21471 continue;
21472 }
21473
21474 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21475 // A list item cannot appear in both a map clause and a data-sharing
21476 // attribute clause on the same construct
21477 //
21478 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21479 // A list item cannot appear in both a map clause and a data-sharing
21480 // attribute clause on the same construct unless the construct is a
21481 // combined construct.
21482 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
21484 DKind == OMPD_target)) {
21485 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
21486 if (isOpenMPPrivate(DVar.CKind)) {
21487 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21488 << getOpenMPClauseName(DVar.CKind)
21489 << getOpenMPClauseName(OMPC_map)
21490 << getOpenMPDirectiveName(DSAS->getCurrentDirective());
21491 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
21492 continue;
21493 }
21494 }
21495 }
21496
21497 // Try to find the associated user-defined mapper.
21499 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
21500 Type.getCanonicalType(), UnresolvedMapper);
21501 if (ER.isInvalid())
21502 continue;
21503 if (!ER.get() && isa<ArraySectionExpr>(VE)) {
21504 // Create implicit mapper as needed.
21505 QualType BaseType = VE->getType().getCanonicalType();
21506 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
21507 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
21509 QualType ElemType;
21510 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
21511 ElemType = ATy->getElementType();
21512 else
21513 ElemType = BType->getPointeeType();
21514 BaseType = ElemType.getCanonicalType();
21515 }
21516 if (BaseType->getAsRecordDecl() &&
21517 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
21518 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
21519 }
21520 }
21521 MVLI.UDMapperList.push_back(ER.get());
21522
21523 // Save the current expression.
21524 MVLI.ProcessedVarList.push_back(RE);
21525
21526 // Store the components in the stack so that they can be used to check
21527 // against other clauses later on.
21528 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
21529 /*WhereFoundClauseKind=*/OMPC_map);
21530
21531 // Save the components and declaration to create the clause. For purposes of
21532 // the clause creation, any component list that has base 'this' uses
21533 // null as base declaration.
21534 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
21535 MVLI.VarComponents.back().append(CurComponents.begin(),
21536 CurComponents.end());
21537 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
21538 : CurDeclaration);
21539 }
21540}
21541
21543 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
21544 ArrayRef<SourceLocation> MapTypeModifiersLoc,
21545 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
21546 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
21547 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
21548 const OMPVarListLocTy &Locs, bool NoDiagnose,
21549 ArrayRef<Expr *> UnresolvedMappers) {
21550 OpenMPMapModifierKind Modifiers[] = {
21555
21556 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
21557 BuiltinType::OMPIterator))
21558 Diag(IteratorModifier->getExprLoc(),
21559 diag::err_omp_map_modifier_not_iterator);
21560
21561 // Process map-type-modifiers, flag errors for duplicate modifiers.
21562 unsigned Count = 0;
21563 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
21564 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
21565 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
21566 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
21567 continue;
21568 }
21569 assert(Count < NumberOfOMPMapClauseModifiers &&
21570 "Modifiers exceed the allowed number of map type modifiers");
21571 Modifiers[Count] = MapTypeModifiers[I];
21572 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
21573 ++Count;
21574 }
21575
21576 MappableVarListInfo MVLI(VarList);
21578 MapperIdScopeSpec, MapperId, UnresolvedMappers,
21579 MapType, Modifiers, IsMapTypeImplicit,
21580 NoDiagnose);
21581
21582 // We need to produce a map clause even if we don't have variables so that
21583 // other diagnostics related with non-existing map clauses are accurate.
21584 return OMPMapClause::Create(
21585 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
21586 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
21587 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
21588 MapperId, MapType, IsMapTypeImplicit, MapLoc);
21589}
21590
21593 assert(ParsedType.isUsable());
21594
21595 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
21596 if (ReductionType.isNull())
21597 return QualType();
21598
21599 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
21600 // A type name in a declare reduction directive cannot be a function type, an
21601 // array type, a reference type, or a type qualified with const, volatile or
21602 // restrict.
21603 if (ReductionType.hasQualifiers()) {
21604 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
21605 return QualType();
21606 }
21607
21608 if (ReductionType->isFunctionType()) {
21609 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
21610 return QualType();
21611 }
21612 if (ReductionType->isReferenceType()) {
21613 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
21614 return QualType();
21615 }
21616 if (ReductionType->isArrayType()) {
21617 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
21618 return QualType();
21619 }
21620 return ReductionType;
21621}
21622
21625 Scope *S, DeclContext *DC, DeclarationName Name,
21626 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
21627 AccessSpecifier AS, Decl *PrevDeclInScope) {
21629 Decls.reserve(ReductionTypes.size());
21630
21631 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21634 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
21635 // A reduction-identifier may not be re-declared in the current scope for the
21636 // same type or for a type that is compatible according to the base language
21637 // rules.
21638 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21639 OMPDeclareReductionDecl *PrevDRD = nullptr;
21640 bool InCompoundScope = true;
21641 if (S != nullptr) {
21642 // Find previous declaration with the same name not referenced in other
21643 // declarations.
21645 InCompoundScope =
21646 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21647 SemaRef.LookupName(Lookup, S);
21648 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21649 /*AllowInlineNamespace=*/false);
21650 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
21651 LookupResult::Filter Filter = Lookup.makeFilter();
21652 while (Filter.hasNext()) {
21653 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
21654 if (InCompoundScope) {
21655 auto I = UsedAsPrevious.find(PrevDecl);
21656 if (I == UsedAsPrevious.end())
21657 UsedAsPrevious[PrevDecl] = false;
21658 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
21659 UsedAsPrevious[D] = true;
21660 }
21661 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21662 PrevDecl->getLocation();
21663 }
21664 Filter.done();
21665 if (InCompoundScope) {
21666 for (const auto &PrevData : UsedAsPrevious) {
21667 if (!PrevData.second) {
21668 PrevDRD = PrevData.first;
21669 break;
21670 }
21671 }
21672 }
21673 } else if (PrevDeclInScope != nullptr) {
21674 auto *PrevDRDInScope = PrevDRD =
21675 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
21676 do {
21677 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
21678 PrevDRDInScope->getLocation();
21679 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
21680 } while (PrevDRDInScope != nullptr);
21681 }
21682 for (const auto &TyData : ReductionTypes) {
21683 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
21684 bool Invalid = false;
21685 if (I != PreviousRedeclTypes.end()) {
21686 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
21687 << TyData.first;
21688 Diag(I->second, diag::note_previous_definition);
21689 Invalid = true;
21690 }
21691 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
21693 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
21694 DC->addDecl(DRD);
21695 DRD->setAccess(AS);
21696 Decls.push_back(DRD);
21697 if (Invalid)
21698 DRD->setInvalidDecl();
21699 else
21700 PrevDRD = DRD;
21701 }
21702
21703 return DeclGroupPtrTy::make(
21704 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
21705}
21706
21708 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21709
21710 // Enter new function scope.
21714
21715 if (S != nullptr)
21716 SemaRef.PushDeclContext(S, DRD);
21717 else
21718 SemaRef.CurContext = DRD;
21719
21722
21723 QualType ReductionType = DRD->getType();
21724 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
21725 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
21726 // uses semantics of argument handles by value, but it should be passed by
21727 // reference. C lang does not support references, so pass all parameters as
21728 // pointers.
21729 // Create 'T omp_in;' variable.
21730 VarDecl *OmpInParm =
21731 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
21732 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
21733 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
21734 // uses semantics of argument handles by value, but it should be passed by
21735 // reference. C lang does not support references, so pass all parameters as
21736 // pointers.
21737 // Create 'T omp_out;' variable.
21738 VarDecl *OmpOutParm =
21739 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
21740 if (S != nullptr) {
21741 SemaRef.PushOnScopeChains(OmpInParm, S);
21742 SemaRef.PushOnScopeChains(OmpOutParm, S);
21743 } else {
21744 DRD->addDecl(OmpInParm);
21745 DRD->addDecl(OmpOutParm);
21746 }
21747 Expr *InE =
21748 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
21749 Expr *OutE =
21750 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
21751 DRD->setCombinerData(InE, OutE);
21752}
21753
21755 Expr *Combiner) {
21756 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21759
21762
21763 if (Combiner != nullptr)
21764 DRD->setCombiner(Combiner);
21765 else
21766 DRD->setInvalidDecl();
21767}
21768
21770 Decl *D) {
21771 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21772
21773 // Enter new function scope.
21776
21777 if (S != nullptr)
21778 SemaRef.PushDeclContext(S, DRD);
21779 else
21780 SemaRef.CurContext = DRD;
21781
21784
21785 QualType ReductionType = DRD->getType();
21786 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
21787 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
21788 // uses semantics of argument handles by value, but it should be passed by
21789 // reference. C lang does not support references, so pass all parameters as
21790 // pointers.
21791 // Create 'T omp_priv;' variable.
21792 VarDecl *OmpPrivParm =
21793 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
21794 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
21795 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
21796 // uses semantics of argument handles by value, but it should be passed by
21797 // reference. C lang does not support references, so pass all parameters as
21798 // pointers.
21799 // Create 'T omp_orig;' variable.
21800 VarDecl *OmpOrigParm =
21801 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
21802 if (S != nullptr) {
21803 SemaRef.PushOnScopeChains(OmpPrivParm, S);
21804 SemaRef.PushOnScopeChains(OmpOrigParm, S);
21805 } else {
21806 DRD->addDecl(OmpPrivParm);
21807 DRD->addDecl(OmpOrigParm);
21808 }
21809 Expr *OrigE =
21810 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
21811 Expr *PrivE =
21812 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
21813 DRD->setInitializerData(OrigE, PrivE);
21814 return OmpPrivParm;
21815}
21816
21818 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
21819 auto *DRD = cast<OMPDeclareReductionDecl>(D);
21822
21825
21826 if (Initializer != nullptr) {
21827 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
21828 } else if (OmpPrivParm->hasInit()) {
21829 DRD->setInitializer(OmpPrivParm->getInit(),
21830 OmpPrivParm->isDirectInit()
21833 } else {
21834 DRD->setInvalidDecl();
21835 }
21836}
21837
21839 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
21840 for (Decl *D : DeclReductions.get()) {
21841 if (IsValid) {
21842 if (S)
21843 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
21844 /*AddToContext=*/false);
21845 } else {
21846 D->setInvalidDecl();
21847 }
21848 }
21849 return DeclReductions;
21850}
21851
21853 Declarator &D) {
21855 QualType T = TInfo->getType();
21856 if (D.isInvalidType())
21857 return true;
21858
21859 if (getLangOpts().CPlusPlus) {
21860 // Check that there are no default arguments (C++ only).
21862 }
21863
21864 return SemaRef.CreateParsedType(T, TInfo);
21865}
21866
21869 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
21870
21872 assert(!MapperType.isNull() && "Expect valid mapper type");
21873
21874 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21875 // The type must be of struct, union or class type in C and C++
21876 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
21877 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
21878 return QualType();
21879 }
21880 return MapperType;
21881}
21882
21884 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
21886 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
21887 LookupResult Lookup(SemaRef, Name, SourceLocation(),
21890 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
21891 // A mapper-identifier may not be redeclared in the current scope for the
21892 // same type or for a type that is compatible according to the base language
21893 // rules.
21894 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
21895 OMPDeclareMapperDecl *PrevDMD = nullptr;
21896 bool InCompoundScope = true;
21897 if (S != nullptr) {
21898 // Find previous declaration with the same name not referenced in other
21899 // declarations.
21901 InCompoundScope =
21902 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
21903 SemaRef.LookupName(Lookup, S);
21904 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
21905 /*AllowInlineNamespace=*/false);
21906 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
21907 LookupResult::Filter Filter = Lookup.makeFilter();
21908 while (Filter.hasNext()) {
21909 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
21910 if (InCompoundScope) {
21911 auto I = UsedAsPrevious.find(PrevDecl);
21912 if (I == UsedAsPrevious.end())
21913 UsedAsPrevious[PrevDecl] = false;
21914 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
21915 UsedAsPrevious[D] = true;
21916 }
21917 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
21918 PrevDecl->getLocation();
21919 }
21920 Filter.done();
21921 if (InCompoundScope) {
21922 for (const auto &PrevData : UsedAsPrevious) {
21923 if (!PrevData.second) {
21924 PrevDMD = PrevData.first;
21925 break;
21926 }
21927 }
21928 }
21929 } else if (PrevDeclInScope) {
21930 auto *PrevDMDInScope = PrevDMD =
21931 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
21932 do {
21933 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
21934 PrevDMDInScope->getLocation();
21935 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
21936 } while (PrevDMDInScope != nullptr);
21937 }
21938 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
21939 bool Invalid = false;
21940 if (I != PreviousRedeclTypes.end()) {
21941 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
21942 << MapperType << Name;
21943 Diag(I->second, diag::note_previous_definition);
21944 Invalid = true;
21945 }
21946 // Build expressions for implicit maps of data members with 'default'
21947 // mappers.
21948 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
21949 if (getLangOpts().OpenMP >= 50)
21951 ClausesWithImplicit);
21952 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
21953 MapperType, VN, ClausesWithImplicit,
21954 PrevDMD);
21955 if (S)
21956 SemaRef.PushOnScopeChains(DMD, S);
21957 else
21958 DC->addDecl(DMD);
21959 DMD->setAccess(AS);
21960 if (Invalid)
21961 DMD->setInvalidDecl();
21962
21963 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
21964 VD->setDeclContext(DMD);
21965 VD->setLexicalDeclContext(DMD);
21966 DMD->addDecl(VD);
21967 DMD->setMapperVarRef(MapperVarRef);
21968
21970}
21971
21973 Scope *S, QualType MapperType, SourceLocation StartLoc,
21974 DeclarationName VN) {
21975 TypeSourceInfo *TInfo =
21976 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
21977 auto *VD = VarDecl::Create(
21978 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
21979 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
21980 if (S)
21981 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
21982 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
21983 DSAStack->addDeclareMapperVarRef(E);
21984 return E;
21985}
21986
21988 if (DSAStack->getDeclareMapperVarRef())
21989 DSAStack->addIteratorVarDecl(VD);
21990}
21991
21993 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
21994 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
21995 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
21996 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
21997 return true;
21999 return true;
22000 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
22001 return true;
22002 return false;
22003 }
22004 return true;
22005}
22006
22008 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
22009 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
22010}
22011
22013 SourceLocation StartLoc,
22014 SourceLocation LParenLoc,
22015 SourceLocation EndLoc) {
22016 if (VarList.empty())
22017 return nullptr;
22018
22019 for (Expr *ValExpr : VarList) {
22020 // OpenMP [teams Constrcut, Restrictions]
22021 // The num_teams expression must evaluate to a positive integer value.
22022 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
22023 /*StrictlyPositive=*/true))
22024 return nullptr;
22025 }
22026
22027 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22029 DKind, OMPC_num_teams, getLangOpts().OpenMP);
22030 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22031 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22032 LParenLoc, EndLoc, VarList,
22033 /*PreInit=*/nullptr);
22034
22035 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22037 for (Expr *ValExpr : VarList) {
22038 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22039 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22040 Vars.push_back(ValExpr);
22041 }
22042
22043 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22044 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
22045 LParenLoc, EndLoc, Vars, PreInit);
22046}
22047
22049 SourceLocation StartLoc,
22050 SourceLocation LParenLoc,
22051 SourceLocation EndLoc) {
22052 if (VarList.empty())
22053 return nullptr;
22054
22055 for (Expr *ValExpr : VarList) {
22056 // OpenMP [teams Constrcut, Restrictions]
22057 // The thread_limit expression must evaluate to a positive integer value.
22058 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
22059 /*StrictlyPositive=*/true))
22060 return nullptr;
22061 }
22062
22063 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22065 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
22066 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
22067 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
22068 StartLoc, LParenLoc, EndLoc, VarList,
22069 /*PreInit=*/nullptr);
22070
22071 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22073 for (Expr *ValExpr : VarList) {
22074 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22075 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22076 Vars.push_back(ValExpr);
22077 }
22078
22079 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
22080 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
22081 LParenLoc, EndLoc, Vars, PreInit);
22082}
22083
22085 SourceLocation StartLoc,
22086 SourceLocation LParenLoc,
22087 SourceLocation EndLoc) {
22088 Expr *ValExpr = Priority;
22089 Stmt *HelperValStmt = nullptr;
22090 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22091
22092 // OpenMP [2.9.1, task Constrcut]
22093 // The priority-value is a non-negative numerical scalar expression.
22095 ValExpr, SemaRef, OMPC_priority,
22096 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
22097 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22098 return nullptr;
22099
22100 return new (getASTContext()) OMPPriorityClause(
22101 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
22102}
22103
22105 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
22106 SourceLocation StartLoc, SourceLocation LParenLoc,
22107 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22108 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22109 "Unexpected grainsize modifier in OpenMP < 51.");
22110
22111 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
22112 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
22114 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22115 << Values << getOpenMPClauseName(OMPC_grainsize);
22116 return nullptr;
22117 }
22118
22119 Expr *ValExpr = Grainsize;
22120 Stmt *HelperValStmt = nullptr;
22121 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22122
22123 // OpenMP [2.9.2, taskloop Constrcut]
22124 // The parameter of the grainsize clause must be a positive integer
22125 // expression.
22126 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
22127 /*StrictlyPositive=*/true,
22128 /*BuildCapture=*/true,
22129 DSAStack->getCurrentDirective(),
22130 &CaptureRegion, &HelperValStmt))
22131 return nullptr;
22132
22133 return new (getASTContext())
22134 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22135 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22136}
22137
22139 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
22140 SourceLocation StartLoc, SourceLocation LParenLoc,
22141 SourceLocation ModifierLoc, SourceLocation EndLoc) {
22142 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
22143 "Unexpected num_tasks modifier in OpenMP < 51.");
22144
22145 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
22146 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
22148 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
22149 << Values << getOpenMPClauseName(OMPC_num_tasks);
22150 return nullptr;
22151 }
22152
22153 Expr *ValExpr = NumTasks;
22154 Stmt *HelperValStmt = nullptr;
22155 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
22156
22157 // OpenMP [2.9.2, taskloop Constrcut]
22158 // The parameter of the num_tasks clause must be a positive integer
22159 // expression.
22161 ValExpr, SemaRef, OMPC_num_tasks,
22162 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
22163 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
22164 return nullptr;
22165
22166 return new (getASTContext())
22167 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
22168 StartLoc, LParenLoc, ModifierLoc, EndLoc);
22169}
22170
22172 SourceLocation StartLoc,
22173 SourceLocation LParenLoc,
22174 SourceLocation EndLoc) {
22175 // OpenMP [2.13.2, critical construct, Description]
22176 // ... where hint-expression is an integer constant expression that evaluates
22177 // to a valid lock hint.
22178 ExprResult HintExpr =
22179 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
22180 if (HintExpr.isInvalid())
22181 return nullptr;
22182 return new (getASTContext())
22183 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
22184}
22185
22186/// Tries to find omp_event_handle_t type.
22188 DSAStackTy *Stack) {
22189 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
22190 if (!OMPEventHandleT.isNull())
22191 return true;
22192 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
22193 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
22194 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
22195 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
22196 return false;
22197 }
22198 Stack->setOMPEventHandleT(PT.get());
22199 return true;
22200}
22201
22203 SourceLocation StartLoc,
22204 SourceLocation LParenLoc,
22205 SourceLocation EndLoc) {
22206 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
22207 !Evt->isInstantiationDependent() &&
22210 return nullptr;
22211 // OpenMP 5.0, 2.10.1 task Construct.
22212 // event-handle is a variable of the omp_event_handle_t type.
22213 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
22214 if (!Ref) {
22215 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22216 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22217 return nullptr;
22218 }
22219 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
22220 if (!VD) {
22221 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22222 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
22223 return nullptr;
22224 }
22225 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
22226 VD->getType()) ||
22227 VD->getType().isConstant(getASTContext())) {
22228 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
22229 << "omp_event_handle_t" << 1 << VD->getType()
22230 << Evt->getSourceRange();
22231 return nullptr;
22232 }
22233 // OpenMP 5.0, 2.10.1 task Construct
22234 // [detach clause]... The event-handle will be considered as if it was
22235 // specified on a firstprivate clause.
22236 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
22237 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
22238 DVar.RefExpr) {
22239 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
22240 << getOpenMPClauseName(DVar.CKind)
22241 << getOpenMPClauseName(OMPC_firstprivate);
22243 return nullptr;
22244 }
22245 }
22246
22247 return new (getASTContext())
22248 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
22249}
22250
22252 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
22253 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
22254 SourceLocation EndLoc) {
22255 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
22256 std::string Values;
22257 Values += "'";
22258 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
22259 Values += "'";
22260 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22261 << Values << getOpenMPClauseName(OMPC_dist_schedule);
22262 return nullptr;
22263 }
22264 Expr *ValExpr = ChunkSize;
22265 Stmt *HelperValStmt = nullptr;
22266 if (ChunkSize) {
22267 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
22268 !ChunkSize->isInstantiationDependent() &&
22269 !ChunkSize->containsUnexpandedParameterPack()) {
22270 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
22271 ExprResult Val =
22272 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
22273 if (Val.isInvalid())
22274 return nullptr;
22275
22276 ValExpr = Val.get();
22277
22278 // OpenMP [2.7.1, Restrictions]
22279 // chunk_size must be a loop invariant integer expression with a positive
22280 // value.
22281 if (std::optional<llvm::APSInt> Result =
22283 if (Result->isSigned() && !Result->isStrictlyPositive()) {
22284 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
22285 << "dist_schedule" << ChunkSize->getSourceRange();
22286 return nullptr;
22287 }
22289 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
22290 getLangOpts().OpenMP) != OMPD_unknown &&
22292 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22293 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22294 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22295 HelperValStmt = buildPreInits(getASTContext(), Captures);
22296 }
22297 }
22298 }
22299
22300 return new (getASTContext())
22301 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
22302 Kind, ValExpr, HelperValStmt);
22303}
22304
22307 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
22308 SourceLocation KindLoc, SourceLocation EndLoc) {
22309 if (getLangOpts().OpenMP < 50) {
22310 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
22311 Kind != OMPC_DEFAULTMAP_scalar) {
22312 std::string Value;
22314 Value += "'";
22315 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
22316 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22317 OMPC_DEFAULTMAP_MODIFIER_tofrom);
22318 Loc = MLoc;
22319 } else {
22320 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
22321 OMPC_DEFAULTMAP_scalar);
22322 Loc = KindLoc;
22323 }
22324 Value += "'";
22325 Diag(Loc, diag::err_omp_unexpected_clause_value)
22326 << Value << getOpenMPClauseName(OMPC_defaultmap);
22327 return nullptr;
22328 }
22329 } else {
22330 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
22331 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
22332 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
22333 if (!isDefaultmapKind || !isDefaultmapModifier) {
22334 StringRef KindValue = getLangOpts().OpenMP < 52
22335 ? "'scalar', 'aggregate', 'pointer'"
22336 : "'scalar', 'aggregate', 'pointer', 'all'";
22337 if (getLangOpts().OpenMP == 50) {
22338 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
22339 "'firstprivate', 'none', 'default'";
22340 if (!isDefaultmapKind && isDefaultmapModifier) {
22341 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22342 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22343 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22344 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22345 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22346 } else {
22347 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22348 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22349 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22350 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22351 }
22352 } else {
22353 StringRef ModifierValue =
22354 "'alloc', 'from', 'to', 'tofrom', "
22355 "'firstprivate', 'none', 'default', 'present'";
22356 if (!isDefaultmapKind && isDefaultmapModifier) {
22357 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22358 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22359 } else if (isDefaultmapKind && !isDefaultmapModifier) {
22360 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22361 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22362 } else {
22363 Diag(MLoc, diag::err_omp_unexpected_clause_value)
22364 << ModifierValue << getOpenMPClauseName(OMPC_defaultmap);
22365 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
22366 << KindValue << getOpenMPClauseName(OMPC_defaultmap);
22367 }
22368 }
22369 return nullptr;
22370 }
22371
22372 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
22373 // At most one defaultmap clause for each category can appear on the
22374 // directive.
22375 if (DSAStack->checkDefaultmapCategory(Kind)) {
22376 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
22377 return nullptr;
22378 }
22379 }
22380 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
22381 // Variable category is not specified - mark all categories.
22382 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
22383 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
22384 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
22385 } else {
22386 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
22387 }
22388
22389 return new (getASTContext())
22390 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
22391}
22392
22395 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
22396 if (!CurLexicalContext->isFileContext() &&
22397 !CurLexicalContext->isExternCContext() &&
22398 !CurLexicalContext->isExternCXXContext() &&
22399 !isa<CXXRecordDecl>(CurLexicalContext) &&
22400 !isa<ClassTemplateDecl>(CurLexicalContext) &&
22401 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
22402 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
22403 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
22404 return false;
22405 }
22406
22407 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22408 if (getLangOpts().HIP)
22409 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
22410
22411 DeclareTargetNesting.push_back(DTCI);
22412 return true;
22413}
22414
22417 assert(!DeclareTargetNesting.empty() &&
22418 "check isInOpenMPDeclareTargetContext() first!");
22419 return DeclareTargetNesting.pop_back_val();
22420}
22421
22424 for (auto &It : DTCI.ExplicitlyMapped)
22425 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
22426}
22427
22429 if (DeclareTargetNesting.empty())
22430 return;
22431 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22432 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
22433 << getOpenMPDirectiveName(DTCI.Kind);
22434}
22435
22437 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
22439 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
22440 /*ObjectType=*/QualType(),
22441 /*AllowBuiltinCreation=*/true);
22442
22443 if (Lookup.isAmbiguous())
22444 return nullptr;
22445 Lookup.suppressDiagnostics();
22446
22447 if (!Lookup.isSingleResult()) {
22448 VarOrFuncDeclFilterCCC CCC(SemaRef);
22449 if (TypoCorrection Corrected =
22450 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
22452 SemaRef.diagnoseTypo(Corrected,
22453 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
22454 << Id.getName());
22455 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
22456 return nullptr;
22457 }
22458
22459 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
22460 return nullptr;
22461 }
22462
22463 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
22464 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
22465 !isa<FunctionTemplateDecl>(ND)) {
22466 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
22467 return nullptr;
22468 }
22469 return ND;
22470}
22471
22473 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
22475 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
22476 isa<FunctionTemplateDecl>(ND)) &&
22477 "Expected variable, function or function template.");
22478
22479 if (auto *VD = dyn_cast<VarDecl>(ND)) {
22480 // Only global variables can be marked as declare target.
22481 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22482 !VD->isStaticDataMember()) {
22483 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
22484 << VD->getNameAsString();
22485 return;
22486 }
22487 }
22488 // Diagnose marking after use as it may lead to incorrect diagnosis and
22489 // codegen.
22490 if (getLangOpts().OpenMP >= 50 &&
22491 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
22492 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
22493
22494 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
22495 if (getLangOpts().HIP)
22496 Diag(Loc, diag::warn_hip_omp_target_directives);
22497
22498 // Explicit declare target lists have precedence.
22499 const unsigned Level = -1;
22500
22501 auto *VD = cast<ValueDecl>(ND);
22502 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22503 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22504 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
22505 (*ActiveAttr)->getLevel() == Level) {
22506 Diag(Loc, diag::err_omp_device_type_mismatch)
22507 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
22508 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
22509 (*ActiveAttr)->getDevType());
22510 return;
22511 }
22512 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
22513 (*ActiveAttr)->getLevel() == Level) {
22514 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
22515 return;
22516 }
22517
22518 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
22519 return;
22520
22521 Expr *IndirectE = nullptr;
22522 bool IsIndirect = false;
22523 if (DTCI.Indirect) {
22524 IndirectE = *DTCI.Indirect;
22525 if (!IndirectE)
22526 IsIndirect = true;
22527 }
22528 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22529 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
22530 SourceRange(Loc, Loc));
22531 ND->addAttr(A);
22532 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22533 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
22535 if (auto *VD = dyn_cast<VarDecl>(ND);
22536 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
22537 VD->hasGlobalStorage())
22539}
22540
22542 Sema &SemaRef, Decl *D) {
22543 if (!D || !isa<VarDecl>(D))
22544 return;
22545 auto *VD = cast<VarDecl>(D);
22546 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
22547 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
22548 if (SemaRef.LangOpts.OpenMP >= 50 &&
22549 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
22550 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
22551 VD->hasGlobalStorage()) {
22552 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
22553 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
22554 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
22555 // If a lambda declaration and definition appears between a
22556 // declare target directive and the matching end declare target
22557 // directive, all variables that are captured by the lambda
22558 // expression must also appear in a to clause.
22559 SemaRef.Diag(VD->getLocation(),
22560 diag::err_omp_lambda_capture_in_declare_target_not_to);
22561 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
22562 << VD << 0 << SR;
22563 return;
22564 }
22565 }
22566 if (MapTy)
22567 return;
22568 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
22569 SemaRef.Diag(SL, diag::note_used_here) << SR;
22570}
22571
22573 Sema &SemaRef, DSAStackTy *Stack,
22574 ValueDecl *VD) {
22575 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
22576 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
22577 /*FullCheck=*/false);
22578}
22579
22581 SourceLocation IdLoc) {
22582 if (!D || D->isInvalidDecl())
22583 return;
22585 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
22586 if (auto *VD = dyn_cast<VarDecl>(D)) {
22587 // Only global variables can be marked as declare target.
22588 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
22589 !VD->isStaticDataMember())
22590 return;
22591 // 2.10.6: threadprivate variable cannot appear in a declare target
22592 // directive.
22593 if (DSAStack->isThreadPrivate(VD)) {
22594 Diag(SL, diag::err_omp_threadprivate_in_target);
22595 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
22596 return;
22597 }
22598 }
22599 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
22600 D = FTD->getTemplatedDecl();
22601 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
22602 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
22603 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
22604 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
22605 Diag(IdLoc, diag::err_omp_function_in_link_clause);
22606 Diag(FD->getLocation(), diag::note_defined_here) << FD;
22607 return;
22608 }
22609 }
22610 if (auto *VD = dyn_cast<ValueDecl>(D)) {
22611 // Problem if any with var declared with incomplete type will be reported
22612 // as normal, so no need to check it here.
22613 if ((E || !VD->getType()->isIncompleteType()) &&
22615 return;
22617 // Checking declaration inside declare target region.
22618 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
22619 isa<FunctionTemplateDecl>(D)) {
22620 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
22621 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
22622 unsigned Level = DeclareTargetNesting.size();
22623 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
22624 return;
22625 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
22626 Expr *IndirectE = nullptr;
22627 bool IsIndirect = false;
22628 if (DTCI.Indirect) {
22629 IndirectE = *DTCI.Indirect;
22630 if (!IndirectE)
22631 IsIndirect = true;
22632 }
22633 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
22634 getASTContext(),
22635 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
22636 : OMPDeclareTargetDeclAttr::MT_To,
22637 DTCI.DT, IndirectE, IsIndirect, Level,
22638 SourceRange(DTCI.Loc, DTCI.Loc));
22639 D->addAttr(A);
22640 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
22641 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
22642 }
22643 return;
22644 }
22645 }
22646 if (!E)
22647 return;
22649}
22650
22651/// This class visits every VarDecl that the initializer references and adds
22652/// OMPDeclareTargetDeclAttr to each of them.
22653class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
22654 SmallVector<VarDecl *> DeclVector;
22655 Attr *A;
22656
22657public:
22658 /// A StmtVisitor class function that visits all DeclRefExpr and adds
22659 /// OMPDeclareTargetDeclAttr to them.
22661 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
22662 VD->addAttr(A);
22663 DeclVector.push_back(VD);
22664 }
22665 }
22666 /// A function that iterates across each of the Expr's children.
22667 void VisitExpr(Expr *Ex) {
22668 for (auto *Child : Ex->children()) {
22669 Visit(Child);
22670 }
22671 }
22672 /// A function that keeps a record of all the Decls that are variables, has
22673 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
22674 /// each Decl one at a time and use the inherited 'visit' functions to look
22675 /// for DeclRefExpr.
22677 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
22678 DeclVector.push_back(cast<VarDecl>(TD));
22679 while (!DeclVector.empty()) {
22680 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
22681 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
22682 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
22683 if (Expr *Ex = TargetVarDecl->getInit())
22684 Visit(Ex);
22685 }
22686 }
22687 }
22688};
22689
22690/// Adding OMPDeclareTargetDeclAttr to variables with static storage
22691/// duration that are referenced in the initializer expression list of
22692/// variables with static storage duration in declare target directive.
22694 GlobalDeclRefChecker Checker;
22695 if (isa<VarDecl>(TargetDecl))
22696 Checker.declareTargetInitializer(TargetDecl);
22697}
22698
22700 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22701 ArrayRef<SourceLocation> MotionModifiersLoc,
22702 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22703 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22704 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22708
22709 // Process motion-modifiers, flag errors for duplicate modifiers.
22710 unsigned Count = 0;
22711 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22712 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22713 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22714 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22715 continue;
22716 }
22717 assert(Count < NumberOfOMPMotionModifiers &&
22718 "Modifiers exceed the allowed number of motion modifiers");
22719 Modifiers[Count] = MotionModifiers[I];
22720 ModifiersLoc[Count] = MotionModifiersLoc[I];
22721 ++Count;
22722 }
22723
22724 MappableVarListInfo MVLI(VarList);
22726 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22727 if (MVLI.ProcessedVarList.empty())
22728 return nullptr;
22729
22730 return OMPToClause::Create(
22731 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22732 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22733 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22734}
22735
22737 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
22738 ArrayRef<SourceLocation> MotionModifiersLoc,
22739 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
22740 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
22741 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
22745
22746 // Process motion-modifiers, flag errors for duplicate modifiers.
22747 unsigned Count = 0;
22748 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
22749 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
22750 llvm::is_contained(Modifiers, MotionModifiers[I])) {
22751 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
22752 continue;
22753 }
22754 assert(Count < NumberOfOMPMotionModifiers &&
22755 "Modifiers exceed the allowed number of motion modifiers");
22756 Modifiers[Count] = MotionModifiers[I];
22757 ModifiersLoc[Count] = MotionModifiersLoc[I];
22758 ++Count;
22759 }
22760
22761 MappableVarListInfo MVLI(VarList);
22762 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
22763 MapperIdScopeSpec, MapperId, UnresolvedMappers);
22764 if (MVLI.ProcessedVarList.empty())
22765 return nullptr;
22766
22767 return OMPFromClause::Create(
22768 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22769 MVLI.VarComponents, MVLI.UDMapperList, Modifiers, ModifiersLoc,
22770 MapperIdScopeSpec.getWithLocInContext(getASTContext()), MapperId);
22771}
22772
22773OMPClause *
22775 const OMPVarListLocTy &Locs) {
22776 MappableVarListInfo MVLI(VarList);
22777 SmallVector<Expr *, 8> PrivateCopies;
22779
22780 for (Expr *RefExpr : VarList) {
22781 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
22782 SourceLocation ELoc;
22783 SourceRange ERange;
22784 Expr *SimpleRefExpr = RefExpr;
22785 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22786 if (Res.second) {
22787 // It will be analyzed later.
22788 MVLI.ProcessedVarList.push_back(RefExpr);
22789 PrivateCopies.push_back(nullptr);
22790 Inits.push_back(nullptr);
22791 }
22792 ValueDecl *D = Res.first;
22793 if (!D)
22794 continue;
22795
22796 QualType Type = D->getType();
22797 Type = Type.getNonReferenceType().getUnqualifiedType();
22798
22799 auto *VD = dyn_cast<VarDecl>(D);
22800
22801 // Item should be a pointer or reference to pointer.
22802 if (!Type->isPointerType()) {
22803 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
22804 << 0 << RefExpr->getSourceRange();
22805 continue;
22806 }
22807
22808 // Build the private variable and the expression that refers to it.
22809 auto VDPrivate =
22810 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
22811 D->hasAttrs() ? &D->getAttrs() : nullptr,
22812 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22813 if (VDPrivate->isInvalidDecl())
22814 continue;
22815
22816 SemaRef.CurContext->addDecl(VDPrivate);
22817 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
22818 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
22819
22820 // Add temporary variable to initialize the private copy of the pointer.
22821 VarDecl *VDInit =
22822 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
22823 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
22824 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
22826 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
22827 /*DirectInit=*/false);
22828
22829 // If required, build a capture to implement the privatization initialized
22830 // with the current list item value.
22831 DeclRefExpr *Ref = nullptr;
22832 if (!VD)
22833 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22834 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22835 PrivateCopies.push_back(VDPrivateRefExpr);
22836 Inits.push_back(VDInitRefExpr);
22837
22838 // We need to add a data sharing attribute for this variable to make sure it
22839 // is correctly captured. A variable that shows up in a use_device_ptr has
22840 // similar properties of a first private variable.
22841 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22842
22843 // Create a mappable component for the list item. List items in this clause
22844 // only need a component.
22845 MVLI.VarBaseDeclarations.push_back(D);
22846 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22847 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
22848 /*IsNonContiguous=*/false);
22849 }
22850
22851 if (MVLI.ProcessedVarList.empty())
22852 return nullptr;
22853
22855 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
22856 MVLI.VarBaseDeclarations, MVLI.VarComponents);
22857}
22858
22859OMPClause *
22861 const OMPVarListLocTy &Locs) {
22862 MappableVarListInfo MVLI(VarList);
22863
22864 for (Expr *RefExpr : VarList) {
22865 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
22866 SourceLocation ELoc;
22867 SourceRange ERange;
22868 Expr *SimpleRefExpr = RefExpr;
22869 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
22870 /*AllowArraySection=*/true);
22871 if (Res.second) {
22872 // It will be analyzed later.
22873 MVLI.ProcessedVarList.push_back(RefExpr);
22874 }
22875 ValueDecl *D = Res.first;
22876 if (!D)
22877 continue;
22878 auto *VD = dyn_cast<VarDecl>(D);
22879
22880 // If required, build a capture to implement the privatization initialized
22881 // with the current list item value.
22882 DeclRefExpr *Ref = nullptr;
22883 if (!VD)
22884 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
22885 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
22886
22887 // We need to add a data sharing attribute for this variable to make sure it
22888 // is correctly captured. A variable that shows up in a use_device_addr has
22889 // similar properties of a first private variable.
22890 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
22891
22892 // Create a mappable component for the list item. List items in this clause
22893 // only need a component.
22894 MVLI.VarBaseDeclarations.push_back(D);
22895 MVLI.VarComponents.emplace_back();
22896 Expr *Component = SimpleRefExpr;
22897 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
22898 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
22899 Component =
22901 MVLI.VarComponents.back().emplace_back(Component, D,
22902 /*IsNonContiguous=*/false);
22903 }
22904
22905 if (MVLI.ProcessedVarList.empty())
22906 return nullptr;
22907
22909 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22910 MVLI.VarComponents);
22911}
22912
22913OMPClause *
22915 const OMPVarListLocTy &Locs) {
22916 MappableVarListInfo MVLI(VarList);
22917 for (Expr *RefExpr : VarList) {
22918 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
22919 SourceLocation ELoc;
22920 SourceRange ERange;
22921 Expr *SimpleRefExpr = RefExpr;
22922 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
22923 if (Res.second) {
22924 // It will be analyzed later.
22925 MVLI.ProcessedVarList.push_back(RefExpr);
22926 }
22927 ValueDecl *D = Res.first;
22928 if (!D)
22929 continue;
22930
22931 QualType Type = D->getType();
22932 // item should be a pointer or array or reference to pointer or array
22933 if (!Type.getNonReferenceType()->isPointerType() &&
22934 !Type.getNonReferenceType()->isArrayType()) {
22935 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
22936 << 0 << RefExpr->getSourceRange();
22937 continue;
22938 }
22939
22940 // Check if the declaration in the clause does not show up in any data
22941 // sharing attribute.
22942 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
22943 if (isOpenMPPrivate(DVar.CKind)) {
22944 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
22945 << getOpenMPClauseName(DVar.CKind)
22946 << getOpenMPClauseName(OMPC_is_device_ptr)
22947 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
22949 continue;
22950 }
22951
22952 const Expr *ConflictExpr;
22953 if (DSAStack->checkMappableExprComponentListsForDecl(
22954 D, /*CurrentRegionOnly=*/true,
22955 [&ConflictExpr](
22957 OpenMPClauseKind) -> bool {
22958 ConflictExpr = R.front().getAssociatedExpression();
22959 return true;
22960 })) {
22961 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
22962 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
22963 << ConflictExpr->getSourceRange();
22964 continue;
22965 }
22966
22967 // Store the components in the stack so that they can be used to check
22968 // against other clauses later on.
22970 SimpleRefExpr, D, /*IsNonContiguous=*/false);
22971 DSAStack->addMappableExpressionComponents(
22972 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
22973
22974 // Record the expression we've just processed.
22975 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
22976
22977 // Create a mappable component for the list item. List items in this clause
22978 // only need a component. We use a null declaration to signal fields in
22979 // 'this'.
22980 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
22981 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
22982 "Unexpected device pointer expression!");
22983 MVLI.VarBaseDeclarations.push_back(
22984 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
22985 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
22986 MVLI.VarComponents.back().push_back(MC);
22987 }
22988
22989 if (MVLI.ProcessedVarList.empty())
22990 return nullptr;
22991
22993 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
22994 MVLI.VarComponents);
22995}
22996
22997OMPClause *
22999 const OMPVarListLocTy &Locs) {
23000 MappableVarListInfo MVLI(VarList);
23001 for (Expr *RefExpr : VarList) {
23002 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
23003 SourceLocation ELoc;
23004 SourceRange ERange;
23005 Expr *SimpleRefExpr = RefExpr;
23006 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23007 /*AllowArraySection=*/true);
23008 if (Res.second) {
23009 // It will be analyzed later.
23010 MVLI.ProcessedVarList.push_back(RefExpr);
23011 }
23012 ValueDecl *D = Res.first;
23013 if (!D)
23014 continue;
23015
23016 // Check if the declaration in the clause does not show up in any data
23017 // sharing attribute.
23018 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23019 if (isOpenMPPrivate(DVar.CKind)) {
23020 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23021 << getOpenMPClauseName(DVar.CKind)
23022 << getOpenMPClauseName(OMPC_has_device_addr)
23023 << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
23025 continue;
23026 }
23027
23028 const Expr *ConflictExpr;
23029 if (DSAStack->checkMappableExprComponentListsForDecl(
23030 D, /*CurrentRegionOnly=*/true,
23031 [&ConflictExpr](
23033 OpenMPClauseKind) -> bool {
23034 ConflictExpr = R.front().getAssociatedExpression();
23035 return true;
23036 })) {
23037 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
23038 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
23039 << ConflictExpr->getSourceRange();
23040 continue;
23041 }
23042
23043 // Store the components in the stack so that they can be used to check
23044 // against other clauses later on.
23045 Expr *Component = SimpleRefExpr;
23046 auto *VD = dyn_cast<VarDecl>(D);
23047 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
23048 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
23049 Component =
23052 Component, D, /*IsNonContiguous=*/false);
23053 DSAStack->addMappableExpressionComponents(
23054 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
23055
23056 // Record the expression we've just processed.
23057 if (!VD && !SemaRef.CurContext->isDependentContext()) {
23058 DeclRefExpr *Ref =
23059 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23060 assert(Ref && "has_device_addr capture failed");
23061 MVLI.ProcessedVarList.push_back(Ref);
23062 } else
23063 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
23064
23065 // Create a mappable component for the list item. List items in this clause
23066 // only need a component. We use a null declaration to signal fields in
23067 // 'this'.
23068 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
23069 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
23070 "Unexpected device pointer expression!");
23071 MVLI.VarBaseDeclarations.push_back(
23072 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
23073 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23074 MVLI.VarComponents.back().push_back(MC);
23075 }
23076
23077 if (MVLI.ProcessedVarList.empty())
23078 return nullptr;
23079
23081 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23082 MVLI.VarComponents);
23083}
23084
23086 Expr *Allocator, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23087 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
23088 if (Allocator) {
23089 // OpenMP [2.11.4 allocate Clause, Description]
23090 // allocator is an expression of omp_allocator_handle_t type.
23091 if (!findOMPAllocatorHandleT(SemaRef, Allocator->getExprLoc(), DSAStack))
23092 return nullptr;
23093
23094 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
23095 if (AllocatorRes.isInvalid())
23096 return nullptr;
23097 AllocatorRes = SemaRef.PerformImplicitConversion(
23098 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
23100 /*AllowExplicit=*/true);
23101 if (AllocatorRes.isInvalid())
23102 return nullptr;
23103 Allocator = AllocatorRes.get();
23104 } else {
23105 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
23106 // allocate clauses that appear on a target construct or on constructs in a
23107 // target region must specify an allocator expression unless a requires
23108 // directive with the dynamic_allocators clause is present in the same
23109 // compilation unit.
23110 if (getLangOpts().OpenMPIsTargetDevice &&
23111 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
23112 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
23113 }
23114 // Analyze and build list of variables.
23116 for (Expr *RefExpr : VarList) {
23117 assert(RefExpr && "NULL expr in OpenMP private clause.");
23118 SourceLocation ELoc;
23119 SourceRange ERange;
23120 Expr *SimpleRefExpr = RefExpr;
23121 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23122 if (Res.second) {
23123 // It will be analyzed later.
23124 Vars.push_back(RefExpr);
23125 }
23126 ValueDecl *D = Res.first;
23127 if (!D)
23128 continue;
23129
23130 auto *VD = dyn_cast<VarDecl>(D);
23131 DeclRefExpr *Ref = nullptr;
23132 if (!VD && !SemaRef.CurContext->isDependentContext())
23133 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
23134 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
23135 ? RefExpr->IgnoreParens()
23136 : Ref);
23137 }
23138
23139 if (Vars.empty())
23140 return nullptr;
23141
23142 if (Allocator)
23143 DSAStack->addInnerAllocatorExpr(Allocator);
23144 return OMPAllocateClause::Create(getASTContext(), StartLoc, LParenLoc,
23145 Allocator, ColonLoc, EndLoc, Vars);
23146}
23147
23149 SourceLocation StartLoc,
23150 SourceLocation LParenLoc,
23151 SourceLocation EndLoc) {
23153 for (Expr *RefExpr : VarList) {
23154 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23155 SourceLocation ELoc;
23156 SourceRange ERange;
23157 Expr *SimpleRefExpr = RefExpr;
23158 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23159 if (Res.second)
23160 // It will be analyzed later.
23161 Vars.push_back(RefExpr);
23162 ValueDecl *D = Res.first;
23163 if (!D)
23164 continue;
23165
23166 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
23167 // A list-item cannot appear in more than one nontemporal clause.
23168 if (const Expr *PrevRef =
23169 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
23170 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23171 << 0 << getOpenMPClauseName(OMPC_nontemporal) << ERange;
23172 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23173 << getOpenMPClauseName(OMPC_nontemporal);
23174 continue;
23175 }
23176
23177 Vars.push_back(RefExpr);
23178 }
23179
23180 if (Vars.empty())
23181 return nullptr;
23182
23183 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
23184 EndLoc, Vars);
23185}
23186
23188 Stmt *AStmt,
23189 SourceLocation StartLoc,
23190 SourceLocation EndLoc) {
23191 if (!AStmt)
23192 return StmtError();
23193
23195
23196 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
23197 AStmt);
23198}
23199
23201 SourceLocation StartLoc,
23202 SourceLocation LParenLoc,
23203 SourceLocation EndLoc) {
23205 for (Expr *RefExpr : VarList) {
23206 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23207 SourceLocation ELoc;
23208 SourceRange ERange;
23209 Expr *SimpleRefExpr = RefExpr;
23210 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23211 /*AllowArraySection=*/true);
23212 if (Res.second)
23213 // It will be analyzed later.
23214 Vars.push_back(RefExpr);
23215 ValueDecl *D = Res.first;
23216 if (!D)
23217 continue;
23218
23219 const DSAStackTy::DSAVarData DVar =
23220 DSAStack->getTopDSA(D, /*FromParent=*/true);
23221 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23222 // A list item that appears in the inclusive or exclusive clause must appear
23223 // in a reduction clause with the inscan modifier on the enclosing
23224 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23225 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
23226 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23227 << RefExpr->getSourceRange();
23228
23229 if (DSAStack->getParentDirective() != OMPD_unknown)
23230 DSAStack->markDeclAsUsedInScanDirective(D);
23231 Vars.push_back(RefExpr);
23232 }
23233
23234 if (Vars.empty())
23235 return nullptr;
23236
23237 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23238 EndLoc, Vars);
23239}
23240
23242 SourceLocation StartLoc,
23243 SourceLocation LParenLoc,
23244 SourceLocation EndLoc) {
23246 for (Expr *RefExpr : VarList) {
23247 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
23248 SourceLocation ELoc;
23249 SourceRange ERange;
23250 Expr *SimpleRefExpr = RefExpr;
23251 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
23252 /*AllowArraySection=*/true);
23253 if (Res.second)
23254 // It will be analyzed later.
23255 Vars.push_back(RefExpr);
23256 ValueDecl *D = Res.first;
23257 if (!D)
23258 continue;
23259
23260 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
23261 DSAStackTy::DSAVarData DVar;
23262 if (ParentDirective != OMPD_unknown)
23263 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
23264 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
23265 // A list item that appears in the inclusive or exclusive clause must appear
23266 // in a reduction clause with the inscan modifier on the enclosing
23267 // worksharing-loop, worksharing-loop SIMD, or simd construct.
23268 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
23269 DVar.Modifier != OMPC_REDUCTION_inscan) {
23270 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
23271 << RefExpr->getSourceRange();
23272 } else {
23273 DSAStack->markDeclAsUsedInScanDirective(D);
23274 }
23275 Vars.push_back(RefExpr);
23276 }
23277
23278 if (Vars.empty())
23279 return nullptr;
23280
23281 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
23282 EndLoc, Vars);
23283}
23284
23285/// Tries to find omp_alloctrait_t type.
23286static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
23287 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
23288 if (!OMPAlloctraitT.isNull())
23289 return true;
23290 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
23291 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
23292 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23293 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
23294 return false;
23295 }
23296 Stack->setOMPAlloctraitT(PT.get());
23297 return true;
23298}
23299
23301 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
23303 ASTContext &Context = getASTContext();
23304 // OpenMP [2.12.5, target Construct]
23305 // allocator is an identifier of omp_allocator_handle_t type.
23306 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
23307 return nullptr;
23308 // OpenMP [2.12.5, target Construct]
23309 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
23310 if (llvm::any_of(
23311 Data,
23312 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
23313 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
23314 return nullptr;
23315 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
23316 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
23317 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
23318 StringRef Allocator =
23319 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
23320 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
23321 PredefinedAllocators.insert(SemaRef.LookupSingleName(
23322 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
23323 }
23324
23326 for (const UsesAllocatorsData &D : Data) {
23327 Expr *AllocatorExpr = nullptr;
23328 // Check allocator expression.
23329 if (D.Allocator->isTypeDependent()) {
23330 AllocatorExpr = D.Allocator;
23331 } else {
23332 // Traits were specified - need to assign new allocator to the specified
23333 // allocator, so it must be an lvalue.
23334 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
23335 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
23336 bool IsPredefinedAllocator = false;
23337 if (DRE) {
23338 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
23339 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
23340 IsPredefinedAllocator =
23341 AllocatorTy !=
23342 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
23343 }
23344 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
23345 QualType AllocatorExprType = AllocatorExpr->getType();
23346 bool IsTypeCompatible = IsPredefinedAllocator;
23347 IsTypeCompatible = IsTypeCompatible ||
23348 Context.hasSameUnqualifiedType(AllocatorExprType,
23349 OMPAllocatorHandleT);
23350 IsTypeCompatible =
23351 IsTypeCompatible ||
23352 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
23353 bool IsNonConstantLValue =
23354 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
23355 if (!DRE || !IsTypeCompatible ||
23356 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
23357 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
23358 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
23359 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
23360 continue;
23361 }
23362 // OpenMP [2.12.5, target Construct]
23363 // Predefined allocators appearing in a uses_allocators clause cannot have
23364 // traits specified.
23365 if (IsPredefinedAllocator && D.AllocatorTraits) {
23366 Diag(D.AllocatorTraits->getExprLoc(),
23367 diag::err_omp_predefined_allocator_with_traits)
23368 << D.AllocatorTraits->getSourceRange();
23369 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
23370 << cast<NamedDecl>(DRE->getDecl())->getName()
23371 << D.Allocator->getSourceRange();
23372 continue;
23373 }
23374 // OpenMP [2.12.5, target Construct]
23375 // Non-predefined allocators appearing in a uses_allocators clause must
23376 // have traits specified.
23377 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
23378 Diag(D.Allocator->getExprLoc(),
23379 diag::err_omp_nonpredefined_allocator_without_traits);
23380 continue;
23381 }
23382 // No allocator traits - just convert it to rvalue.
23383 if (!D.AllocatorTraits)
23384 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
23385 DSAStack->addUsesAllocatorsDecl(
23386 DRE->getDecl(),
23387 IsPredefinedAllocator
23388 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
23389 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
23390 }
23391 Expr *AllocatorTraitsExpr = nullptr;
23392 if (D.AllocatorTraits) {
23393 if (D.AllocatorTraits->isTypeDependent()) {
23394 AllocatorTraitsExpr = D.AllocatorTraits;
23395 } else {
23396 // OpenMP [2.12.5, target Construct]
23397 // Arrays that contain allocator traits that appear in a uses_allocators
23398 // clause must be constant arrays, have constant values and be defined
23399 // in the same scope as the construct in which the clause appears.
23400 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
23401 // Check that traits expr is a constant array.
23402 QualType TraitTy;
23403 if (const ArrayType *Ty =
23404 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
23405 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
23406 TraitTy = ConstArrayTy->getElementType();
23407 if (TraitTy.isNull() ||
23408 !(Context.hasSameUnqualifiedType(TraitTy,
23409 DSAStack->getOMPAlloctraitT()) ||
23410 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
23411 /*CompareUnqualified=*/true))) {
23412 Diag(D.AllocatorTraits->getExprLoc(),
23413 diag::err_omp_expected_array_alloctraits)
23414 << AllocatorTraitsExpr->getType();
23415 continue;
23416 }
23417 // Do not map by default allocator traits if it is a standalone
23418 // variable.
23419 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
23420 DSAStack->addUsesAllocatorsDecl(
23421 DRE->getDecl(),
23422 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
23423 }
23424 }
23425 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
23426 NewD.Allocator = AllocatorExpr;
23427 NewD.AllocatorTraits = AllocatorTraitsExpr;
23428 NewD.LParenLoc = D.LParenLoc;
23429 NewD.RParenLoc = D.RParenLoc;
23430 }
23431 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
23432 EndLoc, NewData);
23433}
23434
23436 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
23437 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
23439 for (Expr *RefExpr : Locators) {
23440 assert(RefExpr && "NULL expr in OpenMP shared clause.");
23441 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
23442 // It will be analyzed later.
23443 Vars.push_back(RefExpr);
23444 continue;
23445 }
23446
23447 SourceLocation ELoc = RefExpr->getExprLoc();
23448 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
23449
23450 if (!SimpleExpr->isLValue()) {
23451 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23452 << 1 << 0 << RefExpr->getSourceRange();
23453 continue;
23454 }
23455
23456 ExprResult Res;
23457 {
23459 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
23460 }
23461 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
23462 !isa<OMPArrayShapingExpr>(SimpleExpr)) {
23463 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
23464 << 1 << 0 << RefExpr->getSourceRange();
23465 continue;
23466 }
23467 Vars.push_back(SimpleExpr);
23468 }
23469
23470 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
23471 ColonLoc, EndLoc, Modifier, Vars);
23472}
23473
23475 SourceLocation KindLoc,
23476 SourceLocation StartLoc,
23477 SourceLocation LParenLoc,
23478 SourceLocation EndLoc) {
23479 if (Kind == OMPC_BIND_unknown) {
23480 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
23481 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
23482 /*Last=*/unsigned(OMPC_BIND_unknown))
23483 << getOpenMPClauseName(OMPC_bind);
23484 return nullptr;
23485 }
23486
23487 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
23488 LParenLoc, EndLoc);
23489}
23490
23492 SourceLocation StartLoc,
23493 SourceLocation LParenLoc,
23494 SourceLocation EndLoc) {
23495 Expr *ValExpr = Size;
23496 Stmt *HelperValStmt = nullptr;
23497
23498 // OpenMP [2.5, Restrictions]
23499 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
23500 // value.
23501 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
23502 /*StrictlyPositive=*/false))
23503 return nullptr;
23504
23505 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23507 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
23508 if (CaptureRegion != OMPD_unknown &&
23510 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23511 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23512 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23513 HelperValStmt = buildPreInits(getASTContext(), Captures);
23514 }
23515
23517 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
23518}
23519
23522 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
23523 SourceLocation LParenLoc, SourceLocation EndLoc) {
23524
23525 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
23526 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
23527 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
23528 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
23529 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
23530 << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
23531 return nullptr;
23532 }
23533
23536 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23537 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
23538 SemaRef,
23539 DepType == OMPC_DOACROSS_source ||
23540 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
23541 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
23542 VarList, DSAStack, EndLoc);
23543 Vars = VarOffset.Vars;
23544 OpsOffs = VarOffset.OpsOffs;
23545 TotalDepCount = VarOffset.TotalDepCount;
23546 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
23547 EndLoc, DepType, DepLoc, ColonLoc, Vars,
23548 TotalDepCount.getZExtValue());
23549 if (DSAStack->isParentOrderedRegion())
23550 DSAStack->addDoacrossDependClause(C, OpsOffs);
23551 return C;
23552}
23553
23555 SourceLocation StartLoc,
23556 SourceLocation LParenLoc,
23557 SourceLocation EndLoc) {
23558 return new (getASTContext())
23559 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
23560}
23561
23563 SourceLocation EndLoc) {
23564 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
23565}
23566
23568 SourceLocation LParenLoc,
23569 SourceLocation EndLoc) {
23570 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
23571}
23572
23576 switch (CK) {
23577 case OMPC_absent:
23578 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23579 case OMPC_contains:
23580 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
23581 default:
23582 llvm_unreachable("Unexpected OpenMP clause");
23583 }
23584}
23585
23588 SourceLocation RLoc) {
23589 switch (CK) {
23590 case OMPC_no_openmp:
23591 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
23592 case OMPC_no_openmp_routines:
23593 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
23594 case OMPC_no_parallelism:
23595 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
23596 default:
23597 llvm_unreachable("Unexpected OpenMP clause");
23598 }
23599}
23600
23602 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
23603 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
23604 Expr *Stride, SourceLocation RBLoc) {
23605 ASTContext &Context = getASTContext();
23606 if (Base->hasPlaceholderType() &&
23607 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23609 if (Result.isInvalid())
23610 return ExprError();
23611 Base = Result.get();
23612 }
23613 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
23615 if (Result.isInvalid())
23616 return ExprError();
23618 if (Result.isInvalid())
23619 return ExprError();
23620 LowerBound = Result.get();
23621 }
23622 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
23624 if (Result.isInvalid())
23625 return ExprError();
23627 if (Result.isInvalid())
23628 return ExprError();
23629 Length = Result.get();
23630 }
23631 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
23633 if (Result.isInvalid())
23634 return ExprError();
23636 if (Result.isInvalid())
23637 return ExprError();
23638 Stride = Result.get();
23639 }
23640
23641 // Build an unanalyzed expression if either operand is type-dependent.
23642 if (Base->isTypeDependent() ||
23643 (LowerBound &&
23644 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
23645 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
23646 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
23647 return new (Context) ArraySectionExpr(
23648 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
23649 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23650 }
23651
23652 // Perform default conversions.
23654 QualType ResultTy;
23655 if (OriginalTy->isAnyPointerType()) {
23656 ResultTy = OriginalTy->getPointeeType();
23657 } else if (OriginalTy->isArrayType()) {
23658 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
23659 } else {
23660 return ExprError(
23661 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
23662 << Base->getSourceRange());
23663 }
23664 // C99 6.5.2.1p1
23665 if (LowerBound) {
23666 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
23667 LowerBound);
23668 if (Res.isInvalid())
23669 return ExprError(Diag(LowerBound->getExprLoc(),
23670 diag::err_omp_typecheck_section_not_integer)
23671 << 0 << LowerBound->getSourceRange());
23672 LowerBound = Res.get();
23673
23674 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23675 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23676 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
23677 << 0 << LowerBound->getSourceRange();
23678 }
23679 if (Length) {
23680 auto Res =
23681 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
23682 if (Res.isInvalid())
23683 return ExprError(Diag(Length->getExprLoc(),
23684 diag::err_omp_typecheck_section_not_integer)
23685 << 1 << Length->getSourceRange());
23686 Length = Res.get();
23687
23688 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23689 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23690 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
23691 << 1 << Length->getSourceRange();
23692 }
23693 if (Stride) {
23694 ExprResult Res =
23696 if (Res.isInvalid())
23697 return ExprError(Diag(Stride->getExprLoc(),
23698 diag::err_omp_typecheck_section_not_integer)
23699 << 1 << Stride->getSourceRange());
23700 Stride = Res.get();
23701
23702 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
23703 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
23704 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
23705 << 1 << Stride->getSourceRange();
23706 }
23707
23708 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
23709 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
23710 // type. Note that functions are not objects, and that (in C99 parlance)
23711 // incomplete types are not object types.
23712 if (ResultTy->isFunctionType()) {
23713 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
23714 << ResultTy << Base->getSourceRange();
23715 return ExprError();
23716 }
23717
23718 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
23719 diag::err_omp_section_incomplete_type, Base))
23720 return ExprError();
23721
23722 if (LowerBound && !OriginalTy->isAnyPointerType()) {
23724 if (LowerBound->EvaluateAsInt(Result, Context)) {
23725 // OpenMP 5.0, [2.1.5 Array Sections]
23726 // The array section must be a subset of the original array.
23727 llvm::APSInt LowerBoundValue = Result.Val.getInt();
23728 if (LowerBoundValue.isNegative()) {
23729 Diag(LowerBound->getExprLoc(),
23730 diag::err_omp_section_not_subset_of_array)
23731 << LowerBound->getSourceRange();
23732 return ExprError();
23733 }
23734 }
23735 }
23736
23737 if (Length) {
23739 if (Length->EvaluateAsInt(Result, Context)) {
23740 // OpenMP 5.0, [2.1.5 Array Sections]
23741 // The length must evaluate to non-negative integers.
23742 llvm::APSInt LengthValue = Result.Val.getInt();
23743 if (LengthValue.isNegative()) {
23744 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
23745 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
23746 << Length->getSourceRange();
23747 return ExprError();
23748 }
23749 }
23750 } else if (ColonLocFirst.isValid() &&
23751 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
23752 !OriginalTy->isVariableArrayType()))) {
23753 // OpenMP 5.0, [2.1.5 Array Sections]
23754 // When the size of the array dimension is not known, the length must be
23755 // specified explicitly.
23756 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
23757 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
23758 return ExprError();
23759 }
23760
23761 if (Stride) {
23763 if (Stride->EvaluateAsInt(Result, Context)) {
23764 // OpenMP 5.0, [2.1.5 Array Sections]
23765 // The stride must evaluate to a positive integer.
23766 llvm::APSInt StrideValue = Result.Val.getInt();
23767 if (!StrideValue.isStrictlyPositive()) {
23768 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
23769 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
23770 << Stride->getSourceRange();
23771 return ExprError();
23772 }
23773 }
23774 }
23775
23776 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
23778 if (Result.isInvalid())
23779 return ExprError();
23780 Base = Result.get();
23781 }
23782 return new (Context) ArraySectionExpr(
23783 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
23784 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
23785}
23786
23788 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
23789 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
23790 ASTContext &Context = getASTContext();
23791 if (Base->hasPlaceholderType()) {
23793 if (Result.isInvalid())
23794 return ExprError();
23796 if (Result.isInvalid())
23797 return ExprError();
23798 Base = Result.get();
23799 }
23800 QualType BaseTy = Base->getType();
23801 // Delay analysis of the types/expressions if instantiation/specialization is
23802 // required.
23803 if (!BaseTy->isPointerType() && Base->isTypeDependent())
23804 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
23805 LParenLoc, RParenLoc, Dims, Brackets);
23806 if (!BaseTy->isPointerType() ||
23807 (!Base->isTypeDependent() &&
23808 BaseTy->getPointeeType()->isIncompleteType()))
23809 return ExprError(Diag(Base->getExprLoc(),
23810 diag::err_omp_non_pointer_type_array_shaping_base)
23811 << Base->getSourceRange());
23812
23813 SmallVector<Expr *, 4> NewDims;
23814 bool ErrorFound = false;
23815 for (Expr *Dim : Dims) {
23816 if (Dim->hasPlaceholderType()) {
23818 if (Result.isInvalid()) {
23819 ErrorFound = true;
23820 continue;
23821 }
23823 if (Result.isInvalid()) {
23824 ErrorFound = true;
23825 continue;
23826 }
23827 Dim = Result.get();
23828 }
23829 if (!Dim->isTypeDependent()) {
23831 PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
23832 if (Result.isInvalid()) {
23833 ErrorFound = true;
23834 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
23835 << Dim->getSourceRange();
23836 continue;
23837 }
23838 Dim = Result.get();
23839 Expr::EvalResult EvResult;
23840 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
23841 // OpenMP 5.0, [2.1.4 Array Shaping]
23842 // Each si is an integral type expression that must evaluate to a
23843 // positive integer.
23844 llvm::APSInt Value = EvResult.Val.getInt();
23845 if (!Value.isStrictlyPositive()) {
23846 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
23847 << toString(Value, /*Radix=*/10, /*Signed=*/true)
23848 << Dim->getSourceRange();
23849 ErrorFound = true;
23850 continue;
23851 }
23852 }
23853 }
23854 NewDims.push_back(Dim);
23855 }
23856 if (ErrorFound)
23857 return ExprError();
23858 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
23859 LParenLoc, RParenLoc, NewDims, Brackets);
23860}
23861
23863 SourceLocation IteratorKwLoc,
23864 SourceLocation LLoc,
23865 SourceLocation RLoc,
23867 ASTContext &Context = getASTContext();
23869 bool IsCorrect = true;
23870 for (const OMPIteratorData &D : Data) {
23871 TypeSourceInfo *TInfo = nullptr;
23872 SourceLocation StartLoc;
23873 QualType DeclTy;
23874 if (!D.Type.getAsOpaquePtr()) {
23875 // OpenMP 5.0, 2.1.6 Iterators
23876 // In an iterator-specifier, if the iterator-type is not specified then
23877 // the type of that iterator is of int type.
23878 DeclTy = Context.IntTy;
23879 StartLoc = D.DeclIdentLoc;
23880 } else {
23881 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
23882 StartLoc = TInfo->getTypeLoc().getBeginLoc();
23883 }
23884
23885 bool IsDeclTyDependent = DeclTy->isDependentType() ||
23886 DeclTy->containsUnexpandedParameterPack() ||
23887 DeclTy->isInstantiationDependentType();
23888 if (!IsDeclTyDependent) {
23889 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
23890 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23891 // The iterator-type must be an integral or pointer type.
23892 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23893 << DeclTy;
23894 IsCorrect = false;
23895 continue;
23896 }
23897 if (DeclTy.isConstant(Context)) {
23898 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
23899 // The iterator-type must not be const qualified.
23900 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
23901 << DeclTy;
23902 IsCorrect = false;
23903 continue;
23904 }
23905 }
23906
23907 // Iterator declaration.
23908 assert(D.DeclIdent && "Identifier expected.");
23909 // Always try to create iterator declarator to avoid extra error messages
23910 // about unknown declarations use.
23911 auto *VD =
23912 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
23913 D.DeclIdent, DeclTy, TInfo, SC_None);
23914 VD->setImplicit();
23915 if (S) {
23916 // Check for conflicting previous declaration.
23917 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
23919 RedeclarationKind::ForVisibleRedeclaration);
23920 Previous.suppressDiagnostics();
23922
23924 /*ConsiderLinkage=*/false,
23925 /*AllowInlineNamespace=*/false);
23926 if (!Previous.empty()) {
23927 NamedDecl *Old = Previous.getRepresentativeDecl();
23928 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
23929 Diag(Old->getLocation(), diag::note_previous_definition);
23930 } else {
23932 }
23933 } else {
23935 }
23936
23937 /// Act on the iterator variable declaration.
23939
23940 Expr *Begin = D.Range.Begin;
23941 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
23942 ExprResult BeginRes =
23944 Begin = BeginRes.get();
23945 }
23946 Expr *End = D.Range.End;
23947 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
23948 ExprResult EndRes =
23950 End = EndRes.get();
23951 }
23952 Expr *Step = D.Range.Step;
23953 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
23954 if (!Step->getType()->isIntegralType(Context)) {
23955 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
23956 << Step << Step->getSourceRange();
23957 IsCorrect = false;
23958 continue;
23959 }
23960 std::optional<llvm::APSInt> Result =
23961 Step->getIntegerConstantExpr(Context);
23962 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
23963 // If the step expression of a range-specification equals zero, the
23964 // behavior is unspecified.
23965 if (Result && Result->isZero()) {
23966 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
23967 << Step << Step->getSourceRange();
23968 IsCorrect = false;
23969 continue;
23970 }
23971 }
23972 if (!Begin || !End || !IsCorrect) {
23973 IsCorrect = false;
23974 continue;
23975 }
23976 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
23977 IDElem.IteratorDecl = VD;
23978 IDElem.AssignmentLoc = D.AssignLoc;
23979 IDElem.Range.Begin = Begin;
23980 IDElem.Range.End = End;
23981 IDElem.Range.Step = Step;
23982 IDElem.ColonLoc = D.ColonLoc;
23983 IDElem.SecondColonLoc = D.SecColonLoc;
23984 }
23985 if (!IsCorrect) {
23986 // Invalidate all created iterator declarations if error is found.
23987 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
23988 if (Decl *ID = D.IteratorDecl)
23989 ID->setInvalidDecl();
23990 }
23991 return ExprError();
23992 }
23995 // Build number of ityeration for each iteration range.
23996 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
23997 // ((Begini-Stepi-1-Endi) / -Stepi);
23999 // (Endi - Begini)
24000 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
24001 D.Range.End, D.Range.Begin);
24002 if (!Res.isUsable()) {
24003 IsCorrect = false;
24004 continue;
24005 }
24006 ExprResult St, St1;
24007 if (D.Range.Step) {
24008 St = D.Range.Step;
24009 // (Endi - Begini) + Stepi
24010 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
24011 St.get());
24012 if (!Res.isUsable()) {
24013 IsCorrect = false;
24014 continue;
24015 }
24016 // (Endi - Begini) + Stepi - 1
24018 D.AssignmentLoc, BO_Sub, Res.get(),
24019 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24020 if (!Res.isUsable()) {
24021 IsCorrect = false;
24022 continue;
24023 }
24024 // ((Endi - Begini) + Stepi - 1) / Stepi
24025 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
24026 St.get());
24027 if (!Res.isUsable()) {
24028 IsCorrect = false;
24029 continue;
24030 }
24031 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
24032 D.Range.Step);
24033 // (Begini - Endi)
24035 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
24036 if (!Res1.isUsable()) {
24037 IsCorrect = false;
24038 continue;
24039 }
24040 // (Begini - Endi) - Stepi
24041 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
24042 St1.get());
24043 if (!Res1.isUsable()) {
24044 IsCorrect = false;
24045 continue;
24046 }
24047 // (Begini - Endi) - Stepi - 1
24049 D.AssignmentLoc, BO_Sub, Res1.get(),
24050 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
24051 if (!Res1.isUsable()) {
24052 IsCorrect = false;
24053 continue;
24054 }
24055 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
24056 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
24057 St1.get());
24058 if (!Res1.isUsable()) {
24059 IsCorrect = false;
24060 continue;
24061 }
24062 // Stepi > 0.
24064 D.AssignmentLoc, BO_GT, D.Range.Step,
24065 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
24066 if (!CmpRes.isUsable()) {
24067 IsCorrect = false;
24068 continue;
24069 }
24070 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
24071 CmpRes.get(), Res.get(), Res1.get());
24072 if (!Res.isUsable()) {
24073 IsCorrect = false;
24074 continue;
24075 }
24076 }
24077 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
24078 if (!Res.isUsable()) {
24079 IsCorrect = false;
24080 continue;
24081 }
24082
24083 // Build counter update.
24084 // Build counter.
24085 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
24086 D.IteratorDecl->getBeginLoc(),
24087 D.IteratorDecl->getBeginLoc(), nullptr,
24088 Res.get()->getType(), nullptr, SC_None);
24089 CounterVD->setImplicit();
24090 ExprResult RefRes =
24091 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
24092 D.IteratorDecl->getBeginLoc());
24093 // Build counter update.
24094 // I = Begini + counter * Stepi;
24095 ExprResult UpdateRes;
24096 if (D.Range.Step) {
24097 UpdateRes = SemaRef.CreateBuiltinBinOp(
24098 D.AssignmentLoc, BO_Mul,
24099 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
24100 } else {
24101 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
24102 }
24103 if (!UpdateRes.isUsable()) {
24104 IsCorrect = false;
24105 continue;
24106 }
24107 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
24108 D.Range.Begin, UpdateRes.get());
24109 if (!UpdateRes.isUsable()) {
24110 IsCorrect = false;
24111 continue;
24112 }
24113 ExprResult VDRes =
24114 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
24115 cast<VarDecl>(D.IteratorDecl)->getType(),
24116 VK_LValue, D.IteratorDecl->getBeginLoc());
24117 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
24118 VDRes.get(), UpdateRes.get());
24119 if (!UpdateRes.isUsable()) {
24120 IsCorrect = false;
24121 continue;
24122 }
24123 UpdateRes =
24124 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
24125 if (!UpdateRes.isUsable()) {
24126 IsCorrect = false;
24127 continue;
24128 }
24129 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
24130 D.AssignmentLoc, UO_PreInc, RefRes.get());
24131 if (!CounterUpdateRes.isUsable()) {
24132 IsCorrect = false;
24133 continue;
24134 }
24135 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
24136 /*DiscardedValue=*/true);
24137 if (!CounterUpdateRes.isUsable()) {
24138 IsCorrect = false;
24139 continue;
24140 }
24141 OMPIteratorHelperData &HD = Helpers.emplace_back();
24142 HD.CounterVD = CounterVD;
24143 HD.Upper = Res.get();
24144 HD.Update = UpdateRes.get();
24145 HD.CounterUpdate = CounterUpdateRes.get();
24146 }
24147 } else {
24148 Helpers.assign(ID.size(), {});
24149 }
24150 if (!IsCorrect) {
24151 // Invalidate all created iterator declarations if error is found.
24152 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
24153 if (Decl *ID = D.IteratorDecl)
24154 ID->setInvalidDecl();
24155 }
24156 return ExprError();
24157 }
24158 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
24159 LLoc, RLoc, ID, Helpers);
24160}
24161
24162/// Check if \p AssumptionStr is a known assumption and warn if not.
24164 StringRef AssumptionStr) {
24165 if (llvm::KnownAssumptionStrings.count(AssumptionStr))
24166 return;
24167
24168 unsigned BestEditDistance = 3;
24169 StringRef Suggestion;
24170 for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) {
24171 unsigned EditDistance =
24172 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
24173 if (EditDistance < BestEditDistance) {
24174 Suggestion = KnownAssumptionIt.getKey();
24175 BestEditDistance = EditDistance;
24176 }
24177 }
24178
24179 if (!Suggestion.empty())
24180 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
24181 << AssumptionStr << Suggestion;
24182 else
24183 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
24184 << AssumptionStr;
24185}
24186
24188 // Handle the case where the attribute has a text message.
24189 StringRef Str;
24190 SourceLocation AttrStrLoc;
24191 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
24192 return;
24193
24194 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
24195
24196 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
24197}
24198
24200 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Definition: ASTContext.h:3341
NodeId Parent
Definition: ASTDiff.cpp:191
DynTypedNode Node
StringRef P
const Decl * D
enum clang::sema::@1655::IndirectLocalPathEntry::EntryKind Kind
Expr * E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
int Priority
Definition: Format.cpp:3005
llvm::DenseSet< const void * > Visited
Definition: HTMLLogger.cpp:146
unsigned Iter
Definition: HTMLLogger.cpp:154
static const Decl * getCanonicalDecl(const Decl *D)
#define X(type, name)
Definition: Value.h:143
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::TargetList TargetList
Definition: MachO.h:52
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Definition: ParentMap.cpp:22
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
uint32_t Id
Definition: SemaARM.cpp:1144
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:758
SourceLocation Loc
Definition: SemaObjC.cpp:759
static Expr * getOrderedNumberExpr(ArrayRef< OMPClause * > Clauses)
static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack, bool Diagnose=true)
Tries to find omp_depend_t. type.
static Stmt * buildPreInits(ASTContext &Context, MutableArrayRef< Decl * > PreInits)
Build preinits statement for the given declarations.
static void argumentDependentLookup(Sema &SemaRef, const DeclarationNameInfo &Id, SourceLocation Loc, QualType Ty, SmallVectorImpl< UnresolvedSet< 8 > > &Lookups)
static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR, Sema &SemaRef, Decl *D)
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, StringRef DiagType="")
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static 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 bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
#define DSAStack
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static VarDecl * buildVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type, StringRef Name, const AttrVec *Attrs=nullptr, DeclRefExpr *OrigRef=nullptr)
Build a variable declaration for OpenMP loop iteration variable.
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers=std::nullopt, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propageted from the selected loop.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
Check consistency of the reduction clauses.
static bool checkTypeMappable(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, QualType QTy, bool FullCheck=true)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskRegionParams(Sema &SemaRef)
static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack, OpenMPDirectiveKind CurrentRegion, const DeclarationNameInfo &CurrentName, OpenMPDirectiveKind CancelRegion, OpenMPBindClauseKind BindKind, SourceLocation StartLoc)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
Definition: SourceCode.cpp:152
const char * Data
This file defines OpenMP AST classes for executable directives and clauses.
static QualType getPointeeType(const MemRegion *R)
Allows QualTypes to be sorted and hence used in maps and sets.
SourceLocation Begin
StateNode * Previous
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF)
bool VisitVarDecl(VarDecl *D)
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F)
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
APSInt & getInt()
Definition: APValue.h:423
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
QualType getMemberPointerType(QualType T, const Type *Cls) const
Return the uniqued reference to the type for a member pointer to the specified type in the specified ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
Definition: ASTContext.h:664
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const
Return a non-unique reference to the type for a variable array of the specified element type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
Definition: ASTContext.h:1242
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2628
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2644
bool DeclMustBeEmitted(const Decl *D)
Determines if the decl can be CodeGen'ed or deserialized from PCH lazily, only when used; this is onl...
CanQualType OMPArrayShapingTy
Definition: ASTContext.h:1160
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1146
void Deallocate(void *Ptr) const
Definition: ASTContext.h:740
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
CanQualType DependentTy
Definition: ASTContext.h:1147
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
Definition: ASTContext.h:1637
CanQualType OMPIteratorTy
Definition: ASTContext.h:1160
IdentifierTable & Idents
Definition: ASTContext.h:660
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
QualType getUIntPtrType() const
Return a type compatible with "uintptr_t" (C99 7.18.1.4), as defined by the target.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType ArraySectionTy
Definition: ASTContext.h:1159
CanQualType BoolTy
Definition: ASTContext.h:1120
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const
Allocate a TypeSourceInfo where all locations have been initialized to a given location,...
CanQualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
CanQualType BoundMemberTy
Definition: ASTContext.h:1147
CanQualType IntTy
Definition: ASTContext.h:1128
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2675
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2394
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
Definition: ASTContext.h:1119
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
Definition: ASTContext.h:1615
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:779
bool typesAreCompatible(QualType T1, QualType T2, bool CompareUnqualified=false)
Compatibility predicates used to check assignment expressions.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
bool isUnset() const
Definition: Ownership.h:167
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition: Expr.h:6926
Expr * getBase()
Get base of the array section.
Definition: Expr.h:6992
Expr * getLength()
Get length of array section.
Definition: Expr.h:7002
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5141
Expr * getLowerBound()
Get lower bound of array section.
Definition: Expr.h:6996
SourceLocation getColonLocFirst() const
Definition: Expr.h:7023
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2674
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3566
QualType getElementType() const
Definition: Type.h:3578
Attr - This represents one attribute.
Definition: Attr.h:42
Represents an attribute applied to a statement.
Definition: Stmt.h:2090
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:3910
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:4007
bool isRelationalOp() const
Definition: Expr.h:3955
SourceLocation getOperatorLoc() const
Definition: Expr.h:3902
SourceLocation getExprLoc() const
Definition: Expr.h:3901
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:3979
Expr * getRHS() const
Definition: Expr.h:3912
Opcode getOpcode() const
Definition: Expr.h:3905
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition: Expr.cpp:2143
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2539
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2866
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition: StmtCXX.h:135
A call to an overloaded operator written using operator syntax.
Definition: ExprCXX.h:81
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition: DeclCXX.h:1238
bool hasDefinition() const
Definition: DeclCXX.h:572
Represents a C++ nested-name-specifier or a global scope specifier.
Definition: DeclSpec.h:74
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition: DeclSpec.h:215
SourceLocation getBeginLoc() const
Definition: DeclSpec.h:84
bool isSet() const
Deprecated.
Definition: DeclSpec.h:228
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition: DeclSpec.cpp:152
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition: DeclSpec.h:213
Represents the this expression in C++.
Definition: ExprCXX.h:1152
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2830
static CallExpr * Create(const ASTContext &Ctx, Expr *Fn, ArrayRef< Expr * > Args, QualType Ty, ExprValueKind VK, SourceLocation RParenLoc, FPOptionsOverride FPFeatures, unsigned MinNumArgs=0, ADLCallKind UsesADL=NotADL)
Create a call expression.
Definition: Expr.cpp:1494
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:1638
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:3000
QualType withConst() const
Retrieves a version of this type with const applied.
A wrapper class around a pointer that always points to its canonical declaration.
Definition: Redeclarable.h:350
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition: Decl.h:4670
unsigned getNumParams() const
Definition: Decl.h:4712
void setNothrow(bool Nothrow=true)
Definition: Decl.cpp:5443
ImplicitParamDecl * getParam(unsigned i) const
Definition: Decl.h:4714
Describes the capture of either a variable, or 'this', or variable-length array type.
Definition: Stmt.h:3780
This captures a statement into a function.
Definition: Stmt.h:3767
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition: Stmt.cpp:1407
SourceRange getSourceRange() const LLVM_READONLY
Definition: Stmt.h:3970
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition: Stmt.h:3871
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:3962
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3498
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition: Type.h:3134
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition: Stmt.h:1611
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:4213
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:195
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1369
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1436
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2090
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition: DeclBase.h:2219
bool isFileContext() const
Definition: DeclBase.h:2161
ASTContext & getParentASTContext() const
Definition: DeclBase.h:2119
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1399
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
Definition: DeclBase.cpp:1333
DeclContext * getLexicalParent()
getLexicalParent - Returns the containing lexical DeclContext.
Definition: DeclBase.h:2106
bool isNamespace() const
Definition: DeclBase.h:2179
bool isTranslationUnit() const
Definition: DeclBase.h:2166
void addDecl(Decl *D)
Add the declaration D into this context.
Definition: DeclBase.cpp:1766
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition: DeclBase.h:2350
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
Definition: DeclBase.cpp:1384
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context encloses the declaration context DC.
Definition: DeclBase.cpp:1403
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
Definition: DeclBase.cpp:1740
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition: DeclGroup.h:68
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1265
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.cpp:551
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition: Expr.cpp:488
ValueDecl * getDecl()
Definition: Expr.h:1333
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Expr.cpp:556
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1502
SourceLocation getEndLoc() const
Definition: Stmt.h:1525
const DeclGroupRef getDeclGroup() const
Definition: Stmt.h:1520
const Decl * getSingleDecl() const
Definition: Stmt.h:1517
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.h:1528
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
T * getAttr() const
Definition: DeclBase.h:580
bool hasAttrs() const
Definition: DeclBase.h:525
void addAttr(Attr *A)
Definition: DeclBase.cpp:1013
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:600
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition: DeclBase.cpp:154
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition: DeclBase.cpp:567
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition: DeclBase.cpp:577
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition: DeclBase.h:974
bool isInvalidDecl() const
Definition: DeclBase.h:595
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition: DeclBase.h:566
void setAccess(AccessSpecifier AS)
Definition: DeclBase.h:509
SourceLocation getLocation() const
Definition: DeclBase.h:446
void setImplicit(bool I=true)
Definition: DeclBase.h:601
void setReferenced(bool R=true)
Definition: DeclBase.h:630
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition: DeclBase.h:1039
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition: DeclBase.cpp:552
DeclContext * getDeclContext()
Definition: DeclBase.h:455
AccessSpecifier getAccess() const
Definition: DeclBase.h:514
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:438
AttrVec & getAttrs()
Definition: DeclBase.h:531
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition: DeclBase.cpp:358
bool hasAttr() const
Definition: DeclBase.h:584
void setLexicalDeclContext(DeclContext *DC)
Definition: DeclBase.cpp:362
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:968
Kind getKind() const
Definition: DeclBase.h:449
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:434
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
Definition: DeclSpec.h:1903
RAII object that enters a new expression evaluation context.
The return type of classify().
Definition: Expr.h:330
This represents one expression.
Definition: Expr.h:110
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isGLValue() const
Definition: Expr.h:280
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition: Expr.h:671
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3075
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:175
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition: Expr.h:437
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition: Expr.h:239
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition: Expr.cpp:3087
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3070
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3058
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition: Expr.h:245
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3066
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition: Expr.h:277
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition: Expr.h:444
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3050
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition: Expr.h:142
Represents difference between two FPOptions values.
Definition: LangOptions.h:947
Represents a member of a struct/union/class.
Definition: Decl.h:3030
bool isBitField() const
Determines whether this field is a bitfield.
Definition: Decl.h:3121
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4652
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition: Decl.h:3258
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition: Expr.cpp:1078
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition: Stmt.h:2791
Stmt * getBody()
Definition: Stmt.h:2835
Represents a function declaration or definition.
Definition: Decl.h:1932
const ParmVarDecl * getParamDecl(unsigned i) const
Definition: Decl.h:2669
ArrayRef< ParmVarDecl * > parameters() const
Definition: Decl.h:2646
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition: Decl.h:2395
bool isConsteval() const
Definition: Decl.h:2407
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3678
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5002
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition: Stmt.h:2148
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition: Expr.h:1717
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition: Expr.cpp:2074
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition: Overload.h:567
Describes the kind of initialization being performed, along with location information for tokens rela...
static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs=false)
Create a copy initialization.
Describes the sequence of initializations required to initialize a given object or reference with a s...
ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)
Perform the actual initialization of the given entity based on the computed initialization sequence.
Definition: SemaInit.cpp:7521
Describes an entity that is being initialized.
static InitializedEntity InitializeVariable(VarDecl *Var)
Create the initialization entity for a variable.
static IntegerLiteral * Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l)
Returns a new integer literal with value 'V' and type 'type'.
Definition: Expr.cpp:977
Describes the capture of a variable or of this, or of a C++1y init-capture.
Definition: LambdaCapture.h:25
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:476
A class for iterating through a result set and possibly filtering out results.
Definition: Lookup.h:675
Represents the results of name lookup.
Definition: Lookup.h:46
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition: Lookup.h:605
DeclClass * getAsSingle() const
Definition: Lookup.h:558
bool empty() const
Return true if no decls were found.
Definition: Lookup.h:362
Filter makeFilter()
Create a filter for this result set.
Definition: Lookup.h:749
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition: Lookup.h:568
bool isAmbiguous() const
Definition: Lookup.h:324
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
Definition: Lookup.h:331
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition: Lookup.h:575
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition: Lookup.h:634
iterator end() const
Definition: Lookup.h:359
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
iterator begin() const
Definition: Lookup.h:358
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3187
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3270
Expr * getBase() const
Definition: Expr.h:3264
static MemberExpr * CreateImplicit(const ASTContext &C, Expr *Base, bool IsArrow, ValueDecl *MemberDecl, QualType T, ExprValueKind VK, ExprObjectKind OK)
Create an implicit MemberExpr, with no location, qualifier, template arguments, and so on.
Definition: Expr.h:3248
This represents a decl that may have a name.
Definition: Decl.h:249
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:315
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition: Decl.h:292
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
Definition: Decl.cpp:1811
A C++ nested-name-specifier augmented with source location information.
static OMPAbsentClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
This represents 'acq_rel' clause in the '#pragma omp atomic|flush' directives.
This represents 'acquire' clause in the '#pragma omp atomic|flush' directives.
static OMPAffinityClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Creates clause with a modifier a list of locator items.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
static OMPAlignedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Expr *A)
Creates clause with a list of variables VL and alignment A.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
Definition: OpenMPClause.h:575
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
Definition: DeclOpenMP.cpp:57
This represents 'allocator' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:414
An explicit cast in C or a C-style cast in C++, which uses the syntax ([s1][s2]......
Definition: ExprOpenMP.h:24
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Definition: Expr.cpp:5222
static OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
Definition: StmtOpenMP.cpp:802
This represents 'at' clause in the '#pragma omp error' directive.
SourceLocation getAtKindKwLoc() const
Returns location of clause kind.
OpenMPAtClauseKind getAtKind() const
Returns kind of the clause.
This represents 'atomic_default_mem_order' clause in the '#pragma omp requires' directive.
static OMPAtomicDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expressions Exprs)
Creates directive with a list of Clauses and 'x', 'v' and 'expr' parts of the atomic construct (see S...
Definition: StmtOpenMP.cpp:970
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:834
This represents 'bind' clause in the '#pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
Definition: StmtOpenMP.cpp:890
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Definition: StmtOpenMP.cpp:876
static OMPCanonicalLoop * create(const ASTContext &Ctx, Stmt *LoopStmt, CapturedStmt *DistanceFunc, CapturedStmt *LoopVarFunc, DeclRefExpr *LoopVarRef)
Create a new OMPCanonicalLoop.
Definition: StmtOpenMP.h:163
This represents 'capture' clause in the '#pragma omp atomic' directive.
Pseudo declaration for capturing expressions.
Definition: DeclOpenMP.h:383
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
Definition: DeclOpenMP.cpp:176
Class that represents a component of a mappable expression.
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'schedule',...
Definition: OpenMPClause.h:195
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
Definition: OpenMPClause.h:55
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
Definition: OpenMPClause.h:71
SourceLocation getEndLoc() const
Returns the ending location of the clause.
Definition: OpenMPClause.h:74
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
Definition: OpenMPClause.h:83
This represents 'collapse' clause in the '#pragma omp ...' directive.
This represents 'compare' clause in the '#pragma omp atomic' directive.
static OMPContainsClause * Create(const ASTContext &C, ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
static OMPCopyinClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
static OMPCopyprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps)
Creates clause with a list of variables VL.
This represents '#pragma omp critical' directive.
Definition: StmtOpenMP.h:2076
static OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:619
This represents '#pragma omp declare mapper ...' directive.
Definition: DeclOpenMP.h:287
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
Definition: DeclOpenMP.cpp:144
This represents '#pragma omp declare reduction ...' directive.
Definition: DeclOpenMP.h:177
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
Definition: DeclOpenMP.cpp:114
This represents 'default' clause in the '#pragma omp ...' directive.
This represents 'defaultmap' clause in the '#pragma omp ...' directive.
This represents implicit clause 'depend' for the '#pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
static OMPDepobjDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:921
This represents 'destroy' clause in the '#pragma omp depobj' directive or the '#pragma omp interop' d...
This represents 'detach' clause in the '#pragma omp task' directive.
This represents 'device' clause in the '#pragma omp ...' directive.
static OMPDispatchDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, SourceLocation TargetCallLoc)
Creates directive with a list of Clauses.
This represents 'dist_schedule' clause in the '#pragma omp ...' directive.
static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents the 'doacross' clause for the '#pragma omp ordered' directive.
static OMPDoacrossClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of expressions VL.
This represents 'dynamic_allocators' clause in the '#pragma omp requires' directive.
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Definition: StmtOpenMP.cpp:819
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This is a basic class for representing single OpenMP executable directive.
Definition: StmtOpenMP.h:266
OpenMPDirectiveKind getDirectiveKind() const
Definition: StmtOpenMP.h:556
This represents 'fail' clause in the '#pragma omp atomic' directive.
This represents 'filter' clause in the '#pragma omp ...' directive.
This represents 'final' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:690
static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL, ArrayRef< Expr * > InitVL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents implicit clause 'flush' for the '#pragma omp flush' directive.
static OMPFlushClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPFlushDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:906
static OMPForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:336
static OMPForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:489
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Representation of the 'full' clause of the '#pragma omp unroll' directive.
Definition: OpenMPClause.h:939
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
static OMPGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'grainsize' clause in the '#pragma omp ...' directive.
static OMPHasDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
This represents 'hint' clause in the '#pragma omp ...' directive.
This represents the 'holds' clause in the '#pragma omp assume' directive.
This represents 'if' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:587
static OMPInReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > TaskgroupDescriptors, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPInclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPInitClause * Create(const ASTContext &C, Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Creates a fully specified clause.
static OMPInterchangeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp interchange'.
Definition: StmtOpenMP.cpp:468
static OMPInteropDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPIsDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
Definition: Expr.cpp:5351
static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > SrcExprs, ArrayRef< Expr * > DstExprs, ArrayRef< Expr * > AssignmentOps, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents clause 'linear' in the '#pragma omp ...' directives.
Expr * getStep()
Returns linear step.
void setUpdates(ArrayRef< Expr * > UL)
Sets the list of update expressions for linear variables.
privates_range privates()
void setFinals(ArrayRef< Expr * > FL)
Sets the list of final update expressions for linear variables.
void setUsedExprs(ArrayRef< Expr * > UE)
Sets the list of used expressions for the linear clause.
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
Expr * getCalcStep()
Returns expression to calculate linear step.
OpenMPLinearClauseKind getModifier() const
Return modifier.
The base class for all loop-based directives, including loop transformation directives.
Definition: StmtOpenMP.h:683
static bool doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops, llvm::function_ref< bool(unsigned, Stmt *)> Callback, llvm::function_ref< void(OMPLoopTransformationDirective *)> OnTransformationCallback)
Calls the specified callback function for all the loops in CurStmt, from the outermost to the innermo...
Definition: StmtOpenMP.cpp:125
The base class for all loop transformation directives.
Definition: StmtOpenMP.h:960
static OMPMapClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapModifiers, ArrayRef< SourceLocation > MapModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId, OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc)
Creates clause with a list of variables VL.
static OMPMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:604
static OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents 'mergeable' clause in the '#pragma omp ...' directive.
This represents 'message' clause in the '#pragma omp error' directive.
Expr * getMessageString() const
Returns message string of the clause.
This represents the 'no_openmp' clause in the '#pragma omp assume' directive.
This represents the 'no_openmp_routines' clause in the '#pragma omp assume' directive.
This represents the 'no_parallelism' clause in the '#pragma omp assume' directive.
This represents 'nocontext' clause in the '#pragma omp ...' directive.
This represents 'nogroup' clause in the '#pragma omp ...' directive.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the '#pragma omp ...' directive.
This represents 'nowait' clause in the '#pragma omp ...' directive.
This represents 'num_tasks' clause in the '#pragma omp ...' directive.
static OMPNumTeamsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'num_threads' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:736
This represents 'order' clause in the '#pragma omp ...' directive.
SourceLocation getKindKwLoc() const
Returns location of clause kind.
OpenMPOrderClauseKind getKind() const
Returns kind of the clause.
This represents 'ordered' clause in the '#pragma omp ...' directive.
Expr * getNumForLoops() const
Return the number of associated for-loops.
static OMPOrderedClause * Create(const ASTContext &C, Expr *Num, unsigned NumLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'ordered' clause.
static OMPOrderedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:951
static OMPParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:281
static OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:635
static OMPParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:680
static OMPParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMaskedDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:740
static OMPParallelMaskedTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMaskedTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelMasterDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:724
static OMPParallelMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPParallelMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPParallelSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:756
Representation of the 'partial' clause of the '#pragma omp unroll' directive.
Definition: OpenMPClause.h:967
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This represents 'priority' clause in the '#pragma omp ...' directive.
static OMPPrivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PrivateVL)
Creates clause with a list of variables VL.
This represents 'proc_bind' clause in the '#pragma omp ...' directive.
This represents 'read' clause in the '#pragma omp atomic' directive.
static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, OpenMPReductionClauseModifier Modifier, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, ArrayRef< Expr * > CopyOps, ArrayRef< Expr * > CopyArrayTemps, ArrayRef< Expr * > CopyArrayElems, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
This represents 'relaxed' clause in the '#pragma omp atomic' directives.
This represents 'release' clause in the '#pragma omp atomic|flush' directives.
This represents '#pragma omp requires...' directive.
Definition: DeclOpenMP.h:417
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
Definition: DeclOpenMP.cpp:86
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp reverse'.
Definition: StmtOpenMP.cpp:451
This represents 'reverse_offload' clause in the '#pragma omp requires' directive.
This represents 'simd' clause in the '#pragma omp ...' directive.
This represents 'safelen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:781
Expr * getSafelen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:801
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:936
This represents 'schedule' clause in the '#pragma omp ...' directive.
SourceLocation getFirstScheduleModifierLoc() const
Get the first modifier location.
OpenMPScheduleClauseModifier getSecondScheduleModifier() const
Get the second modifier of the clause.
OpenMPScheduleClauseModifier getFirstScheduleModifier() const
Get the first modifier of the clause.
SourceLocation getSecondScheduleModifierLoc() const
Get the second modifier location.
static OMPScopeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
Definition: StmtOpenMP.cpp:570
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
Definition: StmtOpenMP.cpp:552
static OMPSectionsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:532
This represents 'seq_cst' clause in the '#pragma omp atomic' directive.
This represents 'severity' clause in the '#pragma omp error' directive.
OpenMPSeverityClauseKind getSeverityKind() const
Returns kind of the clause.
SourceLocation getSeverityKindKwLoc() const
Returns location of clause kind.
static OMPSharedClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static OMPSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:301
This represents 'simdlen' clause in the '#pragma omp ...' directive.
Definition: OpenMPClause.h:816
Expr * getSimdlen() const
Return safe iteration space distance.
Definition: OpenMPClause.h:836
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:587
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:995
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, bool HasCancel)
Creates directive with a list of Clauses.
Definition: StmtOpenMP.cpp:775
static OMPTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTaskReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef< Expr * > Privates, ArrayRef< Expr * > LHSExprs, ArrayRef< Expr * > RHSExprs, ArrayRef< Expr * > ReductionOps, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL.
static OMPTaskgroupDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *ReductionRef)
Creates directive.
Definition: StmtOpenMP.cpp:860
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
Definition: StmtOpenMP.cpp:846
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
Definition: StmtOpenMP.cpp:791
static OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents '#pragma omp threadprivate ...' directive.
Definition: DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
Definition: DeclOpenMP.cpp:28
This represents 'threads' clause in the '#pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp tile'.
Definition: StmtOpenMP.cpp:408
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
This represents 'unified_address' clause in the '#pragma omp requires' directive.
This represents 'unified_shared_memory' clause in the '#pragma omp requires' directive.
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for '#pragma omp unroll'.
Definition: StmtOpenMP.cpp:429
This represents 'untied' clause in the '#pragma omp ...' directive.
static OMPUpdateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates clause for 'atomic' directive.
This represents the 'use' clause in '#pragma omp ...' directives.
static OMPUseDeviceAddrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUseDevicePtrClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< Expr * > PrivateVars, ArrayRef< Expr * > Inits, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists)
Creates clause with a list of variables Vars.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
varlist_range varlist()
Definition: OpenMPClause.h:319
SourceLocation getLParenLoc() const
Returns the location of '('.
Definition: OpenMPClause.h:335
unsigned varlist_size() const
Definition: OpenMPClause.h:316
This represents 'weak' clause in the '#pragma omp atomic' directives.
This represents 'write' clause in the '#pragma omp atomic' directive.
This represents 'ompx_attribute' clause in a directive that might generate an outlined function.
This represents 'ompx_bare' clause in the '#pragma omp target teams ...' directive.
This represents 'ompx_dyn_cgroup_mem' clause in the '#pragma omp target ...' directive.
Wrapper for void* pointer.
Definition: Ownership.h:50
void * getAsOpaquePtr() const
Definition: Ownership.h:90
PtrTy get() const
Definition: Ownership.h:80
static OpaquePtr make(PtrTy P)
Definition: Ownership.h:60
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1173
void setIsUnique(bool V)
Definition: Expr.h:1225
Represents a parameter to a function.
Definition: Decl.h:1722
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition: Decl.cpp:2903
ParsedAttr - Represents a syntactic attribute.
Definition: ParsedAttr.h:129
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
Definition: Expr.cpp:4953
A (possibly-)qualified type.
Definition: Type.h:941
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition: Type.cpp:2751
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition: Type.h:7839
QualType withRestrict() const
Definition: Type.h:1182
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition: Type.cpp:3476
QualType withConst() const
Definition: Type.h:1166
void addConst()
Add the const type qualifier to this QualType.
Definition: Type.h:1163
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:1008
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7750
bool isConstant(const ASTContext &Ctx) const
Definition: Type.h:1101
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: Type.h:7951
QualType getCanonicalType() const
Definition: Type.h:7802
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:7844
bool isMoreQualifiedThan(QualType Other) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition: Type.h:7922
const Type * getTypePtrOrNull() const
Definition: Type.h:7754
Represents a struct/union/class.
Definition: Decl.h:4145
field_range fields() const
Definition: Decl.h:4351
field_iterator field_begin() const
Definition: Decl.cpp:5068
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5965
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
decl_type * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Definition: Redeclarable.h:205
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Definition: Redeclarable.h:227
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3428
Scope - A scope is a transient data structure that is used while parsing the program.
Definition: Scope.h:41
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition: Scope.h:381
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition: Scope.h:305
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition: Scope.h:530
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition: Scope.h:270
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition: Scope.h:523
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition: Scope.h:150
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:110
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition: SemaBase.cpp:32
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
StmtResult ActOnOpenMPTargetParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPNocontextClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nocontext' clause.
OMPClause * ActOnOpenMPXDynCGroupMemClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_dyn_cgroup_mem' clause.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
bool isInOpenMPTaskUntiedContext() const
Return true if currently in OpenMP task with untied clause context.
OMPClause * ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'untied' clause.
OMPClause * ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'safelen' clause.
OMPClause * ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'holds' clause.
StmtResult ActOnOpenMPParallelMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)
Called on well-formed 'absent' or 'contains' clauses.
void tryCaptureOpenMPLambdas(ValueDecl *V)
Function tries to capture lambda's captured variables in the OpenMP region before the original lambda...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPReductionClauseModifier Modifier, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'reduction' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the '#pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
StmtResult ActOnOpenMPDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPFirstprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'firstprivate' clause.
StmtResult ActOnOpenMPDepobjDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp depobj'.
ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc)
OMPClause * ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'priority' clause.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nowait' clause.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
StmtResult ActOnOpenMPMasterTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop simd' after parsing of the associated statement.
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'from' clause.
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers=std::nullopt)
Called on well-formed 'to' clause.
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition: SemaOpenMP.h:111
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
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:243
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
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:55
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'hint' clause.
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)
StmtResult ActOnOpenMPTargetTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute' after parsing of the associated statement...
StmtResult ActOnOpenMPParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for' after parsing of the associated statement.
OMPClause * ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'capture' clause.
StmtResult ActOnOpenMPForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for' after parsing of the associated statement.
StmtResult ActOnOpenMPAtomicDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp atomic' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target update'.
StmtResult ActOnOpenMPOrderedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp ordered' after parsing of the associated statement.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
std::pair< StringRef, QualType > CapturedParamNameType
Definition: SemaOpenMP.h:56
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition: SemaOpenMP.h:371
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void startOpenMPLoop()
If the current region is a loop-based region, mark the start of the loop construct.
StmtResult ActOnOpenMPTargetDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target' after parsing of the associated statement.
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
OMPThreadPrivateDecl * CheckOMPThreadPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPThreadPrivateDecl and checks its correctness.
void handleOMPAssumeAttr(Decl *D, const ParsedAttr &AL)
OMPClause * ActOnOpenMPSeverityClause(OpenMPSeverityClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'severity' clause.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp tile' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions=std::nullopt)
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
Definition: SemaOpenMP.h:431
StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute simd' after parsing of the associated stat...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
Definition: Sema.h:969
Expr * get() const
Definition: Sema.h:7300
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition: Sema.h:12138
Abstract base class used for diagnosing integer constant expression violations.
Definition: Sema.h:7249
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:493
ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo)
Package the given type and TSI into a ParsedType.
Definition: SemaType.cpp:6329
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition: Sema.h:763
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:1558
ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val)
Definition: SemaExpr.cpp:3590
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15288
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:9015
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition: Sema.h:9056
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition: Sema.h:9058
@ LookupAnyName
Look up any declaration with any name.
Definition: Sema.h:9060
ImplicitConversionSequence TryImplicitConversion(Expr *From, QualType ToType, bool SuppressUserConversions, AllowedExplicit AllowExplicit, bool InOverloadResolution, bool CStyle, bool AllowObjCWritebackConversion)
SemaOpenMP & OpenMP()
Definition: Sema.h:1179
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition: Sema.h:4336
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17182
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:20133
SmallVector< sema::FunctionScopeInfo *, 4 > FunctionScopes
Stack containing information about each of the nested function, block, and method scopes that are cur...
Definition: Sema.h:900
@ AR_inaccessible
Definition: Sema.h:1314
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:2296
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition: Sema.cpp:2165
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:6207
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:16940
FPOptionsOverride CurFPFeatureOverrides()
Definition: Sema.h:1710
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:19920
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:1567
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ASTContext & Context
Definition: Sema.h:962
void ActOnCapturedRegionError()
Definition: SemaStmt.cpp:4567
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition: SemaDecl.cpp:72
@ AllowFold
Definition: Sema.h:7265
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
Definition: SemaDecl.cpp:1496
void CleanupVarDeclMarking()
Definition: SemaExpr.cpp:19414
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:752
ASTContext & getASTContext() const
Definition: Sema.h:560
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
Definition: SemaExpr.cpp:15567
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:18696
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:19662
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:17603
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition: Sema.h:868
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
Definition: SemaExpr.cpp:2198
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:2184
const LangOptions & getLangOpts() const
Definition: Sema.h:553
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:961
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:6408
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:960
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition: Sema.cpp:2409
DeclContext * getCurLexicalContext() const
Definition: Sema.h:767
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:4478
sema::FunctionScopeInfo * getCurFunction() const
Definition: Sema.h:993
Expr * BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit)
Build a CXXThisExpr and mark it referenced in the current context.
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:640
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition: Sema.h:14983
FunctionEmissionStatus getEmissionStatus(const FunctionDecl *Decl, bool Final=false)
Definition: SemaDecl.cpp:20204
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition: Sema.cpp:2365
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition: Sema.h:1097
StmtResult ActOnCapturedRegionEnd(Stmt *S)
Definition: SemaStmt.cpp:4582
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
Definition: SemaExpr.cpp:4093
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:20717
bool inTemplateInstantiation() const
Determine whether we are currently performing template instantiation.
Definition: Sema.h:13490
@ TryCapture_ExplicitByVal
Definition: Sema.h:6615
@ AA_Initializing
Definition: Sema.h:6500
@ AA_Converting
Definition: Sema.h:6499
@ AA_Casting
Definition: Sema.h:6502
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:11095
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?: operation.
Definition: SemaExpr.cpp:8705
ExprResult PerformImplicitConversion(Expr *From, QualType ToType, const ImplicitConversionSequence &ICS, AssignmentAction Action, CheckedConversionKind CCK=CheckedConversionKind::Implicit)
PerformImplicitConversion - Perform an implicit conversion of the expression From to the type ToType ...
bool isCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind=CompleteTypeKind::Default)
Definition: Sema.h:14938
@ CTK_ErrorRecovery
Definition: Sema.h:9409
void setFunctionHasBranchProtectedScope()
Definition: Sema.cpp:2350
RedeclarationKind forRedeclarationInCurContext() const
std::pair< StringRef, QualType > CapturedParamNameType
Definition: Sema.h:10939
ParsedType getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec *SS=nullptr, bool isClassName=false, bool HasTrailingDot=false, ParsedType ObjectType=nullptr, bool IsCtorOrDtorName=false, bool WantNontrivialTypeSourceInfo=false, bool IsClassTemplateDeductionContext=true, ImplicitTypenameContext AllowImplicitTypename=ImplicitTypenameContext::No, IdentifierInfo **CorrectedII=nullptr)
If the identifier refers to a type name within this scope, return the declaration of that type.
Definition: SemaDecl.cpp:288
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
Definition: SemaExpr.cpp:5102
@ 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:5653
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:8907
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition: Sema.h:923
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:17681
void PushDeclContext(Scope *S, DeclContext *DC)
Set the current declaration context until it gets popped.
Definition: SemaDecl.cpp:1307
void PopDeclContext()
Definition: SemaDecl.cpp:1314
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:1578
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:13837
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
Definition: SemaDecl.cpp:13277
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition: Sema.cpp:1967
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr)
Definition: SemaExpr.cpp:15135
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:14600
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:2380
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition: Sema.cpp:2738
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:2731
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition: SemaStmt.cpp:416
FullExprArg MakeFullExpr(Expr *Arg)
Definition: Sema.h:7314
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:8293
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Definition: StmtVisitor.h:185
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:350
child_range children()
Definition: Stmt.cpp:287
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Stmt * IgnoreContainers(bool IgnoreCaptured=false)
Skip no-op (attributed, compound) container stmts and skip captured stmt at the top,...
Definition: Stmt.cpp:197
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:338
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4719
bool isTLSSupported() const
Whether the target supports thread-local storage.
Definition: TargetInfo.h:1576
bool isVLASupported() const
Whether target supports variable-length arrays.
Definition: TargetInfo.h:1587
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition: Decl.h:3367
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:192
A container of type source information.
Definition: Type.h:7721
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition: TypeLoc.h:256
QualType getType() const
Return the type wrapped by this type source info.
Definition: Type.h:7732
The base class of the type hierarchy.
Definition: Type.h:1829
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1882
bool isConstantArrayType() const
Definition: Type.h:8079
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
Definition: Type.cpp:2021
bool isArrayType() const
Definition: Type.h:8075
bool isArithmeticType() const
Definition: Type.cpp:2281
bool isPointerType() const
Definition: Type.h:8003
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8359
const T * castAs() const
Member-template castAs<specific type>.
Definition: Type.h:8607
bool isReferenceType() const
Definition: Type.h:8021
bool isEnumeralType() const
Definition: Type.h:8107
bool isScalarType() const
Definition: Type.h:8418
bool isVariableArrayType() const
Definition: Type.h:8087
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition: Type.cpp:2058
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition: Type.cpp:2236
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: Type.h:8313
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2703
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:8288
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2695
bool isAnyComplexType() const
Definition: Type.h:8111
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition: Type.h:2354
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition: Type.cpp:2186
bool isFunctionProtoType() const
Definition: Type.h:2528
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition: Type.h:8460
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition: Type.h:2713
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8593
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition: Type.cpp:2362
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition: Type.h:8557
bool isFunctionType() const
Definition: Type.h:7999
bool isStructureOrClassType() const
Definition: Type.cpp:657
bool isRealFloatingType() const
Floating point categories.
Definition: Type.cpp:2266
bool isFloatingType() const
Definition: Type.cpp:2249
bool isAnyPointerType() const
Definition: Type.h:8011
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8540
bool isRecordType() const
Definition: Type.h:8103
bool isUnionType() const
Definition: Type.cpp:671
bool isFunctionNoProtoType() const
Definition: Type.h:2527
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1886
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2188
Expr * getSubExpr() const
Definition: Expr.h:2233
Opcode getOpcode() const
Definition: Expr.h:2228
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
Definition: ExprCXX.cpp:420
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
Definition: UnresolvedSet.h:92
A set of unresolved declarations.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:667
void setType(QualType newType)
Definition: Decl.h:679
QualType getType() const
Definition: Decl.h:678
VarDecl * getPotentiallyDecomposedVarDecl()
Definition: DeclCXX.cpp:3339
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:1104
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
@ NUM_OVERLOADED_OPERATORS
Definition: OperatorKinds.h:26
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
@ CPlusPlus
Definition: LangStandard.h:56
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition: OpenMPKinds.h:24
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
Definition: OpenMPKinds.h:118
@ OMPC_DEFAULTMAP_MODIFIER_last
Definition: OpenMPKinds.h:123
@ OMPC_DEFAULTMAP_MODIFIER_unknown
Definition: OpenMPKinds.h:119
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
Definition: OpenMPKinds.h:171
@ OMPC_ORDER_MODIFIER_unknown
Definition: OpenMPKinds.h:172
@ OMPC_ORDER_MODIFIER_last
Definition: OpenMPKinds.h:175
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition: Specifiers.h:149
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
Definition: OpenMPKinds.h:135
@ OMPC_AT_unknown
Definition: OpenMPKinds.h:138
Expr * AssertSuccess(ExprResult R)
Definition: Ownership.h:274
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
Definition: Lambda.h:37
@ LCK_This
Capturing the *this object by reference.
Definition: Lambda.h:34
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
Definition: OpenMPKinds.h:186
@ OMPC_REDUCTION_unknown
Definition: OpenMPKinds.h:189
BinaryOperatorKind
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition: OpenMPKinds.h:38
@ OMPC_SCHEDULE_MODIFIER_last
Definition: OpenMPKinds.h:43
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition: OpenMPKinds.h:39
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition: OpenMPKinds.h:27
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
@ CR_Default
Definition: CapturedStmt.h:17
@ CR_OpenMP
Definition: CapturedStmt.h:19
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
@ SC_Auto
Definition: Specifiers.h:256
@ SC_Register
Definition: Specifiers.h:257
@ SC_None
Definition: Specifiers.h:250
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
Definition: OpenMPKinds.h:103
@ OMPC_DIST_SCHEDULE_unknown
Definition: OpenMPKinds.h:106
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition: Decl.h:5031
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
Definition: OpenMPKinds.h:219
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
Definition: OpenMPKinds.h:87
ExprResult ExprEmpty()
Definition: Ownership.h:271
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
StmtResult StmtError()
Definition: Ownership.h:265
@ SD_Static
Static storage duration.
Definition: Specifiers.h:331
@ Parameter
The parameter type of a method or function.
@ Result
The result type of a method or function.
bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a teams-kind directive.
bool isOpenMPGenericLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive constitutes a 'loop' directive in the outermost nest.
OpenMPBindClauseKind
OpenMP bindings for the 'bind' clause.
Definition: OpenMPKinds.h:200
@ OMPC_BIND_unknown
Definition: OpenMPKinds.h:203
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
Definition: OpenMPKinds.h:157
@ OMPC_LASTPRIVATE_unknown
Definition: OpenMPKinds.h:160
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition: OpenMPKinds.h:54
@ OMPC_DEPEND_unknown
Definition: OpenMPKinds.h:58
OpenMPGrainsizeClauseModifier
Definition: OpenMPKinds.h:206
@ OMPC_GRAINSIZE_unknown
Definition: OpenMPKinds.h:209
OpenMPNumTasksClauseModifier
Definition: OpenMPKinds.h:212
@ OMPC_NUMTASKS_unknown
Definition: OpenMPKinds.h:215
ActionResult< Expr * > ExprResult
Definition: Ownership.h:248
ExprResult ExprError()
Definition: Ownership.h:264
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
Definition: OpenMPKinds.h:142
@ OMPC_SEVERITY_unknown
Definition: OpenMPKinds.h:145
bool isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of the composite or combined directives that need loop ...
static constexpr unsigned NumberOfOMPMotionModifiers
Number of allowed motion-modifiers.
Definition: OpenMPKinds.h:99
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition: OpenMPKinds.h:91
@ OMPC_MOTION_MODIFIER_unknown
Definition: OpenMPKinds.h:95
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
Definition: OpenMPKinds.h:110
@ OMPC_DEFAULTMAP_unknown
Definition: OpenMPKinds.h:114
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition: OpenMPKinds.h:62
@ OMPC_LINEAR_unknown
Definition: OpenMPKinds.h:66
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "informational".
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
ExprValueKind
The categorization of expression values, currently following the C++11 scheme.
Definition: Specifiers.h:132
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
for(const auto &A :T->param_types())
const FunctionProtoType * T
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
Definition: OpenMPKinds.h:127
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
Definition: OpenMPKinds.h:131
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
ActionResult< Decl * > DeclResult
Definition: Ownership.h:254
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
Definition: OpenMPKinds.h:47
@ OMPC_DEVICE_unknown
Definition: OpenMPKinds.h:50
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition: OpenMPKinds.h:78
@ OMPC_MAP_MODIFIER_unknown
Definition: OpenMPKinds.h:79
bool isOpenMPCombinedParallelADirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a combined construct for which the first construct is a parallel...
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
Definition: OpenMPKinds.h:164
@ OMPC_ORDER_unknown
Definition: OpenMPKinds.h:167
@ Implicit
An implicit conversion.
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition: OpenMPKinds.h:30
@ OMPC_SCHEDULE_unknown
Definition: OpenMPKinds.h:34
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:123
@ AS_public
Definition: Specifiers.h:124
@ AS_none
Definition: Specifiers.h:127
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition: OpenMPKinds.h:70
@ OMPC_MAP_unknown
Definition: OpenMPKinds.h:74
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition: Specifiers.h:177
unsigned long uint64_t
#define true
Definition: stdbool.h:25
#define false
Definition: stdbool.h:26
#define bool
Definition: stdbool.h:24
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
const Expr * RHS
The original right-hand side.
Definition: ExprCXX.h:310
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition: ExprCXX.h:306
const Expr * LHS
The original left-hand side.
Definition: ExprCXX.h:308
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
SourceLocation getBeginLoc() const
getBeginLoc - Retrieve the location of the first token.
std::string getAsString() const
getAsString - Retrieve the human-readable string for this name.
SourceLocation getEndLoc() const LLVM_READONLY
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:642
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:644
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:630
Extra information about a function prototype.
Definition: Type.h:5087
llvm::SmallVector< Expr *, 4 > PreferTypes
Definition: OpenMPKinds.h:232
Iterator definition representation.
Definition: ExprOpenMP.h:160
Helper expressions and declaration for OMPIteratorExpr class for each iteration space.
Definition: ExprOpenMP.h:111
Expr * CounterUpdate
Updater for the internal counter: ++CounterVD;.
Definition: ExprOpenMP.h:121
Expr * Upper
Normalized upper bound.
Definition: ExprOpenMP.h:116
Expr * Update
Update expression for the originally specified iteration variable, calculated as VD = Begin + Counter...
Definition: ExprOpenMP.h:119
VarDecl * CounterVD
Internal normalized counter.
Definition: ExprOpenMP.h:113
Expr * ParForInDistCond
'omp parallel for' loop condition used when composed with 'omp distribute' in the same construct and ...
Definition: StmtOpenMP.h:736
Expr * LB
DistributeLowerBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:710
Expr * Init
Distribute loop iteration variable init used when composing 'omp distribute' with 'omp for' in a same...
Definition: StmtOpenMP.h:720
Expr * NUB
Update of UpperBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:729
Expr * EUB
DistributeEnsureUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct,...
Definition: StmtOpenMP.h:716
Expr * UB
DistributeUpperBound - used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:713
Expr * NLB
Update of LowerBound for statically scheduled omp loops for outer loop in combined constructs (e....
Definition: StmtOpenMP.h:726
Expr * DistCond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct whe...
Definition: StmtOpenMP.h:732
Expr * Cond
Distribute Loop condition used when composing 'omp distribute' with 'omp for' in a same construct.
Definition: StmtOpenMP.h:723
The expressions built for the OpenMP loop CodeGen for the whole collapsed loop nest.
Definition: StmtOpenMP.h:741
Expr * LastIteration
Loop last iteration number.
Definition: StmtOpenMP.h:745
SmallVector< Expr *, 4 > DependentInits
List of initializers required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:803
SmallVector< Expr *, 4 > Inits
Expressions for loop counters inits for CodeGen.
Definition: StmtOpenMP.h:793
Expr * PrevEUB
PrevEUB - expression similar to EUB but to be used when loop scheduling uses PrevLB and PrevUB (e....
Definition: StmtOpenMP.h:787
Expr * DistInc
DistInc - increment expression for distribute loop when found combined with a further loop level (e....
Definition: StmtOpenMP.h:781
Expr * IL
IsLastIteration - local flag variable passed to runtime.
Definition: StmtOpenMP.h:759
SmallVector< Expr *, 4 > PrivateCounters
PrivateCounters Loop counters.
Definition: StmtOpenMP.h:791
bool builtAll()
Check if all the expressions are built (does not check the worksharing ones).
Definition: StmtOpenMP.h:815
Expr * CalcLastIteration
Calculation of last iteration.
Definition: StmtOpenMP.h:749
SmallVector< Expr *, 4 > Updates
Expressions for loop counters update for CodeGen.
Definition: StmtOpenMP.h:795
Expr * ST
Stride - local variable passed to runtime.
Definition: StmtOpenMP.h:765
SmallVector< Expr *, 4 > Finals
Final loop counter values for GodeGen.
Definition: StmtOpenMP.h:797
SmallVector< Expr *, 4 > FinalsConditions
List of final conditions required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:806
Expr * PreCond
Loop pre-condition.
Definition: StmtOpenMP.h:751
Stmt * PreInits
Init statement for all captured expressions.
Definition: StmtOpenMP.h:808
Expr * IterationVarRef
Loop iteration variable.
Definition: StmtOpenMP.h:743
Expr * NumIterations
Loop number of iterations.
Definition: StmtOpenMP.h:747
SmallVector< Expr *, 4 > Counters
Counters Loop counters.
Definition: StmtOpenMP.h:789
Expr * NLB
Update of LowerBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:769
Expr * PrevUB
PreviousUpperBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:777
DistCombinedHelperExprs DistCombinedFields
Expressions used when combining OpenMP loop pragmas.
Definition: StmtOpenMP.h:811
void clear(unsigned Size)
Initialize all the fields to null.
Definition: StmtOpenMP.h:825
Expr * EUB
EnsureUpperBound – expression UB = min(UB, NumIterations).
Definition: StmtOpenMP.h:767
Expr * UB
UpperBound - local variable passed to runtime.
Definition: StmtOpenMP.h:763
Expr * NUB
Update of UpperBound for statically scheduled 'omp for' loops.
Definition: StmtOpenMP.h:771
Expr * LB
LowerBound - local variable passed to runtime.
Definition: StmtOpenMP.h:761
Expr * PrevLB
PreviousLowerBound - local variable passed to runtime in the enclosing schedule or null if that does ...
Definition: StmtOpenMP.h:774
SmallVector< Expr *, 4 > DependentCounters
List of counters required for the generation of the non-rectangular loops.
Definition: StmtOpenMP.h:800
Expr * Init
Loop iteration variable init.
Definition: StmtOpenMP.h:755
Data for list of allocators.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
This structure contains most locations needed for by an OMPVarListClause.
Definition: OpenMPClause.h:259
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
Definition: OpenMPClause.h:261
SourceLocation LParenLoc
Location of '('.
Definition: OpenMPClause.h:263
SourceLocation EndLoc
Ending location of the clause.
Definition: OpenMPClause.h:265
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition: SemaOpenMP.h:316
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition: SemaOpenMP.h:313
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition: SemaOpenMP.h:310
SourceLocation Loc
The directive location.
Definition: SemaOpenMP.h:319
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition: SemaOpenMP.h:307
Data structure for iterator expression.
Definition: SemaOpenMP.h:1381
Data used for processing a list of variables in OpenMP clauses.
Definition: SemaOpenMP.h:1125
Data for list of allocators.
Definition: SemaOpenMP.h:1321
Clang specific specialization of the OMPContext to lookup target features.