clang 24.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
16
17#include "TreeTransform.h"
20#include "clang/AST/Attr.h"
22#include "clang/AST/Decl.h"
23#include "clang/AST/DeclCXX.h"
28#include "clang/AST/Stmt.h"
29#include "clang/AST/StmtCXX.h"
38#include "clang/Sema/Lookup.h"
40#include "clang/Sema/Scope.h"
42#include "clang/Sema/Sema.h"
43#include "llvm/ADT/IndexedMap.h"
44#include "llvm/ADT/PointerEmbeddedInt.h"
45#include "llvm/ADT/STLExtras.h"
46#include "llvm/ADT/Sequence.h"
47#include "llvm/ADT/SetVector.h"
48#include "llvm/ADT/SmallSet.h"
49#include "llvm/ADT/StringExtras.h"
50#include "llvm/Frontend/OpenMP/OMPAssume.h"
51#include "llvm/Frontend/OpenMP/OMPConstants.h"
52#include "llvm/Frontend/OpenMP/OMPVersion.h"
53#include "llvm/IR/Assumptions.h"
54#include <limits>
55#include <optional>
56
57using namespace clang;
58using namespace llvm::omp;
59
60//===----------------------------------------------------------------------===//
61// Stack of data-sharing attributes for variables
62//===----------------------------------------------------------------------===//
63
65 Sema &SemaRef, Expr *E,
67 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
68
70
71namespace {
72/// Default data sharing attributes, which can be applied to directive.
73enum DefaultDataSharingAttributes {
74 DSA_unspecified = 0, /// Data sharing attribute not specified.
75 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
76 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
77 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
78 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
79};
80
81/// Variable Category attributes to restrict the modifier of the
82/// default clause (DefaultDataSharingAttributes)
83/// Not mentioning any Variable category attribute indicates
84/// the modifier (DefaultDataSharingAttributes) is for all variables.
85enum DefaultDataSharingVCAttributes {
86 DSA_VC_all = 0, /// for all variables.
87 DSA_VC_aggregate, /// for aggregate variables.
88 DSA_VC_pointer, /// for pointer variables.
89 DSA_VC_scalar, /// for scalar variables.
90};
91
92/// Stack for tracking declarations used in OpenMP directives and
93/// clauses and their data-sharing attributes.
94class DSAStackTy {
95public:
96 struct DSAVarData {
97 OpenMPDirectiveKind DKind = OMPD_unknown;
98 OpenMPClauseKind CKind = OMPC_unknown;
99 unsigned Modifier = 0;
100 const Expr *RefExpr = nullptr;
101 DeclRefExpr *PrivateCopy = nullptr;
102 SourceLocation ImplicitDSALoc;
103 bool AppliedToPointee = false;
104 DSAVarData() = default;
105 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
106 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
107 SourceLocation ImplicitDSALoc, unsigned Modifier,
108 bool AppliedToPointee)
109 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
110 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
111 AppliedToPointee(AppliedToPointee) {}
112 };
113 using OperatorOffsetTy =
114 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
115 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
116 /// Kind of the declaration used in the uses_allocators clauses.
117 enum class UsesAllocatorsDeclKind {
118 /// Predefined allocator
119 PredefinedAllocator,
120 /// User-defined allocator
121 UserDefinedAllocator,
122 /// The declaration that represent allocator trait
123 AllocatorTrait,
124 };
125
126private:
127 struct DSAInfo {
128 OpenMPClauseKind Attributes = OMPC_unknown;
129 unsigned Modifier = 0;
130 /// Pointer to a reference expression and a flag which shows that the
131 /// variable is marked as lastprivate(true) or not (false).
132 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
133 DeclRefExpr *PrivateCopy = nullptr;
134 /// true if the attribute is applied to the pointee, not the variable
135 /// itself.
136 bool AppliedToPointee = false;
137 };
138 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
139 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
140 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
141 using LoopControlVariablesMapTy =
142 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
143 /// Struct that associates a component with the clause kind where they are
144 /// found.
145 struct MappedExprComponentTy {
147 OpenMPClauseKind Kind = OMPC_unknown;
148 };
149 using MappedExprComponentsTy =
150 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
151 using CriticalsWithHintsTy =
152 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
153 struct ReductionData {
154 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
155 SourceRange ReductionRange;
156 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
157 ReductionData() = default;
158 void set(BinaryOperatorKind BO, SourceRange RR) {
159 ReductionRange = RR;
160 ReductionOp = BO;
161 }
162 void set(const Expr *RefExpr, SourceRange RR) {
163 ReductionRange = RR;
164 ReductionOp = RefExpr;
165 }
166 };
167 using DeclReductionMapTy =
168 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
169 struct DefaultmapInfo {
170 OpenMPDefaultmapClauseModifier ImplicitBehavior =
172 SourceLocation SLoc;
173 DefaultmapInfo() = default;
174 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
175 : ImplicitBehavior(M), SLoc(Loc) {}
176 };
177
178 struct SharingMapTy {
179 DeclSAMapTy SharingMap;
180 DeclReductionMapTy ReductionMap;
181 UsedRefMapTy AlignedMap;
182 UsedRefMapTy NontemporalMap;
183 MappedExprComponentsTy MappedExprComponents;
184 LoopControlVariablesMapTy LCVMap;
185 /// Track DecompositionDecls and their data-sharing attributes to detect
186 /// conflicting clauses on bindings from the same decomposition.
187 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
188 SourceLocation DefaultAttrLoc;
189 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
190 SourceLocation DefaultAttrVCLoc;
191 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
192 OpenMPDirectiveKind Directive = OMPD_unknown;
193 DeclarationNameInfo DirectiveName;
194 Scope *CurScope = nullptr;
195 DeclContext *Context = nullptr;
196 SourceLocation ConstructLoc;
197 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
198 /// get the data (loop counters etc.) about enclosing loop-based construct.
199 /// This data is required during codegen.
200 DoacrossClauseMapTy DoacrossDepends;
201 /// First argument (Expr *) contains optional argument of the
202 /// 'ordered' clause, the second one is true if the regions has 'ordered'
203 /// clause, false otherwise.
204 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
205 bool RegionHasOrderConcurrent = false;
206 unsigned AssociatedLoops = 1;
207 bool HasMutipleLoops = false;
208 const Decl *PossiblyLoopCounter = nullptr;
209 bool NowaitRegion = false;
210 bool UntiedRegion = false;
211 bool CancelRegion = false;
212 bool LoopStart = false;
213 bool BodyComplete = false;
214 SourceLocation PrevScanLocation;
215 SourceLocation PrevOrderedLocation;
216 SourceLocation InnerTeamsRegionLoc;
217 /// Reference to the taskgroup task_reduction reference expression.
218 Expr *TaskgroupReductionRef = nullptr;
219 llvm::DenseSet<QualType> MappedClassesQualTypes;
220 SmallVector<Expr *, 4> InnerUsedAllocators;
221 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
222 /// List of globals marked as declare target link in this target region
223 /// (isOpenMPTargetExecutionDirective(Directive) == true).
224 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
225 /// List of decls used in inclusive/exclusive clauses of the scan directive.
226 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
227 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
228 UsesAllocatorsDecls;
229 /// Data is required on creating capture fields for implicit
230 /// default first|private clause.
231 struct ImplicitDefaultFDInfoTy {
232 /// Field decl.
233 const FieldDecl *FD = nullptr;
234 /// Nesting stack level
235 size_t StackLevel = 0;
236 /// Capture variable decl.
237 VarDecl *VD = nullptr;
238 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
239 VarDecl *VD)
240 : FD(FD), StackLevel(StackLevel), VD(VD) {}
241 };
242 /// List of captured fields
243 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
244 ImplicitDefaultFirstprivateFDs;
245 Expr *DeclareMapperVar = nullptr;
246 SmallVector<VarDecl *, 16> IteratorVarDecls;
247 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
248 Scope *CurScope, SourceLocation Loc)
249 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
250 ConstructLoc(Loc) {}
251 SharingMapTy() = default;
252 };
253
254 using StackTy = SmallVector<SharingMapTy, 4>;
255
256 /// Stack of used declaration and their data-sharing attributes.
257 DeclSAMapTy Threadprivates;
258 DeclSAMapTy Groupprivates;
259 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
260 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
261 /// true, if check for DSA must be from parent directive, false, if
262 /// from current directive.
263 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
264 Sema &SemaRef;
265 bool ForceCapturing = false;
266 /// true if all the variables in the target executable directives must be
267 /// captured by reference.
268 bool ForceCaptureByReferenceInTargetExecutable = false;
269 CriticalsWithHintsTy Criticals;
270 unsigned IgnoredStackElements = 0;
271
272 /// Iterators over the stack iterate in order from innermost to outermost
273 /// directive.
274 using const_iterator = StackTy::const_reverse_iterator;
275 const_iterator begin() const {
276 return Stack.empty() ? const_iterator()
277 : Stack.back().first.rbegin() + IgnoredStackElements;
278 }
279 const_iterator end() const {
280 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
281 }
282 using iterator = StackTy::reverse_iterator;
283 iterator begin() {
284 return Stack.empty() ? iterator()
285 : Stack.back().first.rbegin() + IgnoredStackElements;
286 }
287 iterator end() {
288 return Stack.empty() ? iterator() : Stack.back().first.rend();
289 }
290
291 // Convenience operations to get at the elements of the stack.
292
293 bool isStackEmpty() const {
294 return Stack.empty() ||
295 Stack.back().second != CurrentNonCapturingFunctionScope ||
296 Stack.back().first.size() <= IgnoredStackElements;
297 }
298 size_t getStackSize() const {
299 return isStackEmpty() ? 0
300 : Stack.back().first.size() - IgnoredStackElements;
301 }
302
303 SharingMapTy *getTopOfStackOrNull() {
304 size_t Size = getStackSize();
305 if (Size == 0)
306 return nullptr;
307 return &Stack.back().first[Size - 1];
308 }
309 const SharingMapTy *getTopOfStackOrNull() const {
310 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
311 }
312 SharingMapTy &getTopOfStack() {
313 assert(!isStackEmpty() && "no current directive");
314 return *getTopOfStackOrNull();
315 }
316 const SharingMapTy &getTopOfStack() const {
317 return const_cast<DSAStackTy &>(*this).getTopOfStack();
318 }
319
320 SharingMapTy *getSecondOnStackOrNull() {
321 size_t Size = getStackSize();
322 if (Size <= 1)
323 return nullptr;
324 return &Stack.back().first[Size - 2];
325 }
326 const SharingMapTy *getSecondOnStackOrNull() const {
327 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
328 }
329
330 /// Get the stack element at a certain level (previously returned by
331 /// \c getNestingLevel).
332 ///
333 /// Note that nesting levels count from outermost to innermost, and this is
334 /// the reverse of our iteration order where new inner levels are pushed at
335 /// the front of the stack.
336 SharingMapTy &getStackElemAtLevel(unsigned Level) {
337 assert(Level < getStackSize() && "no such stack element");
338 return Stack.back().first[Level];
339 }
340 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
341 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
342 }
343
344 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
345
346 /// Checks if the variable is a local for OpenMP region.
347 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
348
349 /// Vector of previously declared requires directives
350 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
351 /// omp_allocator_handle_t type.
352 QualType OMPAllocatorHandleT;
353 /// omp_depend_t type.
354 QualType OMPDependT;
355 /// omp_event_handle_t type.
356 QualType OMPEventHandleT;
357 /// omp_alloctrait_t type.
358 QualType OMPAlloctraitT;
359 /// Expression for the predefined allocators.
360 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
361 nullptr};
362 /// Vector of previously encountered target directives
363 SmallVector<SourceLocation, 2> TargetLocations;
364 SourceLocation AtomicLocation;
365 /// Vector of declare variant construct traits.
366 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
367
368public:
369 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
370
371 /// Sets omp_allocator_handle_t type.
372 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
373 /// Gets omp_allocator_handle_t type.
374 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
375 /// Sets omp_alloctrait_t type.
376 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
377 /// Gets omp_alloctrait_t type.
378 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
379 /// Sets the given default allocator.
380 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
381 Expr *Allocator) {
382 OMPPredefinedAllocators[AllocatorKind] = Allocator;
383 }
384 /// Returns the specified default allocator.
385 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
386 return OMPPredefinedAllocators[AllocatorKind];
387 }
388 /// Sets omp_depend_t type.
389 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
390 /// Gets omp_depend_t type.
391 QualType getOMPDependT() const { return OMPDependT; }
392
393 /// Sets omp_event_handle_t type.
394 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
395 /// Gets omp_event_handle_t type.
396 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
397
398 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
399 OpenMPClauseKind getClauseParsingMode() const {
400 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
401 return ClauseKindMode;
402 }
403 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
404
405 bool isBodyComplete() const {
406 const SharingMapTy *Top = getTopOfStackOrNull();
407 return Top && Top->BodyComplete;
408 }
409 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
410
411 bool isForceVarCapturing() const { return ForceCapturing; }
412 void setForceVarCapturing(bool V) { ForceCapturing = V; }
413
414 void setForceCaptureByReferenceInTargetExecutable(bool V) {
415 ForceCaptureByReferenceInTargetExecutable = V;
416 }
417 bool isForceCaptureByReferenceInTargetExecutable() const {
418 return ForceCaptureByReferenceInTargetExecutable;
419 }
420
421 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
422 Scope *CurScope, SourceLocation Loc) {
423 assert(!IgnoredStackElements &&
424 "cannot change stack while ignoring elements");
425 if (Stack.empty() ||
426 Stack.back().second != CurrentNonCapturingFunctionScope)
427 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
428 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
429 Stack.back().first.back().DefaultAttrLoc = Loc;
430 }
431
432 void pop() {
433 assert(!IgnoredStackElements &&
434 "cannot change stack while ignoring elements");
435 assert(!Stack.back().first.empty() &&
436 "Data-sharing attributes stack is empty!");
437 Stack.back().first.pop_back();
438 }
439
440 /// RAII object to temporarily leave the scope of a directive when we want to
441 /// logically operate in its parent.
442 class ParentDirectiveScope {
443 DSAStackTy &Self;
444 bool Active;
445
446 public:
447 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
448 : Self(Self), Active(false) {
449 if (Activate)
450 enable();
451 }
452 ~ParentDirectiveScope() { disable(); }
453 void disable() {
454 if (Active) {
455 --Self.IgnoredStackElements;
456 Active = false;
457 }
458 }
459 void enable() {
460 if (!Active) {
461 ++Self.IgnoredStackElements;
462 Active = true;
463 }
464 }
465 };
466
467 /// Marks that we're started loop parsing.
468 void loopInit() {
469 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
470 "Expected loop-based directive.");
471 getTopOfStack().LoopStart = true;
472 }
473 /// Start capturing of the variables in the loop context.
474 void loopStart() {
475 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
476 "Expected loop-based directive.");
477 getTopOfStack().LoopStart = false;
478 }
479 /// true, if variables are captured, false otherwise.
480 bool isLoopStarted() const {
481 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
482 "Expected loop-based directive.");
483 return !getTopOfStack().LoopStart;
484 }
485 /// Marks (or clears) declaration as possibly loop counter.
486 void resetPossibleLoopCounter(const Decl *D = nullptr) {
487 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
488 }
489 /// Gets the possible loop counter decl.
490 const Decl *getPossiblyLoopCounter() const {
491 return getTopOfStack().PossiblyLoopCounter;
492 }
493 /// Start new OpenMP region stack in new non-capturing function.
494 void pushFunction() {
495 assert(!IgnoredStackElements &&
496 "cannot change stack while ignoring elements");
497 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
498 assert(!isa<CapturingScopeInfo>(CurFnScope));
499 CurrentNonCapturingFunctionScope = CurFnScope;
500 }
501 /// Pop region stack for non-capturing function.
502 void popFunction(const FunctionScopeInfo *OldFSI) {
503 assert(!IgnoredStackElements &&
504 "cannot change stack while ignoring elements");
505 if (!Stack.empty() && Stack.back().second == OldFSI) {
506 assert(Stack.back().first.empty());
507 Stack.pop_back();
508 }
509 CurrentNonCapturingFunctionScope = nullptr;
510 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
511 if (!isa<CapturingScopeInfo>(FSI)) {
512 CurrentNonCapturingFunctionScope = FSI;
513 break;
514 }
515 }
516 }
517
518 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
519 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
520 }
521 std::pair<const OMPCriticalDirective *, llvm::APSInt>
522 getCriticalWithHint(const DeclarationNameInfo &Name) const {
523 auto I = Criticals.find(Name.getAsString());
524 if (I != Criticals.end())
525 return I->second;
526 return std::make_pair(nullptr, llvm::APSInt());
527 }
528 /// If 'aligned' declaration for given variable \a D was not seen yet,
529 /// add it and return NULL; otherwise return previous occurrence's expression
530 /// for diagnostics.
531 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
532 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
533 /// add it and return NULL; otherwise return previous occurrence's expression
534 /// for diagnostics.
535 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
536
537 /// Register specified variable as loop control variable.
538 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
539 /// Check if the specified variable is a loop control variable for
540 /// current region.
541 /// \return The index of the loop control variable in the list of associated
542 /// for-loops (from outer to inner).
543 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
544 /// Check if the specified variable is a loop control variable for
545 /// parent region.
546 /// \return The index of the loop control variable in the list of associated
547 /// for-loops (from outer to inner).
548 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
549 /// Check if the specified variable is a loop control variable for
550 /// current region.
551 /// \return The index of the loop control variable in the list of associated
552 /// for-loops (from outer to inner).
553 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
554 unsigned Level) const;
555 /// Get the loop control variable for the I-th loop (or nullptr) in
556 /// parent directive.
557 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
558
559 /// Marks the specified decl \p D as used in scan directive.
560 void markDeclAsUsedInScanDirective(ValueDecl *D) {
561 if (SharingMapTy *Stack = getSecondOnStackOrNull())
562 Stack->UsedInScanDirective.insert(D);
563 }
564
565 /// Checks if the specified declaration was used in the inner scan directive.
566 bool isUsedInScanDirective(ValueDecl *D) const {
567 if (const SharingMapTy *Stack = getTopOfStackOrNull())
568 return Stack->UsedInScanDirective.contains(D);
569 return false;
570 }
571
572 /// Adds explicit data sharing attribute to the specified declaration.
573 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
574 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
575 bool AppliedToPointee = false);
576
577 /// Adds additional information for the reduction items with the reduction id
578 /// represented as an operator.
579 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
581 /// Adds additional information for the reduction items with the reduction id
582 /// represented as reduction identifier.
583 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
584 const Expr *ReductionRef);
585 /// Returns the location and reduction operation from the innermost parent
586 /// region for the given \p D.
587 const DSAVarData
588 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
590 Expr *&TaskgroupDescriptor) const;
591 /// Returns the location and reduction operation from the innermost parent
592 /// region for the given \p D.
593 const DSAVarData
594 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
595 const Expr *&ReductionRef,
596 Expr *&TaskgroupDescriptor) const;
597 /// Return reduction reference expression for the current taskgroup or
598 /// parallel/worksharing directives with task reductions.
599 Expr *getTaskgroupReductionRef() const {
600 assert((getTopOfStack().Directive == OMPD_taskgroup ||
601 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
602 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
603 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
604 "taskgroup reference expression requested for non taskgroup or "
605 "parallel/worksharing directive.");
606 return getTopOfStack().TaskgroupReductionRef;
607 }
608 /// Checks if the given \p VD declaration is actually a taskgroup reduction
609 /// descriptor variable at the \p Level of OpenMP regions.
610 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
611 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
612 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
613 ->getDecl() == VD;
614 }
615
616 /// Returns data sharing attributes from top of the stack for the
617 /// specified declaration.
618 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
619 /// Returns data-sharing attributes for the specified declaration.
620 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
621 /// Returns data-sharing attributes for the specified declaration.
622 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
623 /// Checks if the specified variables has data-sharing attributes which
624 /// match specified \a CPred predicate in any directive which matches \a DPred
625 /// predicate.
626 const DSAVarData
627 hasDSA(ValueDecl *D,
628 const llvm::function_ref<bool(OpenMPClauseKind, bool,
629 DefaultDataSharingAttributes)>
630 CPred,
631 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
632 bool FromParent) const;
633 /// Checks if the specified variables has data-sharing attributes which
634 /// match specified \a CPred predicate in any innermost directive which
635 /// matches \a DPred predicate.
636 const DSAVarData
637 hasInnermostDSA(ValueDecl *D,
638 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
639 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
640 bool FromParent) const;
641 /// Checks if the specified variables has explicit data-sharing
642 /// attributes which match specified \a CPred predicate at the specified
643 /// OpenMP region.
644 bool
645 hasExplicitDSA(const ValueDecl *D,
646 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
647 unsigned Level, bool NotLastprivate = false) const;
648
649 /// Returns true if the directive at level \Level matches in the
650 /// specified \a DPred predicate.
651 bool hasExplicitDirective(
652 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
653 unsigned Level) const;
654
655 /// Finds a directive which matches specified \a DPred predicate.
656 bool hasDirective(
657 const llvm::function_ref<bool(
658 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
659 DPred,
660 bool FromParent) const;
661
662 /// Returns currently analyzed directive.
663 OpenMPDirectiveKind getCurrentDirective() const {
664 const SharingMapTy *Top = getTopOfStackOrNull();
665 return Top ? Top->Directive : OMPD_unknown;
666 }
667 /// Returns directive kind at specified level.
668 OpenMPDirectiveKind getDirective(unsigned Level) const {
669 assert(!isStackEmpty() && "No directive at specified level.");
670 return getStackElemAtLevel(Level).Directive;
671 }
672 /// Returns the capture region at the specified level.
673 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
674 unsigned OpenMPCaptureLevel) const {
675 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
676 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
677 return CaptureRegions[OpenMPCaptureLevel];
678 }
679 /// Returns parent directive.
680 OpenMPDirectiveKind getParentDirective() const {
681 const SharingMapTy *Parent = getSecondOnStackOrNull();
682 return Parent ? Parent->Directive : OMPD_unknown;
683 }
684
685 /// Add requires decl to internal vector
686 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
687
688 ArrayRef<const OMPRequiresDecl *> getRequiresDecls() const {
689 return RequiresDecls;
690 }
691
692 /// Checks if the defined 'requires' directive has specified type of clause.
693 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
694 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
695 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
696 return isa<ClauseType>(C);
697 });
698 });
699 }
700
701 /// Checks for a duplicate clause amongst previously declared requires
702 /// directives
703 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
704 bool IsDuplicate = false;
705 for (OMPClause *CNew : ClauseList) {
706 for (const OMPRequiresDecl *D : RequiresDecls) {
707 for (const OMPClause *CPrev : D->clauselists()) {
708 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
709 SemaRef.Diag(CNew->getBeginLoc(),
710 diag::err_omp_requires_clause_redeclaration)
711 << getOpenMPClauseNameForDiag(CNew->getClauseKind());
712 SemaRef.Diag(CPrev->getBeginLoc(),
713 diag::note_omp_requires_previous_clause)
714 << getOpenMPClauseNameForDiag(CPrev->getClauseKind());
715 IsDuplicate = true;
716 }
717 }
718 }
719 }
720 return IsDuplicate;
721 }
722
723 /// Add location of previously encountered target to internal vector
724 void addTargetDirLocation(SourceLocation LocStart) {
725 TargetLocations.push_back(LocStart);
726 }
727
728 /// Add location for the first encountered atomic directive.
729 void addAtomicDirectiveLoc(SourceLocation Loc) {
730 if (AtomicLocation.isInvalid())
731 AtomicLocation = Loc;
732 }
733
734 /// Returns the location of the first encountered atomic directive in the
735 /// module.
736 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
737
738 // Return previously encountered target region locations.
739 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
740 return TargetLocations;
741 }
742
743 /// Set default data sharing attribute to none.
744 void setDefaultDSANone(SourceLocation Loc) {
745 getTopOfStack().DefaultAttr = DSA_none;
746 getTopOfStack().DefaultAttrLoc = Loc;
747 }
748 /// Set default data sharing attribute to shared.
749 void setDefaultDSAShared(SourceLocation Loc) {
750 getTopOfStack().DefaultAttr = DSA_shared;
751 getTopOfStack().DefaultAttrLoc = Loc;
752 }
753 /// Set default data sharing attribute to private.
754 void setDefaultDSAPrivate(SourceLocation Loc) {
755 getTopOfStack().DefaultAttr = DSA_private;
756 getTopOfStack().DefaultAttrLoc = Loc;
757 }
758 /// Set default data sharing attribute to firstprivate.
759 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
760 getTopOfStack().DefaultAttr = DSA_firstprivate;
761 getTopOfStack().DefaultAttrLoc = Loc;
762 }
763 /// Set default data sharing variable category attribute to aggregate.
764 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
765 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
766 getTopOfStack().DefaultAttrVCLoc = VCLoc;
767 }
768 /// Set default data sharing variable category attribute to all.
769 void setDefaultDSAVCAll(SourceLocation VCLoc) {
770 getTopOfStack().DefaultVCAttr = DSA_VC_all;
771 getTopOfStack().DefaultAttrVCLoc = VCLoc;
772 }
773 /// Set default data sharing variable category attribute to pointer.
774 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
775 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
776 getTopOfStack().DefaultAttrVCLoc = VCLoc;
777 }
778 /// Set default data sharing variable category attribute to scalar.
779 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
780 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
781 getTopOfStack().DefaultAttrVCLoc = VCLoc;
782 }
783 /// Set default data mapping attribute to Modifier:Kind
784 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
785 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
786 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
787 DMI.ImplicitBehavior = M;
788 DMI.SLoc = Loc;
789 }
790 /// Check whether the implicit-behavior has been set in defaultmap
791 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
792 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
793 return getTopOfStack()
794 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
795 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
796 getTopOfStack()
797 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
798 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
799 getTopOfStack()
800 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
801 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
802 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
804 }
805
806 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
807 return ConstructTraits;
808 }
809 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
810 bool ScopeEntry) {
811 if (ScopeEntry)
812 ConstructTraits.append(Traits.begin(), Traits.end());
813 else
814 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
815 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
816 assert(Top == Trait && "Something left a trait on the stack!");
817 (void)Trait;
818 (void)Top;
819 }
820 }
821
822 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
823 return getStackSize() <= Level ? DSA_unspecified
824 : getStackElemAtLevel(Level).DefaultAttr;
825 }
826 DefaultDataSharingAttributes getDefaultDSA() const {
827 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
828 }
829 SourceLocation getDefaultDSALocation() const {
830 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
831 }
833 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
834 return isStackEmpty()
836 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
837 }
839 getDefaultmapModifierAtLevel(unsigned Level,
840 OpenMPDefaultmapClauseKind Kind) const {
841 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
842 }
843 bool isDefaultmapCapturedByRef(unsigned Level,
844 OpenMPDefaultmapClauseKind Kind) const {
846 getDefaultmapModifierAtLevel(Level, Kind);
847 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
848 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
849 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
850 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
851 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
852 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
854 }
855 return true;
856 }
857 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
859 switch (Kind) {
860 case OMPC_DEFAULTMAP_scalar:
861 case OMPC_DEFAULTMAP_pointer:
862 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
863 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
864 (M == OMPC_DEFAULTMAP_MODIFIER_default);
865 case OMPC_DEFAULTMAP_aggregate:
866 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
867 default:
868 break;
869 }
870 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
871 }
872 bool mustBeFirstprivateAtLevel(unsigned Level,
873 OpenMPDefaultmapClauseKind Kind) const {
875 getDefaultmapModifierAtLevel(Level, Kind);
876 return mustBeFirstprivateBase(M, Kind);
877 }
878 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
879 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
880 return mustBeFirstprivateBase(M, Kind);
881 }
882
883 /// Checks if the specified variable is a threadprivate.
884 bool isThreadPrivate(VarDecl *D) {
885 const DSAVarData DVar = getTopDSA(D, false);
886 return isOpenMPThreadPrivate(DVar.CKind);
887 }
888
889 /// Marks current region as ordered (it has an 'ordered' clause).
890 void setOrderedRegion(bool IsOrdered, const Expr *Param,
891 OMPOrderedClause *Clause) {
892 if (IsOrdered)
893 getTopOfStack().OrderedRegion.emplace(Param, Clause);
894 else
895 getTopOfStack().OrderedRegion.reset();
896 }
897 /// Returns true, if region is ordered (has associated 'ordered' clause),
898 /// false - otherwise.
899 bool isOrderedRegion() const {
900 if (const SharingMapTy *Top = getTopOfStackOrNull())
901 return Top->OrderedRegion.has_value();
902 return false;
903 }
904 /// Returns optional parameter for the ordered region.
905 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
906 if (const SharingMapTy *Top = getTopOfStackOrNull())
907 if (Top->OrderedRegion)
908 return *Top->OrderedRegion;
909 return std::make_pair(nullptr, nullptr);
910 }
911 /// Returns true, if parent region is ordered (has associated
912 /// 'ordered' clause), false - otherwise.
913 bool isParentOrderedRegion() const {
914 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
915 return Parent->OrderedRegion.has_value();
916 return false;
917 }
918 /// Returns optional parameter for the ordered region.
919 std::pair<const Expr *, OMPOrderedClause *>
920 getParentOrderedRegionParam() const {
921 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
922 if (Parent->OrderedRegion)
923 return *Parent->OrderedRegion;
924 return std::make_pair(nullptr, nullptr);
925 }
926 /// Marks current region as having an 'order' clause.
927 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
928 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
929 }
930 /// Returns true if the nearest enclosing directive that is not a
931 /// loop-transforming construct has an order(concurrent) clause.
932 bool isEnclosingOrderConcurrent() const {
933 for (const_iterator I = begin() + std::min<size_t>(1, getStackSize()),
934 E = end();
935 I != E; ++I) {
936 if (I->RegionHasOrderConcurrent)
937 return true;
938 if (!isOpenMPLoopTransformationDirective(I->Directive))
939 return false;
940 }
941 return false;
942 }
943 /// Returns true if the nearest enclosing directive that is not a
944 /// loop-transforming or ordered simd construct is a simd directive.
945 bool isInSimdRegion() const {
946 for (const_iterator I = begin() + std::min<size_t>(1, getStackSize()),
947 E = end();
948 I != E; ++I) {
949 if (isOpenMPSimdDirective(I->Directive))
950 return true;
951 if (!isOpenMPLoopTransformationDirective(I->Directive) &&
952 I->Directive != OMPD_ordered_blockassoc)
953 return false;
954 }
955 return false;
956 }
957 /// Marks current region as nowait (it has a 'nowait' clause).
958 void setNowaitRegion(bool IsNowait = true) {
959 getTopOfStack().NowaitRegion = IsNowait;
960 }
961 /// Returns true, if parent region is nowait (has associated
962 /// 'nowait' clause), false - otherwise.
963 bool isParentNowaitRegion() const {
964 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
965 return Parent->NowaitRegion;
966 return false;
967 }
968 /// Marks current region as untied (it has a 'untied' clause).
969 void setUntiedRegion(bool IsUntied = true) {
970 getTopOfStack().UntiedRegion = IsUntied;
971 }
972 /// Return true if current region is untied.
973 bool isUntiedRegion() const {
974 const SharingMapTy *Top = getTopOfStackOrNull();
975 return Top ? Top->UntiedRegion : false;
976 }
977 /// Marks parent region as cancel region.
978 void setParentCancelRegion(bool Cancel = true) {
979 if (SharingMapTy *Parent = getSecondOnStackOrNull())
980 Parent->CancelRegion |= Cancel;
981 }
982 /// Return true if current region has inner cancel construct.
983 bool isCancelRegion() const {
984 const SharingMapTy *Top = getTopOfStackOrNull();
985 return Top ? Top->CancelRegion : false;
986 }
987
988 /// Mark that parent region already has scan directive.
989 void setParentHasScanDirective(SourceLocation Loc) {
990 if (SharingMapTy *Parent = getSecondOnStackOrNull())
991 Parent->PrevScanLocation = Loc;
992 }
993 /// Return true if current region has inner cancel construct.
994 bool doesParentHasScanDirective() const {
995 const SharingMapTy *Top = getSecondOnStackOrNull();
996 return Top ? Top->PrevScanLocation.isValid() : false;
997 }
998 /// Return true if current region has inner cancel construct.
999 SourceLocation getParentScanDirectiveLoc() const {
1000 const SharingMapTy *Top = getSecondOnStackOrNull();
1001 return Top ? Top->PrevScanLocation : SourceLocation();
1002 }
1003 /// Mark that parent region already has ordered directive.
1004 void setParentHasOrderedDirective(SourceLocation Loc) {
1005 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1006 Parent->PrevOrderedLocation = Loc;
1007 }
1008 /// Return true if current region has inner ordered construct.
1009 bool doesParentHasOrderedDirective() const {
1010 const SharingMapTy *Top = getSecondOnStackOrNull();
1011 return Top ? Top->PrevOrderedLocation.isValid() : false;
1012 }
1013 /// Returns the location of the previously specified ordered directive.
1014 SourceLocation getParentOrderedDirectiveLoc() const {
1015 const SharingMapTy *Top = getSecondOnStackOrNull();
1016 return Top ? Top->PrevOrderedLocation : SourceLocation();
1017 }
1018
1019 /// Set collapse value for the region.
1020 void setAssociatedLoops(unsigned Val) {
1021 getTopOfStack().AssociatedLoops = Val;
1022 if (Val > 1)
1023 getTopOfStack().HasMutipleLoops = true;
1024 }
1025 /// Return collapse value for region.
1026 unsigned getAssociatedLoops() const {
1027 const SharingMapTy *Top = getTopOfStackOrNull();
1028 return Top ? Top->AssociatedLoops : 0;
1029 }
1030 /// Returns true if the construct is associated with multiple loops.
1031 bool hasMutipleLoops() const {
1032 const SharingMapTy *Top = getTopOfStackOrNull();
1033 return Top ? Top->HasMutipleLoops : false;
1034 }
1035
1036 /// Marks current target region as one with closely nested teams
1037 /// region.
1038 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1039 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1040 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1041 }
1042 /// Returns true, if current region has closely nested teams region.
1043 bool hasInnerTeamsRegion() const {
1044 return getInnerTeamsRegionLoc().isValid();
1045 }
1046 /// Returns location of the nested teams region (if any).
1047 SourceLocation getInnerTeamsRegionLoc() const {
1048 const SharingMapTy *Top = getTopOfStackOrNull();
1049 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1050 }
1051
1052 Scope *getCurScope() const {
1053 const SharingMapTy *Top = getTopOfStackOrNull();
1054 return Top ? Top->CurScope : nullptr;
1055 }
1056 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1057 SourceLocation getConstructLoc() const {
1058 const SharingMapTy *Top = getTopOfStackOrNull();
1059 return Top ? Top->ConstructLoc : SourceLocation();
1060 }
1061
1062 /// Do the check specified in \a Check to all component lists and return true
1063 /// if any issue is found.
1064 bool checkMappableExprComponentListsForDecl(
1065 const ValueDecl *VD, bool CurrentRegionOnly,
1066 const llvm::function_ref<
1069 Check) const {
1070 if (isStackEmpty())
1071 return false;
1072 auto SI = begin();
1073 auto SE = end();
1074
1075 if (SI == SE)
1076 return false;
1077
1078 if (CurrentRegionOnly)
1079 SE = std::next(SI);
1080 else
1081 std::advance(SI, 1);
1082
1083 for (; SI != SE; ++SI) {
1084 auto MI = SI->MappedExprComponents.find(VD);
1085 if (MI != SI->MappedExprComponents.end())
1087 MI->second.Components)
1088 if (Check(L, MI->second.Kind))
1089 return true;
1090 }
1091 return false;
1092 }
1093
1094 /// Do the check specified in \a Check to all component lists at a given level
1095 /// and return true if any issue is found.
1096 bool checkMappableExprComponentListsForDeclAtLevel(
1097 const ValueDecl *VD, unsigned Level,
1098 const llvm::function_ref<
1101 Check) const {
1102 if (getStackSize() <= Level)
1103 return false;
1104
1105 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1106 auto MI = StackElem.MappedExprComponents.find(VD);
1107 if (MI != StackElem.MappedExprComponents.end())
1109 MI->second.Components)
1110 if (Check(L, MI->second.Kind))
1111 return true;
1112 return false;
1113 }
1114
1115 /// Create a new mappable expression component list associated with a given
1116 /// declaration and initialize it with the provided list of components.
1117 void addMappableExpressionComponents(
1118 const ValueDecl *VD,
1120 OpenMPClauseKind WhereFoundClauseKind) {
1121 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1122 // Create new entry and append the new components there.
1123 MEC.Components.resize(MEC.Components.size() + 1);
1124 MEC.Components.back().append(Components.begin(), Components.end());
1125 MEC.Kind = WhereFoundClauseKind;
1126 }
1127
1128 unsigned getNestingLevel() const {
1129 assert(!isStackEmpty());
1130 return getStackSize() - 1;
1131 }
1132 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1133 SharingMapTy *Parent = getSecondOnStackOrNull();
1134 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1135 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1136 }
1137 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1138 getDoacrossDependClauses() const {
1139 const SharingMapTy &StackElem = getTopOfStack();
1140 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1141 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1142 return llvm::make_range(Ref.begin(), Ref.end());
1143 }
1144 return llvm::make_range(StackElem.DoacrossDepends.end(),
1145 StackElem.DoacrossDepends.end());
1146 }
1147
1148 // Store types of classes which have been explicitly mapped
1149 void addMappedClassesQualTypes(QualType QT) {
1150 SharingMapTy &StackElem = getTopOfStack();
1151 StackElem.MappedClassesQualTypes.insert(QT);
1152 }
1153
1154 // Return set of mapped classes types
1155 bool isClassPreviouslyMapped(QualType QT) const {
1156 const SharingMapTy &StackElem = getTopOfStack();
1157 return StackElem.MappedClassesQualTypes.contains(QT);
1158 }
1159
1160 /// Adds global declare target to the parent target region.
1161 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1162 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1163 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1164 "Expected declare target link global.");
1165 for (auto &Elem : *this) {
1166 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1167 Elem.DeclareTargetLinkVarDecls.push_back(E);
1168 return;
1169 }
1170 }
1171 }
1172
1173 /// Returns the list of globals with declare target link if current directive
1174 /// is target.
1175 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1176 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1177 "Expected target executable directive.");
1178 return getTopOfStack().DeclareTargetLinkVarDecls;
1179 }
1180
1181 /// Adds list of allocators expressions.
1182 void addInnerAllocatorExpr(Expr *E) {
1183 getTopOfStack().InnerUsedAllocators.push_back(E);
1184 }
1185 /// Return list of used allocators.
1186 ArrayRef<Expr *> getInnerAllocators() const {
1187 return getTopOfStack().InnerUsedAllocators;
1188 }
1189 /// Marks the declaration as implicitly firstprivate nin the task-based
1190 /// regions.
1191 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1192 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1193 }
1194 /// Checks if the decl is implicitly firstprivate in the task-based region.
1195 bool isImplicitTaskFirstprivate(Decl *D) const {
1196 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1197 }
1198
1199 /// Marks decl as used in uses_allocators clause as the allocator.
1200 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1201 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1202 }
1203 /// Checks if specified decl is used in uses allocator clause as the
1204 /// allocator.
1205 std::optional<UsesAllocatorsDeclKind>
1206 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1207 const SharingMapTy &StackElem = getTopOfStack();
1208 auto I = StackElem.UsesAllocatorsDecls.find(D);
1209 if (I == StackElem.UsesAllocatorsDecls.end())
1210 return std::nullopt;
1211 return I->getSecond();
1212 }
1213 std::optional<UsesAllocatorsDeclKind>
1214 isUsesAllocatorsDecl(const Decl *D) const {
1215 const SharingMapTy &StackElem = getTopOfStack();
1216 auto I = StackElem.UsesAllocatorsDecls.find(D);
1217 if (I == StackElem.UsesAllocatorsDecls.end())
1218 return std::nullopt;
1219 return I->getSecond();
1220 }
1221
1222 void addDeclareMapperVarRef(Expr *Ref) {
1223 SharingMapTy &StackElem = getTopOfStack();
1224 StackElem.DeclareMapperVar = Ref;
1225 }
1226 const Expr *getDeclareMapperVarRef() const {
1227 const SharingMapTy *Top = getTopOfStackOrNull();
1228 return Top ? Top->DeclareMapperVar : nullptr;
1229 }
1230
1231 /// Add a new iterator variable.
1232 void addIteratorVarDecl(VarDecl *VD) {
1233 SharingMapTy &StackElem = getTopOfStack();
1234 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1235 }
1236 /// Check if variable declaration is an iterator VarDecl.
1237 bool isIteratorVarDecl(const VarDecl *VD) const {
1238 const SharingMapTy *Top = getTopOfStackOrNull();
1239 if (!Top)
1240 return false;
1241
1242 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1243 }
1244 /// get captured field from ImplicitDefaultFirstprivateFDs
1245 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1246 const_iterator I = begin();
1247 const_iterator EndI = end();
1248 size_t StackLevel = getStackSize();
1249 for (; I != EndI; ++I) {
1250 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1251 break;
1252 StackLevel--;
1253 }
1254 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1255 if (I == EndI)
1256 return nullptr;
1257 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1258 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1259 return IFD.VD;
1260 return nullptr;
1261 }
1262 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1263 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1264 const_iterator I = begin();
1265 const_iterator EndI = end();
1266 for (; I != EndI; ++I)
1267 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1268 break;
1269 if (I == EndI)
1270 return false;
1271 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1272 if (IFD.VD == VD)
1273 return true;
1274 return false;
1275 }
1276 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1277 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1278 iterator I = begin();
1279 const_iterator EndI = end();
1280 size_t StackLevel = getStackSize();
1281 for (; I != EndI; ++I) {
1282 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1283 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1284 break;
1285 }
1286 StackLevel--;
1287 }
1288 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1289 }
1290 void setOrderedToBlockAssociated() {
1291 assert(getCurrentDirective() == OMPD_ordered_standalone);
1292 getTopOfStack().Directive = OMPD_ordered_blockassoc;
1293 }
1294};
1295
1296bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1297 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1298}
1299
1300bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1301 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1302 DKind == OMPD_unknown;
1303}
1304
1305} // namespace
1306
1307static const Expr *getExprAsWritten(const Expr *E) {
1308 if (const auto *FE = dyn_cast<FullExpr>(E))
1309 E = FE->getSubExpr();
1310
1311 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1312 E = MTE->getSubExpr();
1313
1314 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1315 E = Binder->getSubExpr();
1316
1317 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1318 E = ICE->getSubExprAsWritten();
1319 return E->IgnoreParens();
1320}
1321
1323 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1324}
1325
1326static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1327 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1328 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1329 D = ME->getMemberDecl();
1330
1332 return D;
1333}
1334
1336 return const_cast<ValueDecl *>(
1337 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1338}
1339
1341 if (C == OMPC_threadprivate)
1342 return getOpenMPClauseName(C).str() + " or thread local";
1343 return getOpenMPClauseName(C).str();
1344}
1345
1346DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1347 ValueDecl *D) const {
1348 D = getCanonicalDecl(D);
1349 auto *VD = dyn_cast<VarDecl>(D);
1350 const auto *FD = dyn_cast<FieldDecl>(D);
1351 DSAVarData DVar;
1352 if (Iter == end()) {
1353 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1354 // in a region but not in construct]
1355 // File-scope or namespace-scope variables referenced in called routines
1356 // in the region are shared unless they appear in a threadprivate
1357 // directive.
1358 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1359 DVar.CKind = OMPC_shared;
1360
1361 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1362 // in a region but not in construct]
1363 // Variables with static storage duration that are declared in called
1364 // routines in the region are shared.
1365 if (VD && VD->hasGlobalStorage())
1366 DVar.CKind = OMPC_shared;
1367
1368 // Non-static data members are shared by default.
1369 if (FD)
1370 DVar.CKind = OMPC_shared;
1371
1372 return DVar;
1373 }
1374
1375 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1376 // in a Construct, C/C++, predetermined, p.1]
1377 // Variables with automatic storage duration that are declared in a scope
1378 // inside the construct are private.
1379 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1380 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1381 DVar.CKind = OMPC_private;
1382 return DVar;
1383 }
1384
1385 DVar.DKind = Iter->Directive;
1386 // Explicitly specified attributes and local variables with predetermined
1387 // attributes.
1388 if (Iter->SharingMap.count(D)) {
1389 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1390 DVar.RefExpr = Data.RefExpr.getPointer();
1391 DVar.PrivateCopy = Data.PrivateCopy;
1392 DVar.CKind = Data.Attributes;
1393 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1394 DVar.Modifier = Data.Modifier;
1395 DVar.AppliedToPointee = Data.AppliedToPointee;
1396 // For BindingDecls with OMPC_unknown, fall through to implicit DSA logic
1397 // instead of treating them as explicitly specified.
1398 if (!(isa<BindingDecl>(D) && DVar.CKind == OMPC_unknown)) {
1399 return DVar;
1400 }
1401 }
1402
1403 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1404 switch (Iter->DefaultVCAttr) {
1405 case DSA_VC_aggregate:
1406 if (!D->getType()->isAggregateType())
1407 IterDA = DSA_none;
1408 break;
1409 case DSA_VC_pointer:
1410 if (!D->getType()->isPointerType())
1411 IterDA = DSA_none;
1412 break;
1413 case DSA_VC_scalar:
1414 if (!D->getType()->isScalarType())
1415 IterDA = DSA_none;
1416 break;
1417 case DSA_VC_all:
1418 break;
1419 }
1420
1421 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1422 // in a Construct, C/C++, implicitly determined, p.1]
1423 // In a parallel or task construct, the data-sharing attributes of these
1424 // variables are determined by the default clause, if present.
1425 switch (IterDA) {
1426 case DSA_shared:
1427 DVar.CKind = OMPC_shared;
1428 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1429 return DVar;
1430 case DSA_none:
1431 return DVar;
1432 case DSA_firstprivate:
1433 if (VD && VD->getStorageDuration() == SD_Static &&
1434 VD->getDeclContext()->isFileContext()) {
1435 DVar.CKind = OMPC_unknown;
1436 } else {
1437 DVar.CKind = OMPC_firstprivate;
1438 }
1439 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1440 return DVar;
1441 case DSA_private:
1442 // each variable with static storage duration that is declared
1443 // in a namespace or global scope and referenced in the construct,
1444 // and that does not have a predetermined data-sharing attribute
1445 if (VD && VD->getStorageDuration() == SD_Static &&
1446 VD->getDeclContext()->isFileContext()) {
1447 DVar.CKind = OMPC_unknown;
1448 } else {
1449 DVar.CKind = OMPC_private;
1450 }
1451 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1452 return DVar;
1453 case DSA_unspecified:
1454 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1455 // in a Construct, implicitly determined, p.2]
1456 // In a parallel construct, if no default clause is present, these
1457 // variables are shared.
1458 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1459 if ((isOpenMPParallelDirective(DVar.DKind) &&
1460 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1461 isOpenMPTeamsDirective(DVar.DKind)) {
1462 DVar.CKind = OMPC_shared;
1463 return DVar;
1464 }
1465
1466 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1467 // in a Construct, implicitly determined, p.4]
1468 // In a task construct, if no default clause is present, a variable that in
1469 // the enclosing context is determined to be shared by all implicit tasks
1470 // bound to the current team is shared.
1471 if (isOpenMPTaskingDirective(DVar.DKind)) {
1472 DSAVarData DVarTemp;
1473 const_iterator I = Iter, E = end();
1474 do {
1475 ++I;
1476 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1477 // Referenced in a Construct, implicitly determined, p.6]
1478 // In a task construct, if no default clause is present, a variable
1479 // whose data-sharing attribute is not determined by the rules above is
1480 // firstprivate.
1481 DVarTemp = getDSA(I, D);
1482 if (DVarTemp.CKind != OMPC_shared) {
1483 DVar.RefExpr = nullptr;
1484 DVar.CKind = OMPC_firstprivate;
1485 return DVar;
1486 }
1487 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1488 DVar.CKind =
1489 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1490 return DVar;
1491 }
1492 }
1493 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1494 // in a Construct, implicitly determined, p.3]
1495 // For constructs other than task, if no default clause is present, these
1496 // variables inherit their data-sharing attributes from the enclosing
1497 // context.
1498 return getDSA(++Iter, D);
1499}
1500
1501const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1502 const Expr *NewDE) {
1503 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1504 D = getCanonicalDecl(D);
1505 SharingMapTy &StackElem = getTopOfStack();
1506 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1507 if (Inserted) {
1508 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1509 return nullptr;
1510 }
1511 assert(It->second && "Unexpected nullptr expr in the aligned map");
1512 return It->second;
1513}
1514
1515const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1516 const Expr *NewDE) {
1517 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1518 D = getCanonicalDecl(D);
1519 SharingMapTy &StackElem = getTopOfStack();
1520 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1521 if (Inserted) {
1522 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1523 return nullptr;
1524 }
1525 assert(It->second && "Unexpected nullptr expr in the aligned map");
1526 return It->second;
1527}
1528
1529void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1530 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1531 D = getCanonicalDecl(D);
1532 SharingMapTy &StackElem = getTopOfStack();
1533 StackElem.LCVMap.try_emplace(
1534 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1535}
1536
1537const DSAStackTy::LCDeclInfo
1538DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1539 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1540 D = getCanonicalDecl(D);
1541 const SharingMapTy &StackElem = getTopOfStack();
1542 auto It = StackElem.LCVMap.find(D);
1543 if (It != StackElem.LCVMap.end())
1544 return It->second;
1545 return {0, nullptr};
1546}
1547
1548const DSAStackTy::LCDeclInfo
1549DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1550 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1551 D = getCanonicalDecl(D);
1552 for (unsigned I = Level + 1; I > 0; --I) {
1553 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1554 auto It = StackElem.LCVMap.find(D);
1555 if (It != StackElem.LCVMap.end())
1556 return It->second;
1557 }
1558 return {0, nullptr};
1559}
1560
1561const DSAStackTy::LCDeclInfo
1562DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1563 const SharingMapTy *Parent = getSecondOnStackOrNull();
1564 assert(Parent && "Data-sharing attributes stack is empty");
1565 D = getCanonicalDecl(D);
1566 auto It = Parent->LCVMap.find(D);
1567 if (It != Parent->LCVMap.end())
1568 return It->second;
1569 return {0, nullptr};
1570}
1571
1572const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1573 const SharingMapTy *Parent = getSecondOnStackOrNull();
1574 assert(Parent && "Data-sharing attributes stack is empty");
1575 if (Parent->LCVMap.size() < I)
1576 return nullptr;
1577 for (const auto &Pair : Parent->LCVMap)
1578 if (Pair.second.first == I)
1579 return Pair.first;
1580 return nullptr;
1581}
1582
1583void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1584 DeclRefExpr *PrivateCopy, unsigned Modifier,
1585 bool AppliedToPointee) {
1586 D = getCanonicalDecl(D);
1587 if (A == OMPC_threadprivate) {
1588 DSAInfo &Data = Threadprivates[D];
1589 Data.Attributes = A;
1590 Data.RefExpr.setPointer(E);
1591 Data.PrivateCopy = nullptr;
1592 Data.Modifier = Modifier;
1593 } else if (A == OMPC_groupprivate) {
1594 DSAInfo &Data = Groupprivates[D];
1595 Data.Attributes = A;
1596 Data.RefExpr.setPointer(E);
1597 Data.PrivateCopy = nullptr;
1598 Data.Modifier = Modifier;
1599 } else {
1600 DSAInfo &Data = getTopOfStack().SharingMap[D];
1601 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1602 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1603 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1604 (isLoopControlVariable(D).first && A == OMPC_private));
1605 Data.Modifier = Modifier;
1606 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1607 Data.RefExpr.setInt(/*IntVal=*/true);
1608 return;
1609 }
1610 const bool IsLastprivate =
1611 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1612 Data.Attributes = A;
1613 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1614 Data.PrivateCopy = PrivateCopy;
1615 Data.AppliedToPointee = AppliedToPointee;
1616 if (PrivateCopy) {
1617 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1618 Data.Modifier = Modifier;
1619 Data.Attributes = A;
1620 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1621 Data.PrivateCopy = nullptr;
1622 Data.AppliedToPointee = AppliedToPointee;
1623 }
1624 }
1625}
1626
1627/// Build a variable declaration for OpenMP loop iteration variable.
1629 StringRef Name, const AttrVec *Attrs = nullptr,
1630 DeclRefExpr *OrigRef = nullptr) {
1631 DeclContext *DC = SemaRef.CurContext;
1632 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1633 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1634 auto *Decl =
1635 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1636 if (Attrs) {
1637 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1638 I != E; ++I)
1639 Decl->addAttr(*I);
1640 }
1641 Decl->setImplicit();
1642 if (OrigRef) {
1643 Decl->addAttr(
1644 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1645 }
1646 return Decl;
1647}
1648
1650 SourceLocation Loc,
1651 bool RefersToCapture = false) {
1652 D->setReferenced();
1653 D->markUsed(S.Context);
1655 SourceLocation(), D, RefersToCapture, Loc, Ty,
1656 VK_LValue);
1657}
1658
1659void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1660 BinaryOperatorKind BOK) {
1661 D = getCanonicalDecl(D);
1662 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1663 assert(
1664 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1665 "Additional reduction info may be specified only for reduction items.");
1666 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1667 assert(ReductionData.ReductionRange.isInvalid() &&
1668 (getTopOfStack().Directive == OMPD_taskgroup ||
1669 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1670 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1671 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1672 "Additional reduction info may be specified only once for reduction "
1673 "items.");
1674 ReductionData.set(BOK, SR);
1675 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1676 if (!TaskgroupReductionRef) {
1677 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1678 SemaRef.Context.VoidPtrTy, ".task_red.");
1679 TaskgroupReductionRef =
1680 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1681 }
1682}
1683
1684void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1685 const Expr *ReductionRef) {
1686 D = getCanonicalDecl(D);
1687 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1688 assert(
1689 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1690 "Additional reduction info may be specified only for reduction items.");
1691 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1692 assert(ReductionData.ReductionRange.isInvalid() &&
1693 (getTopOfStack().Directive == OMPD_taskgroup ||
1694 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1695 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1696 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1697 "Additional reduction info may be specified only once for reduction "
1698 "items.");
1699 ReductionData.set(ReductionRef, SR);
1700 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1701 if (!TaskgroupReductionRef) {
1702 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1703 SemaRef.Context.VoidPtrTy, ".task_red.");
1704 TaskgroupReductionRef =
1705 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1706 }
1707}
1708
1709const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1710 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1711 Expr *&TaskgroupDescriptor) const {
1712 D = getCanonicalDecl(D);
1713 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1714 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1715 const DSAInfo &Data = I->SharingMap.lookup(D);
1716 if (Data.Attributes != OMPC_reduction ||
1717 Data.Modifier != OMPC_REDUCTION_task)
1718 continue;
1719 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1720 if (!ReductionData.ReductionOp ||
1721 isa<const Expr *>(ReductionData.ReductionOp))
1722 return DSAVarData();
1723 SR = ReductionData.ReductionRange;
1724 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1725 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1726 "expression for the descriptor is not "
1727 "set.");
1728 TaskgroupDescriptor = I->TaskgroupReductionRef;
1729 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1730 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1731 /*AppliedToPointee=*/false);
1732 }
1733 return DSAVarData();
1734}
1735
1736const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1737 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1738 Expr *&TaskgroupDescriptor) const {
1739 D = getCanonicalDecl(D);
1740 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1741 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1742 const DSAInfo &Data = I->SharingMap.lookup(D);
1743 if (Data.Attributes != OMPC_reduction ||
1744 Data.Modifier != OMPC_REDUCTION_task)
1745 continue;
1746 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1747 if (!ReductionData.ReductionOp ||
1748 !isa<const Expr *>(ReductionData.ReductionOp))
1749 return DSAVarData();
1750 SR = ReductionData.ReductionRange;
1751 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1752 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1753 "expression for the descriptor is not "
1754 "set.");
1755 TaskgroupDescriptor = I->TaskgroupReductionRef;
1756 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1757 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1758 /*AppliedToPointee=*/false);
1759 }
1760 return DSAVarData();
1761}
1762
1763bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1764 D = D->getCanonicalDecl();
1765 for (const_iterator E = end(); I != E; ++I) {
1766 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1767 isOpenMPTargetExecutionDirective(I->Directive)) {
1768 if (I->CurScope) {
1769 Scope *TopScope = I->CurScope->getParent();
1770 Scope *CurScope = getCurScope();
1771 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1772 CurScope = CurScope->getParent();
1773 return CurScope != TopScope;
1774 }
1775 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1776 if (I->Context == DC)
1777 return true;
1778 return false;
1779 }
1780 }
1781 return false;
1782}
1783
1785 bool AcceptIfMutable = true,
1786 bool *IsClassType = nullptr) {
1787 ASTContext &Context = SemaRef.getASTContext();
1788 Type = Type.getNonReferenceType().getCanonicalType();
1789 bool IsConstant = Type.isConstant(Context);
1790 Type = Context.getBaseElementType(Type);
1791 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1793 : nullptr;
1794 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1795 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1796 RD = CTD->getTemplatedDecl();
1797 if (IsClassType)
1798 *IsClassType = RD;
1799 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1800 RD->hasDefinition() && RD->hasMutableFields());
1801}
1802
1803static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1805 SourceLocation ELoc,
1806 bool AcceptIfMutable = true,
1807 bool ListItemNotVar = false) {
1808 ASTContext &Context = SemaRef.getASTContext();
1809 bool IsClassType;
1810 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1811 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1812 : IsClassType ? diag::err_omp_const_not_mutable_variable
1813 : diag::err_omp_const_variable;
1814 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseNameForDiag(CKind);
1815 if (!ListItemNotVar && D) {
1816 const VarDecl *VD = dyn_cast<VarDecl>(D);
1817 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1819 SemaRef.Diag(D->getLocation(),
1820 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1821 << D;
1822 }
1823 return true;
1824 }
1825 return false;
1826}
1827
1828const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1829 bool FromParent) {
1830 D = getCanonicalDecl(D);
1831 DSAVarData DVar;
1832
1833 auto *VD = dyn_cast<VarDecl>(D);
1834 auto TI = Threadprivates.find(D);
1835 if (TI != Threadprivates.end()) {
1836 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1837 DVar.CKind = OMPC_threadprivate;
1838 DVar.Modifier = TI->getSecond().Modifier;
1839 return DVar;
1840 }
1841 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1842 DVar.RefExpr = buildDeclRefExpr(
1843 SemaRef, VD, D->getType().getNonReferenceType(),
1844 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1845 DVar.CKind = OMPC_threadprivate;
1846 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1847 return DVar;
1848 }
1849 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1850 // in a Construct, C/C++, predetermined, p.1]
1851 // Variables appearing in threadprivate directives are threadprivate.
1852 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1853 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1854 SemaRef.getLangOpts().OpenMPUseTLS &&
1855 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1856 (VD && VD->getStorageClass() == SC_Register &&
1857 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1858 DVar.RefExpr = buildDeclRefExpr(
1859 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1860 DVar.CKind = OMPC_threadprivate;
1861 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1862 return DVar;
1863 }
1864 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1865 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1866 !isLoopControlVariable(D).first) {
1867 const_iterator IterTarget =
1868 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1869 return isOpenMPTargetExecutionDirective(Data.Directive);
1870 });
1871 if (IterTarget != end()) {
1872 const_iterator ParentIterTarget = IterTarget + 1;
1873 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1874 if (isOpenMPLocal(VD, Iter)) {
1875 DVar.RefExpr =
1876 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1877 D->getLocation());
1878 DVar.CKind = OMPC_threadprivate;
1879 return DVar;
1880 }
1881 }
1882 if (!isClauseParsingMode() || IterTarget != begin()) {
1883 auto DSAIter = IterTarget->SharingMap.find(D);
1884 if (DSAIter != IterTarget->SharingMap.end() &&
1885 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1886 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1887 DVar.CKind = OMPC_threadprivate;
1888 return DVar;
1889 }
1890 const_iterator End = end();
1891 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1892 D, std::distance(ParentIterTarget, End),
1893 /*OpenMPCaptureLevel=*/0)) {
1894 DVar.RefExpr =
1895 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1896 IterTarget->ConstructLoc);
1897 DVar.CKind = OMPC_threadprivate;
1898 return DVar;
1899 }
1900 }
1901 }
1902 }
1903
1904 if (isStackEmpty())
1905 // Not in OpenMP execution region and top scope was already checked.
1906 return DVar;
1907
1908 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1909 // in a Construct, C/C++, predetermined, p.4]
1910 // Static data members are shared.
1911 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1912 // in a Construct, C/C++, predetermined, p.7]
1913 // Variables with static storage duration that are declared in a scope
1914 // inside the construct are shared.
1915 if (VD && VD->isStaticDataMember()) {
1916 // Check for explicitly specified attributes.
1917 const_iterator I = begin();
1918 const_iterator EndI = end();
1919 if (FromParent && I != EndI)
1920 ++I;
1921 if (I != EndI) {
1922 auto It = I->SharingMap.find(D);
1923 if (It != I->SharingMap.end()) {
1924 const DSAInfo &Data = It->getSecond();
1925 DVar.RefExpr = Data.RefExpr.getPointer();
1926 DVar.PrivateCopy = Data.PrivateCopy;
1927 DVar.CKind = Data.Attributes;
1928 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1929 DVar.DKind = I->Directive;
1930 DVar.Modifier = Data.Modifier;
1931 DVar.AppliedToPointee = Data.AppliedToPointee;
1932 return DVar;
1933 }
1934 }
1935
1936 DVar.CKind = OMPC_shared;
1937 return DVar;
1938 }
1939
1940 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1941 // The predetermined shared attribute for const-qualified types having no
1942 // mutable members was removed after OpenMP 3.1.
1943 if (SemaRef.LangOpts.OpenMP <= 31) {
1944 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1945 // in a Construct, C/C++, predetermined, p.6]
1946 // Variables with const qualified type having no mutable member are
1947 // shared.
1948 if (isConstNotMutableType(SemaRef, D->getType())) {
1949 // Variables with const-qualified type having no mutable member may be
1950 // listed in a firstprivate clause, even if they are static data members.
1951 DSAVarData DVarTemp = hasInnermostDSA(
1952 D,
1953 [](OpenMPClauseKind C, bool) {
1954 return C == OMPC_firstprivate || C == OMPC_shared;
1955 },
1956 MatchesAlways, FromParent);
1957 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1958 return DVarTemp;
1959
1960 DVar.CKind = OMPC_shared;
1961 return DVar;
1962 }
1963 }
1964
1965 // Explicitly specified attributes and local variables with predetermined
1966 // attributes.
1967 const_iterator I = begin();
1968 const_iterator EndI = end();
1969 if (FromParent && I != EndI)
1970 ++I;
1971 if (I == EndI)
1972 return DVar;
1973 auto It = I->SharingMap.find(D);
1974 if (It != I->SharingMap.end()) {
1975 const DSAInfo &Data = It->getSecond();
1976 DVar.RefExpr = Data.RefExpr.getPointer();
1977 DVar.PrivateCopy = Data.PrivateCopy;
1978 DVar.CKind = Data.Attributes;
1979 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1980 DVar.DKind = I->Directive;
1981 DVar.Modifier = Data.Modifier;
1982 DVar.AppliedToPointee = Data.AppliedToPointee;
1983 }
1984
1985 return DVar;
1986}
1987
1988const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1989 bool FromParent) const {
1990 if (isStackEmpty()) {
1991 const_iterator I;
1992 return getDSA(I, D);
1993 }
1994 D = getCanonicalDecl(D);
1995 const_iterator StartI = begin();
1996 const_iterator EndI = end();
1997 if (FromParent && StartI != EndI)
1998 ++StartI;
1999 return getDSA(StartI, D);
2000}
2001
2002const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
2003 unsigned Level) const {
2004 if (getStackSize() <= Level)
2005 return DSAVarData();
2006 D = getCanonicalDecl(D);
2007 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
2008 return getDSA(StartI, D);
2009}
2010
2011const DSAStackTy::DSAVarData
2012DSAStackTy::hasDSA(ValueDecl *D,
2013 const llvm::function_ref<bool(OpenMPClauseKind, bool,
2014 DefaultDataSharingAttributes)>
2015 CPred,
2016 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2017 bool FromParent) const {
2018 if (isStackEmpty())
2019 return {};
2020 D = getCanonicalDecl(D);
2021 const_iterator I = begin();
2022 const_iterator EndI = end();
2023 if (FromParent && I != EndI)
2024 ++I;
2025 for (; I != EndI; ++I) {
2026 if (!DPred(I->Directive) &&
2027 !isImplicitOrExplicitTaskingRegion(I->Directive))
2028 continue;
2029 const_iterator NewI = I;
2030 DSAVarData DVar = getDSA(NewI, D);
2031 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
2032 return DVar;
2033 }
2034 return {};
2035}
2036
2037const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
2038 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2039 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2040 bool FromParent) const {
2041 if (isStackEmpty())
2042 return {};
2043 D = getCanonicalDecl(D);
2044 const_iterator StartI = begin();
2045 const_iterator EndI = end();
2046 if (FromParent && StartI != EndI)
2047 ++StartI;
2048 if (StartI == EndI || !DPred(StartI->Directive))
2049 return {};
2050 const_iterator NewI = StartI;
2051 DSAVarData DVar = getDSA(NewI, D);
2052 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2053 ? DVar
2054 : DSAVarData();
2055}
2056
2057bool DSAStackTy::hasExplicitDSA(
2058 const ValueDecl *D,
2059 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2060 unsigned Level, bool NotLastprivate) const {
2061 if (getStackSize() <= Level)
2062 return false;
2063 D = getCanonicalDecl(D);
2064 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2065 auto I = StackElem.SharingMap.find(D);
2066 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2067 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2068 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2069 return true;
2070 // Check predetermined rules for the loop control variables.
2071 auto LI = StackElem.LCVMap.find(D);
2072 if (LI != StackElem.LCVMap.end())
2073 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2074 return false;
2075}
2076
2077bool DSAStackTy::hasExplicitDirective(
2078 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2079 unsigned Level) const {
2080 if (getStackSize() <= Level)
2081 return false;
2082 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2083 return DPred(StackElem.Directive);
2084}
2085
2086bool DSAStackTy::hasDirective(
2087 const llvm::function_ref<bool(OpenMPDirectiveKind,
2088 const DeclarationNameInfo &, SourceLocation)>
2089 DPred,
2090 bool FromParent) const {
2091 // We look only in the enclosing region.
2092 size_t Skip = FromParent ? 2 : 1;
2093 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2094 I != E; ++I) {
2095 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2096 return true;
2097 }
2098 return false;
2099}
2100
2101void SemaOpenMP::InitDataSharingAttributesStack() {
2102 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2103}
2104
2105#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2106
2108 DSAStack->addRequiresDecl(D);
2109}
2110
2112 return DSAStack->getRequiresDecls();
2113}
2114
2115void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2116
2117void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2118 DSAStack->popFunction(OldFSI);
2119}
2120
2122 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2123 "Expected OpenMP device compilation.");
2125}
2126
2127namespace {
2128/// Status of the function emission on the host/device.
2129enum class FunctionEmissionStatus {
2130 Emitted,
2131 Discarded,
2132 Unknown,
2133};
2134} // anonymous namespace
2135
2136SemaBase::SemaDiagnosticBuilder
2138 const FunctionDecl *FD) {
2139 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2140 "Expected OpenMP device compilation.");
2141
2142 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2143 if (FD) {
2144 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2145 switch (FES) {
2147 Kind = SemaDiagnosticBuilder::K_Immediate;
2148 break;
2150 // TODO: We should always delay diagnostics here in case a target
2151 // region is in a function we do not emit. However, as the
2152 // current diagnostics are associated with the function containing
2153 // the target region and we do not emit that one, we would miss out
2154 // on diagnostics for the target region itself. We need to anchor
2155 // the diagnostics with the new generated function *or* ensure we
2156 // emit diagnostics associated with the surrounding function.
2158 ? SemaDiagnosticBuilder::K_Deferred
2159 : SemaDiagnosticBuilder::K_Immediate;
2160 break;
2163 Kind = SemaDiagnosticBuilder::K_Nop;
2164 break;
2166 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2167 break;
2168 }
2169 }
2170
2171 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2172}
2173
2176 const FunctionDecl *FD) {
2177 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2178 "Expected OpenMP host compilation.");
2179
2180 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2181 if (FD) {
2182 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2183 switch (FES) {
2185 Kind = SemaDiagnosticBuilder::K_Immediate;
2186 break;
2188 Kind = SemaDiagnosticBuilder::K_Deferred;
2189 break;
2193 Kind = SemaDiagnosticBuilder::K_Nop;
2194 break;
2195 }
2196 }
2197
2198 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2199}
2200
2203 if (LO.OpenMP <= 45) {
2205 return OMPC_DEFAULTMAP_scalar;
2206 return OMPC_DEFAULTMAP_aggregate;
2207 }
2209 return OMPC_DEFAULTMAP_pointer;
2211 return OMPC_DEFAULTMAP_scalar;
2212 return OMPC_DEFAULTMAP_aggregate;
2213}
2214
2215bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2216 unsigned OpenMPCaptureLevel) const {
2217 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2218
2219 ASTContext &Ctx = getASTContext();
2220 bool IsByRef = true;
2221
2222 // Find the directive that is associated with the provided scope.
2224 QualType Ty = D->getType();
2225 if (const auto *BD = dyn_cast<BindingDecl>(D))
2226 Ty = BD->getDecomposedDecl()->getType();
2227
2228 bool IsVariableUsedInMapClause = false;
2229 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2230 // This table summarizes how a given variable should be passed to the device
2231 // given its type and the clauses where it appears. This table is based on
2232 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2233 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2234 //
2235 // =========================================================================
2236 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2237 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2238 // =========================================================================
2239 // | scl | | | | - | | bycopy|
2240 // | scl | | - | x | - | - | bycopy|
2241 // | scl | | x | - | - | - | null |
2242 // | scl | x | | | - | | byref |
2243 // | scl | x | - | x | - | - | bycopy|
2244 // | scl | x | x | - | - | - | null |
2245 // | scl | | - | - | - | x | byref |
2246 // | scl | x | - | - | - | x | byref |
2247 //
2248 // | agg | n.a. | | | - | | byref |
2249 // | agg | n.a. | - | x | - | - | byref |
2250 // | agg | n.a. | x | - | - | - | null |
2251 // | agg | n.a. | - | - | - | x | byref |
2252 // | agg | n.a. | - | - | - | x[] | byref |
2253 //
2254 // | ptr | n.a. | | | - | | bycopy|
2255 // | ptr | n.a. | - | x | - | - | bycopy|
2256 // | ptr | n.a. | x | - | - | - | null |
2257 // | ptr | n.a. | - | - | - | x | byref |
2258 // | ptr | n.a. | - | - | - | x, x[] | bycopy|
2259 // | ptr | n.a. | - | - | - | x[] | bycopy|
2260 // | ptr | n.a. | - | - | x | | bycopy|
2261 // | ptr | n.a. | - | - | x | x | bycopy|
2262 // | ptr | n.a. | - | - | x | x[] | bycopy|
2263 // =========================================================================
2264 // Legend:
2265 // scl - scalar
2266 // ptr - pointer
2267 // agg - aggregate
2268 // x - applies
2269 // - - invalid in this combination
2270 // [] - mapped with an array section
2271 // byref - should be mapped by reference
2272 // byval - should be mapped by value
2273 // null - initialize a local variable to null on the device
2274 //
2275 // Observations:
2276 // - All scalar declarations that show up in a map clause have to be passed
2277 // by reference, because they may have been mapped in the enclosing data
2278 // environment.
2279 // - If the scalar value does not fit the size of uintptr, it has to be
2280 // passed by reference, regardless the result in the table above.
2281 // - For pointers mapped by value that have either an implicit map or an
2282 // array section, the runtime library may pass the NULL value to the
2283 // device instead of the value passed to it by the compiler.
2284 // - If both a pointer and a dereference of it are mapped, then the pointer
2285 // should be passed by reference.
2286
2287 if (Ty->isReferenceType())
2288 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2289
2290 // Locate map clauses and see if the variable being captured is mapped by
2291 // itself, or referred to, in any of those clauses. Here we only care about
2292 // variables, not fields, because fields are part of aggregates.
2293 bool IsVariableAssociatedWithSection = false;
2294 bool IsVariableItselfMapped = false;
2295
2296 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2297 D, Level,
2298 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2299 &IsVariableItselfMapped,
2301 MapExprComponents,
2302 OpenMPClauseKind WhereFoundClauseKind) {
2303 // Both map and has_device_addr clauses information influences how a
2304 // variable is captured. E.g. is_device_ptr does not require changing
2305 // the default behavior.
2306 if (WhereFoundClauseKind != OMPC_map &&
2307 WhereFoundClauseKind != OMPC_has_device_addr)
2308 return false;
2309
2310 auto EI = MapExprComponents.rbegin();
2311 auto EE = MapExprComponents.rend();
2312
2313 assert(EI != EE && "Invalid map expression!");
2314
2315 if (isa<DeclRefExpr>(EI->getAssociatedExpression()) &&
2316 EI->getAssociatedDeclaration() == D) {
2317 IsVariableUsedInMapClause = true;
2318
2319 // If the component list has only one element, it's for mapping the
2320 // variable itself, like map(p). This takes precedence in
2321 // determining how it's captured, so we don't need to look further
2322 // for any other maps that use the variable (like map(p[0]) etc.)
2323 if (MapExprComponents.size() == 1) {
2324 IsVariableItselfMapped = true;
2325 return true;
2326 }
2327 }
2328
2329 ++EI;
2330 if (EI == EE)
2331 return false;
2332 auto Last = std::prev(EE);
2333 const auto *UO =
2334 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2335 if ((UO && UO->getOpcode() == UO_Deref) ||
2336 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2337 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2338 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2339 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2340 IsVariableAssociatedWithSection = true;
2341 // We've found a case like map(p[0]) or map(p->a) or map(*p),
2342 // so we are done with this particular map, but we need to keep
2343 // looking in case we find a map(p).
2344 return false;
2345 }
2346
2347 // Keep looking for more map info.
2348 return false;
2349 });
2350
2351 if (IsVariableUsedInMapClause) {
2352 // If variable is identified in a map clause it is always captured by
2353 // reference except if it is a pointer that is dereferenced somehow, but
2354 // not itself mapped.
2355 //
2356 // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
2357 // in a construct::
2358 // If a list item in a has_device_addr clause or in a map clause on the
2359 // target construct has a base pointer, and the base pointer is a scalar
2360 // variable *that is not a list item in a map clause on the construct*,
2361 // the base pointer is firstprivate.
2362 //
2363 // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
2364 // Referenced in a Construct:
2365 // If an array section is a list item in a map clause on the target
2366 // construct and the array section is derived from a variable for which
2367 // the type is pointer then that variable is firstprivate.
2368 IsByRef = IsVariableItselfMapped ||
2369 !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2370 } else {
2371 // By default, all the data that has a scalar type is mapped by copy
2372 // (except for reduction variables).
2373 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2374 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2375 !Ty->isAnyPointerType()) ||
2376 !Ty->isScalarType() ||
2377 DSAStack->isDefaultmapCapturedByRef(
2379 DSAStack->hasExplicitDSA(
2380 D,
2381 [](OpenMPClauseKind K, bool AppliedToPointee) {
2382 return K == OMPC_reduction && !AppliedToPointee;
2383 },
2384 Level);
2385 }
2386 }
2387
2388 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2389 IsByRef =
2390 ((IsVariableUsedInMapClause &&
2391 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2392 OMPD_target) ||
2393 !(DSAStack->hasExplicitDSA(
2394 D,
2395 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2396 return K == OMPC_firstprivate ||
2397 (K == OMPC_reduction && AppliedToPointee);
2398 },
2399 Level, /*NotLastprivate=*/true) ||
2400 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2401 // If the variable is artificial and must be captured by value - try to
2402 // capture by value.
2403 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2404 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2405 // If the variable is implicitly firstprivate and scalar - capture by
2406 // copy. Query the default data-sharing attribute at the capture level
2407 // being considered rather than at the innermost directive: a nested
2408 // default(firstprivate) or default(private) must not make an enclosing
2409 // region capture by copy and lose its writes.
2410 !((DSAStack->getDefaultDSA(Level) == DSA_firstprivate ||
2411 DSAStack->getDefaultDSA(Level) == DSA_private) &&
2412 !DSAStack->hasExplicitDSA(
2413 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2414 Level) &&
2415 !DSAStack->isLoopControlVariable(D, Level).first);
2416 }
2417
2418 // When passing data by copy, we need to make sure it fits the uintptr size
2419 // and alignment, because the runtime library only deals with uintptr types.
2420 // If it does not fit the uintptr size, we need to pass the data by reference
2421 // instead.
2422 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2424 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2425 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2426 IsByRef = true;
2427 }
2428
2429 return IsByRef;
2430}
2431
2432unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2433 assert(getLangOpts().OpenMP);
2434 return DSAStack->getNestingLevel();
2435}
2436
2438 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2439 DSAStack->isUntiedRegion();
2440}
2441
2443 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2444 !DSAStack->isClauseParsingMode()) ||
2445 DSAStack->hasDirective(
2447 SourceLocation) -> bool {
2449 },
2450 false);
2451}
2452
2454 // Only rebuild for Field.
2455 if (!isa<FieldDecl>(D))
2456 return false;
2457 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2458 D,
2459 [](OpenMPClauseKind C, bool AppliedToPointee,
2460 DefaultDataSharingAttributes DefaultAttr) {
2461 return isOpenMPPrivate(C) && !AppliedToPointee &&
2462 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2463 },
2464 [](OpenMPDirectiveKind) { return true; },
2465 DSAStack->isClauseParsingMode());
2466 if (DVarPrivate.CKind != OMPC_unknown)
2467 return true;
2468 return false;
2469}
2470
2472 Expr *CaptureExpr, bool WithInit,
2473 DeclContext *CurContext,
2474 bool AsExpression);
2475
2477 unsigned StopAt) {
2478 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2479 D = getCanonicalDecl(D);
2480
2481 if (auto *BD = dyn_cast<BindingDecl>(D)) {
2482 if (!BD->getHoldingVar())
2483 D = cast<VarDecl>(BD->getDecomposedDecl());
2484 }
2485 auto *VD = dyn_cast<VarDecl>(D);
2486 // Do not capture constexpr variables.
2487 if (VD && VD->isConstexpr())
2488 return nullptr;
2489
2490 // If we want to determine whether the variable should be captured from the
2491 // perspective of the current capturing scope, and we've already left all the
2492 // capturing scopes of the top directive on the stack, check from the
2493 // perspective of its parent directive (if any) instead.
2494 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2495 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2496
2497 // If we are attempting to capture a global variable in a directive with
2498 // 'target' we return true so that this global is also mapped to the device.
2499 //
2500 if (VD && !VD->hasLocalStorage() &&
2501 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2502 SemaRef.getCurLambda())) {
2504 DSAStackTy::DSAVarData DVarTop =
2505 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2506 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2507 return VD;
2508 // If the declaration is enclosed in a 'declare target' directive,
2509 // then it should not be captured.
2510 //
2511 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2512 return nullptr;
2513 CapturedRegionScopeInfo *CSI = nullptr;
2514 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2515 llvm::reverse(SemaRef.FunctionScopes),
2516 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2517 : 0)) {
2518 if (!isa<CapturingScopeInfo>(FSI))
2519 return nullptr;
2520 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2521 if (RSI->CapRegionKind == CR_OpenMP) {
2522 CSI = RSI;
2523 break;
2524 }
2525 }
2526 // Lambdas and blocks at namespace scope have no enclosing function scope.
2527 if (!CSI)
2528 return nullptr;
2531 DSAStack->getDirective(CSI->OpenMPLevel));
2532 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2533 return VD;
2534 }
2536 // Try to mark variable as declare target if it is used in capturing
2537 // regions.
2538 if (getLangOpts().OpenMP <= 45 &&
2539 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2541 return nullptr;
2542 }
2543 }
2544
2545 if (CheckScopeInfo) {
2546 bool OpenMPFound = false;
2547 for (unsigned I = StopAt + 1; I > 0; --I) {
2548 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2549 if (!isa<CapturingScopeInfo>(FSI))
2550 return nullptr;
2551 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2552 if (RSI->CapRegionKind == CR_OpenMP) {
2553 OpenMPFound = true;
2554 break;
2555 }
2556 }
2557 if (!OpenMPFound)
2558 return nullptr;
2559 }
2560
2561 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2562 (!DSAStack->isClauseParsingMode() ||
2563 DSAStack->getParentDirective() != OMPD_unknown)) {
2564 auto &&Info = DSAStack->isLoopControlVariable(D);
2565 if (Info.first ||
2566 (VD && VD->hasLocalStorage() &&
2567 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2568 (VD && DSAStack->isForceVarCapturing()))
2569 return VD ? VD : Info.second;
2570 DSAStackTy::DSAVarData DVarTop =
2571 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2572 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2573 (!VD || VD->hasLocalStorage() ||
2574 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2575 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2576 // Threadprivate variables must not be captured.
2577 if (isOpenMPThreadPrivate(DVarTop.CKind))
2578 return nullptr;
2579 // The variable is not private or it is the variable in the directive with
2580 // default(none) clause and not used in any clause.
2581 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2582 D,
2583 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2584 return isOpenMPPrivate(C) && !AppliedToPointee;
2585 },
2586 [](OpenMPDirectiveKind) { return true; },
2587 DSAStack->isClauseParsingMode());
2588 // Global shared must not be captured.
2589 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2590 ((DSAStack->getDefaultDSA() != DSA_none &&
2591 DSAStack->getDefaultDSA() != DSA_private &&
2592 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2593 DVarTop.CKind == OMPC_shared))
2594 return nullptr;
2595 auto *FD = dyn_cast<FieldDecl>(D);
2596 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2597 !DVarPrivate.PrivateCopy) {
2598 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2599 D,
2600 [](OpenMPClauseKind C, bool AppliedToPointee,
2601 DefaultDataSharingAttributes DefaultAttr) {
2602 return isOpenMPPrivate(C) && !AppliedToPointee &&
2603 (DefaultAttr == DSA_firstprivate ||
2604 DefaultAttr == DSA_private);
2605 },
2606 [](OpenMPDirectiveKind) { return true; },
2607 DSAStack->isClauseParsingMode());
2608 if (DVarPrivate.CKind == OMPC_unknown)
2609 return nullptr;
2610
2611 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2612 if (VD)
2613 return VD;
2614 if (SemaRef.getCurrentThisType().isNull())
2615 return nullptr;
2616 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2617 SemaRef.getCurrentThisType(),
2618 /*IsImplicit=*/true);
2619 Expr *ME = SemaRef.BuildMemberExpr(
2620 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2623 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2626 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2627 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2628 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2630 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2631 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2632 return VD;
2633 }
2634 if (DVarPrivate.CKind != OMPC_unknown ||
2635 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2636 DSAStack->getDefaultDSA() == DSA_private ||
2637 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2638 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2639 }
2640 return nullptr;
2641}
2642
2643void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2644 unsigned Level) const {
2645 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2646}
2647
2649 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2650 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2651 DSAStack->loopInit();
2652}
2653
2655 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2656 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2657 DSAStack->resetPossibleLoopCounter();
2658 DSAStack->loopStart();
2659 }
2660}
2661
2663 unsigned CapLevel) const {
2664 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2665 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2666 (!DSAStack->isClauseParsingMode() ||
2667 DSAStack->getParentDirective() != OMPD_unknown)) {
2668 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2669 D,
2670 [](OpenMPClauseKind C, bool AppliedToPointee,
2671 DefaultDataSharingAttributes DefaultAttr) {
2672 return isOpenMPPrivate(C) && !AppliedToPointee &&
2673 DefaultAttr == DSA_private;
2674 },
2675 [](OpenMPDirectiveKind) { return true; },
2676 DSAStack->isClauseParsingMode());
2677 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2678 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2679 !DSAStack->isLoopControlVariable(D).first)
2680 return OMPC_private;
2681 }
2682 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2683 bool IsTriviallyCopyable =
2685 getASTContext()) &&
2686 !D->getType()
2690 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2692 getOpenMPCaptureRegions(CaptureRegions, DKind);
2693 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2694 (IsTriviallyCopyable ||
2695 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2696 if (DSAStack->hasExplicitDSA(
2697 D,
2698 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2699 Level, /*NotLastprivate=*/true))
2700 return OMPC_firstprivate;
2701 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2702 if (DVar.CKind != OMPC_shared &&
2703 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2704 DSAStack->addImplicitTaskFirstprivate(Level, D);
2705 return OMPC_firstprivate;
2706 }
2707 }
2708 }
2709 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2710 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2711 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2712 DSAStack->resetPossibleLoopCounter(D);
2713 DSAStack->loopStart();
2714 return OMPC_private;
2715 }
2716 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2717 DSAStack->isLoopControlVariable(D).first) &&
2718 !DSAStack->hasExplicitDSA(
2719 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2720 Level) &&
2721 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2722 return OMPC_private;
2723 }
2724 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2725 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2726 DSAStack->isForceVarCapturing() &&
2727 !DSAStack->hasExplicitDSA(
2728 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2729 Level))
2730 return OMPC_private;
2731 }
2732 // User-defined allocators are private since they must be defined in the
2733 // context of target region.
2734 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2735 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2736 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2737 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2738 return OMPC_private;
2739 return (DSAStack->hasExplicitDSA(
2740 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2741 Level) ||
2742 (DSAStack->isClauseParsingMode() &&
2743 DSAStack->getClauseParsingMode() == OMPC_private) ||
2744 // Consider taskgroup reduction descriptor variable a private
2745 // to avoid possible capture in the region.
2746 (DSAStack->hasExplicitDirective(
2747 [](OpenMPDirectiveKind K) {
2748 return K == OMPD_taskgroup ||
2749 ((isOpenMPParallelDirective(K) ||
2750 isOpenMPWorksharingDirective(K)) &&
2751 !isOpenMPSimdDirective(K));
2752 },
2753 Level) &&
2754 DSAStack->isTaskgroupReductionRef(D, Level)))
2755 ? OMPC_private
2756 : OMPC_unknown;
2757}
2758
2760 unsigned Level) {
2761 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2762 D = getCanonicalDecl(D);
2763 OpenMPClauseKind OMPC = OMPC_unknown;
2764 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2765 const unsigned NewLevel = I - 1;
2766 if (DSAStack->hasExplicitDSA(
2767 D,
2768 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2769 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2770 OMPC = K;
2771 return true;
2772 }
2773 return false;
2774 },
2775 NewLevel))
2776 break;
2777 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2778 D, NewLevel,
2780 OpenMPClauseKind) { return true; })) {
2781 OMPC = OMPC_map;
2782 break;
2783 }
2784 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2785 NewLevel)) {
2786 OMPC = OMPC_map;
2787 if (DSAStack->mustBeFirstprivateAtLevel(
2789 OMPC = OMPC_firstprivate;
2790 break;
2791 }
2792 }
2793 if (OMPC != OMPC_unknown)
2794 FD->addAttr(
2795 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2796}
2797
2799 unsigned CaptureLevel) const {
2800 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2801 // Return true if the current level is no longer enclosed in a target region.
2802
2804 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2805 const auto *VD = dyn_cast<VarDecl>(D);
2806 return VD && !VD->hasLocalStorage() &&
2807 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2808 Level) &&
2809 Regions[CaptureLevel] != OMPD_task;
2810}
2811
2813 unsigned CaptureLevel) const {
2814 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2815 // Return true if the current level is no longer enclosed in a target region.
2816
2817 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2818 if (!VD->hasLocalStorage()) {
2820 return true;
2821 DSAStackTy::DSAVarData TopDVar =
2822 DSAStack->getTopDSA(D, /*FromParent=*/false);
2823 unsigned NumLevels =
2824 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2825 if (Level == 0)
2826 // non-file scope static variable with default(firstprivate)
2827 // should be global captured.
2828 return (NumLevels == CaptureLevel + 1 &&
2829 (TopDVar.CKind != OMPC_shared ||
2830 DSAStack->getDefaultDSA() == DSA_firstprivate));
2831 do {
2832 --Level;
2833 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2834 if (DVar.CKind != OMPC_shared)
2835 return true;
2836 } while (Level > 0);
2837 }
2838 }
2839 return true;
2840}
2841
2842void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2843
2845 OMPTraitInfo &TI) {
2846 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2847}
2848
2851 "Not in OpenMP declare variant scope!");
2852
2853 OMPDeclareVariantScopes.pop_back();
2854}
2855
2857 const FunctionDecl *Callee,
2858 SourceLocation Loc) {
2859 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2860 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2861 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2862 // Ignore host functions during device analysis.
2863 if (getLangOpts().OpenMPIsTargetDevice &&
2864 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2865 return;
2866 // Ignore nohost functions during host analysis.
2867 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2868 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2869 return;
2870 const FunctionDecl *FD = Callee->getMostRecentDecl();
2871 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2872 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2873 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2874 // Diagnose host function called during device codegen.
2875 StringRef HostDevTy =
2876 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2877 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2878 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2879 diag::note_omp_marked_device_type_here)
2880 << HostDevTy;
2881 return;
2882 }
2883 if (!getLangOpts().OpenMPIsTargetDevice &&
2884 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2885 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2886 // In OpenMP 5.2 or later, if the function has a host variant then allow
2887 // that to be called instead
2888 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2889 for (OMPDeclareVariantAttr *A :
2890 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2891 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2892 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2893 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2894 OMPDeclareTargetDeclAttr::getDeviceType(
2895 VariantFD->getMostRecentDecl());
2896 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2897 return true;
2898 }
2899 return false;
2900 };
2901 if (getLangOpts().OpenMP >= 52 &&
2902 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2903 return;
2904 // Diagnose nohost function called during host codegen.
2905 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2906 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2907 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2908 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2909 diag::note_omp_marked_device_type_here)
2910 << NoHostDevTy;
2911 }
2912}
2913
2915 const DeclarationNameInfo &DirName,
2916 Scope *CurScope, SourceLocation Loc) {
2917 DSAStack->push(DKind, DirName, CurScope, Loc);
2918 SemaRef.PushExpressionEvaluationContext(
2920}
2921
2923 DSAStack->setClauseParsingMode(K);
2924}
2925
2927 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2928 SemaRef.CleanupVarDeclMarking();
2929}
2930
2931static std::pair<ValueDecl *, bool>
2932getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2933 SourceRange &ERange, bool AllowArraySection = false,
2934 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2935
2936/// Check consistency of the reduction clauses.
2937static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2938 ArrayRef<OMPClause *> Clauses) {
2939 bool InscanFound = false;
2940 SourceLocation InscanLoc;
2941 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2942 // A reduction clause without the inscan reduction-modifier may not appear on
2943 // a construct on which a reduction clause with the inscan reduction-modifier
2944 // appears.
2945 for (OMPClause *C : Clauses) {
2946 if (C->getClauseKind() != OMPC_reduction)
2947 continue;
2948 auto *RC = cast<OMPReductionClause>(C);
2949 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2950 InscanFound = true;
2951 InscanLoc = RC->getModifierLoc();
2952 continue;
2953 }
2954 if (RC->getModifier() == OMPC_REDUCTION_task) {
2955 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2956 // A reduction clause with the task reduction-modifier may only appear on
2957 // a parallel construct, a worksharing construct or a combined or
2958 // composite construct for which any of the aforementioned constructs is a
2959 // constituent construct and simd or loop are not constituent constructs.
2960 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2961 if (!(isOpenMPParallelDirective(CurDir) ||
2963 isOpenMPSimdDirective(CurDir))
2964 S.Diag(RC->getModifierLoc(),
2965 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2966 continue;
2967 }
2968 }
2969 if (InscanFound) {
2970 for (OMPClause *C : Clauses) {
2971 if (C->getClauseKind() != OMPC_reduction)
2972 continue;
2973 auto *RC = cast<OMPReductionClause>(C);
2974 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2975 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2976 ? RC->getBeginLoc()
2977 : RC->getModifierLoc(),
2978 diag::err_omp_inscan_reduction_expected);
2979 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2980 continue;
2981 }
2982 for (Expr *Ref : RC->varlist()) {
2983 assert(Ref && "NULL expr in OpenMP reduction clause.");
2984 SourceLocation ELoc;
2985 SourceRange ERange;
2986 Expr *SimpleRefExpr = Ref;
2987 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2988 /*AllowArraySection=*/true);
2989 ValueDecl *D = Res.first;
2990 if (!D)
2991 continue;
2992 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2993 S.Diag(Ref->getExprLoc(),
2994 diag::err_omp_reduction_not_inclusive_exclusive)
2995 << Ref->getSourceRange();
2996 }
2997 }
2998 }
2999 }
3000}
3001
3002static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
3003 ArrayRef<OMPClause *> Clauses);
3004static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
3005 bool WithInit);
3006
3007static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3008 const ValueDecl *D,
3009 const DSAStackTy::DSAVarData &DVar,
3010 bool IsLoopIterVar = false);
3011
3013 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
3014 // A variable of class type (or array thereof) that appears in a lastprivate
3015 // clause requires an accessible, unambiguous default constructor for the
3016 // class type, unless the list item is also specified in a firstprivate
3017 // clause.
3018
3019 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
3020 SmallVector<Expr *, 8> PrivateCopies;
3021 for (Expr *DE : Clause->varlist()) {
3022 if (DE->isValueDependent() || DE->isTypeDependent()) {
3023 PrivateCopies.push_back(nullptr);
3024 continue;
3025 }
3026 // Data members are captured, and get private copies, on instantiation.
3027 if (isa<MemberExpr>(DE->IgnoreParens())) {
3028 assert(SemaRef.CurContext->isDependentContext() &&
3029 "uncaptured data member in a non-dependent context");
3030 PrivateCopies.push_back(nullptr);
3031 continue;
3032 }
3033 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
3034 auto *D = DRE->getDecl();
3035 if (auto *BD = dyn_cast<BindingDecl>(D)) {
3036 QualType Type = BD->getType().getNonReferenceType();
3037 const DSAStackTy::DSAVarData DVar =
3038 DSAStack->getTopDSA(BD, /*FromParent=*/false);
3039 if (DVar.CKind != OMPC_lastprivate) {
3040 // The variable is also a firstprivate, so initialization sequence
3041 // for private copy is generated already.
3042 PrivateCopies.push_back(nullptr);
3043 continue;
3044 }
3045 VarDecl *VDPrivate = buildVarDecl(
3046 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), BD->getName(),
3047 BD->hasAttrs() ? &BD->getAttrs() : nullptr, DRE);
3048 SemaRef.ActOnUninitializedDecl(VDPrivate);
3049 if (VDPrivate->isInvalidDecl()) {
3050 PrivateCopies.push_back(nullptr);
3051 continue;
3052 }
3053 PrivateCopies.push_back(buildDeclRefExpr(
3054 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
3055 continue;
3056 }
3057 auto *VD = cast<VarDecl>(D);
3059 const DSAStackTy::DSAVarData DVar =
3060 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3061 if (DVar.CKind != OMPC_lastprivate) {
3062 // The variable is also a firstprivate, so initialization sequence
3063 // for private copy is generated already.
3064 PrivateCopies.push_back(nullptr);
3065 continue;
3066 }
3067 // Generate helper private variable and initialize it with the
3068 // default value. The address of the original variable is replaced
3069 // by the address of the new private variable in CodeGen. This new
3070 // variable is not added to IdResolver, so the code in the OpenMP
3071 // region uses original variable for proper diagnostics.
3072 VarDecl *VDPrivate = buildVarDecl(
3073 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
3074 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
3075 SemaRef.ActOnUninitializedDecl(VDPrivate);
3076 if (VDPrivate->isInvalidDecl()) {
3077 PrivateCopies.push_back(nullptr);
3078 continue;
3079 }
3080 PrivateCopies.push_back(buildDeclRefExpr(
3081 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
3082 }
3083 Clause->setPrivateCopies(PrivateCopies);
3084 };
3085
3086 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
3087 // Finalize nontemporal clause by handling private copies, if any.
3088 SmallVector<Expr *, 8> PrivateRefs;
3089 for (Expr *RefExpr : Clause->varlist()) {
3090 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
3091 SourceLocation ELoc;
3092 SourceRange ERange;
3093 Expr *SimpleRefExpr = RefExpr;
3094 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
3095 if (Res.second)
3096 // It will be analyzed later.
3097 PrivateRefs.push_back(RefExpr);
3098 ValueDecl *D = Res.first;
3099 if (!D)
3100 continue;
3101
3102 const DSAStackTy::DSAVarData DVar =
3103 DSAStack->getTopDSA(D, /*FromParent=*/false);
3104 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
3105 : SimpleRefExpr);
3106 }
3107 Clause->setPrivateRefs(PrivateRefs);
3108 };
3109
3110 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3111 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3112 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3113 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
3114 if (!DRE)
3115 continue;
3116 ValueDecl *VD = DRE->getDecl();
3117 if (!VD || !isa<VarDecl>(VD))
3118 continue;
3119 DSAStackTy::DSAVarData DVar =
3120 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3121 // OpenMP [2.12.5, target Construct]
3122 // Memory allocators that appear in a uses_allocators clause cannot
3123 // appear in other data-sharing attribute clauses or data-mapping
3124 // attribute clauses in the same construct.
3125 Expr *MapExpr = nullptr;
3126 if (DVar.RefExpr ||
3127 DSAStack->checkMappableExprComponentListsForDecl(
3128 VD, /*CurrentRegionOnly=*/true,
3129 [VD, &MapExpr](
3131 MapExprComponents,
3133 auto MI = MapExprComponents.rbegin();
3134 auto ME = MapExprComponents.rend();
3135 if (MI != ME &&
3136 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3137 VD->getCanonicalDecl()) {
3138 MapExpr = MI->getAssociatedExpression();
3139 return true;
3140 }
3141 return false;
3142 })) {
3143 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3144 << D.Allocator->getSourceRange();
3145 if (DVar.RefExpr)
3147 else
3148 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3149 << MapExpr->getSourceRange();
3150 }
3151 }
3152 };
3153
3154 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3155 for (OMPClause *C : D->clauses()) {
3156 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
3157 FinalizeLastprivate(Clause);
3158 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
3159 FinalizeNontemporal(Clause);
3160 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
3161 FinalizeAllocators(Clause);
3162 }
3163 }
3164 // Check allocate clauses.
3165 if (!SemaRef.CurContext->isDependentContext())
3166 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3167 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3168 }
3169
3170 DSAStack->pop();
3173}
3174
3175static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3176 Expr *NumIterations, Sema &SemaRef,
3177 Scope *S, DSAStackTy *Stack);
3178
3179static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3180 OMPLoopBasedDirective::HelperExprs &B,
3181 DSAStackTy *Stack) {
3182 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3183 "loop exprs were not built");
3184
3185 if (SemaRef.CurContext->isDependentContext())
3186 return false;
3187
3188 // Finalize the clauses that need pre-built expressions for CodeGen.
3189 for (OMPClause *C : Clauses) {
3190 auto *LC = dyn_cast<OMPLinearClause>(C);
3191 if (!LC)
3192 continue;
3193 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3194 B.NumIterations, SemaRef,
3195 SemaRef.getCurScope(), Stack))
3196 return true;
3197 }
3198
3199 return false;
3200}
3201
3202namespace {
3203
3204class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3205private:
3206 Sema &SemaRef;
3207
3208public:
3209 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3210 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3211 NamedDecl *ND = Candidate.getCorrectionDecl();
3212 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3213 return VD->hasGlobalStorage() &&
3214 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3215 SemaRef.getCurScope());
3216 }
3217 return false;
3218 }
3219
3220 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3221 return std::make_unique<VarDeclFilterCCC>(*this);
3222 }
3223};
3224
3225class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3226private:
3227 Sema &SemaRef;
3228
3229public:
3230 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3231 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3232 NamedDecl *ND = Candidate.getCorrectionDecl();
3233 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3234 isa<FunctionDecl>(ND))) {
3235 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3236 SemaRef.getCurScope());
3237 }
3238 return false;
3239 }
3240
3241 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3242 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3243 }
3244};
3245
3246} // namespace
3247
3249 CXXScopeSpec &ScopeSpec,
3250 const DeclarationNameInfo &Id,
3251 OpenMPDirectiveKind Kind) {
3252 ASTContext &Context = getASTContext();
3253 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3255 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3256 /*ObjectType=*/QualType(),
3257 /*AllowBuiltinCreation=*/true);
3258
3259 if (Lookup.isAmbiguous())
3260 return ExprError();
3261
3262 VarDecl *VD;
3263 if (!Lookup.isSingleResult()) {
3264 VarDeclFilterCCC CCC(SemaRef);
3265 if (TypoCorrection Corrected =
3266 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3268 SemaRef.diagnoseTypo(
3269 Corrected,
3270 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3271 : diag::err_omp_expected_var_arg_suggest)
3272 << Id.getName());
3273 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3274 } else {
3275 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3276 : diag::err_omp_expected_var_arg)
3277 << Id.getName();
3278 return ExprError();
3279 }
3280 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3281 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3282 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3283 return ExprError();
3284 }
3285 Lookup.suppressDiagnostics();
3286
3287 // OpenMP [2.9.2, Syntax, C/C++]
3288 // Variables must be file-scope, namespace-scope, or static block-scope.
3289 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3290 !VD->hasGlobalStorage()) {
3291 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3292 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3293 bool IsDecl =
3295 Diag(VD->getLocation(),
3296 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3297 << VD;
3298 return ExprError();
3299 }
3300
3301 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3302 NamedDecl *ND = CanonicalVD;
3303 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3304 // A threadprivate or groupprivate directive for file-scope variables must
3305 // appear outside any definition or declaration.
3306 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3307 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3308 Diag(Id.getLoc(), diag::err_omp_var_scope)
3309 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3310 bool IsDecl =
3312 Diag(VD->getLocation(),
3313 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3314 << VD;
3315 return ExprError();
3316 }
3317 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3318 // A threadprivate or groupprivate directive for static class member
3319 // variables must appear in the class definition, in the same scope in which
3320 // the member variables are declared.
3321 if (CanonicalVD->isStaticDataMember() &&
3322 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3323 Diag(Id.getLoc(), diag::err_omp_var_scope)
3324 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3325 bool IsDecl =
3327 Diag(VD->getLocation(),
3328 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3329 << VD;
3330 return ExprError();
3331 }
3332 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3333 // A threadprivate or groupprivate directive for namespace-scope variables
3334 // must appear outside any definition or declaration other than the
3335 // namespace definition itself.
3336 if (CanonicalVD->getDeclContext()->isNamespace() &&
3337 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3338 !SemaRef.getCurLexicalContext()->Encloses(
3339 CanonicalVD->getDeclContext()))) {
3340 Diag(Id.getLoc(), diag::err_omp_var_scope)
3341 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3342 bool IsDecl =
3344 Diag(VD->getLocation(),
3345 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3346 << VD;
3347 return ExprError();
3348 }
3349 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3350 // A threadprivate or groupprivate directive for static block-scope
3351 // variables must appear in the scope of the variable and not in a nested
3352 // scope.
3353 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3354 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3355 Diag(Id.getLoc(), diag::err_omp_var_scope)
3356 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3357 bool IsDecl =
3359 Diag(VD->getLocation(),
3360 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3361 << VD;
3362 return ExprError();
3363 }
3364
3365 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3366 // A threadprivate or groupprivate directive must lexically precede all
3367 // references to any of the variables in its list.
3368 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3369 !DSAStack->isThreadPrivate(VD)) ||
3370 (Kind == OMPD_groupprivate && VD->isUsed())) {
3371 Diag(Id.getLoc(), diag::err_omp_var_used)
3372 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3373 return ExprError();
3374 }
3375
3376 QualType ExprType = VD->getType().getNonReferenceType();
3378 SourceLocation(), VD,
3379 /*RefersToEnclosingVariableOrCapture=*/false,
3380 Id.getLoc(), ExprType, VK_LValue);
3381}
3382
3385 ArrayRef<Expr *> VarList) {
3386 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3387 SemaRef.CurContext->addDecl(D);
3389 }
3390 return nullptr;
3391}
3392
3395 ArrayRef<Expr *> VarList) {
3396 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3397 if (!OMPVersion || OMPVersion < 60) {
3398 Diag(Loc, diag::err_omp_unexpected_directive)
3399 << getOpenMPDirectiveName(OMPD_groupprivate, OMPVersion);
3400 return nullptr;
3401 }
3402 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3403 SemaRef.CurContext->addDecl(D);
3405 }
3406 return nullptr;
3407}
3408
3409namespace {
3410class LocalVarRefChecker final
3411 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3412 Sema &SemaRef;
3413
3414public:
3415 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3416 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3417 if (VD->hasLocalStorage()) {
3418 SemaRef.Diag(E->getBeginLoc(),
3419 diag::err_omp_local_var_in_threadprivate_init)
3420 << E->getSourceRange();
3421 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3422 << VD << VD->getSourceRange();
3423 return true;
3424 }
3425 }
3426 return false;
3427 }
3428 bool VisitStmt(const Stmt *S) {
3429 for (const Stmt *Child : S->children()) {
3430 if (Child && Visit(Child))
3431 return true;
3432 }
3433 return false;
3434 }
3435 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3436};
3437} // namespace
3438
3439OMPThreadPrivateDecl *
3441 ArrayRef<Expr *> VarList) {
3442 ASTContext &Context = getASTContext();
3444 for (Expr *RefExpr : VarList) {
3445 auto *DE = cast<DeclRefExpr>(RefExpr);
3446 auto *VD = cast<VarDecl>(DE->getDecl());
3447 SourceLocation ILoc = DE->getExprLoc();
3448
3449 // Mark variable as used.
3450 VD->setReferenced();
3451 VD->markUsed(Context);
3452
3453 QualType QType = VD->getType();
3454 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3455 // It will be analyzed later.
3456 Vars.push_back(DE);
3457 continue;
3458 }
3459
3460 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3461 // A threadprivate variable must not have an incomplete type.
3462 if (SemaRef.RequireCompleteType(
3463 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3464 continue;
3465 }
3466
3467 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3468 // A threadprivate variable must not have a reference type.
3469 if (VD->getType()->isReferenceType()) {
3470 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3471 Diag(ILoc, diag::err_omp_ref_type_arg)
3472 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3473 << VD->getType();
3474 bool IsDecl =
3476 Diag(VD->getLocation(),
3477 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3478 << VD;
3479 continue;
3480 }
3481
3482 // Check if this is a TLS variable. If TLS is not being supported, produce
3483 // the corresponding diagnostic.
3484 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3485 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3486 getLangOpts().OpenMPUseTLS &&
3487 getASTContext().getTargetInfo().isTLSSupported())) ||
3488 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3489 !VD->isLocalVarDecl())) {
3490 Diag(ILoc, diag::err_omp_var_thread_local)
3491 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3492 bool IsDecl =
3494 Diag(VD->getLocation(),
3495 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3496 << VD;
3497 continue;
3498 }
3499
3500 // Check if initial value of threadprivate variable reference variable with
3501 // local storage (it is not supported by runtime).
3502 if (const Expr *Init = VD->getAnyInitializer()) {
3503 LocalVarRefChecker Checker(SemaRef);
3504 if (Checker.Visit(Init))
3505 continue;
3506 }
3507
3508 Vars.push_back(RefExpr);
3509 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3510 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3511 Context, SourceRange(Loc, Loc)));
3512 if (ASTMutationListener *ML = Context.getASTMutationListener())
3513 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3514 }
3515 OMPThreadPrivateDecl *D = nullptr;
3516 if (!Vars.empty()) {
3517 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3518 Loc, Vars);
3519 D->setAccess(AS_public);
3520 }
3521 return D;
3522}
3523
3526 ArrayRef<Expr *> VarList) {
3527 ASTContext &Context = getASTContext();
3529 for (Expr *RefExpr : VarList) {
3530 auto *DE = cast<DeclRefExpr>(RefExpr);
3531 auto *VD = cast<VarDecl>(DE->getDecl());
3532 SourceLocation ILoc = DE->getExprLoc();
3533
3534 // Mark variable as used.
3535 VD->setReferenced();
3536 VD->markUsed(Context);
3537
3538 QualType QType = VD->getType();
3539 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3540 // It will be analyzed later.
3541 Vars.push_back(DE);
3542 continue;
3543 }
3544
3545 // OpenMP groupprivate restrictions:
3546 // A groupprivate variable must not have an incomplete type.
3547 if (SemaRef.RequireCompleteType(
3548 ILoc, VD->getType(), diag::err_omp_groupprivate_incomplete_type)) {
3549 continue;
3550 }
3551
3552 // A groupprivate variable must not have a reference type.
3553 if (VD->getType()->isReferenceType()) {
3554 Diag(ILoc, diag::err_omp_ref_type_arg)
3555 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->getType();
3556 bool IsDecl =
3558 Diag(VD->getLocation(),
3559 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3560 << VD;
3561 continue;
3562 }
3563
3564 // A variable that is declared with an initializer must not appear in a
3565 // groupprivate directive.
3566 if (VD->getAnyInitializer()) {
3567 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3568 << VD->getDeclName();
3569 bool IsDecl =
3571 Diag(VD->getLocation(),
3572 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3573 << VD;
3574 continue;
3575 }
3576
3577 Vars.push_back(RefExpr);
3578 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3579 VD->addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3580 SourceRange(Loc, Loc)));
3581 if (ASTMutationListener *ML = Context.getASTMutationListener())
3582 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3583 }
3584 OMPGroupPrivateDecl *D = nullptr;
3585 if (!Vars.empty()) {
3586 D = OMPGroupPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3587 Loc, Vars);
3588 D->setAccess(AS_public);
3589 }
3590 return D;
3591}
3592
3593static OMPAllocateDeclAttr::AllocatorTypeTy
3594getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3595 if (!Allocator)
3596 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3597 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3598 Allocator->isInstantiationDependent() ||
3600 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3601 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3602 llvm::FoldingSetNodeID AEId;
3603 const Expr *AE = Allocator->IgnoreParenImpCasts();
3604 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3605 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3606 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3607 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3608 llvm::FoldingSetNodeID DAEId;
3609 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3610 /*Canonical=*/true);
3611 if (AEId == DAEId) {
3612 AllocatorKindRes = AllocatorKind;
3613 break;
3614 }
3615 }
3616 return AllocatorKindRes;
3617}
3618
3620 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3621 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3622 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3623 return false;
3624 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3625 Expr *PrevAllocator = A->getAllocator();
3626 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3627 getAllocatorKind(S, Stack, PrevAllocator);
3628 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3629 if (AllocatorsMatch &&
3630 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3631 Allocator && PrevAllocator) {
3632 const Expr *AE = Allocator->IgnoreParenImpCasts();
3633 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3634 llvm::FoldingSetNodeID AEId, PAEId;
3635 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3636 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3637 AllocatorsMatch = AEId == PAEId;
3638 }
3639 if (!AllocatorsMatch) {
3640 SmallString<256> AllocatorBuffer;
3641 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3642 if (Allocator)
3643 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3644 SmallString<256> PrevAllocatorBuffer;
3645 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3646 if (PrevAllocator)
3647 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3648 S.getPrintingPolicy());
3649
3650 SourceLocation AllocatorLoc =
3651 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3652 SourceRange AllocatorRange =
3653 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3654 SourceLocation PrevAllocatorLoc =
3655 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3656 SourceRange PrevAllocatorRange =
3657 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3658 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3659 << (Allocator ? 1 : 0) << AllocatorStream.str()
3660 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3661 << AllocatorRange;
3662 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3663 << PrevAllocatorRange;
3664 return true;
3665 }
3666 return false;
3667}
3668
3669static void
3671 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3672 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3673 if (VD->hasAttr<OMPAllocateDeclAttr>())
3674 return;
3675 if (Alignment &&
3676 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3677 Alignment->isInstantiationDependent() ||
3678 Alignment->containsUnexpandedParameterPack()))
3679 // Apply later when we have a usable value.
3680 return;
3681 if (Allocator &&
3682 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3683 Allocator->isInstantiationDependent() ||
3684 Allocator->containsUnexpandedParameterPack()))
3685 return;
3686 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3687 Allocator, Alignment, SR);
3688 VD->addAttr(A);
3690 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3691}
3692
3695 DeclContext *Owner) {
3696 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3697 Expr *Alignment = nullptr;
3698 Expr *Allocator = nullptr;
3699 if (Clauses.empty()) {
3700 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3701 // allocate directives that appear in a target region must specify an
3702 // allocator clause unless a requires directive with the dynamic_allocators
3703 // clause is present in the same compilation unit.
3704 if (getLangOpts().OpenMPIsTargetDevice &&
3705 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3706 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3707 } else {
3708 for (const OMPClause *C : Clauses)
3709 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3710 Allocator = AC->getAllocator();
3711 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3712 Alignment = AC->getAlignment();
3713 else
3714 llvm_unreachable("Unexpected clause on allocate directive");
3715 }
3716 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3717 getAllocatorKind(SemaRef, DSAStack, Allocator);
3719 for (Expr *RefExpr : VarList) {
3720 auto *DE = cast<DeclRefExpr>(RefExpr);
3721 auto *VD = cast<VarDecl>(DE->getDecl());
3722
3723 // Check if this is a TLS variable or global register.
3724 if (VD->getTLSKind() != VarDecl::TLS_None ||
3725 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3726 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3727 !VD->isLocalVarDecl()))
3728 continue;
3729
3730 // If the used several times in the allocate directive, the same allocator
3731 // must be used.
3733 AllocatorKind, Allocator))
3734 continue;
3735
3736 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3737 // If a list item has a static storage type, the allocator expression in the
3738 // allocator clause must be a constant expression that evaluates to one of
3739 // the predefined memory allocator values.
3740 if (Allocator && VD->hasGlobalStorage()) {
3741 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3742 Diag(Allocator->getExprLoc(),
3743 diag::err_omp_expected_predefined_allocator)
3744 << Allocator->getSourceRange();
3745 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3747 Diag(VD->getLocation(),
3748 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3749 << VD;
3750 continue;
3751 }
3752 }
3753
3754 Vars.push_back(RefExpr);
3755 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3756 DE->getSourceRange());
3757 }
3758 if (Vars.empty())
3759 return nullptr;
3760 if (!Owner)
3761 Owner = SemaRef.getCurLexicalContext();
3762 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3763 D->setAccess(AS_public);
3764 Owner->addDecl(D);
3766}
3767
3770 ArrayRef<OMPClause *> ClauseList) {
3771 OMPRequiresDecl *D = nullptr;
3772 if (!SemaRef.CurContext->isFileContext()) {
3773 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3774 } else {
3775 D = CheckOMPRequiresDecl(Loc, ClauseList);
3776 if (D) {
3777 SemaRef.CurContext->addDecl(D);
3778 DSAStack->addRequiresDecl(D);
3779 }
3780 }
3782}
3783
3785 OpenMPDirectiveKind DKind,
3786 ArrayRef<std::string> Assumptions,
3787 bool SkippedClauses) {
3788 if (!SkippedClauses && Assumptions.empty()) {
3789 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
3790 Diag(Loc, diag::err_omp_no_clause_for_directive)
3791 << llvm::omp::getAllAssumeClauseOptions()
3792 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3793 }
3794
3795 auto *AA =
3796 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3797 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3798 OMPAssumeScoped.push_back(AA);
3799 return;
3800 }
3801
3802 // Global assumes without assumption clauses are ignored.
3803 if (Assumptions.empty())
3804 return;
3805
3806 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3807 "Unexpected omp assumption directive!");
3808 OMPAssumeGlobal.push_back(AA);
3809
3810 // The OMPAssumeGlobal scope above will take care of new declarations but
3811 // we also want to apply the assumption to existing ones, e.g., to
3812 // declarations in included headers. To this end, we traverse all existing
3813 // declaration contexts and annotate function declarations here.
3814 SmallVector<DeclContext *, 8> DeclContexts;
3815 auto *Ctx = SemaRef.CurContext;
3816 while (Ctx->getLexicalParent())
3817 Ctx = Ctx->getLexicalParent();
3818 DeclContexts.push_back(Ctx);
3819 while (!DeclContexts.empty()) {
3820 DeclContext *DC = DeclContexts.pop_back_val();
3821 for (auto *SubDC : DC->decls()) {
3822 if (SubDC->isInvalidDecl())
3823 continue;
3824 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3825 DeclContexts.push_back(CTD->getTemplatedDecl());
3826 llvm::append_range(DeclContexts, CTD->specializations());
3827 continue;
3828 }
3829 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3830 DeclContexts.push_back(DC);
3831 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3832 F->addAttr(AA);
3833 continue;
3834 }
3835 }
3836 }
3837}
3838
3840 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3841 OMPAssumeScoped.pop_back();
3842}
3843
3845 Stmt *AStmt,
3846 SourceLocation StartLoc,
3847 SourceLocation EndLoc) {
3848 if (!AStmt)
3849 return StmtError();
3850
3851 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3852 AStmt);
3853}
3854
3856 SourceLocation StartLoc, SourceLocation EndLoc,
3857 ArrayRef<OMPTraitInfo *> TraitInfos, ArrayRef<Stmt *> Variants) {
3858 // Without an 'otherwise' clause, the last variant is the implicit one.
3859 bool HasImplicitOtherwise = Variants.size() == TraitInfos.size() + 1;
3860 assert((HasImplicitOtherwise || Variants.size() == TraitInfos.size()) &&
3861 "Expected one variant per metadirective clause");
3862 SmallVector<OMPTraitInfo *, 4> AllTraitInfos(TraitInfos);
3863 if (HasImplicitOtherwise)
3864 AllTraitInfos.push_back(&getASTContext().getNewOMPTraitInfo());
3865 // The user condition of each variant; null for 'otherwise'.
3866 SmallVector<Expr *, 4> Conditions;
3867 for (OMPTraitInfo *TI : AllTraitInfos) {
3868 Expr *Cond = nullptr;
3869 TI->anyScoreOrCondition([&](Expr *&E, bool IsScore) {
3870 if (!IsScore)
3871 Cond = E;
3872 return !IsScore;
3873 });
3874 if (Cond) {
3875 ExprResult Val = SemaRef.CheckBooleanCondition(Cond->getExprLoc(), Cond);
3876 if (Val.isInvalid())
3877 return StmtError();
3878 Cond = SemaRef.MakeFullExpr(Val.get()).get();
3879 }
3880 Conditions.push_back(Cond);
3881 }
3882 return OMPMetaDirective::Create(getASTContext(), StartLoc, EndLoc, Variants,
3883 Conditions, AllTraitInfos,
3884 HasImplicitOtherwise);
3885}
3886
3889 ArrayRef<OMPClause *> ClauseList) {
3890 /// For target specific clauses, the requires directive cannot be
3891 /// specified after the handling of any of the target regions in the
3892 /// current compilation unit.
3893 ArrayRef<SourceLocation> TargetLocations =
3894 DSAStack->getEncounteredTargetLocs();
3895 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3896 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3897 for (const OMPClause *CNew : ClauseList) {
3898 // Check if any of the requires clauses affect target regions.
3903 Diag(Loc, diag::err_omp_directive_before_requires)
3904 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3905 for (SourceLocation TargetLoc : TargetLocations) {
3906 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3907 << "target";
3908 }
3909 } else if (!AtomicLoc.isInvalid() &&
3911 Diag(Loc, diag::err_omp_directive_before_requires)
3912 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3913 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3914 << "atomic";
3915 }
3916 }
3917 }
3918
3919 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3921 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3922 return nullptr;
3923}
3924
3925static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3926 const ValueDecl *D,
3927 const DSAStackTy::DSAVarData &DVar,
3928 bool IsLoopIterVar) {
3929 if (DVar.RefExpr) {
3930 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3931 << getOpenMPClauseNameForDiag(DVar.CKind);
3932 return;
3933 }
3934 enum {
3935 PDSA_StaticMemberShared,
3936 PDSA_StaticLocalVarShared,
3937 PDSA_LoopIterVarPrivate,
3938 PDSA_LoopIterVarLinear,
3939 PDSA_LoopIterVarLastprivate,
3940 PDSA_ConstVarShared,
3941 PDSA_GlobalVarShared,
3942 PDSA_TaskVarFirstprivate,
3943 PDSA_LocalVarPrivate,
3944 PDSA_Implicit
3945 } Reason = PDSA_Implicit;
3946 bool ReportHint = false;
3947 auto ReportLoc = D->getLocation();
3948 auto *VD = dyn_cast<VarDecl>(D);
3949 if (IsLoopIterVar) {
3950 if (DVar.CKind == OMPC_private)
3951 Reason = PDSA_LoopIterVarPrivate;
3952 else if (DVar.CKind == OMPC_lastprivate)
3953 Reason = PDSA_LoopIterVarLastprivate;
3954 else
3955 Reason = PDSA_LoopIterVarLinear;
3956 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3957 DVar.CKind == OMPC_firstprivate) {
3958 Reason = PDSA_TaskVarFirstprivate;
3959 ReportLoc = DVar.ImplicitDSALoc;
3960 } else if (VD && VD->isStaticLocal())
3961 Reason = PDSA_StaticLocalVarShared;
3962 else if (VD && VD->isStaticDataMember())
3963 Reason = PDSA_StaticMemberShared;
3964 else if (VD && VD->isFileVarDecl())
3965 Reason = PDSA_GlobalVarShared;
3966 else if (D->getType().isConstant(SemaRef.getASTContext()))
3967 Reason = PDSA_ConstVarShared;
3968 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3969 ReportHint = true;
3970 Reason = PDSA_LocalVarPrivate;
3971 }
3972 if (Reason != PDSA_Implicit) {
3973 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
3974 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3975 << Reason << ReportHint
3976 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3977 } else if (DVar.ImplicitDSALoc.isValid()) {
3978 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3979 << getOpenMPClauseNameForDiag(DVar.CKind);
3980 }
3981}
3982
3983namespace {
3984/// Visitor to collect variables used in a statement.
3985class VarUsageVisitor : public DynamicRecursiveASTVisitor {
3986 llvm::SmallPtrSet<const VarDecl *, 8> &UsedVars;
3987 llvm::SmallPtrSet<const BindingDecl *, 8> &UsedBindings;
3988
3989public:
3990 VarUsageVisitor(llvm::SmallPtrSet<const VarDecl *, 8> &UsedVars,
3991 llvm::SmallPtrSet<const BindingDecl *, 8> &UsedBindings)
3992 : UsedVars(UsedVars), UsedBindings(UsedBindings) {}
3993
3994 bool VisitDeclRefExpr(DeclRefExpr *DRE) override {
3995 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
3996 UsedVars.insert(cast<VarDecl>(VD->getCanonicalDecl()));
3997 else if (auto *BD = dyn_cast<BindingDecl>(DRE->getDecl()))
3998 UsedBindings.insert(cast<BindingDecl>(BD->getCanonicalDecl()));
3999 return true;
4000 }
4001};
4002} // namespace
4003
4004/// Check if bindings from the same structured binding have conflicting
4005/// capture kinds (by-ref vs by-copy). Bindings share the underlying
4006/// DecompositionDecl storage, so mixing by-ref and by-copy clauses on
4007/// different bindings from the same decomposition is not representable.
4008/// For example: map(a) creates by-ref, firstprivate(b) creates by-copy.
4010 Sema &SemaRef, OpenMPDirectiveKind DKind,
4011 llvm::SmallDenseMap<const DecompositionDecl *,
4012 std::pair<bool, SourceLocation>, 4> &SeenDecompositions,
4013 const ValueDecl *D, SourceLocation ELoc, OpenMPClauseKind ClauseKind) {
4014 const auto *BD = dyn_cast<BindingDecl>(D);
4015 if (!BD)
4016 return false;
4017
4018 const auto *DD = dyn_cast<DecompositionDecl>(BD->getDecomposedDecl());
4019 if (!DD)
4020 return false;
4021
4022 // Determine if this clause creates by-ref or by-copy capture.
4023 bool IsByRef = false;
4024 switch (ClauseKind) {
4025 case OMPC_map:
4026 case OMPC_shared:
4027 // Map and shared clauses are by-reference.
4028 IsByRef = true;
4029 break;
4030 case OMPC_firstprivate:
4031 case OMPC_private:
4032 case OMPC_lastprivate:
4033 // These are by-copy.
4034 IsByRef = false;
4035 break;
4036 default:
4037 // Other clauses don't create capture conflicts.
4038 return false;
4039 }
4040 auto [It, Inserted] = SeenDecompositions.insert({DD, {IsByRef, ELoc}});
4041 if (!Inserted && It->second.first != IsByRef) {
4042 // Conflict: same DecompositionDecl needs both by-ref and by-copy
4043 // Emit diagnostic showing the binding name, not the decomposition.
4044 SemaRef.Diag(ELoc,
4045 diag::err_omp_decomposition_bindings_different_capture_kinds)
4046 << BD;
4047 return true;
4048 }
4049 return false;
4050}
4051
4052/// Helper to check all clauses in a directive for structured binding
4053/// capture conflicts. Returns true if an error was found. If Body is
4054/// provided and the directive has default(shared), bindings used in the
4055/// body but not listed in explicit clauses are treated as implicit
4056/// shared (by-reference).
4058 OpenMPDirectiveKind DKind,
4059 ArrayRef<OMPClause *> Clauses,
4060 Stmt *Body = nullptr) {
4061 llvm::SmallDenseMap<const DecompositionDecl *,
4062 std::pair<bool, SourceLocation>, 4>
4063 SeenDecompositions;
4065 bool HasError = false;
4066 bool HasDefaultShared = false;
4067 SourceLocation DefaultSharedLoc;
4068 for (OMPClause *C : Clauses) {
4069 if (auto *DC = dyn_cast<OMPDefaultClause>(C)) {
4070 if (DC->getDefaultKind() == llvm::omp::DefaultKind::OMP_DEFAULT_shared) {
4071 HasDefaultShared = true;
4072 DefaultSharedLoc = DC->getBeginLoc();
4073 }
4074 continue;
4075 }
4076 OpenMPClauseKind CK = C->getClauseKind();
4077 if (CK != OMPC_map && CK != OMPC_firstprivate && CK != OMPC_private &&
4078 CK != OMPC_shared && CK != OMPC_lastprivate)
4079 continue;
4080 ArrayRef<Expr *> Varlist;
4081 if (auto *MPC = dyn_cast<OMPMapClause>(C))
4082 Varlist = MPC->varlist();
4083 else if (auto *FPC = dyn_cast<OMPFirstprivateClause>(C))
4084 Varlist = FPC->varlist();
4085 else if (auto *PC = dyn_cast<OMPPrivateClause>(C))
4086 Varlist = PC->varlist();
4087 else if (auto *SC = dyn_cast<OMPSharedClause>(C))
4088 Varlist = SC->varlist();
4089 else if (auto *LPC = dyn_cast<OMPLastprivateClause>(C))
4090 Varlist = LPC->varlist();
4091
4092 for (Expr *VE : Varlist) {
4093 if (auto *DRE = dyn_cast<DeclRefExpr>(VE->IgnoreParenImpCasts())) {
4094 ValueDecl *D = DRE->getDecl();
4095 // Look through OMPCapturedExprDecl (used when clauses reference
4096 // variables from an enclosing captured region) to find the
4097 // underlying BindingDecl.
4098 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(D)) {
4099 if (auto *InitDRE =
4100 dyn_cast<DeclRefExpr>(CED->getInit()->IgnoreParenImpCasts()))
4101 D = InitDRE->getDecl();
4102 }
4103 if (auto *BD = dyn_cast<BindingDecl>(D))
4104 ExplicitBindings.insert(cast<BindingDecl>(BD->getCanonicalDecl()));
4106 SemaRef, DKind, SeenDecompositions, D, VE->getExprLoc(), CK))
4107 HasError = true;
4108 }
4109 }
4110 }
4111
4112 // With default(shared), bindings used in the body but not in an explicit
4113 // clause become implicit shared (by-reference). Check those for conflicts
4114 // with explicit by-copy clauses on the same decomposition.
4115 if (HasDefaultShared && Body) {
4118 VarUsageVisitor Visitor(UsedVars, UsedBindings);
4119 Visitor.TraverseStmt(Body);
4120 for (const BindingDecl *BD : UsedBindings) {
4121 if (ExplicitBindings.contains(BD))
4122 continue;
4123 if (checkDecompositionCaptureConflict(SemaRef, DKind, SeenDecompositions,
4124 BD, DefaultSharedLoc, OMPC_shared))
4125 HasError = true;
4126 }
4127 }
4128 return HasError;
4129}
4130
4131/// Check if original variable is explicitly mapped but only bindings are used.
4132/// Returns true if an error was found.
4134 Sema &SemaRef, ArrayRef<OMPClause *> Clauses, Stmt *Body) {
4135 llvm::SmallDenseMap<const VarDecl *, SourceLocation, 4> MappedOrigVars;
4136
4137 for (OMPClause *C : Clauses) {
4138 if (auto *MPC = dyn_cast<OMPMapClause>(C)) {
4139 for (Expr *VE : MPC->varlist()) {
4140 if (auto *DRE = dyn_cast<DeclRefExpr>(VE->IgnoreParenImpCasts())) {
4141 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
4142 MappedOrigVars[VD->getCanonicalDecl()] = VE->getExprLoc();
4143 }
4144 }
4145 }
4146 }
4147 }
4148 if (MappedOrigVars.empty())
4149 return false;
4150
4153 VarUsageVisitor Visitor(UsedVars, UsedBindings);
4154 Visitor.TraverseStmt(Body);
4155 bool HasError = false;
4156 for (const auto &Entry : MappedOrigVars) {
4157 const VarDecl *OrigVar = Entry.first;
4158 SourceLocation Loc = Entry.second;
4159
4160 // Check if this original variable has bindings that are used.
4161 // For reference bindings (`auto &[a, b] = p`), the bindings alias the
4162 // original variable, so mapping `p` covers them correctly.
4163 bool BindingsFromThisVarUsed = false;
4164 for (const BindingDecl *BD : UsedBindings) {
4165 if (auto *DD = dyn_cast<DecompositionDecl>(BD->getDecomposedDecl())) {
4166 if (DD->getType()->isReferenceType())
4167 continue;
4168 if (auto *OrigFromDD = DD->getOriginalVar().Var) {
4169 if (OrigFromDD->getCanonicalDecl() == OrigVar) {
4170 BindingsFromThisVarUsed = true;
4171 break;
4172 }
4173 }
4174 }
4175 }
4176
4177 // Error if: original is mapped, bindings are used, but original is not
4178 // used.
4179 if (BindingsFromThisVarUsed && !UsedVars.count(OrigVar)) {
4180 SemaRef.Diag(Loc, diag::err_omp_original_var_mapped_bindings_only_used)
4181 << OrigVar;
4182 HasError = true;
4183 }
4184 }
4185
4186 return HasError;
4187}
4188
4191 bool IsAggregateOrDeclareTarget,
4192 bool HasConstQualifier) {
4194 switch (M) {
4195 case OMPC_DEFAULTMAP_MODIFIER_alloc:
4196 case OMPC_DEFAULTMAP_MODIFIER_storage:
4197 Kind = OMPC_MAP_alloc;
4198 break;
4199 case OMPC_DEFAULTMAP_MODIFIER_to:
4200 Kind = OMPC_MAP_to;
4201 break;
4202 case OMPC_DEFAULTMAP_MODIFIER_from:
4203 Kind = OMPC_MAP_from;
4204 break;
4205 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
4206 Kind = OMPC_MAP_tofrom;
4207 break;
4208 case OMPC_DEFAULTMAP_MODIFIER_present:
4209 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
4210 // If implicit-behavior is present, each variable referenced in the
4211 // construct in the category specified by variable-category is treated as if
4212 // it had been listed in a map clause with the map-type of alloc and
4213 // map-type-modifier of present.
4214 Kind = OMPC_MAP_alloc;
4215 break;
4216 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
4217 case OMPC_DEFAULTMAP_MODIFIER_private:
4219 llvm_unreachable("Unexpected defaultmap implicit behavior");
4220 case OMPC_DEFAULTMAP_MODIFIER_none:
4221 case OMPC_DEFAULTMAP_MODIFIER_default:
4223 // IsAggregateOrDeclareTarget could be true if:
4224 // 1. the implicit behavior for aggregate is tofrom
4225 // 2. it's a declare target link
4226 if (IsAggregateOrDeclareTarget) {
4227 if (HasConstQualifier)
4228 Kind = OMPC_MAP_to;
4229 else
4230 Kind = OMPC_MAP_tofrom;
4231 break;
4232 }
4233 llvm_unreachable("Unexpected defaultmap implicit behavior");
4234 }
4235 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
4236 return Kind;
4237}
4238
4239static bool hasNoMutableFields(const CXXRecordDecl *RD) {
4240 for (const auto *FD : RD->fields()) {
4241 if (FD->isMutable())
4242 return false;
4243 QualType FT = FD->getType();
4244 while (FT->isArrayType())
4246 if (const auto *NestedRD = FT->getAsCXXRecordDecl())
4247 if (!hasNoMutableFields(NestedRD))
4248 return false;
4249 }
4250 return true;
4251}
4252
4254 while (T->isArrayType())
4255 T = T->getAsArrayTypeUnsafe()->getElementType();
4256 if (!T.isConstQualified())
4257 return false;
4258 if (const auto *RD = T->getAsCXXRecordDecl())
4259 // TODO : Per OpenMP 6.0 p299 lines 3-4, non-mutable members of a
4260 // const-qualified struct should also be ignored for 'from'. This
4261 // requires per-member mapping granularity via compiler-generated
4262 // default mappers and a mechanism to ensure constness to the mapper.
4263 // For now we conservatively treat any struct with mutable members as
4264 // requiring full 'tofrom'.
4265 return hasNoMutableFields(RD);
4266 return true;
4267}
4268
4269namespace {
4270/// Try to extract the original variable from a DecompositionDecl.
4271/// If extraction fails, emit a diagnostic. Returns the original VarDecl* on
4272/// success, nullptr on failure.
4273static const VarDecl *getOriginalVarOrDiagnose(Sema &S,
4274 const DecompositionDecl *DD,
4275 SourceLocation Loc) {
4276 auto Result = DD->getOriginalVar();
4277 if (!Result.Var)
4278 S.Diag(Loc, diag::err_omp_unsupported_structured_binding_init)
4279 << Result.DiagKind;
4280 return Result.Var;
4281}
4282
4283struct VariableImplicitInfo {
4284 static const unsigned MapKindNum = OMPC_MAP_unknown;
4285 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
4286
4287 llvm::SetVector<Expr *> Privates;
4288 llvm::SetVector<Expr *> Firstprivates;
4289 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
4290 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
4291 MapModifiers[DefaultmapKindNum];
4292};
4293
4294class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
4295 DSAStackTy *Stack;
4296 Sema &SemaRef;
4297 OpenMPDirectiveKind DKind = OMPD_unknown;
4298 bool ErrorFound = false;
4299 bool TryCaptureCXXThisMembers = false;
4300 CapturedStmt *CS = nullptr;
4301
4302 VariableImplicitInfo ImpInfo;
4303 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
4304 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
4305
4306 void VisitSubCaptures(OMPExecutableDirective *S) {
4307 // Check implicitly captured variables.
4308 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
4309 return;
4310 if (S->getDirectiveKind() == OMPD_atomic ||
4311 S->getDirectiveKind() == OMPD_critical ||
4312 S->getDirectiveKind() == OMPD_section ||
4313 S->getDirectiveKind() == OMPD_master ||
4314 S->getDirectiveKind() == OMPD_masked ||
4315 S->getDirectiveKind() == OMPD_scope ||
4316 S->getDirectiveKind() == OMPD_assume ||
4317 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
4318 Visit(S->getAssociatedStmt());
4319 return;
4320 }
4321 visitSubCaptures(S->getInnermostCapturedStmt());
4322 // Try to capture inner this->member references to generate correct mappings
4323 // and diagnostics.
4324 if (TryCaptureCXXThisMembers ||
4326 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
4327 [](const CapturedStmt::Capture &C) {
4328 return C.capturesThis();
4329 }))) {
4330 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
4331 TryCaptureCXXThisMembers = true;
4332 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
4333 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
4334 }
4335 // In tasks firstprivates are not captured anymore, need to analyze them
4336 // explicitly.
4337 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
4338 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
4339 for (OMPClause *C : S->clauses())
4340 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
4341 for (Expr *Ref : FC->varlist())
4342 Visit(Ref);
4343 }
4344 }
4345 }
4346
4347public:
4348 void VisitDeclRefExpr(DeclRefExpr *E) {
4349 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
4353 return;
4354 ValueDecl *D = const_cast<ValueDecl *>(E->getDecl());
4355 BindingDecl *BD = dyn_cast<BindingDecl>(D);
4356 if (BD)
4357 D = BD->getDecomposedDecl();
4358 if (auto *VD = dyn_cast<VarDecl>(D)) {
4359 // For BindingDecls, use the original binding for DSA lookups;
4360 // fall back to DecompositionDecl if lookup fails.
4361 ValueDecl *LookupDecl = BD ? static_cast<ValueDecl *>(BD) : VD;
4362 // Check the datasharing rules for the expressions in the clauses.
4363 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
4364 !Stack->getTopDSA(LookupDecl, /*FromParent=*/false).RefExpr &&
4365 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
4366 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
4367 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
4368 Visit(const_cast<Expr *>(CED->getInit()));
4369 return;
4370 }
4371 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
4372 // Do not analyze internal variables and do not enclose them into
4373 // implicit clauses.
4374 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
4375 return;
4376 VD = VD->getCanonicalDecl();
4377 // Skip DecompositionDecls (but not BindingDecls in DSA contexts) -
4378 // they should be handled through explicit mapping of the original
4379 // variable or as member expressions. When bindings are captured,
4380 // the original variable is what needs to be mapped, not the
4381 // decomposition itself. However, BindingDecls need DSA checking for
4382 // default(none)/private/firstprivate contexts, but NOT in target
4383 // offloading contexts (where map clause handles them).
4384 if (isa<DecompositionDecl>(VD)) {
4385 // For BindingDecls, continue checking only if:
4386 // - We are in a DSA context (tasking/parallel/worksharing/teams), or
4387 // - We are in a target context and the binding is scalar (implicit
4388 // firstprivate).
4389 bool InTargetAndScalar = BD &&
4391 BD->getType()->isScalarType();
4392 if (!BD ||
4393 (isOpenMPTargetExecutionDirective(DKind) && !InTargetAndScalar) ||
4394 (!InTargetAndScalar && !isImplicitOrExplicitTaskingRegion(DKind) &&
4395 !isOpenMPParallelDirective(DKind) &&
4397 !isOpenMPTeamsDirective(DKind)))
4398 return;
4399 }
4400 // Skip internally declared variables.
4401 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
4402 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4403 !Stack->isImplicitTaskFirstprivate(VD))
4404 return;
4405 // Skip allocators in uses_allocators clauses.
4406 if (Stack->isUsesAllocatorsDecl(VD))
4407 return;
4408
4409 DSAStackTy::DSAVarData DVar =
4410 Stack->getTopDSA(LookupDecl, /*FromParent=*/false);
4411 // If lookup on BindingDecl failed, try on DecompositionDecl.
4412 if (BD && !DVar.RefExpr)
4413 DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
4414 // Check if the variable has explicit DSA set and stop analysis if it so.
4415 if (DVar.RefExpr ||
4416 !ImplicitDeclarations
4417 .insert(cast<ValueDecl>(LookupDecl->getCanonicalDecl()))
4418 .second)
4419 return;
4420
4421 // Skip internally declared static variables.
4422 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4423 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4424 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
4425 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4426 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4427 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4428 !Stack->isImplicitTaskFirstprivate(VD))
4429 return;
4430
4431 SourceLocation ELoc = E->getExprLoc();
4432 // The default(none) clause requires that each variable that is referenced
4433 // in the construct, and does not have a predetermined data-sharing
4434 // attribute, must have its data-sharing attribute explicitly determined
4435 // by being listed in a data-sharing attribute clause.
4436 if (DVar.CKind == OMPC_unknown &&
4437 (Stack->getDefaultDSA() == DSA_none ||
4438 Stack->getDefaultDSA() == DSA_private ||
4439 Stack->getDefaultDSA() == DSA_firstprivate) &&
4440 isImplicitOrExplicitTaskingRegion(DKind) &&
4441 VarsWithInheritedDSA.count(VD) == 0) {
4442 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4443 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4444 Stack->getDefaultDSA() == DSA_private)) {
4445 DSAStackTy::DSAVarData DVar =
4446 Stack->getImplicitDSA(LookupDecl, /*FromParent=*/false);
4447 if (BD && DVar.CKind == OMPC_unknown)
4448 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4449 InheritedDSA = DVar.CKind == OMPC_unknown;
4450 }
4451 if (InheritedDSA)
4452 VarsWithInheritedDSA[cast<ValueDecl>(
4453 LookupDecl->getCanonicalDecl())] = E;
4454 if (Stack->getDefaultDSA() == DSA_none)
4455 return;
4456 }
4457
4458 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4459 // If implicit-behavior is none, each variable referenced in the
4460 // construct that does not have a predetermined data-sharing attribute
4461 // and does not appear in a to or link clause on a declare target
4462 // directive must be listed in a data-mapping attribute clause, a
4463 // data-sharing attribute clause (including a data-sharing attribute
4464 // clause on a combined construct where target. is one of the
4465 // constituent constructs), or an is_device_ptr clause.
4466 // For BindingDecls, use the binding's type to determine category.
4468 SemaRef.getLangOpts(), BD ? static_cast<const ValueDecl *>(BD)
4469 : static_cast<const ValueDecl *>(VD));
4470 if (SemaRef.getLangOpts().OpenMP >= 50) {
4471 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4472 OMPC_DEFAULTMAP_MODIFIER_none;
4473 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4474 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4475 // Only check for data-mapping attribute and is_device_ptr here
4476 // since we have already make sure that the declaration does not
4477 // have a data-sharing attribute above
4478 if (!Stack->checkMappableExprComponentListsForDecl(
4479 VD, /*CurrentRegionOnly=*/true,
4481 MapExprComponents,
4483 auto MI = MapExprComponents.rbegin();
4484 auto ME = MapExprComponents.rend();
4485 return MI != ME && MI->getAssociatedDeclaration() == VD;
4486 })) {
4487 VarsWithInheritedDSA[cast<ValueDecl>(
4488 LookupDecl->getCanonicalDecl())] = E;
4489 return;
4490 }
4491 }
4492 }
4493 if (SemaRef.getLangOpts().OpenMP > 50) {
4494 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4495 OMPC_DEFAULTMAP_MODIFIER_present;
4496 if (IsModifierPresent) {
4497 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4498 OMPC_MAP_MODIFIER_present)) {
4499 ImpInfo.MapModifiers[ClauseKind].push_back(
4500 OMPC_MAP_MODIFIER_present);
4501 }
4502 }
4503 }
4504
4506 !Stack->isLoopControlVariable(VD).first) {
4507 // Check if VD is already mapped. For DecompositionDecls, also check if
4508 // the original variable they decompose has been mapped (via BindingDecl
4509 // map clauses).
4510 bool AlreadyMapped = Stack->checkMappableExprComponentListsForDecl(
4511 VD, /*CurrentRegionOnly=*/true, [this](auto StackComponents, auto) {
4512 if (SemaRef.LangOpts.OpenMP >= 50)
4513 return !StackComponents.empty();
4514 // Variable is used if it has been marked as an array, array
4515 // section, array shaping or the variable itself.
4516 return StackComponents.size() == 1 ||
4517 llvm::all_of(
4518 llvm::drop_begin(llvm::reverse(StackComponents)),
4519 [](const auto &MC) {
4520 return MC.getAssociatedDeclaration() == nullptr &&
4522 MC.getAssociatedExpression()) ||
4524 MC.getAssociatedExpression()) ||
4526 MC.getAssociatedExpression()));
4527 });
4528 });
4529
4530 // For DecompositionDecls, check if the original variable has been
4531 // mapped.
4532 const auto *DD = dyn_cast<DecompositionDecl>(VD);
4533 if (!AlreadyMapped && DD) {
4534 // Don't diagnose here. Just check if we can extract the original
4535 // var. Diagnostics happen when processing explicit map clauses.
4536 if (const VarDecl *OrigVar = DD->getOriginalVar().Var) {
4537 AlreadyMapped = Stack->checkMappableExprComponentListsForDecl(
4538 OrigVar, /*CurrentRegionOnly=*/true,
4539 [this](auto StackComponents, auto) {
4540 if (SemaRef.LangOpts.OpenMP >= 50)
4541 return !StackComponents.empty();
4542 return StackComponents.size() == 1;
4543 });
4544 }
4545 }
4546 if (!AlreadyMapped) {
4547 bool IsFirstprivate = false;
4548 // By default lambdas are captured as firstprivates.
4549 QualType CheckType = BD ? BD->getType() : VD->getType();
4550 if (const auto *RD =
4552 IsFirstprivate = RD->isLambda();
4553 IsFirstprivate =
4554 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4555 if (IsFirstprivate) {
4556 ImpInfo.Firstprivates.insert(E);
4557 } else {
4559 Stack->getDefaultmapModifier(ClauseKind);
4560 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4561 ImpInfo.Privates.insert(E);
4562 } else {
4564 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res,
4566 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4567 }
4568 }
4569 return;
4570 }
4571 }
4572
4573 // OpenMP [2.9.3.6, Restrictions, p.2]
4574 // A list item that appears in a reduction clause of the innermost
4575 // enclosing worksharing or parallel construct may not be accessed in an
4576 // explicit task.
4577 DVar = Stack->hasInnermostDSA(
4578 LookupDecl,
4579 [](OpenMPClauseKind C, bool AppliedToPointee) {
4580 return C == OMPC_reduction && !AppliedToPointee;
4581 },
4582 [](OpenMPDirectiveKind K) {
4583 return isOpenMPParallelDirective(K) ||
4585 },
4586 /*FromParent=*/true);
4587 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4588 ErrorFound = true;
4589 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4590 reportOriginalDsa(SemaRef, Stack, BD ? LookupDecl : VD, DVar);
4591 return;
4592 }
4593
4594 // Define implicit data-sharing attributes for task.
4595 DVar = Stack->getImplicitDSA(LookupDecl, /*FromParent=*/false);
4596 if (BD && DVar.CKind == OMPC_unknown)
4597 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4598 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
4599 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4600 DVar.CKind == OMPC_firstprivate) ||
4601 (Stack->getDefaultDSA() == DSA_private &&
4602 DVar.CKind == OMPC_private)) &&
4603 !DVar.RefExpr)) &&
4604 !Stack->isLoopControlVariable(VD).first) {
4605 if (Stack->getDefaultDSA() == DSA_private)
4606 ImpInfo.Privates.insert(E);
4607 else
4608 ImpInfo.Firstprivates.insert(E);
4609 return;
4610 }
4611
4612 // Store implicitly used globals with declare target link for parent
4613 // target.
4614 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4615 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4616 Stack->addToParentTargetRegionLinkGlobals(E);
4617 return;
4618 }
4619 }
4620 }
4621 void VisitMemberExpr(MemberExpr *E) {
4622 if (E->isTypeDependent() || E->isValueDependent() ||
4624 return;
4625 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4626 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4627 if (!FD)
4628 return;
4629 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4630 // Check if the variable has explicit DSA set and stop analysis if it
4631 // so.
4632 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4633 return;
4634
4636 !Stack->isLoopControlVariable(FD).first &&
4637 !Stack->checkMappableExprComponentListsForDecl(
4638 FD, /*CurrentRegionOnly=*/true,
4640 StackComponents,
4642 return isa<CXXThisExpr>(
4643 cast<MemberExpr>(
4644 StackComponents.back().getAssociatedExpression())
4645 ->getBase()
4646 ->IgnoreParens());
4647 })) {
4648 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4649 // A bit-field cannot appear in a map clause.
4650 //
4651 if (FD->isBitField())
4652 return;
4653
4654 // Check to see if the member expression is referencing a class that
4655 // has already been explicitly mapped
4656 if (Stack->isClassPreviouslyMapped(TE->getType()))
4657 return;
4658
4660 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4661 OpenMPDefaultmapClauseKind ClauseKind =
4664 Modifier, /*IsAggregateOrDeclareTarget=*/true,
4665 /*HasConstQualifier=*/false);
4666 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4667 return;
4668 }
4669
4670 SourceLocation ELoc = E->getExprLoc();
4671 // OpenMP [2.9.3.6, Restrictions, p.2]
4672 // A list item that appears in a reduction clause of the innermost
4673 // enclosing worksharing or parallel construct may not be accessed in
4674 // an explicit task.
4675 DVar = Stack->hasInnermostDSA(
4676 FD,
4677 [](OpenMPClauseKind C, bool AppliedToPointee) {
4678 return C == OMPC_reduction && !AppliedToPointee;
4679 },
4680 [](OpenMPDirectiveKind K) {
4681 return isOpenMPParallelDirective(K) ||
4683 },
4684 /*FromParent=*/true);
4685 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4686 ErrorFound = true;
4687 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4688 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4689 return;
4690 }
4691
4692 // Define implicit data-sharing attributes for task.
4693 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4694 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4695 !Stack->isLoopControlVariable(FD).first) {
4696 // Check if there is a captured expression for the current field in the
4697 // region. Do not mark it as firstprivate unless there is no captured
4698 // expression.
4699 // TODO: try to make it firstprivate.
4700 if (DVar.CKind != OMPC_unknown)
4701 ImpInfo.Firstprivates.insert(E);
4702 }
4703 return;
4704 }
4707 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4708 DKind, /*NoDiagnose=*/true))
4709 return;
4710 const auto *VD = cast<ValueDecl>(
4711 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4712 if (!Stack->checkMappableExprComponentListsForDecl(
4713 VD, /*CurrentRegionOnly=*/true,
4714 [&CurComponents](
4716 StackComponents,
4718 auto CCI = CurComponents.rbegin();
4719 auto CCE = CurComponents.rend();
4720 for (const auto &SC : llvm::reverse(StackComponents)) {
4721 // Do both expressions have the same kind?
4722 if (CCI->getAssociatedExpression()->getStmtClass() !=
4723 SC.getAssociatedExpression()->getStmtClass())
4724 if (!((isa<ArraySectionExpr>(
4725 SC.getAssociatedExpression()) ||
4726 isa<OMPArrayShapingExpr>(
4727 SC.getAssociatedExpression())) &&
4728 isa<ArraySubscriptExpr>(
4729 CCI->getAssociatedExpression())))
4730 return false;
4731
4732 const Decl *CCD = CCI->getAssociatedDeclaration();
4733 const Decl *SCD = SC.getAssociatedDeclaration();
4734 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4735 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4736 if (SCD != CCD)
4737 return false;
4738 std::advance(CCI, 1);
4739 if (CCI == CCE)
4740 break;
4741 }
4742 return true;
4743 })) {
4744 Visit(E->getBase());
4745 }
4746 } else if (!TryCaptureCXXThisMembers) {
4747 Visit(E->getBase());
4748 }
4749 }
4750 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4751 for (OMPClause *C : S->clauses()) {
4752 // Skip analysis of arguments of private clauses for task|target
4753 // directives.
4754 if (isa_and_nonnull<OMPPrivateClause>(C))
4755 continue;
4756 // Skip analysis of arguments of implicitly defined firstprivate clause
4757 // for task|target directives.
4758 // Skip analysis of arguments of implicitly defined map clause for target
4759 // directives.
4761 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4762 for (Stmt *CC : C->children()) {
4763 if (CC)
4764 Visit(CC);
4765 }
4766 }
4767 }
4768 // Check implicitly captured variables.
4769 VisitSubCaptures(S);
4770 }
4771
4772 void VisitOMPCanonicalLoopNestTransformationDirective(
4773 OMPCanonicalLoopNestTransformationDirective *S) {
4774 // Loop transformation directives do not introduce data sharing
4775 VisitStmt(S);
4776 }
4777
4778 // A metadirective has no associated statement; visit its variants and
4779 // conditions.
4780 void VisitOMPMetaDirective(OMPMetaDirective *S) { VisitStmt(S); }
4781
4782 void VisitCallExpr(CallExpr *S) {
4783 for (Stmt *C : S->arguments()) {
4784 if (C) {
4785 // Check implicitly captured variables in the task-based directives to
4786 // check if they must be firstprivatized.
4787 Visit(C);
4788 }
4789 }
4790 if (Expr *Callee = S->getCallee()) {
4791 auto *CI = Callee->IgnoreParenImpCasts();
4792 if (auto *CE = dyn_cast<MemberExpr>(CI))
4793 Visit(CE->getBase());
4794 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4795 Visit(CE);
4796 }
4797 }
4798 void VisitStmt(Stmt *S) {
4799 for (Stmt *C : S->children()) {
4800 if (C) {
4801 // Check implicitly captured variables in the task-based directives to
4802 // check if they must be firstprivatized.
4803 Visit(C);
4804 }
4805 }
4806 }
4807
4808 void visitSubCaptures(CapturedStmt *S) {
4809 for (const CapturedStmt::Capture &Cap : S->captures()) {
4810 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4811 continue;
4812 VarDecl *VD = Cap.getCapturedVar();
4813 // Do not try to map the variable if it or its sub-component was mapped
4814 // already.
4816 Stack->checkMappableExprComponentListsForDecl(
4817 VD, /*CurrentRegionOnly=*/true,
4819 OpenMPClauseKind) { return true; }))
4820 continue;
4821 DeclRefExpr *DRE = buildDeclRefExpr(
4822 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4823 Cap.getLocation(), /*RefersToCapture=*/true);
4824 Visit(DRE);
4825 }
4826 }
4827 bool isErrorFound() const { return ErrorFound; }
4828 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4829 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4830 return VarsWithInheritedDSA;
4831 }
4832
4833 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4834 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4835 DKind = S->getCurrentDirective();
4836 // Process declare target link variables for the target directives.
4838 for (DeclRefExpr *E : Stack->getLinkGlobals())
4839 Visit(E);
4840 }
4841 }
4842};
4843} // namespace
4844
4845static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4846 OpenMPDirectiveKind DKind,
4847 bool ScopeEntry) {
4850 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4851 if (isOpenMPTeamsDirective(DKind))
4852 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4853 if (isOpenMPParallelDirective(DKind))
4854 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4856 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4857 if (isOpenMPSimdDirective(DKind))
4858 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4859 Stack->handleConstructTrait(Traits, ScopeEntry);
4860}
4861
4862static SmallVector<SemaOpenMP::CapturedParamNameType>
4863getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4864 ASTContext &Context = SemaRef.getASTContext();
4865 QualType KmpInt32Ty =
4866 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4867 QualType KmpInt32PtrTy =
4868 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4870 std::make_pair(".global_tid.", KmpInt32PtrTy),
4871 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4872 };
4873 if (LoopBoundSharing) {
4874 QualType KmpSizeTy = Context.getSizeType().withConst();
4875 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4876 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4877 }
4878
4879 // __context with shared vars
4880 Params.push_back(std::make_pair(StringRef(), QualType()));
4881 return Params;
4882}
4883
4884static SmallVector<SemaOpenMP::CapturedParamNameType>
4886 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4887}
4888
4889static SmallVector<SemaOpenMP::CapturedParamNameType>
4891 ASTContext &Context = SemaRef.getASTContext();
4892 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4893 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4894 QualType KmpInt32PtrTy =
4895 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4896 QualType Args[] = {VoidPtrTy};
4898 EPI.Variadic = true;
4899 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4901 std::make_pair(".global_tid.", KmpInt32Ty),
4902 std::make_pair(".part_id.", KmpInt32PtrTy),
4903 std::make_pair(".privates.", VoidPtrTy),
4904 std::make_pair(
4905 ".copy_fn.",
4906 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4907 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4908 std::make_pair(StringRef(), QualType()) // __context with shared vars
4909 };
4910 return Params;
4911}
4912
4913static SmallVector<SemaOpenMP::CapturedParamNameType>
4915 ASTContext &Context = SemaRef.getASTContext();
4917 // __context with shared vars
4918 Params.push_back(std::make_pair(StringRef(), QualType()));
4919 // Implicit dyn_ptr argument, appended as the last parameter. Present on both
4920 // host and device so argument counts match without runtime manipulation.
4921 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4922 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4923 return Params;
4924}
4925
4926static SmallVector<SemaOpenMP::CapturedParamNameType>
4929 std::make_pair(StringRef(), QualType()) // __context with shared vars
4930 };
4931 return Params;
4932}
4933
4934static SmallVector<SemaOpenMP::CapturedParamNameType>
4936 ASTContext &Context = SemaRef.getASTContext();
4937 QualType KmpInt32Ty =
4938 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4939 QualType KmpUInt64Ty =
4940 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4941 QualType KmpInt64Ty =
4942 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4943 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4944 QualType KmpInt32PtrTy =
4945 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4946 QualType Args[] = {VoidPtrTy};
4948 EPI.Variadic = true;
4949 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4951 std::make_pair(".global_tid.", KmpInt32Ty),
4952 std::make_pair(".part_id.", KmpInt32PtrTy),
4953 std::make_pair(".privates.", VoidPtrTy),
4954 std::make_pair(
4955 ".copy_fn.",
4956 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4957 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4958 std::make_pair(".lb.", KmpUInt64Ty),
4959 std::make_pair(".ub.", KmpUInt64Ty),
4960 std::make_pair(".st.", KmpInt64Ty),
4961 std::make_pair(".liter.", KmpInt32Ty),
4962 std::make_pair(".reductions.", VoidPtrTy),
4963 std::make_pair(StringRef(), QualType()) // __context with shared vars
4964 };
4965 return Params;
4966}
4967
4969 Scope *CurScope, SourceLocation Loc) {
4971 getOpenMPCaptureRegions(Regions, DKind);
4972
4973 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4974
4975 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4976 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4977 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4978 };
4979
4980 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4981 switch (RKind) {
4982 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4983 // are listed here.
4984 case OMPD_parallel:
4986 Loc, CurScope, CR_OpenMP,
4987 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4988 break;
4989 case OMPD_teams:
4990 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4991 getTeamsRegionParams(SemaRef), Level);
4992 break;
4993 case OMPD_task:
4994 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4995 getTaskRegionParams(SemaRef), Level);
4996 // Mark this captured region as inlined, because we don't use outlined
4997 // function directly.
4998 MarkAsInlined(SemaRef.getCurCapturedRegion());
4999 break;
5000 case OMPD_taskloop:
5001 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
5002 getTaskloopRegionParams(SemaRef), Level);
5003 // Mark this captured region as inlined, because we don't use outlined
5004 // function directly.
5005 MarkAsInlined(SemaRef.getCurCapturedRegion());
5006 break;
5007 case OMPD_target:
5008 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
5009 getTargetRegionParams(SemaRef), Level);
5010 break;
5011 case OMPD_unknown:
5012 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
5013 getUnknownRegionParams(SemaRef));
5014 break;
5015 case OMPD_metadirective:
5016 case OMPD_nothing:
5017 default:
5018 llvm_unreachable("Unexpected capture region");
5019 }
5020 }
5021}
5022
5024 Scope *CurScope) {
5025 if (DKind == OMPD_ordered_blockassoc &&
5026 DSAStack->getCurrentDirective() == OMPD_ordered_standalone) {
5027 DSAStack->setOrderedToBlockAssociated();
5028 }
5029 switch (DKind) {
5030 case OMPD_atomic:
5031 case OMPD_critical:
5032 case OMPD_masked:
5033 case OMPD_master:
5034 case OMPD_section:
5035 case OMPD_tile:
5036 case OMPD_stripe:
5037 case OMPD_unroll:
5038 case OMPD_reverse:
5039 case OMPD_split:
5040 case OMPD_interchange:
5041 case OMPD_flatten:
5042 case OMPD_fuse:
5043 case OMPD_assume:
5044 break;
5045 default:
5046 processCapturedRegions(SemaRef, DKind, CurScope,
5047 DSAStack->getConstructLoc());
5048 break;
5049 }
5050
5051 DSAStack->setContext(SemaRef.CurContext);
5052 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
5053}
5054
5055int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
5056 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
5057}
5058
5061 getOpenMPCaptureRegions(CaptureRegions, DKind);
5062 return CaptureRegions.size();
5063}
5064
5066 Expr *CaptureExpr, bool WithInit,
5067 DeclContext *CurContext,
5068 bool AsExpression) {
5069 assert(CaptureExpr);
5070 ASTContext &C = S.getASTContext();
5071 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
5072 QualType Ty = Init->getType();
5073 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
5074 if (S.getLangOpts().CPlusPlus) {
5075 Ty = C.getLValueReferenceType(Ty);
5076 } else {
5077 Ty = C.getPointerType(Ty);
5078 ExprResult Res =
5079 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
5080 if (!Res.isUsable())
5081 return nullptr;
5082 Init = Res.get();
5083 }
5084 WithInit = true;
5085 }
5086 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
5087 CaptureExpr->getBeginLoc());
5088 if (!WithInit)
5089 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
5090 CurContext->addHiddenDecl(CED);
5092 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
5093 return CED;
5094}
5095
5096static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
5097 bool WithInit) {
5099 // For BindingDecls, always create a new capture instead of reusing the
5100 // decomposed decl, since the decomposed decl is a regular VarDecl, not an
5101 // OMPCapturedExprDecl.
5102 if (!isa<BindingDecl>(D)) {
5103 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
5105 else
5106 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
5107 S.CurContext,
5108 /*AsExpression=*/false);
5109 } else {
5110 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
5111 S.CurContext,
5112 /*AsExpression=*/false);
5113 }
5114 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
5115 CaptureExpr->getExprLoc());
5116}
5117
5118static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
5119 StringRef Name) {
5120 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
5121 if (!Ref) {
5123 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
5124 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
5125 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
5126 CaptureExpr->getExprLoc());
5127 }
5128 ExprResult Res = Ref;
5129 if (!S.getLangOpts().CPlusPlus &&
5130 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
5131 Ref->getType()->isPointerType()) {
5132 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
5133 if (!Res.isUsable())
5134 return ExprError();
5135 }
5136 return S.DefaultLvalueConversion(Res.get());
5137}
5138
5139namespace {
5140// OpenMP directives parsed in this section are represented as a
5141// CapturedStatement with an associated statement. If a syntax error
5142// is detected during the parsing of the associated statement, the
5143// compiler must abort processing and close the CapturedStatement.
5144//
5145// Combined directives such as 'target parallel' have more than one
5146// nested CapturedStatements. This RAII ensures that we unwind out
5147// of all the nested CapturedStatements when an error is found.
5148class CaptureRegionUnwinderRAII {
5149private:
5150 Sema &S;
5151 bool &ErrorFound;
5152 OpenMPDirectiveKind DKind = OMPD_unknown;
5153
5154public:
5155 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
5156 OpenMPDirectiveKind DKind)
5157 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
5158 ~CaptureRegionUnwinderRAII() {
5159 if (ErrorFound) {
5160 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
5161 while (--ThisCaptureLevel >= 0)
5163 }
5164 }
5165};
5166} // namespace
5167
5169 // Capture variables captured by reference in lambdas for target-based
5170 // directives.
5171 if (!SemaRef.CurContext->isDependentContext() &&
5172 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
5174 DSAStack->getCurrentDirective()))) {
5175 QualType Type = V->getType();
5176 if (const auto *RD = Type.getCanonicalType()
5177 .getNonReferenceType()
5178 ->getAsCXXRecordDecl()) {
5179 bool SavedForceCaptureByReferenceInTargetExecutable =
5180 DSAStack->isForceCaptureByReferenceInTargetExecutable();
5181 DSAStack->setForceCaptureByReferenceInTargetExecutable(
5182 /*V=*/true);
5183 if (RD->isLambda()) {
5184 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
5185 FieldDecl *ThisCapture;
5186 RD->getCaptureFields(Captures, ThisCapture);
5187 for (const LambdaCapture &LC : RD->captures()) {
5188 if (LC.getCaptureKind() == LCK_ByRef) {
5189 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
5190 DeclContext *VDC = VD->getDeclContext();
5191 if (!VDC->Encloses(SemaRef.CurContext))
5192 continue;
5193 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
5194 } else if (LC.getCaptureKind() == LCK_This) {
5195 QualType ThisTy = SemaRef.getCurrentThisType();
5196 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
5197 ThisTy, ThisCapture->getType()))
5198 SemaRef.CheckCXXThisCapture(LC.getLocation());
5199 }
5200 }
5201 }
5202 DSAStack->setForceCaptureByReferenceInTargetExecutable(
5203 SavedForceCaptureByReferenceInTargetExecutable);
5204 }
5205 }
5206}
5207
5209 const ArrayRef<OMPClause *> Clauses) {
5210 const OMPOrderedClause *Ordered = nullptr;
5211 const OMPOrderClause *Order = nullptr;
5212
5213 for (const OMPClause *Clause : Clauses) {
5214 if (Clause->getClauseKind() == OMPC_ordered)
5215 Ordered = cast<OMPOrderedClause>(Clause);
5216 else if (Clause->getClauseKind() == OMPC_order) {
5217 Order = cast<OMPOrderClause>(Clause);
5218 if (Order->getKind() != OMPC_ORDER_concurrent)
5219 Order = nullptr;
5220 }
5221 if (Ordered && Order)
5222 break;
5223 }
5224
5225 if (Ordered && Order) {
5226 S.Diag(Order->getKindKwLoc(),
5227 diag::err_omp_simple_clause_incompatible_with_ordered)
5228 << getOpenMPClauseNameForDiag(OMPC_order)
5229 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
5230 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
5231 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
5232 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
5233 return true;
5234 }
5235 return false;
5236}
5237
5239 ArrayRef<OMPClause *> Clauses) {
5241 /*ScopeEntry=*/false);
5242 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
5243 return S;
5244
5245 bool ErrorFound = false;
5246 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
5247 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
5248 if (!S.isUsable()) {
5249 ErrorFound = true;
5250 return StmtError();
5251 }
5252
5254 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
5255 OMPOrderedClause *OC = nullptr;
5256 OMPScheduleClause *SC = nullptr;
5259 // This is required for proper codegen.
5260 for (OMPClause *Clause : Clauses) {
5261 if (!getLangOpts().OpenMPSimd &&
5262 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
5263 DSAStack->getCurrentDirective() == OMPD_target) &&
5264 Clause->getClauseKind() == OMPC_in_reduction) {
5265 // Capture taskgroup task_reduction descriptors inside the tasking regions
5266 // with the corresponding in_reduction items.
5267 auto *IRC = cast<OMPInReductionClause>(Clause);
5268 for (Expr *E : IRC->taskgroup_descriptors())
5269 if (E)
5270 SemaRef.MarkDeclarationsReferencedInExpr(E);
5271 }
5272 if (isOpenMPPrivate(Clause->getClauseKind()) ||
5273 Clause->getClauseKind() == OMPC_copyprivate ||
5274 (getLangOpts().OpenMPUseTLS &&
5275 getASTContext().getTargetInfo().isTLSSupported() &&
5276 Clause->getClauseKind() == OMPC_copyin)) {
5277 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
5278 // Mark all variables in private list clauses as used in inner region.
5279 for (Stmt *VarRef : Clause->children()) {
5280 if (auto *E = cast_or_null<Expr>(VarRef)) {
5281 SemaRef.MarkDeclarationsReferencedInExpr(E);
5282 }
5283 }
5284 DSAStack->setForceVarCapturing(/*V=*/false);
5285 } else if (CaptureRegions.size() > 1 ||
5286 CaptureRegions.back() != OMPD_unknown) {
5287 if (auto *C = OMPClauseWithPreInit::get(Clause))
5288 PICs.push_back(C);
5289 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
5290 if (Expr *E = C->getPostUpdateExpr())
5291 SemaRef.MarkDeclarationsReferencedInExpr(E);
5292 }
5293 }
5294 if (Clause->getClauseKind() == OMPC_schedule)
5295 SC = cast<OMPScheduleClause>(Clause);
5296 else if (Clause->getClauseKind() == OMPC_ordered)
5297 OC = cast<OMPOrderedClause>(Clause);
5298 else if (Clause->getClauseKind() == OMPC_linear)
5299 LCs.push_back(cast<OMPLinearClause>(Clause));
5300 }
5301 // Capture allocator expressions if used.
5302 for (Expr *E : DSAStack->getInnerAllocators())
5303 SemaRef.MarkDeclarationsReferencedInExpr(E);
5304 // OpenMP, 2.7.1 Loop Construct, Restrictions
5305 // The nonmonotonic modifier cannot be specified if an ordered clause is
5306 // specified.
5307 if (SC &&
5308 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
5309 SC->getSecondScheduleModifier() ==
5310 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
5311 OC) {
5312 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
5313 ? SC->getFirstScheduleModifierLoc()
5314 : SC->getSecondScheduleModifierLoc(),
5315 diag::err_omp_simple_clause_incompatible_with_ordered)
5316 << getOpenMPClauseNameForDiag(OMPC_schedule)
5317 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
5318 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
5319 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
5320 ErrorFound = true;
5321 }
5322 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
5323 // If an order(concurrent) clause is present, an ordered clause may not appear
5324 // on the same directive.
5325 if (checkOrderedOrderSpecified(SemaRef, Clauses))
5326 ErrorFound = true;
5327 if (!LCs.empty() && OC && OC->getNumForLoops()) {
5328 for (const OMPLinearClause *C : LCs) {
5329 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
5330 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
5331 }
5332 ErrorFound = true;
5333 }
5334 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
5335 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
5336 OC->getNumForLoops()) {
5337 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
5338 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
5339 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
5340 ErrorFound = true;
5341 }
5342 if (ErrorFound) {
5343 return StmtError();
5344 }
5345 StmtResult SR = S;
5346 unsigned CompletedRegions = 0;
5347 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
5348 // Mark all variables in private list clauses as used in inner region.
5349 // Required for proper codegen of combined directives.
5350 // TODO: add processing for other clauses.
5351 if (ThisCaptureRegion != OMPD_unknown) {
5352 for (const clang::OMPClauseWithPreInit *C : PICs) {
5353 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
5354 // Find the particular capture region for the clause if the
5355 // directive is a combined one with multiple capture regions.
5356 // If the directive is not a combined one, the capture region
5357 // associated with the clause is OMPD_unknown and is generated
5358 // only once.
5359 if (CaptureRegion == ThisCaptureRegion ||
5360 CaptureRegion == OMPD_unknown) {
5361 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
5362 for (Decl *D : DS->decls())
5363 SemaRef.MarkVariableReferenced(D->getLocation(),
5364 cast<VarDecl>(D));
5365 }
5366 }
5367 }
5368 }
5369 if (ThisCaptureRegion == OMPD_target) {
5370 // Capture allocator traits in the target region. They are used implicitly
5371 // and, thus, are not captured by default.
5372 for (OMPClause *C : Clauses) {
5373 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
5374 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
5375 ++I) {
5376 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
5377 if (Expr *E = D.AllocatorTraits)
5378 SemaRef.MarkDeclarationsReferencedInExpr(E);
5379 }
5380 continue;
5381 }
5382 }
5383 }
5384 if (ThisCaptureRegion == OMPD_parallel) {
5385 // Capture temp arrays for inscan reductions and locals in aligned
5386 // clauses.
5387 for (OMPClause *C : Clauses) {
5388 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
5389 if (RC->getModifier() != OMPC_REDUCTION_inscan)
5390 continue;
5391 for (Expr *E : RC->copy_array_temps())
5392 if (E)
5393 SemaRef.MarkDeclarationsReferencedInExpr(E);
5394 }
5395 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
5396 for (Expr *E : AC->varlist())
5397 SemaRef.MarkDeclarationsReferencedInExpr(E);
5398 }
5399 }
5400 }
5401 if (++CompletedRegions == CaptureRegions.size())
5402 DSAStack->setBodyComplete();
5403 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
5404 }
5405 return SR;
5406}
5407
5408static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
5409 OpenMPDirectiveKind CancelRegion,
5410 SourceLocation StartLoc) {
5411 // CancelRegion is only needed for cancel and cancellation_point.
5412 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
5413 return false;
5414
5415 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
5416 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
5417 return false;
5418
5419 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
5420 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
5421 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
5422 return true;
5423}
5424
5425static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
5426 OpenMPDirectiveKind CurrentRegion,
5427 const DeclarationNameInfo &CurrentName,
5428 OpenMPDirectiveKind CancelRegion,
5429 OpenMPBindClauseKind BindKind,
5430 SourceLocation StartLoc) {
5431 if (!Stack->getCurScope())
5432 return false;
5433
5434 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
5435 OpenMPDirectiveKind OffendingRegion = ParentRegion;
5436 bool NestingProhibited = false;
5437 bool CloseNesting = true;
5438 bool OrphanSeen = false;
5439 enum {
5440 NoRecommend,
5441 ShouldBeInParallelRegion,
5442 ShouldBeInOrderedRegion,
5443 ShouldBeInTargetRegion,
5444 ShouldBeInTeamsRegion,
5445 ShouldBeInLoopSimdRegion,
5446 } Recommend = NoRecommend;
5447
5450 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
5451 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
5452 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
5453
5454 if (OMPVersion >= 50 && Stack->isEnclosingOrderConcurrent() &&
5456 SemaRef.LangOpts)) {
5457 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5458 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5459 return true;
5460 }
5461 // A construct nested in a loop-transforming or ordered construct is still
5462 // encountered during execution of an enclosing simd region.
5463 if (Stack->isInSimdRegion() &&
5464 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered_blockassoc) ||
5465 (OMPVersion >= 50 && !isOpenMPSimdizableDirective(
5466 CurrentRegion, BindKind, SemaRef.LangOpts)))) {
5467 // OpenMP [2.16, Nesting of Regions]
5468 // OpenMP constructs may not be nested inside a simd region.
5469 // OpenMP [2.8.1,simd Construct, Restrictions]
5470 // An ordered construct with the simd clause is the only OpenMP
5471 // construct that can appear in the simd region.
5472 // Allowing a SIMD construct nested in another SIMD construct is an
5473 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5474 // message.
5475 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5476 // The only OpenMP constructs that can be encountered during execution of
5477 // a simd region are the atomic construct, the loop construct, the simd
5478 // construct and the ordered construct with the simd clause.
5479 // OpenMP 5.2 [10.4, simd Construct, Restrictions]
5480 // Only simdizable constructs can be encountered during execution of a
5481 // simd region.
5482 // OpenMP 6.0 makes all loop-transforming constructs simdizable.
5483 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5484 ? diag::err_omp_prohibited_region_simd
5485 : diag::warn_omp_nesting_simd)
5486 << (OMPVersion >= 60 ? 2
5487 : OMPVersion >= 50 ? 1
5488 : 0);
5489 return CurrentRegion != OMPD_simd;
5490 }
5491 if (EnclosingConstruct == OMPD_atomic) {
5492 // OpenMP [2.16, Nesting of Regions]
5493 // OpenMP constructs may not be nested inside an atomic region.
5494 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5495 return true;
5496 }
5497 if (CurrentRegion == OMPD_section) {
5498 // OpenMP [2.7.2, sections Construct, Restrictions]
5499 // Orphaned section directives are prohibited. That is, the section
5500 // directives must appear within the sections construct and must not be
5501 // encountered elsewhere in the sections region.
5502 if (EnclosingConstruct != OMPD_sections) {
5503 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5504 << (ParentRegion != OMPD_unknown)
5505 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5506 return true;
5507 }
5508 return false;
5509 }
5510 // Allow some constructs (except teams and cancellation constructs) to be
5511 // orphaned (they could be used in functions, called from OpenMP regions
5512 // with the required preconditions).
5513 if (ParentRegion == OMPD_unknown &&
5514 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5515 CurrentRegion != OMPD_cancellation_point &&
5516 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5517 return false;
5518 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5519 // for a detailed explanation
5520 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5521 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5522 (isOpenMPWorksharingDirective(ParentRegion) ||
5523 EnclosingConstruct == OMPD_loop)) {
5524 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5525 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5526 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5527 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5528 return true;
5529 }
5530 if (CurrentRegion == OMPD_cancellation_point ||
5531 CurrentRegion == OMPD_cancel) {
5532 // OpenMP [2.16, Nesting of Regions]
5533 // A cancellation point construct for which construct-type-clause is
5534 // taskgroup must be nested inside a task construct. A cancellation
5535 // point construct for which construct-type-clause is not taskgroup must
5536 // be closely nested inside an OpenMP construct that matches the type
5537 // specified in construct-type-clause.
5538 // A cancel construct for which construct-type-clause is taskgroup must be
5539 // nested inside a task construct. A cancel construct for which
5540 // construct-type-clause is not taskgroup must be closely nested inside an
5541 // OpenMP construct that matches the type specified in
5542 // construct-type-clause.
5543 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
5544 if (CancelRegion == OMPD_taskgroup) {
5545 NestingProhibited =
5546 EnclosingConstruct != OMPD_task &&
5547 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5548 } else if (CancelRegion == OMPD_sections) {
5549 NestingProhibited = EnclosingConstruct != OMPD_section &&
5550 EnclosingConstruct != OMPD_sections;
5551 } else {
5552 NestingProhibited = CancelRegion != Leafs.back();
5553 }
5554 OrphanSeen = ParentRegion == OMPD_unknown;
5555 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5556 // OpenMP 5.1 [2.22, Nesting of Regions]
5557 // A masked region may not be closely nested inside a worksharing, loop,
5558 // atomic, task, or taskloop region.
5559 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5560 isOpenMPGenericLoopDirective(ParentRegion) ||
5561 isOpenMPTaskingDirective(ParentRegion);
5562 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5563 // OpenMP [2.16, Nesting of Regions]
5564 // A critical region may not be nested (closely or otherwise) inside a
5565 // critical region with the same name. Note that this restriction is not
5566 // sufficient to prevent deadlock.
5567 SourceLocation PreviousCriticalLoc;
5568 bool DeadLock = Stack->hasDirective(
5569 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5570 const DeclarationNameInfo &DNI,
5571 SourceLocation Loc) {
5572 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5573 PreviousCriticalLoc = Loc;
5574 return true;
5575 }
5576 return false;
5577 },
5578 false /* skip top directive */);
5579 if (DeadLock) {
5580 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5581 << CurrentName.getName();
5582 if (PreviousCriticalLoc.isValid())
5583 SemaRef.Diag(PreviousCriticalLoc,
5584 diag::note_omp_previous_critical_region);
5585 return true;
5586 }
5587 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5588 // OpenMP 5.1 [2.22, Nesting of Regions]
5589 // A scope region may not be closely nested inside a worksharing, loop,
5590 // task, taskloop, critical, ordered, atomic, or masked region.
5591 // OpenMP 5.1 [2.22, Nesting of Regions]
5592 // A barrier region may not be closely nested inside a worksharing, loop,
5593 // task, taskloop, critical, ordered, atomic, or masked region.
5594 NestingProhibited =
5595 isOpenMPWorksharingDirective(ParentRegion) ||
5596 isOpenMPGenericLoopDirective(ParentRegion) ||
5597 isOpenMPTaskingDirective(ParentRegion) ||
5598 llvm::is_contained(
5599 {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5600 EnclosingConstruct);
5601 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5602 !isOpenMPParallelDirective(CurrentRegion) &&
5603 !isOpenMPTeamsDirective(CurrentRegion)) {
5604 // OpenMP 5.1 [2.22, Nesting of Regions]
5605 // A loop region that binds to a parallel region or a worksharing region
5606 // may not be closely nested inside a worksharing, loop, task, taskloop,
5607 // critical, ordered, atomic, or masked region.
5608 NestingProhibited =
5609 isOpenMPWorksharingDirective(ParentRegion) ||
5610 isOpenMPGenericLoopDirective(ParentRegion) ||
5611 isOpenMPTaskingDirective(ParentRegion) ||
5612 llvm::is_contained(
5613 {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
5614 EnclosingConstruct);
5615 Recommend = ShouldBeInParallelRegion;
5616 } else if (CurrentRegion == OMPD_ordered_blockassoc ||
5617 CurrentRegion == OMPD_ordered_standalone) {
5618 // OpenMP [2.16, Nesting of Regions]
5619 // An ordered region may not be closely nested inside a critical,
5620 // atomic, or explicit task region.
5621 // An ordered region must be closely nested inside a loop region (or
5622 // parallel loop region) with an ordered clause.
5623 // OpenMP [2.8.1,simd Construct, Restrictions]
5624 // An ordered construct with the simd clause is the only OpenMP construct
5625 // that can appear in the simd region.
5626 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5627 isOpenMPTaskingDirective(ParentRegion) ||
5628 !(isOpenMPSimdDirective(ParentRegion) ||
5629 Stack->isParentOrderedRegion());
5630 Recommend = ShouldBeInOrderedRegion;
5631 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5632 // OpenMP [2.16, Nesting of Regions]
5633 // If specified, a teams construct must be contained within a target
5634 // construct.
5635 NestingProhibited =
5636 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5637 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5638 EnclosingConstruct != OMPD_target);
5639 OrphanSeen = ParentRegion == OMPD_unknown;
5640 Recommend = ShouldBeInTargetRegion;
5641 } else if (CurrentRegion == OMPD_scan) {
5642 if (OMPVersion >= 50) {
5643 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5644 // simd, or for simd. This has to take into account combined directives.
5645 // In 5.2 this seems to be implied by the fact that the specified
5646 // separated constructs are do, for, and simd.
5647 NestingProhibited = !llvm::is_contained(
5648 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5649 } else {
5650 NestingProhibited = true;
5651 }
5652 OrphanSeen = ParentRegion == OMPD_unknown;
5653 Recommend = ShouldBeInLoopSimdRegion;
5654 }
5655 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5656 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5657 EnclosingConstruct == OMPD_teams) {
5658 // OpenMP [5.1, 2.22, Nesting of Regions]
5659 // distribute, distribute simd, distribute parallel worksharing-loop,
5660 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5661 // including any parallel regions arising from combined constructs,
5662 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5663 // only OpenMP regions that may be strictly nested inside the teams
5664 // region.
5665 //
5666 // As an extension, we permit atomic within teams as well.
5667 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5668 !isOpenMPDistributeDirective(CurrentRegion) &&
5669 CurrentRegion != OMPD_loop &&
5670 !(SemaRef.getLangOpts().OpenMPExtensions &&
5671 CurrentRegion == OMPD_atomic);
5672 Recommend = ShouldBeInParallelRegion;
5673 }
5674 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5675 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5676 // If the bind clause is present on the loop construct and binding is
5677 // teams then the corresponding loop region must be strictly nested inside
5678 // a teams region.
5679 NestingProhibited =
5680 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5681 Recommend = ShouldBeInTeamsRegion;
5682 }
5683 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5684 // OpenMP 4.5 [2.17 Nesting of Regions]
5685 // The region associated with the distribute construct must be strictly
5686 // nested inside a teams region
5687 NestingProhibited = EnclosingConstruct != OMPD_teams;
5688 Recommend = ShouldBeInTeamsRegion;
5689 }
5690 if (!NestingProhibited &&
5691 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5692 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5693 // OpenMP 4.5 [2.17 Nesting of Regions]
5694 // If a target, target update, target data, target enter data, or
5695 // target exit data construct is encountered during execution of a
5696 // target region, the behavior is unspecified.
5697 NestingProhibited = Stack->hasDirective(
5698 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5701 OffendingRegion = K;
5702 return true;
5703 }
5704 return false;
5705 },
5706 false /* don't skip top directive */);
5707 CloseNesting = false;
5708 }
5709 if (NestingProhibited) {
5710 if (OrphanSeen) {
5711 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5712 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5713 } else {
5714 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5715 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5716 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5717 }
5718 return true;
5719 }
5720 return false;
5721}
5722
5728 ArrayRef<OMPClause *> Clauses,
5729 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5730 bool ErrorFound = false;
5731 unsigned NamedModifiersNumber = 0;
5732 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5733 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5734 SmallVector<SourceLocation, 4> NameModifierLoc;
5735 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
5736 for (const OMPClause *C : Clauses) {
5737 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5738 // At most one if clause without a directive-name-modifier can appear on
5739 // the directive.
5740 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5741 auto &FNM = FoundNameModifiers[CurNM];
5742 if (FNM) {
5743 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5744 << getOpenMPDirectiveName(Kind, OMPVersion)
5745 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5746 << getOpenMPDirectiveName(CurNM, OMPVersion);
5747 ErrorFound = true;
5748 } else if (CurNM != OMPD_unknown) {
5749 NameModifierLoc.push_back(IC->getNameModifierLoc());
5750 ++NamedModifiersNumber;
5751 }
5752 FNM = IC;
5753 if (CurNM == OMPD_unknown)
5754 continue;
5755 // Check if the specified name modifier is allowed for the current
5756 // directive.
5757 // At most one if clause with the particular directive-name-modifier can
5758 // appear on the directive.
5759 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5760 S.Diag(IC->getNameModifierLoc(),
5761 diag::err_omp_wrong_if_directive_name_modifier)
5762 << getOpenMPDirectiveName(CurNM, OMPVersion)
5763 << getOpenMPDirectiveName(Kind, OMPVersion);
5764 ErrorFound = true;
5765 }
5766 }
5767 }
5768 // If any if clause on the directive includes a directive-name-modifier then
5769 // all if clauses on the directive must include a directive-name-modifier.
5770 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5771 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5772 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5773 diag::err_omp_no_more_if_clause);
5774 } else {
5775 std::string Values;
5776 std::string Sep(", ");
5777 unsigned AllowedCnt = 0;
5778 unsigned TotalAllowedNum =
5779 AllowedNameModifiers.size() - NamedModifiersNumber;
5780 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5781 ++Cnt) {
5782 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5783 if (!FoundNameModifiers[NM]) {
5784 Values += "'";
5785 Values += getOpenMPDirectiveName(NM, OMPVersion);
5786 Values += "'";
5787 if (AllowedCnt + 2 == TotalAllowedNum)
5788 Values += " or ";
5789 else if (AllowedCnt + 1 != TotalAllowedNum)
5790 Values += Sep;
5791 ++AllowedCnt;
5792 }
5793 }
5794 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5795 diag::err_omp_unnamed_if_clause)
5796 << (TotalAllowedNum > 1) << Values;
5797 }
5798 for (SourceLocation Loc : NameModifierLoc) {
5799 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5800 }
5801 ErrorFound = true;
5802 }
5803 return ErrorFound;
5804}
5805
5806static std::pair<ValueDecl *, bool>
5808 SourceRange &ERange, bool AllowArraySection,
5809 bool AllowAssumedSizeArray, StringRef DiagType) {
5810 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5812 return std::make_pair(nullptr, true);
5813
5814 // OpenMP [3.1, C/C++]
5815 // A list item is a variable name.
5816 // OpenMP [2.9.3.3, Restrictions, p.1]
5817 // A variable that is part of another variable (as an array or
5818 // structure element) cannot appear in a private clause.
5819 //
5820 // OpenMP [6.0]
5821 // 5.2.5 Array Sections, p. 166, L28-29
5822 // When the length is absent and the size of the dimension is not known,
5823 // the array section is an assumed-size array.
5824 // 2 Glossary, p. 23, L4-6
5825 // assumed-size array
5826 // For C/C++, an array section for which the length is absent and the
5827 // size of the dimensions is not known.
5828 // 5.2.5 Array Sections, p. 168, L11
5829 // An assumed-size array can appear only in clauses for which it is
5830 // explicitly allowed.
5831 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5832 // Assumed-size arrays must not be privatized.
5833 RefExpr = RefExpr->IgnoreParens();
5834 enum {
5835 NoArrayExpr = -1,
5836 ArraySubscript = 0,
5837 OMPArraySection = 1
5838 } IsArrayExpr = NoArrayExpr;
5839 if (AllowArraySection) {
5840 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5841 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5842 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5843 Base = TempASE->getBase()->IgnoreParenImpCasts();
5844 RefExpr = Base;
5845 IsArrayExpr = ArraySubscript;
5846 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5847 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5848 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5849 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5851 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5852 !BaseType->isVariableArrayType())) {
5853 S.Diag(OASE->getColonLocFirst(),
5854 diag::err_omp_section_length_undefined)
5855 << (!BaseType.isNull() && BaseType->isArrayType());
5856 return std::make_pair(nullptr, false);
5857 }
5858 }
5859 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5860 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5861 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5862 Base = TempASE->getBase()->IgnoreParenImpCasts();
5863 RefExpr = Base;
5864 IsArrayExpr = OMPArraySection;
5865 }
5866 }
5867 ELoc = RefExpr->getExprLoc();
5868 ERange = RefExpr->getSourceRange();
5869 RefExpr = RefExpr->IgnoreParenImpCasts();
5870 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5871 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5872 if ((!DE || !isa<VarDecl, BindingDecl>(DE->getDecl())) &&
5873 (S.getCurrentThisType().isNull() || !ME ||
5874 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5875 !isa<FieldDecl>(ME->getMemberDecl()))) {
5876 if (IsArrayExpr != NoArrayExpr) {
5877 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5878 << IsArrayExpr << ERange;
5879 } else if (!DiagType.empty()) {
5880 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5881 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5882 : 0;
5883 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5884 << DiagSelect << DiagType << ERange;
5885 } else {
5886 S.Diag(ELoc,
5887 AllowArraySection
5888 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5889 : diag::err_omp_expected_var_name_member_expr)
5890 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5891 }
5892 return std::make_pair(nullptr, false);
5893 }
5894 return std::make_pair(
5895 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5896}
5897
5898namespace {
5899/// Checks if the allocator is used in uses_allocators clause to be allowed in
5900/// target regions.
5901class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5902 DSAStackTy *S = nullptr;
5903
5904public:
5905 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5906 return S->isUsesAllocatorsDecl(E->getDecl())
5907 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5908 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5909 }
5910 bool VisitStmt(const Stmt *S) {
5911 for (const Stmt *Child : S->children()) {
5912 if (Child && Visit(Child))
5913 return true;
5914 }
5915 return false;
5916 }
5917 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5918};
5919} // namespace
5920
5921static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5922 ArrayRef<OMPClause *> Clauses) {
5923 assert(!S.CurContext->isDependentContext() &&
5924 "Expected non-dependent context.");
5925 auto AllocateRange =
5926 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5927 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5928 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5929 return isOpenMPPrivate(C->getClauseKind());
5930 });
5931 for (OMPClause *Cl : PrivateRange) {
5933 if (Cl->getClauseKind() == OMPC_private) {
5934 auto *PC = cast<OMPPrivateClause>(Cl);
5935 I = PC->private_copies().begin();
5936 It = PC->varlist_begin();
5937 Et = PC->varlist_end();
5938 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5939 auto *PC = cast<OMPFirstprivateClause>(Cl);
5940 I = PC->private_copies().begin();
5941 It = PC->varlist_begin();
5942 Et = PC->varlist_end();
5943 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5944 auto *PC = cast<OMPLastprivateClause>(Cl);
5945 I = PC->private_copies().begin();
5946 It = PC->varlist_begin();
5947 Et = PC->varlist_end();
5948 } else if (Cl->getClauseKind() == OMPC_linear) {
5949 auto *PC = cast<OMPLinearClause>(Cl);
5950 I = PC->privates().begin();
5951 It = PC->varlist_begin();
5952 Et = PC->varlist_end();
5953 } else if (Cl->getClauseKind() == OMPC_reduction) {
5954 auto *PC = cast<OMPReductionClause>(Cl);
5955 I = PC->privates().begin();
5956 It = PC->varlist_begin();
5957 Et = PC->varlist_end();
5958 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5959 auto *PC = cast<OMPTaskReductionClause>(Cl);
5960 I = PC->privates().begin();
5961 It = PC->varlist_begin();
5962 Et = PC->varlist_end();
5963 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5964 auto *PC = cast<OMPInReductionClause>(Cl);
5965 I = PC->privates().begin();
5966 It = PC->varlist_begin();
5967 Et = PC->varlist_end();
5968 } else {
5969 llvm_unreachable("Expected private clause.");
5970 }
5971 for (Expr *E : llvm::make_range(It, Et)) {
5972 if (!*I) {
5973 ++I;
5974 continue;
5975 }
5976 SourceLocation ELoc;
5977 SourceRange ERange;
5978 Expr *SimpleRefExpr = E;
5979 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5980 /*AllowArraySection=*/true);
5981 DeclToCopy.try_emplace(Res.first,
5982 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5983 ++I;
5984 }
5985 }
5986 for (OMPClause *C : AllocateRange) {
5987 auto *AC = cast<OMPAllocateClause>(C);
5988 if (S.getLangOpts().OpenMP >= 50 &&
5989 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5990 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5991 AC->getAllocator()) {
5992 Expr *Allocator = AC->getAllocator();
5993 // OpenMP, 2.12.5 target Construct
5994 // Memory allocators that do not appear in a uses_allocators clause cannot
5995 // appear as an allocator in an allocate clause or be used in the target
5996 // region unless a requires directive with the dynamic_allocators clause
5997 // is present in the same compilation unit.
5998 AllocatorChecker Checker(Stack);
5999 if (Checker.Visit(Allocator))
6000 S.Diag(Allocator->getExprLoc(),
6001 diag::err_omp_allocator_not_in_uses_allocators)
6002 << Allocator->getSourceRange();
6003 }
6004 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
6005 getAllocatorKind(S, Stack, AC->getAllocator());
6006 // OpenMP, 2.11.4 allocate Clause, Restrictions.
6007 // For task, taskloop or target directives, allocation requests to memory
6008 // allocators with the trait access set to thread result in unspecified
6009 // behavior.
6010 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
6011 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
6012 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
6013 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
6014 S.Diag(AC->getAllocator()->getExprLoc(),
6015 diag::warn_omp_allocate_thread_on_task_target_directive)
6016 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
6017 }
6018 for (Expr *E : AC->varlist()) {
6019 SourceLocation ELoc;
6020 SourceRange ERange;
6021 Expr *SimpleRefExpr = E;
6022 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
6023 ValueDecl *VD = Res.first;
6024 if (!VD)
6025 continue;
6026 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
6027 if (!isOpenMPPrivate(Data.CKind)) {
6028 S.Diag(E->getExprLoc(),
6029 diag::err_omp_expected_private_copy_for_allocate);
6030 continue;
6031 }
6032 VarDecl *PrivateVD = DeclToCopy[VD];
6033 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
6034 AllocatorKind, AC->getAllocator()))
6035 continue;
6036 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
6037 AC->getAlignment(), E->getSourceRange());
6038 }
6039 }
6040}
6041
6042namespace {
6043/// Rewrite statements and expressions for Sema \p Actions CurContext.
6044///
6045/// Used to wrap already parsed statements/expressions into a new CapturedStmt
6046/// context. DeclRefExpr used inside the new context are changed to refer to the
6047/// captured variable instead.
6048class CaptureVars : public TreeTransform<CaptureVars> {
6049 using BaseTransform = TreeTransform<CaptureVars>;
6050
6051public:
6052 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
6053
6054 bool AlwaysRebuild() { return true; }
6055};
6056} // namespace
6057
6058/// Like ASTContext::getIntTypeForBitwidth, but falls back to a _BitInt type
6059/// when no standard integer type has the requested width.
6061 bool Signed) {
6062 QualType Ty = C.getIntTypeForBitwidth(Bits, Signed);
6063 if (Ty.isNull())
6064 Ty = C.getBitIntType(/*IsUnsigned=*/!Signed, Bits);
6065 return Ty;
6066}
6067
6068static Expr *buildInitListValue(Sema &SemaRef, Expr *E) {
6069 auto *ILE = dyn_cast<InitListExpr>(E->IgnoreImplicit());
6070 if (!ILE)
6071 return E;
6072 if (ILE->isTransparent())
6073 return buildInitListValue(SemaRef, ILE->getInit(0));
6074 QualType Ty = ILE->getType();
6075 bool IsEmptyScalar = ILE->getNumInits() == 0 && Ty->isScalarType();
6076 SourceLocation LBrace = ILE->getLBraceLoc();
6077 if (!SemaRef.getLangOpts().CPlusPlus) {
6078 if (!IsEmptyScalar)
6079 return E;
6081 SemaRef.ActOnIntegerConstant(LBrace, 0).get(), Ty,
6083 return Zero.isUsable() ? Zero.get() : E;
6084 }
6085 Expr *Syntactic = ILE->getSyntacticForm();
6086 if ((!IsEmptyScalar && !Ty->isRecordType()) || !Syntactic)
6087 return E;
6088 Sema::TentativeAnalysisScope Trap(SemaRef);
6090 SemaRef.Context.getTrivialTypeSourceInfo(Ty, LBrace), LBrace, Syntactic,
6091 ILE->getRBraceLoc(), /*ListInitialization=*/true);
6092 return Value.isUsable() ? Value.get() : E;
6093}
6094
6095static VarDecl *precomputeExpr(Sema &Actions,
6096 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
6097 StringRef Name) {
6098 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
6099 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
6100 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
6101 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
6102 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
6103 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
6104 BodyStmts.push_back(NewDeclStmt);
6105 return NewVar;
6106}
6107
6108/// Create a closure that computes the number of iterations of a loop.
6109///
6110/// \param Actions The Sema object.
6111/// \param LogicalTy Type for the logical iteration number.
6112/// \param Rel Comparison operator of the loop condition.
6113/// \param StartExpr Value of the loop counter at the first iteration.
6114/// \param StopExpr Expression the loop counter is compared against in the loop
6115/// condition. \param StepExpr Amount of increment after each iteration.
6116///
6117/// \return Closure (CapturedStmt) of the distance calculation.
6118static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
6120 Expr *StartExpr, Expr *StopExpr,
6121 Expr *StepExpr) {
6122 ASTContext &Ctx = Actions.getASTContext();
6123 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
6124
6125 // Captured regions currently don't support return values, we use an
6126 // out-parameter instead. All inputs are implicit captures.
6127 // TODO: Instead of capturing each DeclRefExpr occurring in
6128 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
6129 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
6130 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
6131 {StringRef(), QualType()}};
6132 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
6133
6134 Stmt *Body;
6135 {
6136 Sema::CompoundScopeRAII CompoundScope(Actions);
6138
6139 // Get the LValue expression for the result.
6140 ImplicitParamDecl *DistParam = CS->getParam(0);
6141 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
6142 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
6143
6144 SmallVector<Stmt *, 4> BodyStmts;
6145
6146 // Capture all referenced variable references.
6147 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
6148 // CapturedStmt, we could compute them before and capture the result, to be
6149 // used jointly with the LoopVar function.
6150 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
6151 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
6152 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
6153 auto BuildVarRef = [&](VarDecl *VD) {
6154 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
6155 };
6156
6158 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
6160 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
6161 Expr *Dist;
6162 if (Rel == BO_NE) {
6163 // When using a != comparison, the increment can be +1 or -1. This can be
6164 // dynamic at runtime, so we need to check for the direction.
6165 Expr *IsNegStep = AssertSuccess(
6166 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
6167
6168 // Positive increment.
6169 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
6170 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
6171 ForwardRange = AssertSuccess(
6172 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
6173 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
6174 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
6175
6176 // Negative increment.
6177 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
6178 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
6179 BackwardRange = AssertSuccess(
6180 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
6181 Expr *NegIncAmount = AssertSuccess(
6182 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
6183 Expr *BackwardDist = AssertSuccess(
6184 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
6185
6186 // Use the appropriate case.
6187 Dist = AssertSuccess(Actions.ActOnConditionalOp(
6188 {}, {}, IsNegStep, BackwardDist, ForwardDist));
6189 } else {
6190 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
6191 "Expected one of these relational operators");
6192
6193 // We can derive the direction from any other comparison operator. It is
6194 // non well-formed OpenMP if Step increments/decrements in the other
6195 // directions. Whether at least the first iteration passes the loop
6196 // condition.
6197 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
6198 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
6199
6200 // Compute the range between first and last counter value.
6201 Expr *Range;
6202 if (Rel == BO_GE || Rel == BO_GT)
6203 Range = AssertSuccess(Actions.BuildBinOp(
6204 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
6205 else
6206 Range = AssertSuccess(Actions.BuildBinOp(
6207 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
6208
6209 // Ensure unsigned range space.
6210 Range =
6211 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
6212
6213 if (Rel == BO_LE || Rel == BO_GE) {
6214 // Add one to the range if the relational operator is inclusive.
6215 Range =
6216 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
6217 }
6218
6219 // Divide by the absolute step amount. If the range is not a multiple of
6220 // the step size, rounding-up the effective upper bound ensures that the
6221 // last iteration is included.
6222 // Note that the rounding-up may cause an overflow in a temporary that
6223 // could be avoided, but would have occurred in a C-style for-loop as
6224 // well.
6225 Expr *Divisor = BuildVarRef(NewStep);
6226 if (Rel == BO_GE || Rel == BO_GT)
6227 Divisor =
6228 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
6229 Expr *DivisorMinusOne =
6230 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
6231 Expr *RangeRoundUp = AssertSuccess(
6232 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
6233 Dist = AssertSuccess(
6234 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
6235
6236 // If there is not at least one iteration, the range contains garbage. Fix
6237 // to zero in this case.
6238 Dist = AssertSuccess(
6239 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
6240 }
6241
6242 // Assign the result to the out-parameter.
6243 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
6244 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
6245 BodyStmts.push_back(ResultAssign);
6246
6247 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
6248 }
6249
6250 return cast<CapturedStmt>(
6251 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
6252}
6253
6254/// Create a closure that computes the loop variable from the logical iteration
6255/// number.
6256///
6257/// \param Actions The Sema object.
6258/// \param LoopVarTy Type for the loop variable used for result value.
6259/// \param LogicalTy Type for the logical iteration number.
6260/// \param StartExpr Value of the loop counter at the first iteration.
6261/// \param Step Amount of increment after each iteration.
6262/// \param Deref Whether the loop variable is a dereference of the loop
6263/// counter variable.
6264///
6265/// \return Closure (CapturedStmt) of the loop value calculation.
6266static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
6267 QualType LogicalTy,
6268 DeclRefExpr *StartExpr, Expr *Step,
6269 bool Deref) {
6270 ASTContext &Ctx = Actions.getASTContext();
6271
6272 // Pass the result as an out-parameter. Passing as return value would require
6273 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
6274 // invoke a copy constructor.
6275 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
6276 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
6277 {"Logical", LogicalTy},
6278 {StringRef(), QualType()}};
6279 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
6280
6281 // Capture the initial iterator which represents the LoopVar value at the
6282 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
6283 // it in every iteration, capture it by value before it is modified.
6284 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
6285 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
6287 (void)Invalid;
6288 assert(!Invalid && "Expecting capture-by-value to work.");
6289
6290 Expr *Body;
6291 {
6292 Sema::CompoundScopeRAII CompoundScope(Actions);
6293 auto *CS = cast<CapturedDecl>(Actions.CurContext);
6294
6295 ImplicitParamDecl *TargetParam = CS->getParam(0);
6296 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
6297 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
6298 ImplicitParamDecl *IndvarParam = CS->getParam(1);
6299 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
6300 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
6301
6302 // Capture the Start expression.
6303 CaptureVars Recap(Actions);
6304 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
6305 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
6306
6308 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
6309 // TODO: Explicitly cast to the iterator's difference_type instead of
6310 // relying on implicit conversion.
6311 Expr *Advanced =
6312 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
6313
6314 if (Deref) {
6315 // For range-based for-loops convert the loop counter value to a concrete
6316 // loop variable value by dereferencing the iterator.
6317 Advanced =
6318 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
6319 }
6320
6321 // Assign the result to the output parameter.
6322 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
6323 BO_Assign, TargetRef, Advanced));
6324 }
6325 return cast<CapturedStmt>(
6326 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
6327}
6328
6330 ASTContext &Ctx = getASTContext();
6331
6332 // Extract the common elements of ForStmt and CXXForRangeStmt:
6333 // Loop variable, repeat condition, increment
6334 Expr *Cond, *Inc;
6335 VarDecl *LIVDecl, *LUVDecl;
6336 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
6337 Stmt *Init = For->getInit();
6338 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
6339 // For statement declares loop variable.
6340 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
6341 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
6342 // For statement reuses variable.
6343 assert(LCAssign->getOpcode() == BO_Assign &&
6344 "init part must be a loop variable assignment");
6345 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
6346 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
6347 } else
6348 llvm_unreachable("Cannot determine loop variable");
6349 LUVDecl = LIVDecl;
6350
6351 Cond = For->getCond();
6352 Inc = For->getInc();
6353 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
6354 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
6355 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
6356 LUVDecl = RangeFor->getLoopVariable();
6357
6358 Cond = RangeFor->getCond();
6359 Inc = RangeFor->getInc();
6360 } else
6361 llvm_unreachable("unhandled kind of loop");
6362
6363 QualType CounterTy = LIVDecl->getType();
6364 QualType LVTy = LUVDecl->getType();
6365
6366 // Analyze the loop condition.
6367 Expr *LHS, *RHS;
6368 BinaryOperator::Opcode CondRel;
6369 Cond = Cond->IgnoreImplicit();
6370 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
6371 LHS = CondBinExpr->getLHS();
6372 RHS = CondBinExpr->getRHS();
6373 CondRel = CondBinExpr->getOpcode();
6374 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
6375 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
6376 LHS = CondCXXOp->getArg(0);
6377 RHS = CondCXXOp->getArg(1);
6378 switch (CondCXXOp->getOperator()) {
6379 case OO_ExclaimEqual:
6380 CondRel = BO_NE;
6381 break;
6382 case OO_Less:
6383 CondRel = BO_LT;
6384 break;
6385 case OO_LessEqual:
6386 CondRel = BO_LE;
6387 break;
6388 case OO_Greater:
6389 CondRel = BO_GT;
6390 break;
6391 case OO_GreaterEqual:
6392 CondRel = BO_GE;
6393 break;
6394 default:
6395 llvm_unreachable("unexpected iterator operator");
6396 }
6397 } else
6398 llvm_unreachable("unexpected loop condition");
6399
6400 // Normalize such that the loop counter is on the LHS.
6401 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
6402 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
6403 std::swap(LHS, RHS);
6404 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
6405 }
6406 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
6407
6408 // Decide the bit width for the logical iteration counter. By default use the
6409 // unsigned ptrdiff_t integer size (for iterators and pointers).
6410 // TODO: For iterators, use iterator::difference_type,
6411 // std::iterator_traits<>::difference_type or decltype(it - end).
6412 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
6413 if (CounterTy->isIntegerType()) {
6414 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
6415 LogicalTy = getIntTypeForBitwidthOrBitInt(Ctx, BitWidth, /*Signed=*/false);
6416 }
6417
6418 // Analyze the loop increment.
6419 Expr *Step;
6420 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
6421 int Direction;
6422 switch (IncUn->getOpcode()) {
6423 case UO_PreInc:
6424 case UO_PostInc:
6425 Direction = 1;
6426 break;
6427 case UO_PreDec:
6428 case UO_PostDec:
6429 Direction = -1;
6430 break;
6431 default:
6432 llvm_unreachable("unhandled unary increment operator");
6433 }
6435 Ctx,
6436 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
6437 LogicalTy, {});
6438 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
6439 Expr *IncRHS = buildInitListValue(SemaRef, IncBin->getRHS());
6440 if (IncBin->getOpcode() == BO_AddAssign) {
6441 Step = IncRHS;
6442 } else if (IncBin->getOpcode() == BO_SubAssign) {
6443 Step = AssertSuccess(SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncRHS));
6444 } else
6445 llvm_unreachable("unhandled binary increment operator");
6446 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
6447 switch (CondCXXOp->getOperator()) {
6448 case OO_PlusPlus:
6450 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
6451 break;
6452 case OO_MinusMinus:
6454 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
6455 break;
6456 case OO_PlusEqual:
6457 Step = buildInitListValue(SemaRef, CondCXXOp->getArg(1));
6458 break;
6459 case OO_MinusEqual:
6460 Step = AssertSuccess(SemaRef.BuildUnaryOp(
6461 nullptr, {}, UO_Minus,
6462 buildInitListValue(SemaRef, CondCXXOp->getArg(1))));
6463 break;
6464 default:
6465 llvm_unreachable("unhandled overloaded increment operator");
6466 }
6467 } else
6468 llvm_unreachable("unknown increment expression");
6469
6470 CapturedStmt *DistanceFunc =
6471 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
6472 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
6473 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
6474 DeclRefExpr *LVRef =
6475 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
6476 nullptr, nullptr, {}, nullptr);
6477 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
6478 LoopVarFunc, LVRef);
6479}
6480
6482 // Handle a literal loop.
6483 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
6484 return ActOnOpenMPCanonicalLoop(AStmt);
6485
6486 // If not a literal loop, it must be the result of a loop transformation.
6488 assert(
6489 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
6490 "Loop transformation directive expected");
6491 return LoopTransform;
6492}
6493
6495 CXXScopeSpec &MapperIdScopeSpec,
6496 const DeclarationNameInfo &MapperId,
6497 QualType Type,
6498 Expr *UnresolvedMapper,
6499 SourceLocation ItemLoc);
6500
6501/// Perform DFS through the structure/class data members trying to find
6502/// member(s) with user-defined 'default' mapper and generate implicit map
6503/// clauses for such members with the found 'default' mapper.
6504static void
6507 // Check for the default mapper for data members.
6508 if (S.getLangOpts().OpenMP < 50)
6509 return;
6510 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6511 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6512 if (!C)
6513 continue;
6514 SmallVector<Expr *, 4> SubExprs;
6515 auto *MI = C->mapperlist_begin();
6516 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6517 ++I, ++MI) {
6518 // Expression is mapped using mapper - skip it.
6519 if (*MI)
6520 continue;
6521 Expr *E = *I;
6522 // Expression is dependent - skip it, build the mapper when it gets
6523 // instantiated.
6524 if (E->isTypeDependent() || E->isValueDependent() ||
6526 continue;
6527 // Array section - need to check for the mapping of the array section
6528 // element.
6529 QualType CanonType = E->getType().getCanonicalType();
6530 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
6531 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
6532 QualType BaseType =
6534 QualType ElemType;
6535 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6536 ElemType = ATy->getElementType();
6537 else
6538 ElemType = BaseType->getPointeeType();
6539 CanonType = ElemType;
6540 }
6541
6542 // DFS over data members in structures/classes.
6544 1, {CanonType, nullptr});
6545 llvm::DenseMap<const Type *, Expr *> Visited;
6547 1, {nullptr, 1});
6548 while (!Types.empty()) {
6549 QualType BaseType;
6550 FieldDecl *CurFD;
6551 std::tie(BaseType, CurFD) = Types.pop_back_val();
6552 while (ParentChain.back().second == 0)
6553 ParentChain.pop_back();
6554 --ParentChain.back().second;
6555 if (BaseType.isNull())
6556 continue;
6557 // Only structs/classes are allowed to have mappers.
6558 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6559 if (!RD)
6560 continue;
6561 auto It = Visited.find(BaseType.getTypePtr());
6562 if (It == Visited.end()) {
6563 // Try to find the associated user-defined mapper.
6564 CXXScopeSpec MapperIdScopeSpec;
6565 DeclarationNameInfo DefaultMapperId;
6567 &S.Context.Idents.get("default")));
6568 DefaultMapperId.setLoc(E->getExprLoc());
6570 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6571 BaseType, /*UnresolvedMapper=*/nullptr, E->getExprLoc());
6572 if (ER.isInvalid())
6573 continue;
6574 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6575 }
6576 // Found default mapper.
6577 if (It->second) {
6578 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6580 OE->setIsUnique(/*V=*/true);
6581 Expr *BaseExpr = OE;
6582 for (const auto &P : ParentChain) {
6583 if (P.first) {
6584 BaseExpr = S.BuildMemberExpr(
6585 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6587 DeclAccessPair::make(P.first, P.first->getAccess()),
6588 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6589 P.first->getType(), VK_LValue, OK_Ordinary);
6590 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6591 }
6592 }
6593 if (CurFD)
6594 BaseExpr = S.BuildMemberExpr(
6595 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6597 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6598 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6599 CurFD->getType(), VK_LValue, OK_Ordinary);
6600 SubExprs.push_back(BaseExpr);
6601 continue;
6602 }
6603 // Check for the "default" mapper for data members.
6604 bool FirstIter = true;
6605 for (FieldDecl *FD : RD->fields()) {
6606 if (!FD)
6607 continue;
6608 QualType FieldTy = FD->getType();
6609 if (FieldTy.isNull() ||
6610 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6611 continue;
6612 if (FirstIter) {
6613 FirstIter = false;
6614 ParentChain.emplace_back(CurFD, 1);
6615 } else {
6616 ++ParentChain.back().second;
6617 }
6618 Types.emplace_back(FieldTy, FD);
6619 }
6620 }
6621 }
6622 if (SubExprs.empty())
6623 continue;
6624 CXXScopeSpec MapperIdScopeSpec;
6625 DeclarationNameInfo MapperId;
6626 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6627 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6628 MapperIdScopeSpec, MapperId, C->getMapType(),
6629 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6630 SubExprs, OMPVarListLocTy()))
6631 Clauses.push_back(NewClause);
6632 }
6633}
6634
6635namespace {
6636/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6637/// call in the associated loop-nest cannot be a 'parallel for'.
6638class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6639 Sema &SemaRef;
6640
6641public:
6642 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6643
6644 // Is there a nested OpenMP loop bind(parallel)
6645 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6646 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6647 if (const auto *C = D->getSingleClause<OMPBindClause>())
6648 if (C->getBindKind() == OMPC_BIND_parallel) {
6649 TeamsLoopCanBeParallelFor = false;
6650 // No need to continue visiting any more
6651 return;
6652 }
6653 }
6654 for (const Stmt *Child : D->children())
6655 if (Child)
6656 Visit(Child);
6657 }
6658
6659 void VisitCallExpr(const CallExpr *C) {
6660 // Function calls inhibit parallel loop translation of 'target teams loop'
6661 // unless the assume-no-nested-parallelism flag has been specified.
6662 // OpenMP API runtime library calls do not inhibit parallel loop
6663 // translation, regardless of the assume-no-nested-parallelism.
6664 bool IsOpenMPAPI = false;
6665 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6666 if (FD) {
6667 std::string Name = FD->getNameInfo().getAsString();
6668 IsOpenMPAPI = Name.find("omp_") == 0;
6669 }
6670 TeamsLoopCanBeParallelFor =
6671 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6672 if (!TeamsLoopCanBeParallelFor)
6673 return;
6674
6675 for (const Stmt *Child : C->children())
6676 if (Child)
6677 Visit(Child);
6678 }
6679
6680 void VisitCapturedStmt(const CapturedStmt *S) {
6681 if (!S)
6682 return;
6683 Visit(S->getCapturedDecl()->getBody());
6684 }
6685
6686 void VisitStmt(const Stmt *S) {
6687 if (!S)
6688 return;
6689 for (const Stmt *Child : S->children())
6690 if (Child)
6691 Visit(Child);
6692 }
6693 explicit TeamsLoopChecker(Sema &SemaRef)
6694 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6695
6696private:
6697 bool TeamsLoopCanBeParallelFor;
6698};
6699} // namespace
6700
6701static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6702 TeamsLoopChecker Checker(SemaRef);
6703 Checker.Visit(AStmt);
6704 return Checker.teamsLoopCanBeParallelFor();
6705}
6706
6708 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6709 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6710 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6711 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6712
6713 StmtResult Res = StmtError();
6715 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6716
6717 if (const OMPBindClause *BC =
6718 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6719 BindKind = BC->getBindKind();
6720
6721 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6722 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6723
6724 // Setting the enclosing teams or parallel construct for the loop
6725 // directive without bind clause.
6726 // [5.0:129:25-28] If the bind clause is not present on the construct and
6727 // the loop construct is closely nested inside a teams or parallel
6728 // construct, the binding region is the corresponding teams or parallel
6729 // region. If none of those conditions hold, the binding region is not
6730 // defined.
6731 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6732 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6733 getLeafConstructsOrSelf(ParentDirective);
6734
6735 if (ParentDirective == OMPD_unknown) {
6736 Diag(DSAStack->getDefaultDSALocation(),
6737 diag::err_omp_bind_required_on_loop);
6738 } else if (ParentLeafs.back() == OMPD_parallel) {
6739 BindKind = OMPC_BIND_parallel;
6740 } else if (ParentLeafs.back() == OMPD_teams) {
6741 BindKind = OMPC_BIND_teams;
6742 }
6743
6744 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6745
6746 OMPClause *C =
6749 ClausesWithImplicit.push_back(C);
6750 }
6751
6752 // Diagnose "loop bind(teams)" with "reduction".
6753 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6754 for (OMPClause *C : Clauses) {
6755 if (C->getClauseKind() == OMPC_reduction)
6756 Diag(DSAStack->getDefaultDSALocation(),
6757 diag::err_omp_loop_reduction_clause);
6758 }
6759 }
6760
6761 // First check CancelRegion which is then used in checkNestingOfRegions.
6762 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6763 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6764 BindKind, StartLoc)) {
6765 return StmtError();
6766 }
6767
6768 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6771 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6772
6773 VarsWithInheritedDSAType VarsWithInheritedDSA;
6774 bool ErrorFound = false;
6775 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6776
6777 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6779 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6780
6781 // Check default data sharing attributes for referenced variables.
6782 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6783 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6784 Stmt *S = AStmt;
6785 while (--ThisCaptureLevel >= 0)
6786 S = cast<CapturedStmt>(S)->getCapturedStmt();
6787 DSAChecker.Visit(S);
6789 !isOpenMPTaskingDirective(Kind)) {
6790 // Visit subcaptures to generate implicit clauses for captured vars.
6791 auto *CS = cast<CapturedStmt>(AStmt);
6793 getOpenMPCaptureRegions(CaptureRegions, Kind);
6794 // Ignore outer tasking regions for target directives.
6795 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6797 DSAChecker.visitSubCaptures(CS);
6798 }
6799 if (DSAChecker.isErrorFound())
6800 return StmtError();
6801 // Generate list of implicitly defined firstprivate variables.
6802 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6803 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6804
6806 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6807 // Get the original location of present modifier from Defaultmap clause.
6808 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6809 for (OMPClause *C : Clauses) {
6810 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6811 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6812 PresentModifierLocs[DMC->getDefaultmapKind()] =
6813 DMC->getDefaultmapModifierLoc();
6814 }
6815
6817 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6819 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6820 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6821 }
6822 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6823 for (OMPClause *C : Clauses) {
6824 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6825 for (Expr *E : IRC->taskgroup_descriptors())
6826 if (E)
6827 ImpInfo.Firstprivates.insert(E);
6828 }
6829 // OpenMP 5.0, 2.10.1 task Construct
6830 // [detach clause]... The event-handle will be considered as if it was
6831 // specified on a firstprivate clause.
6832 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6833 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6834 }
6835 if (!ImpInfo.Firstprivates.empty()) {
6837 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6839 ClausesWithImplicit.push_back(Implicit);
6840 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6841 ImpInfo.Firstprivates.size();
6842 } else {
6843 ErrorFound = true;
6844 }
6845 }
6846 if (!ImpInfo.Privates.empty()) {
6848 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6850 ClausesWithImplicit.push_back(Implicit);
6851 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6852 ImpInfo.Privates.size();
6853 } else {
6854 ErrorFound = true;
6855 }
6856 }
6857 // OpenMP 5.0 [2.19.7]
6858 // If a list item appears in a reduction, lastprivate or linear
6859 // clause on a combined target construct then it is treated as
6860 // if it also appears in a map clause with a map-type of tofrom
6861 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6863 SmallVector<Expr *, 4> ImplicitExprs;
6864 for (OMPClause *C : Clauses) {
6865 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6866 for (Expr *E : RC->varlist())
6868 ImplicitExprs.emplace_back(E);
6869 }
6870 if (!ImplicitExprs.empty()) {
6871 ArrayRef<Expr *> Exprs = ImplicitExprs;
6872 CXXScopeSpec MapperIdScopeSpec;
6873 DeclarationNameInfo MapperId;
6876 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6877 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6878 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6879 ClausesWithImplicit.emplace_back(Implicit);
6880 }
6881 }
6882 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6883 int ClauseKindCnt = -1;
6884 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6885 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6886 ++ClauseKindCnt;
6887 if (ImplicitMap.empty())
6888 continue;
6889 CXXScopeSpec MapperIdScopeSpec;
6890 DeclarationNameInfo MapperId;
6891 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6893 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6894 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6895 SourceLocation(), SourceLocation(), ImplicitMap,
6896 OMPVarListLocTy())) {
6897 ClausesWithImplicit.emplace_back(Implicit);
6898 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6899 ImplicitMap.size();
6900 } else {
6901 ErrorFound = true;
6902 }
6903 }
6904 }
6905 // Build expressions for implicit maps of data members with 'default'
6906 // mappers.
6907 if (getLangOpts().OpenMP >= 50)
6909 ClausesWithImplicit);
6910 }
6911
6912 switch (Kind) {
6913 case OMPD_parallel:
6914 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6915 EndLoc);
6916 break;
6917 case OMPD_simd:
6918 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6919 VarsWithInheritedDSA);
6920 break;
6921 case OMPD_tile:
6922 Res =
6923 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6924 break;
6925 case OMPD_stripe:
6926 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6927 EndLoc);
6928 break;
6929 case OMPD_unroll:
6930 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6931 EndLoc);
6932 break;
6933 case OMPD_reverse:
6934 assert(ClausesWithImplicit.empty() &&
6935 "reverse directive does not support any clauses");
6936 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6937 break;
6938 case OMPD_split:
6939 Res =
6940 ActOnOpenMPSplitDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6941 break;
6942 case OMPD_interchange:
6943 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6944 EndLoc);
6945 break;
6946 case OMPD_flatten:
6947 Res = ActOnOpenMPFlattenDirective(ClausesWithImplicit, AStmt, StartLoc,
6948 EndLoc);
6949 break;
6950 case OMPD_fuse:
6951 Res =
6952 ActOnOpenMPFuseDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6953 break;
6954 case OMPD_for:
6955 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6956 VarsWithInheritedDSA);
6957 break;
6958 case OMPD_for_simd:
6959 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6960 EndLoc, VarsWithInheritedDSA);
6961 break;
6962 case OMPD_sections:
6963 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6964 EndLoc);
6965 break;
6966 case OMPD_section:
6967 assert(ClausesWithImplicit.empty() &&
6968 "No clauses are allowed for 'omp section' directive");
6969 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6970 break;
6971 case OMPD_single:
6972 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6973 EndLoc);
6974 break;
6975 case OMPD_master:
6976 assert(ClausesWithImplicit.empty() &&
6977 "No clauses are allowed for 'omp master' directive");
6978 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6979 break;
6980 case OMPD_masked:
6981 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6982 EndLoc);
6983 break;
6984 case OMPD_critical:
6985 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6986 StartLoc, EndLoc);
6987 break;
6988 case OMPD_parallel_for:
6989 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6990 EndLoc, VarsWithInheritedDSA);
6991 break;
6992 case OMPD_parallel_for_simd:
6994 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6995 break;
6996 case OMPD_scope:
6997 Res =
6998 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6999 break;
7000 case OMPD_parallel_master:
7001 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
7002 StartLoc, EndLoc);
7003 break;
7004 case OMPD_parallel_masked:
7005 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
7006 StartLoc, EndLoc);
7007 break;
7008 case OMPD_parallel_sections:
7009 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
7010 StartLoc, EndLoc);
7011 break;
7012 case OMPD_task:
7013 Res =
7014 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
7015 break;
7016 case OMPD_taskyield:
7017 assert(ClausesWithImplicit.empty() &&
7018 "No clauses are allowed for 'omp taskyield' directive");
7019 assert(AStmt == nullptr &&
7020 "No associated statement allowed for 'omp taskyield' directive");
7021 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
7022 break;
7023 case OMPD_error:
7024 assert(AStmt == nullptr &&
7025 "No associated statement allowed for 'omp error' directive");
7026 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
7027 break;
7028 case OMPD_barrier:
7029 assert(ClausesWithImplicit.empty() &&
7030 "No clauses are allowed for 'omp barrier' directive");
7031 assert(AStmt == nullptr &&
7032 "No associated statement allowed for 'omp barrier' directive");
7033 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
7034 break;
7035 case OMPD_taskwait:
7036 assert(AStmt == nullptr &&
7037 "No associated statement allowed for 'omp taskwait' directive");
7038 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
7039 break;
7040 case OMPD_taskgroup:
7041 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
7042 EndLoc);
7043 break;
7044 case OMPD_flush:
7045 assert(AStmt == nullptr &&
7046 "No associated statement allowed for 'omp flush' directive");
7047 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
7048 break;
7049 case OMPD_depobj:
7050 assert(AStmt == nullptr &&
7051 "No associated statement allowed for 'omp depobj' directive");
7052 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
7053 break;
7054 case OMPD_scan:
7055 assert(AStmt == nullptr &&
7056 "No associated statement allowed for 'omp scan' directive");
7057 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
7058 break;
7059 case OMPD_ordered_blockassoc:
7060 case OMPD_ordered_standalone:
7061 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
7062 EndLoc);
7063 break;
7064 case OMPD_atomic:
7065 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
7066 EndLoc);
7067 break;
7068 case OMPD_teams:
7069 Res =
7070 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
7071 break;
7072 case OMPD_target:
7073 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
7074 EndLoc);
7075 break;
7076 case OMPD_target_parallel:
7077 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
7078 StartLoc, EndLoc);
7079 break;
7080 case OMPD_target_parallel_for:
7082 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7083 break;
7084 case OMPD_cancellation_point:
7085 assert(ClausesWithImplicit.empty() &&
7086 "No clauses are allowed for 'omp cancellation point' directive");
7087 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
7088 "cancellation point' directive");
7089 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
7090 break;
7091 case OMPD_cancel:
7092 assert(AStmt == nullptr &&
7093 "No associated statement allowed for 'omp cancel' directive");
7094 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
7095 CancelRegion);
7096 break;
7097 case OMPD_target_data:
7098 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
7099 EndLoc);
7100 break;
7101 case OMPD_target_enter_data:
7102 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
7103 EndLoc, AStmt);
7104 break;
7105 case OMPD_target_exit_data:
7106 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
7107 EndLoc, AStmt);
7108 break;
7109 case OMPD_taskloop:
7110 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
7111 EndLoc, VarsWithInheritedDSA);
7112 break;
7113 case OMPD_taskloop_simd:
7114 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
7115 EndLoc, VarsWithInheritedDSA);
7116 break;
7117 case OMPD_master_taskloop:
7119 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7120 break;
7121 case OMPD_masked_taskloop:
7123 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7124 break;
7125 case OMPD_master_taskloop_simd:
7127 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7128 break;
7129 case OMPD_masked_taskloop_simd:
7131 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7132 break;
7133 case OMPD_parallel_master_taskloop:
7135 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7136 break;
7137 case OMPD_parallel_masked_taskloop:
7139 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7140 break;
7141 case OMPD_parallel_master_taskloop_simd:
7143 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7144 break;
7145 case OMPD_parallel_masked_taskloop_simd:
7147 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7148 break;
7149 case OMPD_distribute:
7150 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
7151 EndLoc, VarsWithInheritedDSA);
7152 break;
7153 case OMPD_target_update:
7154 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
7155 EndLoc, AStmt);
7156 break;
7157 case OMPD_distribute_parallel_for:
7159 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7160 break;
7161 case OMPD_distribute_parallel_for_simd:
7163 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7164 break;
7165 case OMPD_distribute_simd:
7167 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7168 break;
7169 case OMPD_target_parallel_for_simd:
7171 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7172 break;
7173 case OMPD_target_simd:
7174 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
7175 EndLoc, VarsWithInheritedDSA);
7176 break;
7177 case OMPD_teams_distribute:
7179 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7180 break;
7181 case OMPD_teams_distribute_simd:
7183 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7184 break;
7185 case OMPD_teams_distribute_parallel_for_simd:
7187 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7188 break;
7189 case OMPD_teams_distribute_parallel_for:
7191 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7192 break;
7193 case OMPD_target_teams:
7194 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
7195 EndLoc);
7196 break;
7197 case OMPD_target_teams_distribute:
7199 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7200 break;
7201 case OMPD_target_teams_distribute_parallel_for:
7203 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7204 break;
7205 case OMPD_target_teams_distribute_parallel_for_simd:
7207 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7208 break;
7209 case OMPD_target_teams_distribute_simd:
7211 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7212 break;
7213 case OMPD_interop:
7214 assert(AStmt == nullptr &&
7215 "No associated statement allowed for 'omp interop' directive");
7216 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
7217 break;
7218 case OMPD_dispatch:
7219 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
7220 EndLoc);
7221 break;
7222 case OMPD_loop:
7223 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
7224 EndLoc, VarsWithInheritedDSA);
7225 break;
7226 case OMPD_teams_loop:
7228 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7229 break;
7230 case OMPD_target_teams_loop:
7232 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7233 break;
7234 case OMPD_parallel_loop:
7236 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7237 break;
7238 case OMPD_target_parallel_loop:
7240 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
7241 break;
7242 case OMPD_declare_target:
7243 case OMPD_end_declare_target:
7244 case OMPD_threadprivate:
7245 case OMPD_allocate:
7246 case OMPD_declare_reduction:
7247 case OMPD_declare_mapper:
7248 case OMPD_declare_simd:
7249 case OMPD_requires:
7250 case OMPD_declare_variant:
7251 case OMPD_begin_declare_variant:
7252 case OMPD_end_declare_variant:
7253 llvm_unreachable("OpenMP Directive is not allowed");
7254 case OMPD_taskgraph:
7255 Diag(StartLoc, diag::err_omp_unexpected_directive)
7256 << 1 << getOpenMPDirectiveName(OMPD_taskgraph);
7257 return StmtError();
7258 case OMPD_unknown:
7259 default:
7260 llvm_unreachable("Unknown OpenMP directive");
7261 }
7262
7263 ErrorFound = Res.isInvalid() || ErrorFound;
7264
7265 // Check variables in the clauses if default(none) or
7266 // default(firstprivate) was specified.
7267 if (DSAStack->getDefaultDSA() == DSA_none ||
7268 DSAStack->getDefaultDSA() == DSA_private ||
7269 DSAStack->getDefaultDSA() == DSA_firstprivate) {
7270 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
7271 for (OMPClause *C : Clauses) {
7272 switch (C->getClauseKind()) {
7273 case OMPC_num_threads:
7274 case OMPC_dist_schedule:
7275 // Do not analyze if no parent teams directive.
7276 if (isOpenMPTeamsDirective(Kind))
7277 break;
7278 continue;
7279 case OMPC_if:
7280 if (isOpenMPTeamsDirective(Kind) &&
7281 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
7282 break;
7283 if (isOpenMPParallelDirective(Kind) &&
7285 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
7286 break;
7287 continue;
7288 case OMPC_schedule:
7289 case OMPC_detach:
7290 break;
7291 case OMPC_grainsize:
7292 case OMPC_num_tasks:
7293 case OMPC_final:
7294 case OMPC_priority:
7295 case OMPC_novariants:
7296 case OMPC_nocontext:
7297 // Do not analyze if no parent parallel directive.
7298 if (isOpenMPParallelDirective(Kind))
7299 break;
7300 continue;
7301 case OMPC_ordered:
7302 case OMPC_device:
7303 case OMPC_num_teams:
7304 case OMPC_thread_limit:
7305 case OMPC_hint:
7306 case OMPC_collapse:
7307 case OMPC_safelen:
7308 case OMPC_simdlen:
7309 case OMPC_sizes:
7310 case OMPC_depth:
7311 case OMPC_default:
7312 case OMPC_proc_bind:
7313 case OMPC_private:
7314 case OMPC_firstprivate:
7315 case OMPC_lastprivate:
7316 case OMPC_shared:
7317 case OMPC_reduction:
7318 case OMPC_task_reduction:
7319 case OMPC_in_reduction:
7320 case OMPC_linear:
7321 case OMPC_aligned:
7322 case OMPC_copyin:
7323 case OMPC_copyprivate:
7324 case OMPC_nowait:
7325 case OMPC_untied:
7326 case OMPC_mergeable:
7327 case OMPC_allocate:
7328 case OMPC_read:
7329 case OMPC_write:
7330 case OMPC_update:
7331 case OMPC_capture:
7332 case OMPC_compare:
7333 case OMPC_seq_cst:
7334 case OMPC_acq_rel:
7335 case OMPC_acquire:
7336 case OMPC_release:
7337 case OMPC_relaxed:
7338 case OMPC_depend:
7339 case OMPC_threads:
7340 case OMPC_simd:
7341 case OMPC_map:
7342 case OMPC_nogroup:
7343 case OMPC_defaultmap:
7344 case OMPC_to:
7345 case OMPC_from:
7346 case OMPC_use_device_ptr:
7347 case OMPC_use_device_addr:
7348 case OMPC_is_device_ptr:
7349 case OMPC_has_device_addr:
7350 case OMPC_nontemporal:
7351 case OMPC_order:
7352 case OMPC_destroy:
7353 case OMPC_inclusive:
7354 case OMPC_exclusive:
7355 case OMPC_uses_allocators:
7356 case OMPC_affinity:
7357 case OMPC_bind:
7358 case OMPC_filter:
7359 case OMPC_severity:
7360 case OMPC_message:
7361 continue;
7362 case OMPC_allocator:
7363 case OMPC_flush:
7364 case OMPC_depobj:
7365 case OMPC_threadprivate:
7366 case OMPC_groupprivate:
7367 case OMPC_uniform:
7368 case OMPC_unknown:
7369 case OMPC_unified_address:
7370 case OMPC_unified_shared_memory:
7371 case OMPC_reverse_offload:
7372 case OMPC_dynamic_allocators:
7373 case OMPC_atomic_default_mem_order:
7374 case OMPC_self_maps:
7375 case OMPC_device_type:
7376 case OMPC_match:
7377 case OMPC_when:
7378 case OMPC_at:
7379 default:
7380 llvm_unreachable("Unexpected clause");
7381 }
7382 for (Stmt *CC : C->children()) {
7383 if (CC)
7384 DSAChecker.Visit(CC);
7385 }
7386 }
7387 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
7388 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
7389 }
7390 for (const auto &P : VarsWithInheritedDSA) {
7391 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
7392 continue;
7393 ErrorFound = true;
7394 if (DSAStack->getDefaultDSA() == DSA_none ||
7395 DSAStack->getDefaultDSA() == DSA_private ||
7396 DSAStack->getDefaultDSA() == DSA_firstprivate) {
7397 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
7398 << P.first << P.second->getSourceRange();
7399 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
7400 } else if (getLangOpts().OpenMP >= 50) {
7401 Diag(P.second->getExprLoc(),
7402 diag::err_omp_defaultmap_no_attr_for_variable)
7403 << P.first << P.second->getSourceRange();
7404 Diag(DSAStack->getDefaultDSALocation(),
7405 diag::note_omp_defaultmap_attr_none);
7406 }
7407 }
7408
7409 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
7410 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
7411 if (isAllowedClauseForDirective(D, OMPC_if,
7412 getLangOpts().getOpenMPVersion()))
7413 AllowedNameModifiers.push_back(D);
7414 }
7415 if (!AllowedNameModifiers.empty())
7416 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
7417 ErrorFound;
7418
7419 if (ErrorFound)
7420 return StmtError();
7421
7422 if (!SemaRef.CurContext->isDependentContext() &&
7424 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
7425 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
7426 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
7427 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
7428 // Register target to DSA Stack.
7429 DSAStack->addTargetDirLocation(StartLoc);
7430 }
7431
7432 return Res;
7433}
7434
7436 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
7437 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
7438 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
7439 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
7440 assert(Aligneds.size() == Alignments.size());
7441 assert(Linears.size() == LinModifiers.size());
7442 assert(Linears.size() == Steps.size());
7443 if (!DG || DG.get().isNull())
7444 return DeclGroupPtrTy();
7445
7446 const int SimdId = 0;
7447 if (!DG.get().isSingleDecl()) {
7448 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7449 << SimdId;
7450 return DG;
7451 }
7452 Decl *ADecl = DG.get().getSingleDecl();
7453 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7454 ADecl = FTD->getTemplatedDecl();
7455
7456 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7457 if (!FD) {
7458 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
7459 return DeclGroupPtrTy();
7460 }
7461
7462 // OpenMP [2.8.2, declare simd construct, Description]
7463 // The parameter of the simdlen clause must be a constant positive integer
7464 // expression.
7465 ExprResult SL;
7466 if (Simdlen)
7467 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
7468 // OpenMP [2.8.2, declare simd construct, Description]
7469 // The special this pointer can be used as if was one of the arguments to the
7470 // function in any of the linear, aligned, or uniform clauses.
7471 // The uniform clause declares one or more arguments to have an invariant
7472 // value for all concurrent invocations of the function in the execution of a
7473 // single SIMD loop.
7474 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
7475 const Expr *UniformedLinearThis = nullptr;
7476 for (const Expr *E : Uniforms) {
7477 E = E->IgnoreParenImpCasts();
7478 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7479 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
7480 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7481 FD->getParamDecl(PVD->getFunctionScopeIndex())
7482 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
7483 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
7484 continue;
7485 }
7486 if (isa<CXXThisExpr>(E)) {
7487 UniformedLinearThis = E;
7488 continue;
7489 }
7490 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7491 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7492 }
7493 // OpenMP [2.8.2, declare simd construct, Description]
7494 // The aligned clause declares that the object to which each list item points
7495 // is aligned to the number of bytes expressed in the optional parameter of
7496 // the aligned clause.
7497 // The special this pointer can be used as if was one of the arguments to the
7498 // function in any of the linear, aligned, or uniform clauses.
7499 // The type of list items appearing in the aligned clause must be array,
7500 // pointer, reference to array, or reference to pointer.
7501 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
7502 const Expr *AlignedThis = nullptr;
7503 for (const Expr *E : Aligneds) {
7504 E = E->IgnoreParenImpCasts();
7505 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7506 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7507 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7508 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7509 FD->getParamDecl(PVD->getFunctionScopeIndex())
7510 ->getCanonicalDecl() == CanonPVD) {
7511 // OpenMP [2.8.1, simd construct, Restrictions]
7512 // A list-item cannot appear in more than one aligned clause.
7513 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
7514 if (!Inserted) {
7515 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7516 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
7517 << E->getSourceRange();
7518 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7519 << getOpenMPClauseNameForDiag(OMPC_aligned);
7520 continue;
7521 }
7522 QualType QTy = PVD->getType()
7523 .getNonReferenceType()
7524 .getUnqualifiedType()
7525 .getCanonicalType();
7526 const Type *Ty = QTy.getTypePtrOrNull();
7527 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7528 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7529 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7530 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7531 }
7532 continue;
7533 }
7534 }
7535 if (isa<CXXThisExpr>(E)) {
7536 if (AlignedThis) {
7537 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7538 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
7539 << E->getSourceRange();
7540 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7541 << getOpenMPClauseNameForDiag(OMPC_aligned);
7542 }
7543 AlignedThis = E;
7544 continue;
7545 }
7546 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7547 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7548 }
7549 // The optional parameter of the aligned clause, alignment, must be a constant
7550 // positive integer expression. If no optional parameter is specified,
7551 // implementation-defined default alignments for SIMD instructions on the
7552 // target platforms are assumed.
7554 for (Expr *E : Alignments) {
7555 ExprResult Align;
7556 if (E)
7557 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7558 NewAligns.push_back(Align.get());
7559 }
7560 // OpenMP [2.8.2, declare simd construct, Description]
7561 // The linear clause declares one or more list items to be private to a SIMD
7562 // lane and to have a linear relationship with respect to the iteration space
7563 // of a loop.
7564 // The special this pointer can be used as if was one of the arguments to the
7565 // function in any of the linear, aligned, or uniform clauses.
7566 // When a linear-step expression is specified in a linear clause it must be
7567 // either a constant integer expression or an integer-typed parameter that is
7568 // specified in a uniform clause on the directive.
7569 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7570 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7571 auto MI = LinModifiers.begin();
7572 for (const Expr *E : Linears) {
7573 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7574 ++MI;
7575 E = E->IgnoreParenImpCasts();
7576 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7577 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7578 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7579 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7580 FD->getParamDecl(PVD->getFunctionScopeIndex())
7581 ->getCanonicalDecl() == CanonPVD) {
7582 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7583 // A list-item cannot appear in more than one linear clause.
7584 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7585 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7586 << getOpenMPClauseNameForDiag(OMPC_linear)
7587 << getOpenMPClauseNameForDiag(OMPC_linear)
7588 << E->getSourceRange();
7589 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7590 << getOpenMPClauseNameForDiag(OMPC_linear);
7591 continue;
7592 }
7593 // Each argument can appear in at most one uniform or linear clause.
7594 if (auto It = UniformedArgs.find(CanonPVD);
7595 It != UniformedArgs.end()) {
7596 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7597 << getOpenMPClauseNameForDiag(OMPC_linear)
7598 << getOpenMPClauseNameForDiag(OMPC_uniform)
7599 << E->getSourceRange();
7600 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7601 << getOpenMPClauseNameForDiag(OMPC_uniform);
7602 continue;
7603 }
7604 LinearArgs[CanonPVD] = E;
7605 if (E->isValueDependent() || E->isTypeDependent() ||
7608 continue;
7609 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7610 PVD->getOriginalType(),
7611 /*IsDeclareSimd=*/true);
7612 continue;
7613 }
7614 }
7615 if (isa<CXXThisExpr>(E)) {
7616 if (UniformedLinearThis) {
7617 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7618 << getOpenMPClauseNameForDiag(OMPC_linear)
7619 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7620 : OMPC_linear)
7621 << E->getSourceRange();
7622 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7623 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7624 : OMPC_linear);
7625 continue;
7626 }
7627 UniformedLinearThis = E;
7628 if (E->isValueDependent() || E->isTypeDependent() ||
7630 continue;
7631 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7632 E->getType(), /*IsDeclareSimd=*/true);
7633 continue;
7634 }
7635 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7636 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7637 }
7638 Expr *Step = nullptr;
7639 Expr *NewStep = nullptr;
7640 SmallVector<Expr *, 4> NewSteps;
7641 for (Expr *E : Steps) {
7642 // Skip the same step expression, it was checked already.
7643 if (Step == E || !E) {
7644 NewSteps.push_back(E ? NewStep : nullptr);
7645 continue;
7646 }
7647 Step = E;
7648 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7649 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7650 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7651 if (UniformedArgs.count(CanonPVD) == 0) {
7652 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7653 << Step->getSourceRange();
7654 } else if (E->isValueDependent() || E->isTypeDependent() ||
7657 CanonPVD->getType()->hasIntegerRepresentation()) {
7658 NewSteps.push_back(Step);
7659 } else {
7660 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7661 << Step->getSourceRange();
7662 }
7663 continue;
7664 }
7665 NewStep = Step;
7666 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7667 !Step->isInstantiationDependent() &&
7669 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7670 .get();
7671 if (NewStep)
7672 NewStep = SemaRef
7673 .VerifyIntegerConstantExpression(
7674 NewStep, /*FIXME*/ AllowFoldKind::Allow)
7675 .get();
7676 }
7677 NewSteps.push_back(NewStep);
7678 }
7679 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7680 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7681 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7682 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7683 const_cast<Expr **>(Linears.data()), Linears.size(),
7684 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7685 NewSteps.data(), NewSteps.size(), SR);
7686 ADecl->addAttr(NewAttr);
7687 return DG;
7688}
7689
7691 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7692 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7693 SourceLocation EndLoc) {
7694 assert(isOpenMPInformationalDirective(Kind) &&
7695 "Unexpected directive category");
7696
7697 StmtResult Res = StmtError();
7698
7699 switch (Kind) {
7700 case OMPD_assume:
7701 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7702 break;
7703 default:
7704 llvm_unreachable("Unknown OpenMP directive");
7705 }
7706
7707 return Res;
7708}
7709
7710static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7711 QualType NewType) {
7712 assert(NewType->isFunctionProtoType() &&
7713 "Expected function type with prototype.");
7714 assert(FD->getType()->isFunctionNoProtoType() &&
7715 "Expected function with type with no prototype.");
7716 assert(FDWithProto->getType()->isFunctionProtoType() &&
7717 "Expected function with prototype.");
7718 // Synthesize parameters with the same types.
7719 FD->setType(NewType);
7721 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7722 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7723 SourceLocation(), nullptr, P->getType(),
7724 /*TInfo=*/nullptr, SC_None, nullptr);
7725 Param->setScopeInfo(0, Params.size());
7726 Param->setImplicit();
7727 Params.push_back(Param);
7728 }
7729
7730 FD->setParams(Params);
7731}
7732
7734 if (D->isInvalidDecl())
7735 return;
7736 FunctionDecl *FD = nullptr;
7737 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7738 FD = UTemplDecl->getTemplatedDecl();
7739 else
7740 FD = cast<FunctionDecl>(D);
7741 assert(FD && "Expected a function declaration!");
7742
7743 // If we are instantiating templates we do *not* apply scoped assumptions but
7744 // only global ones. We apply scoped assumption to the template definition
7745 // though.
7746 if (!SemaRef.inTemplateInstantiation()) {
7747 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7748 FD->addAttr(AA);
7749 }
7750 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7751 FD->addAttr(AA);
7752}
7753
7754SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7755 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7756
7758 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7760 if (!D.getIdentifier())
7761 return;
7762
7763 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7764
7765 // Template specialization is an extension, check if we do it.
7766 bool IsTemplated = !TemplateParamLists.empty();
7767 if (IsTemplated &&
7768 !DVScope.TI->isExtensionActive(
7769 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7770 return;
7771
7772 const IdentifierInfo *BaseII = D.getIdentifier();
7775 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7776 /*ObjectType=*/QualType());
7777
7778 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7779 QualType FType = TInfo->getType();
7780
7781 bool IsConstexpr =
7783 bool IsConsteval =
7785
7786 for (auto *Candidate : Lookup) {
7787 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7788 FunctionDecl *UDecl = nullptr;
7789 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7790 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7791 // FIXME: Should this compare the template parameter lists on all levels?
7792 if (SemaRef.Context.isSameTemplateParameterList(
7793 FTD->getTemplateParameters(), TemplateParamLists.back()))
7794 UDecl = FTD->getTemplatedDecl();
7795 } else if (!IsTemplated)
7796 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7797 if (!UDecl)
7798 continue;
7799
7800 // Don't specialize constexpr/consteval functions with
7801 // non-constexpr/consteval functions.
7802 if (UDecl->isConstexpr() && !IsConstexpr)
7803 continue;
7804 if (UDecl->isConsteval() && !IsConsteval)
7805 continue;
7806
7807 QualType UDeclTy = UDecl->getType();
7808 if (!UDeclTy->isDependentType()) {
7810 FType, UDeclTy, /*OfBlockPointer=*/false,
7811 /*Unqualified=*/false, /*AllowCXX=*/true);
7812 if (NewType.isNull())
7813 continue;
7814 }
7815
7816 // Found a base!
7817 Bases.push_back(UDecl);
7818 }
7819
7820 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7821 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7822 // If no base was found we create a declaration that we use as base.
7823 if (Bases.empty() && UseImplicitBase) {
7825 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7826 BaseD->setImplicit(true);
7827 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7828 Bases.push_back(BaseTemplD->getTemplatedDecl());
7829 else
7830 Bases.push_back(cast<FunctionDecl>(BaseD));
7831 }
7832
7833 std::string MangledName;
7834 MangledName += D.getIdentifier()->getName();
7835 MangledName += getOpenMPVariantManglingSeparatorStr();
7836 MangledName += DVScope.NameSuffix;
7837 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7838
7839 VariantII.setMangledOpenMPVariantName(true);
7840 D.SetIdentifier(&VariantII, D.getBeginLoc());
7841}
7842
7845 // Do not mark function as is used to prevent its emission if this is the
7846 // only place where it is used.
7849
7850 FunctionDecl *FD = nullptr;
7851 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7852 FD = UTemplDecl->getTemplatedDecl();
7853 else
7854 FD = cast<FunctionDecl>(D);
7855 auto *VariantFuncRef = DeclRefExpr::Create(
7857 /*RefersToEnclosingVariableOrCapture=*/false,
7858 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7859
7860 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7861 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7862 getASTContext(), VariantFuncRef, DVScope.TI,
7863 /*AdjustArgs=*/nullptr, /*AdjustArgsSize=*/0,
7864 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7865 for (FunctionDecl *BaseFD : Bases)
7866 BaseFD->addAttr(OMPDeclareVariantA);
7867}
7868
7870 SourceLocation LParenLoc,
7871 MultiExprArg ArgExprs,
7872 SourceLocation RParenLoc,
7873 Expr *ExecConfig) {
7874 // The common case is a regular call we do not want to specialize at all. Try
7875 // to make that case fast by bailing early.
7876 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7877 if (!CE)
7878 return Call;
7879
7880 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7881
7882 // Mark indirect calls inside target regions, to allow for insertion of
7883 // __llvm_omp_indirect_call_lookup calls during codegen.
7884 if (!CalleeFnDecl) {
7886 Expr *E = CE->getCallee()->IgnoreParenImpCasts();
7887 DeclRefExpr *DRE = nullptr;
7888 while (E) {
7889 if ((DRE = dyn_cast<DeclRefExpr>(E)))
7890 break;
7891 if (auto *ME = dyn_cast<MemberExpr>(E))
7892 E = ME->getBase()->IgnoreParenImpCasts();
7893 else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
7894 E = ASE->getBase()->IgnoreParenImpCasts();
7895 else
7896 break;
7897 }
7898 VarDecl *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
7899 if (VD && !VD->hasAttr<OMPTargetIndirectCallAttr>()) {
7900 VD->addAttr(OMPTargetIndirectCallAttr::CreateImplicit(getASTContext()));
7901 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
7902 ML->DeclarationMarkedOpenMPIndirectCall(VD);
7903 }
7904 }
7905
7906 return Call;
7907 }
7908
7909 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7910 CalleeFnDecl->getIdentifier() &&
7911 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7912 // checking for any calls inside an Order region
7914 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7915 }
7916
7917 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7918 return Call;
7919
7920 ASTContext &Context = getASTContext();
7921 std::function<void(StringRef)> DiagUnknownTrait = [this,
7922 CE](StringRef ISATrait) {
7923 // TODO Track the selector locations in a way that is accessible here to
7924 // improve the diagnostic location.
7925 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7926 << ISATrait;
7927 };
7928 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7929 SemaRef.getCurFunctionDecl(),
7930 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7931
7932 QualType CalleeFnType = CalleeFnDecl->getType();
7933
7936 while (CalleeFnDecl) {
7937 for (OMPDeclareVariantAttr *A :
7938 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7939 Expr *VariantRef = A->getVariantFuncRef();
7940
7941 VariantMatchInfo VMI;
7942 OMPTraitInfo &TI = A->getTraitInfo();
7943 TI.getAsVariantMatchInfo(Context, VMI);
7944 if (!isVariantApplicableInContext(VMI, OMPCtx,
7945 /*DeviceSetOnly=*/false))
7946 continue;
7947
7948 VMIs.push_back(VMI);
7949 Exprs.push_back(VariantRef);
7950 }
7951
7952 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7953 }
7954
7955 ExprResult NewCall;
7956 do {
7957 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7958 if (BestIdx < 0)
7959 return Call;
7960 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7961 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7962
7963 {
7964 // Try to build a (member) call expression for the current best applicable
7965 // variant expression. We allow this to fail in which case we continue
7966 // with the next best variant expression. The fail case is part of the
7967 // implementation defined behavior in the OpenMP standard when it talks
7968 // about what differences in the function prototypes: "Any differences
7969 // that the specific OpenMP context requires in the prototype of the
7970 // variant from the base function prototype are implementation defined."
7971 // This wording is there to allow the specialized variant to have a
7972 // different type than the base function. This is intended and OK but if
7973 // we cannot create a call the difference is not in the "implementation
7974 // defined range" we allow.
7976
7977 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7978 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7979 BestExpr = MemberExpr::CreateImplicit(
7980 Context, MemberCall->getImplicitObjectArgument(),
7981 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7982 MemberCall->getValueKind(), MemberCall->getObjectKind());
7983 }
7984 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7985 RParenLoc, ExecConfig);
7986 if (NewCall.isUsable()) {
7987 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7988 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7990 CalleeFnType, NewCalleeFnDecl->getType(),
7991 /*OfBlockPointer=*/false,
7992 /*Unqualified=*/false, /*AllowCXX=*/true);
7993 if (!NewType.isNull())
7994 break;
7995 // Don't use the call if the function type was not compatible.
7996 NewCall = nullptr;
7997 }
7998 }
7999 }
8000
8001 VMIs.erase(VMIs.begin() + BestIdx);
8002 Exprs.erase(Exprs.begin() + BestIdx);
8003 } while (!VMIs.empty());
8004
8005 if (!NewCall.isUsable())
8006 return Call;
8007 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
8008}
8009
8010std::optional<std::pair<FunctionDecl *, Expr *>>
8012 Expr *VariantRef,
8013 OMPTraitInfo &TI,
8014 unsigned NumAppendArgs,
8015 SourceRange SR) {
8016 ASTContext &Context = getASTContext();
8017 if (!DG || DG.get().isNull())
8018 return std::nullopt;
8019
8020 const int VariantId = 1;
8021 // Must be applied only to single decl.
8022 if (!DG.get().isSingleDecl()) {
8023 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
8024 << VariantId << SR;
8025 return std::nullopt;
8026 }
8027 Decl *ADecl = DG.get().getSingleDecl();
8028 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
8029 ADecl = FTD->getTemplatedDecl();
8030
8031 // Decl must be a function.
8032 auto *FD = dyn_cast<FunctionDecl>(ADecl);
8033 if (!FD) {
8034 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
8035 << VariantId << SR;
8036 return std::nullopt;
8037 }
8038
8039 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
8040 // The 'target' attribute needs to be separately checked because it does
8041 // not always signify a multiversion function declaration.
8042 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
8043 };
8044 // OpenMP is not compatible with multiversion function attributes.
8045 if (HasMultiVersionAttributes(FD)) {
8046 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
8047 << SR;
8048 return std::nullopt;
8049 }
8050
8051 // Allow #pragma omp declare variant only if the function is not used.
8052 if (FD->isUsed(false))
8053 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
8054 << FD->getLocation();
8055
8056 // Check if the function was emitted already.
8057 const FunctionDecl *Definition;
8058 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
8059 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
8060 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
8061 << FD->getLocation();
8062
8063 // The VariantRef must point to function.
8064 if (!VariantRef) {
8065 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
8066 return std::nullopt;
8067 }
8068
8069 auto ShouldDelayChecks = [](Expr *&E, bool) {
8070 return E && (E->isTypeDependent() || E->isValueDependent() ||
8073 };
8074 // Do not check templates, wait until instantiation.
8075 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
8076 TI.anyScoreOrCondition(ShouldDelayChecks))
8077 return std::make_pair(FD, VariantRef);
8078
8079 // Deal with non-constant score and user condition expressions.
8080 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
8081 bool IsScore) -> bool {
8082 if (!E || E->isIntegerConstantExpr(getASTContext()))
8083 return false;
8084
8085 if (IsScore) {
8086 // We warn on non-constant scores and pretend they were not present.
8087 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
8088 << E;
8089 E = nullptr;
8090 } else {
8091 // We could replace a non-constant user condition with "false" but we
8092 // will soon need to handle these anyway for the dynamic version of
8093 // OpenMP context selectors.
8094 Diag(E->getExprLoc(),
8095 diag::err_omp_declare_variant_user_condition_not_constant)
8096 << E;
8097 }
8098 return true;
8099 };
8100 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
8101 return std::nullopt;
8102
8103 QualType AdjustedFnType = FD->getType();
8104 if (NumAppendArgs) {
8105 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
8106 if (!PTy) {
8107 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
8108 << SR;
8109 return std::nullopt;
8110 }
8111 // Adjust the function type to account for an extra omp_interop_t for each
8112 // specified in the append_args clause.
8113 const TypeDecl *TD = nullptr;
8114 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
8116 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
8117 NamedDecl *ND = Result.getFoundDecl();
8118 TD = dyn_cast_or_null<TypeDecl>(ND);
8119 }
8120 if (!TD) {
8121 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
8122 return std::nullopt;
8123 }
8124 QualType InteropType =
8125 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
8126 /*Qualifier=*/std::nullopt, TD);
8127 if (PTy->isVariadic()) {
8128 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
8129 return std::nullopt;
8130 }
8132 Params.append(PTy->param_type_begin(), PTy->param_type_end());
8133 Params.insert(Params.end(), NumAppendArgs, InteropType);
8134 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
8135 PTy->getExtProtoInfo());
8136 }
8137
8138 // Convert VariantRef expression to the type of the original function to
8139 // resolve possible conflicts.
8140 ExprResult VariantRefCast = VariantRef;
8141 if (getLangOpts().CPlusPlus) {
8142 QualType FnPtrType;
8143 auto *Method = dyn_cast<CXXMethodDecl>(FD);
8144 if (Method && !Method->isStatic()) {
8145 FnPtrType = Context.getMemberPointerType(
8146 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
8147 ExprResult ER;
8148 {
8149 // Build addr_of unary op to correctly handle type checks for member
8150 // functions.
8152 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
8153 VariantRef);
8154 }
8155 if (!ER.isUsable()) {
8156 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
8157 << VariantId << VariantRef->getSourceRange();
8158 return std::nullopt;
8159 }
8160 VariantRef = ER.get();
8161 } else {
8162 FnPtrType = Context.getPointerType(AdjustedFnType);
8163 }
8164 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
8165 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
8166 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
8167 VariantRef, FnPtrType.getUnqualifiedType(),
8168 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
8169 /*InOverloadResolution=*/false,
8170 /*CStyle=*/false,
8171 /*AllowObjCWritebackConversion=*/false);
8172 if (ICS.isFailure()) {
8173 Diag(VariantRef->getExprLoc(),
8174 diag::err_omp_declare_variant_incompat_types)
8175 << VariantRef->getType()
8176 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
8177 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
8178 return std::nullopt;
8179 }
8180 VariantRefCast = SemaRef.PerformImplicitConversion(
8181 VariantRef, FnPtrType.getUnqualifiedType(),
8183 if (!VariantRefCast.isUsable())
8184 return std::nullopt;
8185 }
8186 // Drop previously built artificial addr_of unary op for member functions.
8187 if (Method && !Method->isStatic()) {
8188 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
8189 if (auto *UO = dyn_cast<UnaryOperator>(
8190 PossibleAddrOfVariantRef->IgnoreImplicit()))
8191 VariantRefCast = UO->getSubExpr();
8192 }
8193 }
8194
8195 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
8196 if (!ER.isUsable() ||
8198 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
8199 << VariantId << VariantRef->getSourceRange();
8200 return std::nullopt;
8201 }
8202
8203 // The VariantRef must point to function.
8204 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
8205 if (!DRE) {
8206 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
8207 << VariantId << VariantRef->getSourceRange();
8208 return std::nullopt;
8209 }
8210 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
8211 if (!NewFD) {
8212 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
8213 << VariantId << VariantRef->getSourceRange();
8214 return std::nullopt;
8215 }
8216
8217 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
8218 Diag(VariantRef->getExprLoc(),
8219 diag::err_omp_declare_variant_same_base_function)
8220 << VariantRef->getSourceRange();
8221 return std::nullopt;
8222 }
8223
8224 // Check if function types are compatible in C.
8225 if (!getLangOpts().CPlusPlus) {
8226 QualType NewType =
8227 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
8228 if (NewType.isNull()) {
8229 Diag(VariantRef->getExprLoc(),
8230 diag::err_omp_declare_variant_incompat_types)
8231 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
8232 << VariantRef->getSourceRange();
8233 return std::nullopt;
8234 }
8235 if (NewType->isFunctionProtoType()) {
8236 if (FD->getType()->isFunctionNoProtoType())
8237 setPrototype(SemaRef, FD, NewFD, NewType);
8238 else if (NewFD->getType()->isFunctionNoProtoType())
8239 setPrototype(SemaRef, NewFD, FD, NewType);
8240 }
8241 }
8242
8243 // Check if variant function is not marked with declare variant directive.
8244 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
8245 Diag(VariantRef->getExprLoc(),
8246 diag::warn_omp_declare_variant_marked_as_declare_variant)
8247 << VariantRef->getSourceRange();
8248 SourceRange SR =
8249 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
8250 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
8251 return std::nullopt;
8252 }
8253
8254 enum DoesntSupport {
8255 VirtFuncs = 1,
8256 Constructors = 3,
8257 Destructors = 4,
8258 DeletedFuncs = 5,
8259 DefaultedFuncs = 6,
8260 ConstexprFuncs = 7,
8261 ConstevalFuncs = 8,
8262 };
8263 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
8264 if (CXXFD->isVirtual()) {
8265 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
8266 << VirtFuncs;
8267 return std::nullopt;
8268 }
8269
8270 if (isa<CXXConstructorDecl>(FD)) {
8271 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
8272 << Constructors;
8273 return std::nullopt;
8274 }
8275
8276 if (isa<CXXDestructorDecl>(FD)) {
8277 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
8278 << Destructors;
8279 return std::nullopt;
8280 }
8281 }
8282
8283 if (FD->isDeleted()) {
8284 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
8285 << DeletedFuncs;
8286 return std::nullopt;
8287 }
8288
8289 if (FD->isDefaulted()) {
8290 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
8291 << DefaultedFuncs;
8292 return std::nullopt;
8293 }
8294
8295 if (FD->isConstexpr()) {
8296 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
8297 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
8298 return std::nullopt;
8299 }
8300
8301 // Check general compatibility.
8302 if (SemaRef.areMultiversionVariantFunctionsCompatible(
8307 VariantRef->getExprLoc(),
8308 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
8309 PartialDiagnosticAt(VariantRef->getExprLoc(),
8310 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
8311 << FD->getLocation()),
8312 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
8313 /*CLinkageMayDiffer=*/true))
8314 return std::nullopt;
8315 return std::make_pair(FD, cast<Expr>(DRE));
8316}
8317
8318/// Validate prefer_type fr() and attr() arguments in an OMPInteropInfo.
8319/// fr() must be a string literal or constant integer expression.
8320/// attr() must be a string literal starting with "ompx_" and containing no
8321/// commas. Returns true if valid; emits diagnostic and returns false on first
8322/// error.
8323static bool checkPreferTypeArgs(SemaOpenMP &S, const OMPInteropInfo &Info) {
8324 auto isDependent = [](const Expr *E) {
8325 return E->isValueDependent() || E->isTypeDependent() ||
8328 };
8329 for (const OMPInteropPref &P : Info.Prefs) {
8330 const Expr *E = P.Fr;
8331 if (!E) {
8332 assert(Info.HasPreferAttrs && "null Fr requires OMP 6.0 syntax");
8333 } else if (!isDependent(E)) {
8334 if (!E->isIntegerConstantExpr(S.getASTContext()) &&
8335 !isa<StringLiteral>(E)) {
8336 S.Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
8337 return false;
8338 }
8339 }
8340 for (const Expr *A : P.Attrs) {
8341 if (isDependent(A))
8342 continue;
8343 const auto *SL = dyn_cast<StringLiteral>(A);
8344 if (!SL) {
8345 S.Diag(A->getExprLoc(), diag::err_omp_interop_attr_not_string);
8346 return false;
8347 }
8348 StringRef Str = SL->getString();
8349 if (!Str.starts_with("ompx_")) {
8350 S.Diag(A->getExprLoc(), diag::err_omp_interop_attr_missing_ompx_prefix)
8351 << Str;
8352 return false;
8353 }
8354 if (Str.contains(',')) {
8355 S.Diag(A->getExprLoc(), diag::err_omp_interop_attr_contains_comma)
8356 << Str;
8357 return false;
8358 }
8359 }
8360 }
8361 return true;
8362}
8363
8365
8366/// Check one 'adjust_args' integer expression for the constant property plus
8367/// either the positive or the non-negative property (OpenMP 6.0 [5.2.1]).
8369 bool StrictlyPositive,
8370 llvm::APSInt &Result) {
8371 if (E->isInstantiationDependent())
8372 return OMPAdjustArgsVal::Dependent; // re-checked on instantiation
8374 return OMPAdjustArgsVal::Invalid; // already diagnosed
8375 if (StrictlyPositive ? !Result.isStrictlyPositive() : Result.isNegative()) {
8376 S.Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
8377 << getOpenMPClauseNameForDiag(OMPC_adjust_args)
8378 << (StrictlyPositive ? 1 : 0) << E->getSourceRange();
8380 }
8381 if (!Result.isRepresentableByInt64()) {
8382 S.Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
8383 << getOpenMPClauseNameForDiag(OMPC_adjust_args) << E->getSourceRange();
8385 }
8387}
8388
8389/// Check one bound of a parameter range 'lb:ub' (OpenMP 6.0 [5.2.1]).
8390/// A plain bound has the positive property, checked via
8391/// checkOMPAdjustArgsValue. An 'omp_num_args' bound's logical_offset has the
8392/// non-negative property instead, so it is checked with a different lower
8393/// bound.
8395 const OMPAdjustArgsItem::Bound &Bound) {
8397 return true;
8398 if (Bound.Kind == OMPAdjustArgsItem::Bound::NumArgs && !Bound.E)
8399 return true;
8400
8401 assert((Bound.Kind == OMPAdjustArgsItem::Bound::Expression ||
8403 Bound.E && "expected an adjust_args bound expression");
8404 llvm::APSInt Result;
8405 bool StrictlyPositive = Bound.Kind == OMPAdjustArgsItem::Bound::Expression;
8406 return checkOMPAdjustArgsValue(S, Bound.E, StrictlyPositive, Result) !=
8408}
8409
8411 const OMPAdjustArgsItem &Range) {
8412 assert(Range.Kind == OMPAdjustArgsItem::Range &&
8413 "expected an adjust_args range");
8414 return checkOMPAdjustArgsBound(S, Range.Lower) &&
8415 checkOMPAdjustArgsBound(S, Range.Upper);
8416}
8417
8419 SourceLocation FallbackLoc) {
8420 if (Item.E)
8421 return Item.E->getExprLoc();
8422 if (Item.Lower.E)
8423 return Item.Lower.E->getExprLoc();
8424 if (Item.Upper.E)
8425 return Item.Upper.E->getExprLoc();
8426 return FallbackLoc;
8427}
8428
8430 OpenMPAdjustArgsOpKind AdjustOp,
8431 OpenMPNeedDevicePtrModifier NeedDevicePtrModifier,
8433 // OpenMP 6.0 [9.6.2]: the fallback modifier is only valid with
8434 // need_device_ptr.
8435 if (NeedDevicePtrModifier != OMPC_NEED_DEVICE_PTR_unknown &&
8436 AdjustOp != OMPC_ADJUST_ARGS_need_device_ptr) {
8437 Diag(Loc, diag::err_omp_unexpected_clause_modifier)
8438 << getOpenMPClauseName(OMPC_adjust_args);
8439 return nullptr;
8440 }
8442 NeedDevicePtrModifier, Items);
8443}
8444
8446 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
8448 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
8449 SourceLocation AppendArgsLoc, SourceRange SR) {
8450
8451 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
8452 // An adjust_args clause or append_args clause can only be specified if the
8453 // dispatch selector of the construct selector set appears in the match
8454 // clause.
8455
8456 if (!AdjustArgs.empty() || !AppendArgs.empty()) {
8457 VariantMatchInfo VMI;
8459 if (!llvm::is_contained(
8460 VMI.ConstructTraits,
8461 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
8462 if (!AdjustArgs.empty())
8463 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
8464 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
8465 if (!AppendArgs.empty())
8466 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
8467 << getOpenMPClauseNameForDiag(OMPC_append_args);
8468 return;
8469 }
8470 }
8471
8472 // OpenMP 6.0 [5.2.1]: each parameter list item may be specified only once
8473 // across all clauses of the same type in a directive. A range has the effect
8474 // of specifying each of its parameter positions individually.
8475 llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars; // named items
8476 llvm::SmallSet<uint64_t, 4> AdjustPositions; // positions, including ranges
8477
8478 for (const OMPAdjustArgsDescriptor *Desc : AdjustArgs) {
8479 for (const OMPAdjustArgsItem &ItemInfo : Desc->items()) {
8480 if (ItemInfo.Kind == OMPAdjustArgsItem::Range) {
8481 if (!checkOMPAdjustArgsRange(*this, ItemInfo))
8482 continue;
8483 SmallVector<unsigned, 8> Positions;
8484 if (resolveOMPAdjustArgsItem(ItemInfo, FD, FD->getNumParams(),
8485 getASTContext(), Positions)) {
8486 for (unsigned Pos : Positions) {
8487 if (!AdjustPositions.insert(Pos).second) {
8488 Diag(getOMPAdjustArgsItemLoc(ItemInfo, AdjustArgsLoc),
8489 diag::err_omp_adjust_arg_multiple_clauses)
8490 << Pos;
8491 return;
8492 }
8493 }
8494 }
8495 continue;
8496 }
8497
8498 assert(ItemInfo.E && "expected an adjust_args expression");
8499 Expr *Item = ItemInfo.E->IgnoreParenImpCasts();
8500
8501 // A named parameter list item — unchanged from OpenMP 5.1.
8502 if (const auto *DRE = dyn_cast<DeclRefExpr>(Item)) {
8503 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
8504 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
8505 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
8506 FD->getParamDecl(PVD->getFunctionScopeIndex())
8507 ->getCanonicalDecl() == CanonPVD) {
8508 if (!AdjustVars.insert(CanonPVD).second) {
8509 Diag(DRE->getLocation(),
8510 diag::err_omp_adjust_arg_multiple_clauses)
8511 << PVD;
8512 return;
8513 }
8514 continue;
8515 }
8516 }
8517 }
8518
8519 if (getLangOpts().OpenMP < 60) {
8520 // Anything that is not a function parameter is an error before 6.0.
8521 Diag(Item->getExprLoc(), diag::err_omp_param_or_this_in_clause)
8522 << FD << 0;
8523 return;
8524 }
8525
8526 // OpenMP 6.0 [5.2.1]: the position of a parameter, given as a
8527 // positive constant integer expression. A dependent item is skipped
8528 // here and rechecked when the template is instantiated.
8529 if (Item->isTypeDependent() || Item->getType()->isIntegerType()) {
8530 llvm::APSInt Pos;
8531 switch (checkOMPAdjustArgsValue(*this, Item,
8532 /*StrictlyPositive=*/true, Pos)) {
8534 return;
8536 continue;
8538 if (!AdjustPositions.insert(Pos.getZExtValue()).second) {
8539 Diag(Item->getExprLoc(), diag::err_omp_adjust_arg_multiple_clauses)
8540 << Pos;
8541 return;
8542 }
8543 continue;
8544 }
8545 }
8546
8547 if (isa<DeclRefExpr>(Item)) {
8548 Diag(Item->getExprLoc(), diag::err_omp_param_or_this_in_clause)
8549 << FD << 0;
8550 return;
8551 }
8552
8553 // Not a name or a position: neither form OpenMP 6.0 allows for a
8554 // non-range item.
8555 Diag(Item->getExprLoc(), diag::err_omp_adjust_args_invalid_item);
8556 return;
8557 }
8558 }
8559
8560 // OpenMP 6.0 [9.6.2]: if the need_device_addr adjust-op modifier
8561 // is present, each list item that appears in the clause must refer to an
8562 // argument in the declaration of the function variant that has a reference
8563 // type. Unlike the need_device_ptr restriction, this one is not scoped to
8564 // named items ("that refers to a specific named argument" is absent here),
8565 // so positions and ranges are checked too, via the shared item-to-positions
8566 // resolver.
8567 if (getLangOpts().OpenMP >= 60) {
8568 for (const OMPAdjustArgsDescriptor *Desc : AdjustArgs) {
8569 if (Desc->AdjustOp != OMPC_ADJUST_ARGS_need_device_addr)
8570 continue;
8571 for (const OMPAdjustArgsItem &Item : Desc->items()) {
8572 SmallVector<unsigned, 8> Positions;
8573 // With no call site in hand, 'omp_num_args' is the declared parameter
8574 // count (OpenMP 6.0 [20.1]). Positions past it denote variadic
8575 // actuals, which have no declared parameter to check against, and are
8576 // dropped by the resolver (OpenMP 6.0 [9.6.2]).
8578 Positions);
8579 for (unsigned Pos : Positions) {
8580 QualType ParamTy = FD->getParamDecl(Pos - 1)->getType();
8581 if (ParamTy->isReferenceType() || ParamTy->isDependentType())
8582 continue;
8583 Diag(getOMPAdjustArgsItemLoc(Item, AdjustArgsLoc.isValid()
8584 ? AdjustArgsLoc
8585 : SR.getBegin()),
8586 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
8587 break; // One diagnostic per written item.
8588 }
8589 }
8590 }
8591 }
8592
8593 // OpenMP 6.0 [16.1.3] Check prefer_type fr()/attr() arguments in
8594 // append_args.
8595 for (const OMPInteropInfo &Info : AppendArgs) {
8596 if (!checkPreferTypeArgs(*this, Info))
8597 return;
8598 }
8599
8600 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
8601 getASTContext(), VariantRef, &TI,
8602 const_cast<OMPAdjustArgsDescriptor **>(AdjustArgs.data()),
8603 AdjustArgs.size(), const_cast<OMPInteropInfo *>(AppendArgs.data()),
8604 AppendArgs.size(), SR);
8605 FD->addAttr(NewAttr);
8606}
8607
8608static CapturedStmt *
8610 auto *CS = dyn_cast<CapturedStmt>(AStmt);
8611 assert(CS && "Captured statement expected");
8612 // 1.2.2 OpenMP Language Terminology
8613 // Structured block - An executable statement with a single entry at the
8614 // top and a single exit at the bottom.
8615 // The point of exit cannot be a branch out of the structured block.
8616 // longjmp() and throw() must not violate the entry/exit criteria.
8617 CS->getCapturedDecl()->setNothrow();
8618
8619 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
8620 ThisCaptureLevel > 1; --ThisCaptureLevel) {
8622 // 1.2.2 OpenMP Language Terminology
8623 // Structured block - An executable statement with a single entry at the
8624 // top and a single exit at the bottom.
8625 // The point of exit cannot be a branch out of the structured block.
8626 // longjmp() and throw() must not violate the entry/exit criteria.
8627 CS->getCapturedDecl()->setNothrow();
8628 }
8630 return CS;
8631}
8632
8635 Stmt *AStmt, SourceLocation StartLoc,
8636 SourceLocation EndLoc) {
8637 if (!AStmt)
8638 return StmtError();
8639
8640 // Check for conflicting capture kinds on structured bindings.
8641 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_parallel, Clauses,
8642 AStmt))
8643 return StmtError();
8644
8645 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
8646
8647 return OMPParallelDirective::Create(
8648 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
8649 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
8650}
8651
8652namespace {
8653/// Iteration space of a single for loop.
8654struct LoopIterationSpace final {
8655 /// True if the condition operator is the strict compare operator (<, > or
8656 /// !=).
8657 bool IsStrictCompare = false;
8658 /// Condition of the loop.
8659 Expr *PreCond = nullptr;
8660 /// This expression calculates the number of iterations in the loop.
8661 /// It is always possible to calculate it before starting the loop.
8662 Expr *NumIterations = nullptr;
8663 /// The loop counter variable.
8664 Expr *CounterVar = nullptr;
8665 /// Private loop counter variable.
8666 Expr *PrivateCounterVar = nullptr;
8667 /// This is initializer for the initial value of #CounterVar.
8668 Expr *CounterInit = nullptr;
8669 /// This is step for the #CounterVar used to generate its update:
8670 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
8671 Expr *CounterStep = nullptr;
8672 /// Should step be subtracted?
8673 bool Subtract = false;
8674 /// Source range of the loop init.
8675 SourceRange InitSrcRange;
8676 /// Source range of the loop condition.
8677 SourceRange CondSrcRange;
8678 /// Source range of the loop increment.
8679 SourceRange IncSrcRange;
8680 /// Minimum value that can have the loop control variable. Used to support
8681 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
8682 /// since only such variables can be used in non-loop invariant expressions.
8683 Expr *MinValue = nullptr;
8684 /// Maximum value that can have the loop control variable. Used to support
8685 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
8686 /// since only such variables can be used in non-loop invariant expressions.
8687 Expr *MaxValue = nullptr;
8688 /// true, if the lower bound depends on the outer loop control var.
8689 bool IsNonRectangularLB = false;
8690 /// true, if the upper bound depends on the outer loop control var.
8691 bool IsNonRectangularUB = false;
8692 /// Index of the loop this loop depends on and forms non-rectangular loop
8693 /// nest.
8694 unsigned LoopDependentIdx = 0;
8695 /// Final condition for the non-rectangular loop nest support. It is used to
8696 /// check that the number of iterations for this particular counter must be
8697 /// finished.
8698 Expr *FinalCondition = nullptr;
8699};
8700
8701/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
8702/// set are referenced. Used for verifying loop nest structure before
8703/// performing a loop collapse operation.
8704class ForSubExprChecker : public DynamicRecursiveASTVisitor {
8705 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8706 VarDecl *ForbiddenVar = nullptr;
8707 SourceRange ErrLoc;
8708
8709public:
8710 explicit ForSubExprChecker(
8711 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
8712 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
8713 // We want to visit implicit code, i.e. synthetic initialisation statements
8714 // created during range-for lowering.
8715 ShouldVisitImplicitCode = true;
8716 }
8717
8718 bool VisitDeclRefExpr(DeclRefExpr *E) override {
8719 ValueDecl *VD = E->getDecl();
8721 return true;
8722 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
8723 if (V->getType()->isReferenceType()) {
8724 VarDecl *VD = V->getDefinition();
8725 if (VD && VD->hasInit()) {
8726 Expr *I = VD->getInit();
8727 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
8728 if (!DRE)
8729 return true;
8731 }
8732 }
8733 Decl *Canon = V->getCanonicalDecl();
8734 if (CollapsedLoopVarDecls.contains(Canon)) {
8735 ForbiddenVar = V;
8736 ErrLoc = E->getSourceRange();
8737 return false;
8738 }
8739
8740 return true;
8741 }
8742
8743 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
8744 SourceRange getErrRange() const { return ErrLoc; }
8745};
8746
8747/// Helper class for checking canonical form of the OpenMP loops and
8748/// extracting iteration space of each loop in the loop nest, that will be used
8749/// for IR generation.
8750class OpenMPIterationSpaceChecker {
8751 /// Reference to Sema.
8752 Sema &SemaRef;
8753 /// Does the loop associated directive support non-rectangular loops?
8754 bool SupportsNonRectangular;
8755 /// Data-sharing stack.
8756 DSAStackTy &Stack;
8757 /// A location for diagnostics (when there is no some better location).
8758 SourceLocation DefaultLoc;
8759 /// A location for diagnostics (when increment is not compatible).
8760 SourceLocation ConditionLoc;
8761 /// The set of variables declared within the (to be collapsed) loop nest.
8762 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8763 /// The set of induction variables from outer collapsed loops.
8764 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars;
8765 /// A source location for referring to loop init later.
8766 SourceRange InitSrcRange;
8767 /// A source location for referring to condition later.
8768 SourceRange ConditionSrcRange;
8769 /// A source location for referring to increment later.
8770 SourceRange IncrementSrcRange;
8771 /// Loop variable.
8772 ValueDecl *LCDecl = nullptr;
8773 /// Reference to loop variable.
8774 Expr *LCRef = nullptr;
8775 /// Lower bound (initializer for the var).
8776 Expr *LB = nullptr;
8777 /// Upper bound.
8778 Expr *UB = nullptr;
8779 /// Loop step (increment).
8780 Expr *Step = nullptr;
8781 /// This flag is true when condition is one of:
8782 /// Var < UB
8783 /// Var <= UB
8784 /// UB > Var
8785 /// UB >= Var
8786 /// This will have no value when the condition is !=
8787 std::optional<bool> TestIsLessOp;
8788 /// This flag is true when condition is strict ( < or > ).
8789 bool TestIsStrictOp = false;
8790 /// This flag is true when step is subtracted on each iteration.
8791 bool SubtractStep = false;
8792 /// The outer loop counter this loop depends on (if any).
8793 const ValueDecl *DepDecl = nullptr;
8794 /// Contains number of loop (starts from 1) on which loop counter init
8795 /// expression of this loop depends on.
8796 std::optional<unsigned> InitDependOnLC;
8797 /// Contains number of loop (starts from 1) on which loop counter condition
8798 /// expression of this loop depends on.
8799 std::optional<unsigned> CondDependOnLC;
8800 /// Checks if the provide statement depends on the loop counter.
8801 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8802 bool IsInitializer);
8803 /// Original condition required for checking of the exit condition for
8804 /// non-rectangular loop.
8805 Expr *Condition = nullptr;
8806
8807public:
8808 OpenMPIterationSpaceChecker(
8809 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8810 SourceLocation DefaultLoc,
8811 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls,
8812 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars)
8813 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8814 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8815 CollapsedLoopVarDecls(CollapsedLoopDecls),
8816 CollapsedLoopInductionVars(CollapsedLoopInductionVars) {}
8817 /// Check init-expr for canonical loop form and save loop counter
8818 /// variable - #Var and its initialization value - #LB.
8819 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8820 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8821 /// for less/greater and for strict/non-strict comparison.
8822 bool checkAndSetCond(Expr *S);
8823 /// Check incr-expr for canonical loop form and return true if it
8824 /// does not conform, otherwise save loop step (#Step).
8825 bool checkAndSetInc(Expr *S);
8826 /// Return the loop counter variable.
8827 ValueDecl *getLoopDecl() const { return LCDecl; }
8828 /// Return the reference expression to loop counter variable.
8829 Expr *getLoopDeclRefExpr() const { return LCRef; }
8830 /// Source range of the loop init.
8831 SourceRange getInitSrcRange() const { return InitSrcRange; }
8832 /// Source range of the loop condition.
8833 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8834 /// Source range of the loop increment.
8835 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8836 /// True if the step should be subtracted.
8837 bool shouldSubtractStep() const { return SubtractStep; }
8838 /// True, if the compare operator is strict (<, > or !=).
8839 bool isStrictTestOp() const { return TestIsStrictOp; }
8840 /// Build the expression to calculate the number of iterations.
8841 Expr *buildNumIterations(
8842 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8843 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8844 /// Build the precondition expression for the loops.
8845 Expr *
8846 buildPreCond(Scope *S, Expr *Cond,
8847 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8848 /// Build reference expression to the counter be used for codegen.
8849 DeclRefExpr *
8850 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8851 DSAStackTy &DSA) const;
8852 /// Build reference expression to the private counter be used for
8853 /// codegen.
8854 Expr *buildPrivateCounterVar() const;
8855 /// Build initialization of the counter be used for codegen.
8856 Expr *buildCounterInit() const;
8857 /// Build step of the counter be used for codegen.
8858 Expr *buildCounterStep() const;
8859 /// Build loop data with counter value for depend clauses in ordered
8860 /// directives.
8861 Expr *
8862 buildOrderedLoopData(Scope *S, Expr *Counter,
8863 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8864 SourceLocation Loc, Expr *Inc = nullptr,
8865 OverloadedOperatorKind OOK = OO_Amp);
8866 /// Builds the minimum value for the loop counter.
8867 std::pair<Expr *, Expr *> buildMinMaxValues(
8868 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8869 /// Builds final condition for the non-rectangular loops.
8870 Expr *buildFinalCondition(Scope *S) const;
8871 /// Return true if any expression is dependent.
8872 bool dependent() const;
8873 /// Returns true if the initializer forms non-rectangular loop.
8874 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8875 /// Returns true if the condition forms non-rectangular loop.
8876 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8877 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8878 unsigned getLoopDependentIdx() const {
8879 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8880 }
8881
8882private:
8883 /// Check the right-hand side of an assignment in the increment
8884 /// expression.
8885 bool checkAndSetIncRHS(Expr *RHS);
8886 /// Helper to set loop counter variable and its initializer.
8887 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8888 bool EmitDiags);
8889 /// Helper to set upper bound.
8890 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8891 SourceRange SR, SourceLocation SL);
8892 /// Helper to set loop increment.
8893 bool setStep(Expr *NewStep, bool Subtract);
8894 /// Diagnose a statement expression in a bound of a non-rectangular loop.
8895 bool checkNonRectangularBound(const Expr *E, bool IsInitializer) const;
8896};
8897
8898bool OpenMPIterationSpaceChecker::dependent() const {
8899 if (!LCDecl) {
8900 assert(!LB && !UB && !Step);
8901 return false;
8902 }
8903 return LCDecl->getType()->isDependentType() ||
8904 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8905 (Step && Step->isValueDependent());
8906}
8907
8908/// Find a statement expression in \p E.
8909static const StmtExpr *findStmtExpr(const Expr *E) {
8910 SmallVector<const Stmt *, 8> Worklist{E};
8911 while (!Worklist.empty()) {
8912 const Stmt *S = Worklist.pop_back_val();
8913 if (!S)
8914 continue;
8915 if (const auto *SE = dyn_cast<StmtExpr>(S))
8916 return SE;
8917 llvm::append_range(Worklist, S->children());
8918 }
8919 return nullptr;
8920}
8921
8922bool OpenMPIterationSpaceChecker::checkNonRectangularBound(
8923 const Expr *E, bool IsInitializer) const {
8924 // Such a bound is emitted at every use, its declarations cannot be.
8925 const StmtExpr *SE = findStmtExpr(E);
8926 if (!SE)
8927 return false;
8928 SemaRef.Diag(SE->getBeginLoc(),
8929 diag::err_omp_stmt_expr_in_non_rectangular_loop)
8930 << (IsInitializer ? 0 : 1);
8931 return true;
8932}
8933
8934bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8935 Expr *NewLCRefExpr,
8936 Expr *NewLB, bool EmitDiags) {
8937 // State consistency checking to ensure correct usage.
8938 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8939 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8940 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8941 return true;
8942 NewLB = buildInitListValue(SemaRef, NewLB);
8943 LCDecl = getCanonicalDecl(NewLCDecl);
8944 LCRef = NewLCRefExpr;
8945 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8946 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8947 if ((Ctor->isCopyOrMoveConstructor() ||
8948 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8949 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8950 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8951 LB = NewLB;
8952 if (EmitDiags) {
8953 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8954 if (InitDependOnLC && checkNonRectangularBound(LB, /*IsInitializer=*/true))
8955 return true;
8956 }
8957 return false;
8958}
8959
8960bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8961 bool StrictOp, SourceRange SR,
8962 SourceLocation SL) {
8963 // State consistency checking to ensure correct usage.
8964 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8965 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8966 if (!NewUB || NewUB->containsErrors())
8967 return true;
8968 UB = NewUB;
8969 if (LessOp)
8970 TestIsLessOp = LessOp;
8971 TestIsStrictOp = StrictOp;
8972 ConditionSrcRange = SR;
8973 ConditionLoc = SL;
8974 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8975 // The condition is also emitted as the body guard of a non-rectangular loop.
8976 if ((InitDependOnLC || CondDependOnLC) &&
8977 checkNonRectangularBound(UB, /*IsInitializer=*/false))
8978 return true;
8979 return false;
8980}
8981
8982bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8983 // State consistency checking to ensure correct usage.
8984 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8985 if (!NewStep || NewStep->containsErrors())
8986 return true;
8987 NewStep = buildInitListValue(SemaRef, NewStep);
8988 if (!NewStep->isValueDependent()) {
8989 // Check that the step is integer expression.
8990 SourceLocation StepLoc = NewStep->getBeginLoc();
8992 StepLoc, getExprAsWritten(NewStep));
8993 if (Val.isInvalid())
8994 return true;
8995 NewStep = Val.get();
8996
8997 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8998 // If test-expr is of form var relational-op b and relational-op is < or
8999 // <= then incr-expr must cause var to increase on each iteration of the
9000 // loop. If test-expr is of form var relational-op b and relational-op is
9001 // > or >= then incr-expr must cause var to decrease on each iteration of
9002 // the loop.
9003 // If test-expr is of form b relational-op var and relational-op is < or
9004 // <= then incr-expr must cause var to decrease on each iteration of the
9005 // loop. If test-expr is of form b relational-op var and relational-op is
9006 // > or >= then incr-expr must cause var to increase on each iteration of
9007 // the loop.
9008 std::optional<llvm::APSInt> Result =
9009 NewStep->getIntegerConstantExpr(SemaRef.Context);
9010 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
9011 bool IsConstNeg =
9012 Result && Result->isSigned() && (Subtract != Result->isNegative());
9013 bool IsConstPos =
9014 Result && Result->isSigned() && (Subtract == Result->isNegative());
9015 bool IsConstZero = Result && !Result->getBoolValue();
9016
9017 // != with increment is treated as <; != with decrement is treated as >
9018 if (!TestIsLessOp)
9019 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
9020 if (UB && (IsConstZero ||
9021 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
9022 : (IsConstPos || (IsUnsigned && !Subtract))))) {
9023 SemaRef.Diag(NewStep->getExprLoc(),
9024 diag::err_omp_loop_incr_not_compatible)
9025 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
9026 SemaRef.Diag(ConditionLoc,
9027 diag::note_omp_loop_cond_requires_compatible_incr)
9028 << *TestIsLessOp << ConditionSrcRange;
9029 return true;
9030 }
9031 if (*TestIsLessOp == Subtract) {
9032 NewStep =
9033 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
9034 .get();
9035 Subtract = !Subtract;
9036 }
9037 }
9038
9039 Step = NewStep;
9040 SubtractStep = Subtract;
9041 return false;
9042}
9043
9044namespace {
9045/// Checker for the non-rectangular loops. Checks if the initializer or
9046/// condition expression references loop counter variable.
9047class LoopCounterRefChecker final
9048 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
9049 Sema &SemaRef;
9050 DSAStackTy &Stack;
9051 const ValueDecl *CurLCDecl = nullptr;
9052 const ValueDecl *DepDecl = nullptr;
9053 const ValueDecl *PrevDepDecl = nullptr;
9054 bool IsInitializer = true;
9055 bool SupportsNonRectangular;
9056 unsigned BaseLoopId = 0;
9057 bool checkDecl(const Expr *E, const ValueDecl *VD) {
9058 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
9059 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
9060 << (IsInitializer ? 0 : 1);
9061 return false;
9062 }
9063 const auto &&Data = Stack.isLoopControlVariable(VD);
9064 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
9065 // The type of the loop iterator on which we depend may not have a random
9066 // access iterator type.
9067 if (Data.first && VD->getType()->isRecordType()) {
9068 SmallString<128> Name;
9069 llvm::raw_svector_ostream OS(Name);
9070 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
9071 /*Qualified=*/true);
9072 SemaRef.Diag(E->getExprLoc(),
9073 diag::err_omp_wrong_dependency_iterator_type)
9074 << OS.str();
9075 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
9076 return false;
9077 }
9078 if (Data.first && !SupportsNonRectangular) {
9079 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
9080 return false;
9081 }
9082 if (Data.first &&
9083 (DepDecl || (PrevDepDecl &&
9084 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
9085 if (!DepDecl && PrevDepDecl)
9086 DepDecl = PrevDepDecl;
9087 SmallString<128> Name;
9088 llvm::raw_svector_ostream OS(Name);
9089 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
9090 /*Qualified=*/true);
9091 SemaRef.Diag(E->getExprLoc(),
9092 diag::err_omp_invariant_or_linear_dependency)
9093 << OS.str();
9094 return false;
9095 }
9096 if (Data.first) {
9097 DepDecl = VD;
9098 BaseLoopId = Data.first;
9099 }
9100 return Data.first;
9101 }
9102
9103public:
9104 bool VisitDeclRefExpr(const DeclRefExpr *E) {
9105 const ValueDecl *VD = E->getDecl();
9106 if (isa<VarDecl>(VD))
9107 return checkDecl(E, VD);
9108 return false;
9109 }
9110 bool VisitMemberExpr(const MemberExpr *E) {
9111 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
9112 const ValueDecl *VD = E->getMemberDecl();
9113 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
9114 return checkDecl(E, VD);
9115 }
9116 return false;
9117 }
9118 bool VisitStmt(const Stmt *S) {
9119 bool Res = false;
9120 for (const Stmt *Child : S->children())
9121 Res = (Child && Visit(Child)) || Res;
9122 return Res;
9123 }
9124 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
9125 const ValueDecl *CurLCDecl, bool IsInitializer,
9126 const ValueDecl *PrevDepDecl = nullptr,
9127 bool SupportsNonRectangular = true)
9128 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
9129 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
9130 SupportsNonRectangular(SupportsNonRectangular) {}
9131 unsigned getBaseLoopId() const {
9132 assert(CurLCDecl && "Expected loop dependency.");
9133 return BaseLoopId;
9134 }
9135 const ValueDecl *getDepDecl() const {
9136 assert(CurLCDecl && "Expected loop dependency.");
9137 return DepDecl;
9138 }
9139};
9140} // namespace
9141
9142std::optional<unsigned>
9143OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
9144 bool IsInitializer) {
9145 // Check for the non-rectangular loops.
9146 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
9147 DepDecl, SupportsNonRectangular);
9148 if (LoopStmtChecker.Visit(S)) {
9149 DepDecl = LoopStmtChecker.getDepDecl();
9150 return LoopStmtChecker.getBaseLoopId();
9151 }
9152 return std::nullopt;
9153}
9154
9155bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
9156 // Check init-expr for canonical loop form and save loop counter
9157 // variable - #Var and its initialization value - #LB.
9158 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
9159 // var = lb
9160 // integer-type var = lb
9161 // random-access-iterator-type var = lb
9162 // pointer-type var = lb
9163 //
9164 if (!S) {
9165 if (EmitDiags) {
9166 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
9167 }
9168 return true;
9169 }
9170 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
9171 if (!ExprTemp->cleanupsHaveSideEffects())
9172 S = ExprTemp->getSubExpr();
9173
9174 if (!CollapsedLoopVarDecls.empty()) {
9175 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
9176 if (!FSEC.TraverseStmt(S)) {
9177 SourceRange Range = FSEC.getErrRange();
9178 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
9179 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
9180 return true;
9181 }
9182 }
9183
9184 // Helper lambda to reject structured bindings used as OpenMP loop
9185 // control variables. Loop counters are implicitly private, but bindings
9186 // share storage with their decomposition, so this is not representable.
9187 auto CheckBindingAsLoopVar = [&](ValueDecl *LoopVar,
9188 SourceLocation Loc) -> bool {
9189 if (!isa<BindingDecl>(LoopVar))
9190 return false;
9191 if (EmitDiags)
9192 SemaRef.Diag(Loc, diag::err_omp_loop_var_is_structured_binding)
9193 << LoopVar;
9194 return true;
9195 };
9196
9197 // Helper lambda to check if a loop variable is already used in an outer
9198 // loop.
9199 auto CheckLoopVarReuse = [&](ValueDecl *LoopVar, SourceLocation Loc) -> bool {
9200 if (EmitDiags &&
9201 CollapsedLoopInductionVars.count(LoopVar->getCanonicalDecl())) {
9202 SemaRef.Diag(Loc, diag::err_omp_loop_var_reused_in_collapsed_loop)
9203 << LoopVar;
9204 return true;
9205 }
9206 return false;
9207 };
9208
9209 InitSrcRange = S->getSourceRange();
9210 if (Expr *E = dyn_cast<Expr>(S))
9211 S = E->IgnoreParens();
9212 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
9213 if (BO->getOpcode() == BO_Assign) {
9214 Expr *LHS = BO->getLHS()->IgnoreParens();
9215 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
9216 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
9217 if (auto *ME =
9218 dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) {
9219 ValueDecl *LoopVar = ME->getMemberDecl();
9220 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
9221 return true;
9222 return setLCDeclAndLB(LoopVar, ME, BO->getRHS(), EmitDiags);
9223 }
9224 ValueDecl *LoopVar = DRE->getDecl();
9225 if (CheckBindingAsLoopVar(LoopVar, DRE->getLocation()))
9226 return true;
9227 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
9228 return true;
9229 return setLCDeclAndLB(LoopVar, DRE, BO->getRHS(), EmitDiags);
9230 }
9231 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
9232 if (ME->isArrow() &&
9233 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) {
9234 ValueDecl *LoopVar = ME->getMemberDecl();
9235 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
9236 return true;
9237 return setLCDeclAndLB(LoopVar, ME, BO->getRHS(), EmitDiags);
9238 }
9239 }
9240 }
9241 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
9242 if (DS->isSingleDecl()) {
9243 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
9244 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
9245 // Accept non-canonical init form here but emit ext. warning.
9246 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
9247 SemaRef.Diag(S->getBeginLoc(),
9248 diag::ext_omp_loop_not_canonical_init)
9249 << S->getSourceRange();
9250 if (CheckLoopVarReuse(Var, Var->getLocation()))
9251 return true;
9252 return setLCDeclAndLB(
9253 Var,
9254 buildDeclRefExpr(SemaRef, Var,
9255 Var->getType().getNonReferenceType(),
9256 DS->getBeginLoc()),
9257 Var->getInit(), EmitDiags);
9258 }
9259 }
9260 }
9261 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
9262 if (CE->getOperator() == OO_Equal) {
9263 Expr *LHS = CE->getArg(0);
9264 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
9265 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
9266 if (auto *ME =
9267 dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit()))) {
9268 ValueDecl *LoopVar = ME->getMemberDecl();
9269 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
9270 return true;
9271 return setLCDeclAndLB(LoopVar, ME, CE->getArg(1), EmitDiags);
9272 }
9273 ValueDecl *LoopVar = DRE->getDecl();
9274 if (CheckBindingAsLoopVar(LoopVar, DRE->getLocation()))
9275 return true;
9276 if (CheckLoopVarReuse(LoopVar, DRE->getLocation()))
9277 return true;
9278 return setLCDeclAndLB(LoopVar, DRE, CE->getArg(1), EmitDiags);
9279 }
9280 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
9281 if (ME->isArrow() &&
9282 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) {
9283 ValueDecl *LoopVar = ME->getMemberDecl();
9284 if (CheckLoopVarReuse(LoopVar, LHS->getBeginLoc()))
9285 return true;
9286 return setLCDeclAndLB(LoopVar, ME, CE->getArg(1), EmitDiags);
9287 }
9288 }
9289 }
9290 }
9291
9292 if (dependent() || SemaRef.CurContext->isDependentContext())
9293 return false;
9294 if (EmitDiags) {
9295 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
9296 << S->getSourceRange();
9297 }
9298 return true;
9299}
9300
9301/// Ignore parenthesizes, implicit casts, copy constructor and return the
9302/// variable (which may be the loop variable) if possible.
9303static const ValueDecl *getInitLCDecl(const Expr *E) {
9304 if (!E)
9305 return nullptr;
9306 E = getExprAsWritten(E);
9307 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
9308 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
9309 if ((Ctor->isCopyOrMoveConstructor() ||
9310 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
9311 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
9312 E = CE->getArg(0)->IgnoreParenImpCasts();
9313 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
9314 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
9315 return getCanonicalDecl(VD);
9316 }
9317 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
9318 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
9319 return getCanonicalDecl(ME->getMemberDecl());
9320 return nullptr;
9321}
9322
9323bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
9324 // Check test-expr for canonical form, save upper-bound UB, flags for
9325 // less/greater and for strict/non-strict comparison.
9326 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
9327 // var relational-op b
9328 // b relational-op var
9329 //
9330 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
9331 if (!S) {
9332 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
9333 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
9334 return true;
9335 }
9336 Condition = S;
9337 S = getExprAsWritten(S);
9338
9339 if (!CollapsedLoopVarDecls.empty()) {
9340 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
9341 if (!FSEC.TraverseStmt(S)) {
9342 SourceRange Range = FSEC.getErrRange();
9343 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
9344 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
9345 return true;
9346 }
9347 }
9348
9349 SourceLocation CondLoc = S->getBeginLoc();
9350 auto &&CheckAndSetCond =
9351 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
9352 const Expr *RHS, SourceRange SR,
9353 SourceLocation OpLoc) -> std::optional<bool> {
9354 if (BinaryOperator::isRelationalOp(Opcode)) {
9355 if (getInitLCDecl(LHS) == LCDecl)
9356 return setUB(const_cast<Expr *>(RHS),
9357 (Opcode == BO_LT || Opcode == BO_LE),
9358 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
9359 if (getInitLCDecl(RHS) == LCDecl)
9360 return setUB(const_cast<Expr *>(LHS),
9361 (Opcode == BO_GT || Opcode == BO_GE),
9362 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
9363 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
9364 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
9365 /*LessOp=*/std::nullopt,
9366 /*StrictOp=*/true, SR, OpLoc);
9367 }
9368 return std::nullopt;
9369 };
9370 std::optional<bool> Res;
9371 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
9372 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
9373 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
9374 RBO->getOperatorLoc());
9375 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
9376 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
9377 BO->getSourceRange(), BO->getOperatorLoc());
9378 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
9379 if (CE->getNumArgs() == 2) {
9380 Res = CheckAndSetCond(
9381 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
9382 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
9383 }
9384 }
9385 if (Res)
9386 return *Res;
9387 if (dependent() || SemaRef.CurContext->isDependentContext())
9388 return false;
9389 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
9390 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
9391 return true;
9392}
9393
9394bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
9395 // RHS of canonical loop form increment can be:
9396 // var + incr
9397 // incr + var
9398 // var - incr
9399 //
9400 RHS = RHS->IgnoreParenImpCasts();
9401 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
9402 if (BO->isAdditiveOp()) {
9403 bool IsAdd = BO->getOpcode() == BO_Add;
9404 if (getInitLCDecl(BO->getLHS()) == LCDecl)
9405 return setStep(BO->getRHS(), !IsAdd);
9406 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
9407 return setStep(BO->getLHS(), /*Subtract=*/false);
9408 }
9409 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
9410 bool IsAdd = CE->getOperator() == OO_Plus;
9411 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
9412 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
9413 return setStep(CE->getArg(1), !IsAdd);
9414 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
9415 return setStep(CE->getArg(0), /*Subtract=*/false);
9416 }
9417 }
9418 if (dependent() || SemaRef.CurContext->isDependentContext())
9419 return false;
9420 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
9421 << RHS->getSourceRange() << LCDecl;
9422 return true;
9423}
9424
9425bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
9426 // Check incr-expr for canonical loop form and return true if it
9427 // does not conform.
9428 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
9429 // ++var
9430 // var++
9431 // --var
9432 // var--
9433 // var += incr
9434 // var -= incr
9435 // var = var + incr
9436 // var = incr + var
9437 // var = var - incr
9438 //
9439 if (!S) {
9440 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
9441 return true;
9442 }
9443 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
9444 if (!ExprTemp->cleanupsHaveSideEffects())
9445 S = ExprTemp->getSubExpr();
9446
9447 if (!CollapsedLoopVarDecls.empty()) {
9448 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
9449 if (!FSEC.TraverseStmt(S)) {
9450 SourceRange Range = FSEC.getErrRange();
9451 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
9452 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
9453 return true;
9454 }
9455 }
9456
9457 IncrementSrcRange = S->getSourceRange();
9458 S = S->IgnoreParens();
9459 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
9460 if (UO->isIncrementDecrementOp() &&
9461 getInitLCDecl(UO->getSubExpr()) == LCDecl)
9462 return setStep(SemaRef
9463 .ActOnIntegerConstant(UO->getBeginLoc(),
9464 (UO->isDecrementOp() ? -1 : 1))
9465 .get(),
9466 /*Subtract=*/false);
9467 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
9468 switch (BO->getOpcode()) {
9469 case BO_AddAssign:
9470 case BO_SubAssign:
9471 if (getInitLCDecl(BO->getLHS()) == LCDecl)
9472 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
9473 break;
9474 case BO_Assign:
9475 if (getInitLCDecl(BO->getLHS()) == LCDecl)
9476 return checkAndSetIncRHS(BO->getRHS());
9477 break;
9478 default:
9479 break;
9480 }
9481 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
9482 switch (CE->getOperator()) {
9483 case OO_PlusPlus:
9484 case OO_MinusMinus:
9485 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
9486 return setStep(SemaRef
9487 .ActOnIntegerConstant(
9488 CE->getBeginLoc(),
9489 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
9490 .get(),
9491 /*Subtract=*/false);
9492 break;
9493 case OO_PlusEqual:
9494 case OO_MinusEqual:
9495 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
9496 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
9497 break;
9498 case OO_Equal:
9499 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
9500 return checkAndSetIncRHS(CE->getArg(1));
9501 break;
9502 default:
9503 break;
9504 }
9505 }
9506 if (dependent() || SemaRef.CurContext->isDependentContext())
9507 return false;
9508 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
9509 << S->getSourceRange() << LCDecl;
9510 return true;
9511}
9512
9513static ExprResult
9514tryBuildCapture(Sema &SemaRef, Expr *Capture,
9515 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9516 StringRef Name = ".capture_expr.") {
9517 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
9518 return Capture;
9519 // A statement expression must be captured even if it is constant, since the
9520 // declarations inside it can only be emitted once.
9521 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects) &&
9522 !findStmtExpr(Capture))
9523 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
9524 Capture->getType(),
9526 /*AllowExplicit=*/true);
9527 auto I = Captures.find(Capture);
9528 if (I != Captures.end())
9529 return buildCapture(SemaRef, Capture, I->second, Name);
9530 DeclRefExpr *Ref = nullptr;
9531 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
9532 Captures[Capture] = Ref;
9533 return Res;
9534}
9535
9536/// Calculate number of iterations, transforming to unsigned, if number of
9537/// iterations may be larger than the original type.
9538static Expr *
9539calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
9540 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
9541 bool TestIsStrictOp, bool RoundToStep,
9542 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9543 std::optional<unsigned> InitDependOnLC,
9544 std::optional<unsigned> CondDependOnLC) {
9545 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9546 if (!NewStep.isUsable())
9547 return nullptr;
9548 llvm::APSInt LRes, SRes;
9549 bool IsLowerConst = false, IsStepConst = false;
9550 if (std::optional<llvm::APSInt> Res =
9551 Lower->getIntegerConstantExpr(SemaRef.Context)) {
9552 LRes = *Res;
9553 IsLowerConst = true;
9554 }
9555 if (std::optional<llvm::APSInt> Res =
9556 Step->getIntegerConstantExpr(SemaRef.Context)) {
9557 SRes = *Res;
9558 IsStepConst = true;
9559 }
9560 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
9561 ((!TestIsStrictOp && LRes.isNonNegative()) ||
9562 (TestIsStrictOp && LRes.isStrictlyPositive()));
9563 bool NeedToReorganize = false;
9564 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
9565 if (!NoNeedToConvert && IsLowerConst &&
9566 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
9567 NoNeedToConvert = true;
9568 if (RoundToStep) {
9569 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
9570 ? LRes.getBitWidth()
9571 : SRes.getBitWidth();
9572 LRes = LRes.extend(BW + 1);
9573 LRes.setIsSigned(true);
9574 SRes = SRes.extend(BW + 1);
9575 SRes.setIsSigned(true);
9576 LRes -= SRes;
9577 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
9578 LRes = LRes.trunc(BW);
9579 }
9580 if (TestIsStrictOp) {
9581 unsigned BW = LRes.getBitWidth();
9582 LRes = LRes.extend(BW + 1);
9583 LRes.setIsSigned(true);
9584 ++LRes;
9585 NoNeedToConvert =
9586 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
9587 // truncate to the original bitwidth.
9588 LRes = LRes.trunc(BW);
9589 }
9590 NeedToReorganize = NoNeedToConvert;
9591 }
9592 llvm::APSInt URes;
9593 bool IsUpperConst = false;
9594 if (std::optional<llvm::APSInt> Res =
9595 Upper->getIntegerConstantExpr(SemaRef.Context)) {
9596 URes = *Res;
9597 IsUpperConst = true;
9598 }
9599 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
9600 (!RoundToStep || IsStepConst)) {
9601 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
9602 : URes.getBitWidth();
9603 LRes = LRes.extend(BW + 1);
9604 LRes.setIsSigned(true);
9605 URes = URes.extend(BW + 1);
9606 URes.setIsSigned(true);
9607 URes -= LRes;
9608 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
9609 NeedToReorganize = NoNeedToConvert;
9610 }
9611 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
9612 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
9613 // unsigned.
9614 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
9615 !LCTy->isDependentType() && LCTy->isIntegerType()) {
9616 QualType LowerTy = Lower->getType();
9617 QualType UpperTy = Upper->getType();
9618 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
9619 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
9620 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
9621 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
9623 SemaRef.Context, LowerSize > UpperSize ? LowerSize : UpperSize,
9624 /*Signed=*/false);
9625 Upper =
9626 SemaRef
9628 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9630 .get();
9631 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
9632 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
9633 }
9634 }
9635 if (!Lower || !Upper || NewStep.isInvalid())
9636 return nullptr;
9637
9638 ExprResult Diff;
9639
9640 // For nested triangular loops (depth >= 2), use already computed Upper and
9641 // Lower bounds to calculate the number of iterations: Upper - Lower + 1.
9642 // Don't apply to first-level triangular loops as the standard formula handles
9643 // those correctly.
9644 if (TestIsStrictOp && InitDependOnLC.has_value() &&
9645 InitDependOnLC.value() >= 2 && !CondDependOnLC.has_value()) {
9646 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
9647 if (!Diff.isUsable())
9648 return nullptr;
9649
9650 Diff =
9651 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(),
9652 SemaRef.ActOnIntegerConstant(DefaultLoc, 1).get());
9653 if (!Diff.isUsable())
9654 return nullptr;
9655
9656 return Diff.get();
9657 }
9658
9659 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
9660 // 1]).
9661 if (NeedToReorganize) {
9662 Diff = Lower;
9663
9664 // (Lower - Step [+ 1]) may be negative. Compute it in at least Upper's
9665 // width: in a narrower unsigned type it would wrap around and then be
9666 // zero-extended in the subtraction from Upper, giving a wrong number of
9667 // iterations, e.g. for
9668 // for (unsigned i = 0; i < (size_t)N; i += 2)
9669 QualType LowerTy = Lower->getType();
9670 QualType UpperTy = Upper->getType();
9671 if (!LowerTy->isDependentType() && !UpperTy->isDependentType() &&
9672 LowerTy->isIntegerType() && UpperTy->isIntegerType() &&
9673 SemaRef.Context.getTypeSize(LowerTy) <
9674 SemaRef.Context.getTypeSize(UpperTy)) {
9676 SemaRef.Context, SemaRef.Context.getTypeSize(UpperTy),
9678 Diff = SemaRef.PerformImplicitConversion(Lower, WideTy,
9680 if (!Diff.isUsable())
9681 return nullptr;
9682 }
9683
9684 if (RoundToStep) {
9685 // Lower - Step
9686 Diff =
9687 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
9688 if (!Diff.isUsable())
9689 return nullptr;
9690 }
9691
9692 // Lower - Step [+ 1]
9693 if (TestIsStrictOp)
9694 Diff = SemaRef.BuildBinOp(
9695 S, DefaultLoc, BO_Add, Diff.get(),
9696 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9697 if (!Diff.isUsable())
9698 return nullptr;
9699
9700 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9701 if (!Diff.isUsable())
9702 return nullptr;
9703
9704 // Upper - (Lower - Step [+ 1]).
9705 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
9706 if (!Diff.isUsable())
9707 return nullptr;
9708 } else {
9709 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
9710
9711 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
9712 // BuildBinOp already emitted error, this one is to point user to upper
9713 // and lower bound, and to tell what is passed to 'operator-'.
9714 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
9715 << Upper->getSourceRange() << Lower->getSourceRange();
9716 return nullptr;
9717 }
9718
9719 if (!Diff.isUsable())
9720 return nullptr;
9721
9722 // Upper - Lower [- 1]
9723 if (TestIsStrictOp)
9724 Diff = SemaRef.BuildBinOp(
9725 S, DefaultLoc, BO_Sub, Diff.get(),
9726 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
9727 if (!Diff.isUsable())
9728 return nullptr;
9729
9730 if (RoundToStep) {
9731 // Upper - Lower [- 1] + Step
9732 Diff =
9733 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
9734 if (!Diff.isUsable())
9735 return nullptr;
9736 }
9737 }
9738
9739 // Parentheses (for dumping/debugging purposes only).
9740 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9741 if (!Diff.isUsable())
9742 return nullptr;
9743
9744 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
9745 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
9746 if (!Diff.isUsable())
9747 return nullptr;
9748
9749 return Diff.get();
9750}
9751
9752/// Build the expression to calculate the number of iterations.
9753Expr *OpenMPIterationSpaceChecker::buildNumIterations(
9754 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
9755 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9756 QualType VarType = LCDecl->getType().getNonReferenceType();
9757 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9758 !SemaRef.getLangOpts().CPlusPlus)
9759 return nullptr;
9760 Expr *LBVal = LB;
9761 Expr *UBVal = UB;
9762 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
9763 // max(LB(MinVal), LB(MaxVal)))
9764 if (InitDependOnLC) {
9765 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
9766 if (!IS.MinValue || !IS.MaxValue)
9767 return nullptr;
9768 // OuterVar = Min
9769 ExprResult MinValue =
9770 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
9771 if (!MinValue.isUsable())
9772 return nullptr;
9773
9774 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9775 IS.CounterVar, MinValue.get());
9776 if (!LBMinVal.isUsable())
9777 return nullptr;
9778 // OuterVar = Min, LBVal
9779 LBMinVal =
9780 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
9781 if (!LBMinVal.isUsable())
9782 return nullptr;
9783 // (OuterVar = Min, LBVal)
9784 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
9785 if (!LBMinVal.isUsable())
9786 return nullptr;
9787
9788 // OuterVar = Max
9789 ExprResult MaxValue =
9790 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
9791 if (!MaxValue.isUsable())
9792 return nullptr;
9793
9794 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9795 IS.CounterVar, MaxValue.get());
9796 if (!LBMaxVal.isUsable())
9797 return nullptr;
9798 // OuterVar = Max, LBVal
9799 LBMaxVal =
9800 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
9801 if (!LBMaxVal.isUsable())
9802 return nullptr;
9803 // (OuterVar = Max, LBVal)
9804 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
9805 if (!LBMaxVal.isUsable())
9806 return nullptr;
9807
9808 Expr *LBMin =
9809 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
9810 Expr *LBMax =
9811 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
9812 if (!LBMin || !LBMax)
9813 return nullptr;
9814 // LB(MinVal) < LB(MaxVal)
9815 ExprResult MinLessMaxRes =
9816 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
9817 if (!MinLessMaxRes.isUsable())
9818 return nullptr;
9819 Expr *MinLessMax =
9820 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
9821 .get();
9822 if (!MinLessMax)
9823 return nullptr;
9824 if (*TestIsLessOp) {
9825 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
9826 // LB(MaxVal))
9827 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
9828 MinLessMax, LBMin, LBMax);
9829 if (!MinLB.isUsable())
9830 return nullptr;
9831 LBVal = MinLB.get();
9832 } else {
9833 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
9834 // LB(MaxVal))
9835 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
9836 MinLessMax, LBMax, LBMin);
9837 if (!MaxLB.isUsable())
9838 return nullptr;
9839 LBVal = MaxLB.get();
9840 }
9841 // OuterVar = LB
9842 LBMinVal =
9843 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
9844 if (!LBMinVal.isUsable())
9845 return nullptr;
9846 LBVal = LBMinVal.get();
9847 }
9848 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
9849 // min(UB(MinVal), UB(MaxVal))
9850 if (CondDependOnLC) {
9851 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9852 if (!IS.MinValue || !IS.MaxValue)
9853 return nullptr;
9854 // OuterVar = Min
9855 ExprResult MinValue =
9856 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
9857 if (!MinValue.isUsable())
9858 return nullptr;
9859
9860 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9861 IS.CounterVar, MinValue.get());
9862 if (!UBMinVal.isUsable())
9863 return nullptr;
9864 // OuterVar = Min, UBVal
9865 UBMinVal =
9866 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
9867 if (!UBMinVal.isUsable())
9868 return nullptr;
9869 // (OuterVar = Min, UBVal)
9870 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
9871 if (!UBMinVal.isUsable())
9872 return nullptr;
9873
9874 // OuterVar = Max
9875 ExprResult MaxValue =
9876 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
9877 if (!MaxValue.isUsable())
9878 return nullptr;
9879
9880 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9881 IS.CounterVar, MaxValue.get());
9882 if (!UBMaxVal.isUsable())
9883 return nullptr;
9884 // OuterVar = Max, UBVal
9885 UBMaxVal =
9886 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
9887 if (!UBMaxVal.isUsable())
9888 return nullptr;
9889 // (OuterVar = Max, UBVal)
9890 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
9891 if (!UBMaxVal.isUsable())
9892 return nullptr;
9893
9894 Expr *UBMin =
9895 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
9896 Expr *UBMax =
9897 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
9898 if (!UBMin || !UBMax)
9899 return nullptr;
9900 // UB(MinVal) > UB(MaxVal)
9901 ExprResult MinGreaterMaxRes =
9902 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9903 if (!MinGreaterMaxRes.isUsable())
9904 return nullptr;
9905 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
9906 Captures, ".min_greater_max")
9907 .get();
9908 if (!MinGreaterMax)
9909 return nullptr;
9910 if (*TestIsLessOp) {
9911 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9912 // UB(MaxVal))
9913 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9914 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9915 if (!MaxUB.isUsable())
9916 return nullptr;
9917 UBVal = MaxUB.get();
9918 } else {
9919 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9920 // UB(MaxVal))
9921 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9922 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9923 if (!MinUB.isUsable())
9924 return nullptr;
9925 UBVal = MinUB.get();
9926 }
9927 }
9928 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9929 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9930 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9931 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9932 if (!Upper || !Lower)
9933 return nullptr;
9934
9935 ExprResult Diff = calculateNumIters(
9936 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9937 /*RoundToStep=*/true, Captures, InitDependOnLC, CondDependOnLC);
9938 if (!Diff.isUsable())
9939 return nullptr;
9940
9941 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9942 QualType Type = Diff.get()->getType();
9943 ASTContext &C = SemaRef.Context;
9944 bool UseVarType = VarType->hasIntegerRepresentation() &&
9945 C.getTypeSize(Type) > C.getTypeSize(VarType);
9946 if (!Type->isIntegerType() || UseVarType) {
9947 unsigned NewSize =
9948 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9949 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9951 Type = getIntTypeForBitwidthOrBitInt(C, NewSize, IsSigned);
9952 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9953 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9955 /*AllowExplicit=*/true);
9956 if (!Diff.isUsable())
9957 return nullptr;
9958 }
9959 }
9960 if (LimitedType) {
9961 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9962 if (NewSize != C.getTypeSize(Type)) {
9963 if (NewSize < C.getTypeSize(Type)) {
9964 assert(NewSize == 64 && "incorrect loop var size");
9965 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9966 << InitSrcRange << ConditionSrcRange;
9967 }
9968 QualType NewType = C.getIntTypeForBitwidth(
9970 C.getTypeSize(Type) < NewSize);
9971 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9972 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9974 /*AllowExplicit=*/true);
9975 if (!Diff.isUsable())
9976 return nullptr;
9977 }
9978 }
9979 }
9980
9981 return Diff.get();
9982}
9983
9984std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9985 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9986 // Do not build for iterators, they cannot be used in non-rectangular loop
9987 // nests.
9988 if (LCDecl->getType()->isRecordType())
9989 return std::make_pair(nullptr, nullptr);
9990 // If we subtract, the min is in the condition, otherwise the min is in the
9991 // init value.
9992 Expr *MinExpr = nullptr;
9993 Expr *MaxExpr = nullptr;
9994 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9995 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9996 bool LBNonRect =
9997 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9998 bool UBNonRect =
9999 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
10000 Expr *Lower =
10001 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
10002 Expr *Upper =
10003 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
10004 if (!Upper || !Lower)
10005 return std::make_pair(nullptr, nullptr);
10006
10007 if (*TestIsLessOp)
10008 MinExpr = Lower;
10009 else
10010 MaxExpr = Upper;
10011
10012 // Build minimum/maximum value based on number of iterations.
10013 QualType VarType = LCDecl->getType().getNonReferenceType();
10014
10015 ExprResult Diff = calculateNumIters(
10016 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
10017 /*RoundToStep=*/false, Captures, InitDependOnLC, CondDependOnLC);
10018
10019 if (!Diff.isUsable())
10020 return std::make_pair(nullptr, nullptr);
10021
10022 // ((Upper - Lower [- 1]) / Step) * Step
10023 // Parentheses (for dumping/debugging purposes only).
10024 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
10025 if (!Diff.isUsable())
10026 return std::make_pair(nullptr, nullptr);
10027
10028 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
10029 if (!NewStep.isUsable())
10030 return std::make_pair(nullptr, nullptr);
10031 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
10032 if (!Diff.isUsable())
10033 return std::make_pair(nullptr, nullptr);
10034
10035 // Parentheses (for dumping/debugging purposes only).
10036 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
10037 if (!Diff.isUsable())
10038 return std::make_pair(nullptr, nullptr);
10039
10040 // Convert to the ptrdiff_t, if original type is pointer.
10041 if (VarType->isAnyPointerType() &&
10042 !SemaRef.Context.hasSameType(
10043 Diff.get()->getType(),
10045 Diff = SemaRef.PerformImplicitConversion(
10046 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
10047 AssignmentAction::Converting, /*AllowExplicit=*/true);
10048 }
10049 if (!Diff.isUsable())
10050 return std::make_pair(nullptr, nullptr);
10051
10052 if (*TestIsLessOp) {
10053 // MinExpr = Lower;
10054 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
10055 Diff = SemaRef.BuildBinOp(
10056 S, DefaultLoc, BO_Add,
10057 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
10058 Diff.get());
10059 if (!Diff.isUsable())
10060 return std::make_pair(nullptr, nullptr);
10061 } else {
10062 // MaxExpr = Upper;
10063 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
10064 Diff = SemaRef.BuildBinOp(
10065 S, DefaultLoc, BO_Sub,
10066 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
10067 Diff.get());
10068 if (!Diff.isUsable())
10069 return std::make_pair(nullptr, nullptr);
10070 }
10071
10072 // Convert to the original type.
10073 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
10074 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
10076 /*AllowExplicit=*/true);
10077 if (!Diff.isUsable())
10078 return std::make_pair(nullptr, nullptr);
10079
10080 Sema::TentativeAnalysisScope Trap(SemaRef);
10081 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
10082 if (!Diff.isUsable())
10083 return std::make_pair(nullptr, nullptr);
10084
10085 if (*TestIsLessOp)
10086 MaxExpr = Diff.get();
10087 else
10088 MinExpr = Diff.get();
10089
10090 return std::make_pair(MinExpr, MaxExpr);
10091}
10092
10093Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
10094 if (InitDependOnLC || CondDependOnLC)
10095 return Condition;
10096 return nullptr;
10097}
10098
10099Expr *OpenMPIterationSpaceChecker::buildPreCond(
10100 Scope *S, Expr *Cond,
10101 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
10102 // Do not build a precondition when the condition/initialization is dependent
10103 // to prevent pessimistic early loop exit.
10104 // TODO: this can be improved by calculating min/max values but not sure that
10105 // it will be very effective.
10106 if (CondDependOnLC || InitDependOnLC)
10107 return SemaRef
10109 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
10110 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
10111 /*AllowExplicit=*/true)
10112 .get();
10113
10114 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
10115 Sema::TentativeAnalysisScope Trap(SemaRef);
10116
10117 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
10118 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
10119 if (!NewLB.isUsable() || !NewUB.isUsable())
10120 return nullptr;
10121
10122 ExprResult CondExpr =
10123 SemaRef.BuildBinOp(S, DefaultLoc,
10124 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
10125 : (TestIsStrictOp ? BO_GT : BO_GE),
10126 NewLB.get(), NewUB.get());
10127 if (CondExpr.isUsable()) {
10128 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
10129 SemaRef.Context.BoolTy))
10130 CondExpr = SemaRef.PerformImplicitConversion(
10131 CondExpr.get(), SemaRef.Context.BoolTy,
10132 /*Action=*/AssignmentAction::Casting,
10133 /*AllowExplicit=*/true);
10134 }
10135
10136 // Otherwise use original loop condition and evaluate it in runtime.
10137 return CondExpr.isUsable() ? CondExpr.get() : Cond;
10138}
10139
10140/// Build reference expression to the counter be used for codegen.
10141DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
10142 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
10143 DSAStackTy &DSA) const {
10144 auto *VD = dyn_cast<VarDecl>(LCDecl);
10145 if (!VD) {
10146 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
10148 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
10149 const DSAStackTy::DSAVarData Data =
10150 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
10151 // If the loop control decl is explicitly marked as private, do not mark it
10152 // as captured again.
10153 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
10154 Captures.insert(std::make_pair(LCRef, Ref));
10155 return Ref;
10156 }
10157 return cast<DeclRefExpr>(LCRef);
10158}
10159
10160Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
10161 if (LCDecl && !LCDecl->isInvalidDecl()) {
10163 VarDecl *PrivateVar = buildVarDecl(
10164 SemaRef, DefaultLoc, Type, LCDecl->getName(),
10165 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
10166 isa<VarDecl>(LCDecl)
10167 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
10168 : nullptr);
10169 if (PrivateVar->isInvalidDecl())
10170 return nullptr;
10171 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
10172 }
10173 return nullptr;
10174}
10175
10176/// Build initialization of the counter to be used for codegen.
10177Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
10178
10179/// Build step of the counter be used for codegen.
10180Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
10181
10182Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
10183 Scope *S, Expr *Counter,
10184 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
10185 Expr *Inc, OverloadedOperatorKind OOK) {
10186 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
10187 if (!Cnt)
10188 return nullptr;
10189 if (Inc) {
10190 assert((OOK == OO_Plus || OOK == OO_Minus) &&
10191 "Expected only + or - operations for depend clauses.");
10192 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
10193 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
10194 if (!Cnt)
10195 return nullptr;
10196 }
10197 QualType VarType = LCDecl->getType().getNonReferenceType();
10198 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
10199 !SemaRef.getLangOpts().CPlusPlus)
10200 return nullptr;
10201 // Upper - Lower
10202 Expr *Upper =
10203 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
10204 Expr *Lower =
10205 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
10206 if (!Upper || !Lower)
10207 return nullptr;
10208
10209 ExprResult Diff =
10210 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
10211 /*TestIsStrictOp=*/false, /*RoundToStep=*/false,
10212 Captures, InitDependOnLC, CondDependOnLC);
10213 if (!Diff.isUsable())
10214 return nullptr;
10215
10216 return Diff.get();
10217}
10218} // namespace
10219
10221 Stmt *Init) {
10222 assert(getLangOpts().OpenMP && "OpenMP is not active.");
10223 assert(Init && "Expected loop in canonical form.");
10224 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
10225 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
10226 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
10227 return;
10228
10229 DSAStack->loopStart();
10231 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
10232 *DSAStack, ForLoc, EmptyDeclSet,
10233 EmptyDeclSet);
10234 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
10235 if (ValueDecl *D = ISC.getLoopDecl()) {
10236 auto *VD = dyn_cast<VarDecl>(D);
10237 DeclRefExpr *PrivateRef = nullptr;
10238 if (!VD) {
10240 VD = Private;
10241 } else {
10242 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
10243 /*WithInit=*/false);
10244 VD = cast<VarDecl>(PrivateRef->getDecl());
10245 }
10246 }
10247 DSAStack->addLoopControlVariable(D, VD);
10248 const Decl *LD = DSAStack->getPossiblyLoopCounter();
10249 if (LD != D->getCanonicalDecl()) {
10250 DSAStack->resetPossibleLoopCounter();
10251 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
10252 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
10253 SemaRef, const_cast<VarDecl *>(Var),
10254 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
10255 /*RefersToCapture=*/true));
10256 }
10257 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
10258 // Referenced in a Construct, C/C++]. The loop iteration variable in the
10259 // associated for-loop of a simd construct with just one associated
10260 // for-loop may be listed in a linear clause with a constant-linear-step
10261 // that is the increment of the associated for-loop. The loop iteration
10262 // variable(s) in the associated for-loop(s) of a for or parallel for
10263 // construct may be listed in a private or lastprivate clause.
10264 DSAStackTy::DSAVarData DVar =
10265 DSAStack->getTopDSA(D, /*FromParent=*/false);
10266 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
10267 // is declared in the loop and it is predetermined as a private.
10268 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
10269 OpenMPClauseKind PredeterminedCKind =
10271 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
10272 : OMPC_private;
10273 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
10274 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
10275 };
10276 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
10277 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
10278 (getLangOpts().OpenMP <= 45 ||
10279 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
10281 IsOpenMPTaskloopDirective(DKind) ||
10283 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
10284 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
10285 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
10286 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
10287 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
10288 << getOpenMPClauseNameForDiag(DVar.CKind)
10289 << getOpenMPDirectiveName(DKind, OMPVersion)
10290 << getOpenMPClauseNameForDiag(PredeterminedCKind);
10291 if (DVar.RefExpr == nullptr)
10292 DVar.CKind = PredeterminedCKind;
10293 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
10294 } else if (LoopDeclRefExpr) {
10295 // Make the loop iteration variable private (for worksharing
10296 // constructs), linear (for simd directives with the only one
10297 // associated loop) or lastprivate (for simd directives with several
10298 // collapsed or ordered loops).
10299 if (DVar.CKind == OMPC_unknown)
10300 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
10301 }
10302 }
10303 }
10304 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
10305}
10306
10307namespace {
10308// Utility for OpenMP doacross clause kind
10309class OMPDoacrossKind {
10310public:
10311 bool isSource(const OMPDoacrossClause *C) {
10312 return C->getDependenceType() == OMPC_DOACROSS_source ||
10313 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
10314 }
10315 bool isSink(const OMPDoacrossClause *C) {
10316 return C->getDependenceType() == OMPC_DOACROSS_sink;
10317 }
10318 bool isSinkIter(const OMPDoacrossClause *C) {
10319 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
10320 }
10321};
10322} // namespace
10323/// Called on a for stmt to check and extract its iteration space
10324/// for further processing (such as collapsing).
10326 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
10327 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
10328 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
10329 Expr *OrderedLoopCountExpr,
10330 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
10332 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
10333 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls,
10334 llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopInductionVars) {
10335 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
10336
10337 // See the tile reinterpretation design note in ActOnOpenMPTileDirective.
10338 // If the loop carries the hint, analyze its rectangular form instead.
10339 //
10340 // Only directives that emit the per-iteration body guard (i.e. those going
10341 // through EmitOMPLoopBody's finals-conditions handling) may reinterpret the
10342 // loop; a loop transformation such as an enclosing 'tile' has nowhere to put
10343 // the overshoot guard, so for those the stored min-bounded form is analyzed
10344 // exactly as it is on a build without this hint.
10345 // OpenMP [2.9.1, Canonical Loop Form]
10346 // for (init-expr; test-expr; incr-expr) structured-block
10347 // for (range-decl: range-expr) structured-block
10348 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
10349 S = CanonLoop->getLoopStmt();
10350 const OMPInvariantPredicateBoundAttr *IntraTileHint =
10351 OMPLoopBasedDirective::getIntraTileHint(S);
10352 if (IntraTileHint)
10353 S = OMPLoopBasedDirective::ignoreIntraTileHint(S);
10354 Expr *TileRectCond = nullptr;
10355 Expr *TileBodyPredicate = nullptr;
10356 Expr *TileTripCount = nullptr;
10357 if (IntraTileHint && !isOpenMPLoopTransformationDirective(DKind)) {
10358 TileRectCond = IntraTileHint->getRectCond();
10359 TileBodyPredicate = IntraTileHint->getPredicate();
10360 TileTripCount = IntraTileHint->getTileSize();
10361 }
10362 auto *For = dyn_cast_or_null<ForStmt>(S);
10363 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
10364 // Ranged for is supported only in OpenMP 5.0.
10365 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
10366 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
10367 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
10368 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
10369 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
10370 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
10371 if (TotalNestedLoopCount > 1) {
10372 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
10373 SemaRef.Diag(DSA.getConstructLoc(),
10374 diag::note_omp_collapse_ordered_expr)
10375 << 2 << CollapseLoopCountExpr->getSourceRange()
10376 << OrderedLoopCountExpr->getSourceRange();
10377 else if (CollapseLoopCountExpr)
10378 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
10379 diag::note_omp_collapse_ordered_expr)
10380 << 0 << CollapseLoopCountExpr->getSourceRange();
10381 else if (OrderedLoopCountExpr)
10382 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
10383 diag::note_omp_collapse_ordered_expr)
10384 << 1 << OrderedLoopCountExpr->getSourceRange();
10385 }
10386 return true;
10387 }
10388 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
10389 "No loop body.");
10390 // Postpone analysis in dependent contexts for ranged for loops.
10391 if (CXXFor && SemaRef.CurContext->isDependentContext())
10392 return false;
10393
10394 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
10395 For ? For->getForLoc() : CXXFor->getForLoc(),
10396 CollapsedLoopVarDecls,
10397 CollapsedLoopInductionVars);
10398
10399 // Check init.
10400 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
10401 if (ISC.checkAndSetInit(Init))
10402 return true;
10403
10404 bool HasErrors = false;
10405
10406 // Condition used for iteration-space analysis: the rectangular hint when
10407 // reinterpreting an intra-tile loop, otherwise the loop's own condition.
10408 Expr *EffectiveCond =
10409 TileRectCond ? TileRectCond : (For ? For->getCond() : CXXFor->getCond());
10410
10411 // Check loop variable's type.
10412 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
10413 // OpenMP [2.6, Canonical Loop Form]
10414 // Var is one of the following:
10415 // A variable of signed or unsigned integer type.
10416 // For C++, a variable of a random access iterator type.
10417 // For C, a variable of a pointer type.
10418 QualType VarType = LCDecl->getType().getNonReferenceType();
10419 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
10420 !VarType->isPointerType() &&
10421 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
10422 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
10423 << SemaRef.getLangOpts().CPlusPlus;
10424 HasErrors = true;
10425 }
10426
10427 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
10428 // a Construct
10429 // The loop iteration variable(s) in the associated for-loop(s) of a for or
10430 // parallel for construct is (are) private.
10431 // The loop iteration variable in the associated for-loop of a simd
10432 // construct with just one associated for-loop is linear with a
10433 // constant-linear-step that is the increment of the associated for-loop.
10434 // Exclude loop var from the list of variables with implicitly defined data
10435 // sharing attributes.
10436 VarsWithImplicitDSA.erase(LCDecl);
10437
10438 assert((isOpenMPLoopDirective(DKind) ||
10440 "DSA for non-loop vars");
10441
10442 // Check test-expr.
10443 HasErrors |= ISC.checkAndSetCond(EffectiveCond);
10444
10445 // Check incr-expr.
10446 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
10447 }
10448
10449 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
10450 return HasErrors;
10451
10452 // Build the loop's iteration space representation.
10453 //
10454 // A reinterpreted intra-tile loop takes all three of these from the hint
10455 // instead of deriving them: the precondition is trivially true (the floor
10456 // loop's own precondition already covers an empty iteration space), the trip
10457 // count is the constant tile size, and any overshoot on the remainder tile
10458 // is handled by the body guard.
10459 if (TileRectCond) {
10460 ResultIterSpaces[CurrentNestedLoopCount].PreCond =
10461 SemaRef
10463 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
10465 /*AllowExplicit=*/true)
10466 .get();
10467 ResultIterSpaces[CurrentNestedLoopCount].NumIterations = TileTripCount;
10468 } else {
10469 ResultIterSpaces[CurrentNestedLoopCount].PreCond =
10470 ISC.buildPreCond(DSA.getCurScope(), EffectiveCond, Captures);
10471 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
10472 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
10478 Captures);
10479 }
10480 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
10481 ISC.buildCounterVar(Captures, DSA);
10482 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
10483 ISC.buildPrivateCounterVar();
10484 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
10485 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
10486 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
10487 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
10488 ISC.getConditionSrcRange();
10489 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
10490 ISC.getIncrementSrcRange();
10491 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
10492 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
10493 ISC.isStrictTestOp();
10494 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
10495 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
10496 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
10497 if (TileRectCond) {
10498 // Floor is not a registered loop-control variable, so this helper is null.
10499 // Use the overshoot guard only (null when N % T == 0).
10500 assert(!ISC.buildFinalCondition(DSA.getCurScope()) &&
10501 "intra-tile floor is not a registered loop-control variable");
10502 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition = TileBodyPredicate;
10503
10504 // Re-read .floor.iv each outer trip. Match it to an outer collapsed
10505 // counter.
10506 bool FoundFloor = false;
10507 if (Expr *InitExpr = ResultIterSpaces[CurrentNestedLoopCount].CounterInit) {
10508 if (const auto *LBRef =
10509 dyn_cast<DeclRefExpr>(InitExpr->IgnoreParenImpCasts())) {
10510 const Decl *FloorDecl = LBRef->getDecl()->getCanonicalDecl();
10511 for (unsigned K = 0; K < CurrentNestedLoopCount; ++K) {
10512 const auto *CV =
10513 dyn_cast_or_null<DeclRefExpr>(ResultIterSpaces[K].CounterVar);
10514 if (CV && CV->getDecl()->getCanonicalDecl() == FloorDecl) {
10515 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB = true;
10516 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx = K + 1;
10517 FoundFloor = true;
10518 break;
10519 }
10520 }
10521 }
10522 }
10523 if (!FoundFloor) {
10524 // The floor this intra-tile loop starts from is not one of the
10525 // collapsed counters: it is assigned in the body of an enclosing
10526 // transformed loop, so the collapsed nest would read a stale value
10527 // instead of recomputing it per iteration. Diagnose to avoid silently
10528 // producing the wrong iteration space.
10529 SemaRef.Diag(ISC.getInitSrcRange().getBegin(),
10530 diag::err_omp_collapse_stacked_tile)
10531 << /*Collapse=*/0;
10532 return true;
10533 }
10534 } else {
10535 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
10536 ISC.buildFinalCondition(DSA.getCurScope());
10537 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
10538 ISC.doesInitDependOnLC();
10539 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
10540 ISC.doesCondDependOnLC();
10541 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
10542 ISC.getLoopDependentIdx();
10543 }
10544
10545 HasErrors |=
10546 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
10547 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
10548 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
10549 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
10550 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
10551 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
10552 if (!HasErrors && DSA.isOrderedRegion()) {
10553 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
10554 if (CurrentNestedLoopCount <
10555 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
10556 DSA.getOrderedRegionParam().second->setLoopNumIterations(
10557 CurrentNestedLoopCount,
10558 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
10559 DSA.getOrderedRegionParam().second->setLoopCounter(
10560 CurrentNestedLoopCount,
10561 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
10562 }
10563 }
10564 for (auto &Pair : DSA.getDoacrossDependClauses()) {
10565 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
10566 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
10567 unsigned NumLoops =
10568 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
10569 if (CurrentNestedLoopCount >= NumLoops) {
10570 // Erroneous case - clause has some problems.
10571 continue;
10572 }
10573 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
10574 Pair.second.size() <= CurrentNestedLoopCount) {
10575 // Erroneous case - clause has some problems.
10576 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
10577 continue;
10578 }
10579 OMPDoacrossKind ODK;
10580 if (DoacrossC && ODK.isSink(DoacrossC) &&
10581 Pair.second.size() <= CurrentNestedLoopCount) {
10582 // Erroneous case - clause has some problems.
10583 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
10584 continue;
10585 }
10586 Expr *CntValue;
10587 SourceLocation DepLoc =
10588 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
10589 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
10590 (DoacrossC && ODK.isSource(DoacrossC)))
10591 CntValue = ISC.buildOrderedLoopData(
10592 DSA.getCurScope(),
10593 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10594 DepLoc);
10595 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
10596 Expr *Cnt = SemaRef
10598 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
10599 .get();
10600 if (!Cnt)
10601 continue;
10602 // build CounterVar - 1
10603 Expr *Inc =
10604 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
10605 .get();
10606 CntValue = ISC.buildOrderedLoopData(
10607 DSA.getCurScope(),
10608 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10609 DepLoc, Inc, clang::OO_Minus);
10610 } else
10611 CntValue = ISC.buildOrderedLoopData(
10612 DSA.getCurScope(),
10613 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
10614 DepLoc, Pair.second[CurrentNestedLoopCount].first,
10615 Pair.second[CurrentNestedLoopCount].second);
10616 if (DependC)
10617 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
10618 else
10619 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
10620 }
10621 }
10622 // Record the loop induction variable for nested loop reuse checking.
10623 if (CurrentNestedLoopCount < NestedLoopCount && !HasErrors) {
10624 if (const ValueDecl *LCDecl = ISC.getLoopDecl())
10625 CollapsedLoopInductionVars.insert(LCDecl->getCanonicalDecl());
10626 }
10627 return HasErrors;
10628}
10629
10630/// Build 'VarRef = Start.
10631static ExprResult
10633 ExprResult Start, bool IsNonRectangularLB,
10634 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
10635 // Build 'VarRef = Start.
10636 ExprResult NewStart = IsNonRectangularLB
10637 ? Start.get()
10638 : tryBuildCapture(SemaRef, Start.get(), Captures);
10639 if (!NewStart.isUsable())
10640 return ExprError();
10641 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
10642 VarRef.get()->getType())) {
10643 NewStart = SemaRef.PerformImplicitConversion(
10644 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
10645 /*AllowExplicit=*/true);
10646 if (!NewStart.isUsable())
10647 return ExprError();
10648 }
10649
10651 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
10652 return Init;
10653}
10654
10655/// Build 'VarRef = Start + Iter * Step'.
10657 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
10658 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
10659 bool IsNonRectangularLB,
10660 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
10661 // Add parentheses (for debugging purposes only).
10662 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
10663 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
10664 !Step.isUsable())
10665 return ExprError();
10666
10667 ExprResult NewStep = Step;
10668 if (Captures)
10669 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
10670 if (NewStep.isInvalid())
10671 return ExprError();
10673 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
10674 if (!Update.isUsable())
10675 return ExprError();
10676
10677 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
10678 // 'VarRef = Start (+|-) Iter * Step'.
10679 if (!Start.isUsable())
10680 return ExprError();
10681 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
10682 if (!NewStart.isUsable())
10683 return ExprError();
10684 if (Captures && !IsNonRectangularLB)
10685 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
10686 if (NewStart.isInvalid())
10687 return ExprError();
10688
10689 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
10690 ExprResult SavedUpdate = Update;
10691 ExprResult UpdateVal;
10692 if (VarRef.get()->getType()->isOverloadableType() ||
10693 NewStart.get()->getType()->isOverloadableType() ||
10694 Update.get()->getType()->isOverloadableType()) {
10695 Sema::TentativeAnalysisScope Trap(SemaRef);
10696
10697 Update =
10698 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
10699 if (Update.isUsable()) {
10700 UpdateVal =
10701 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
10702 VarRef.get(), SavedUpdate.get());
10703 if (UpdateVal.isUsable()) {
10704 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
10705 UpdateVal.get());
10706 }
10707 }
10708 }
10709
10710 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
10711 if (!Update.isUsable() || !UpdateVal.isUsable()) {
10712 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
10713 NewStart.get(), SavedUpdate.get());
10714 if (!Update.isUsable())
10715 return ExprError();
10716
10717 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
10718 VarRef.get()->getType())) {
10720 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
10721 /*AllowExplicit=*/true);
10722 if (!Update.isUsable())
10723 return ExprError();
10724 }
10725
10726 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
10727 }
10728 return Update;
10729}
10730
10731/// Convert integer expression \a E to make it have at least \a Bits
10732/// bits.
10733static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
10734 if (E == nullptr)
10735 return ExprError();
10736 ASTContext &C = SemaRef.Context;
10737 QualType OldType = E->getType();
10738 unsigned HasBits = C.getTypeSize(OldType);
10739 if (HasBits >= Bits)
10740 return ExprResult(E);
10741 // OK to convert to signed, because new type has more bits than old.
10742 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
10743 return SemaRef.PerformImplicitConversion(
10744 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
10745}
10746
10747/// Check if the given expression \a E is a constant integer that fits
10748/// into \a Bits bits.
10749static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
10750 if (E == nullptr)
10751 return false;
10752 if (std::optional<llvm::APSInt> Result =
10753 E->getIntegerConstantExpr(SemaRef.Context))
10754 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
10755 return false;
10756}
10757
10758/// Build preinits statement for the given declarations.
10760 MutableArrayRef<Decl *> PreInits) {
10761 if (!PreInits.empty()) {
10762 return new (Context) DeclStmt(
10763 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
10765 }
10766 return nullptr;
10767}
10768
10769/// Append the \p Item or the content of a CompoundStmt to the list \p
10770/// TargetList.
10771///
10772/// A CompoundStmt is used as container in case multiple statements need to be
10773/// stored in lieu of using an explicit list. Flattening is necessary because
10774/// contained DeclStmts need to be visible after the execution of the list. Used
10775/// for OpenMP pre-init declarations/statements.
10777 Stmt *Item) {
10778 // nullptr represents an empty list.
10779 if (!Item)
10780 return;
10781
10782 if (auto *CS = dyn_cast<CompoundStmt>(Item))
10783 llvm::append_range(TargetList, CS->body());
10784 else
10785 TargetList.push_back(Item);
10786}
10787
10788/// Build preinits statement for the given declarations.
10789static Stmt *
10791 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
10792 if (!Captures.empty()) {
10793 SmallVector<Decl *, 16> PreInits;
10794 for (const auto &Pair : Captures)
10795 PreInits.push_back(Pair.second->getDecl());
10796 return buildPreInits(Context, PreInits);
10797 }
10798 return nullptr;
10799}
10800
10801/// Build pre-init statement for the given statements.
10802static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
10803 if (PreInits.empty())
10804 return nullptr;
10805
10806 SmallVector<Stmt *> Stmts;
10807 for (Stmt *S : PreInits)
10808 appendFlattenedStmtList(Stmts, S);
10809 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
10810}
10811
10812/// Build postupdate expression for the given list of postupdates expressions.
10813static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
10814 Expr *PostUpdate = nullptr;
10815 if (!PostUpdates.empty()) {
10816 for (Expr *E : PostUpdates) {
10817 Expr *ConvE = S.BuildCStyleCastExpr(
10818 E->getExprLoc(),
10820 E->getExprLoc(), E)
10821 .get();
10822 PostUpdate = PostUpdate
10823 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
10824 PostUpdate, ConvE)
10825 .get()
10826 : ConvE;
10827 }
10828 }
10829 return PostUpdate;
10830}
10831
10832/// Look for variables declared in the body parts of a for-loop nest. Used
10833/// for verifying loop nest structure before performing a loop collapse
10834/// operation.
10836 int NestingDepth = 0;
10837 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
10838
10839public:
10840 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
10841 : VarDecls(VD) {}
10842
10843 bool VisitForStmt(ForStmt *F) override {
10844 ++NestingDepth;
10845 TraverseStmt(F->getBody());
10846 --NestingDepth;
10847 return false;
10848 }
10849
10851 ++NestingDepth;
10852 TraverseStmt(RF->getBody());
10853 --NestingDepth;
10854 return false;
10855 }
10856
10857 bool VisitVarDecl(VarDecl *D) override {
10858 Decl *C = D->getCanonicalDecl();
10859 if (NestingDepth > 0)
10860 VarDecls.insert(C);
10861 return true;
10862 }
10863};
10864
10865/// Called on a for stmt to check itself and nested loops (if any).
10866/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
10867/// number of collapsed loops otherwise.
10868static unsigned
10869checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
10870 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
10871 DSAStackTy &DSA,
10872 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
10873 OMPLoopBasedDirective::HelperExprs &Built) {
10874 // If either of the loop expressions exist and contain errors, we bail out
10875 // early because diagnostics have already been emitted and we can't reliably
10876 // check more about the loop.
10877 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
10878 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
10879 return 0;
10880
10881 unsigned NestedLoopCount = 1;
10882 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
10884 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
10885 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopInductionVars;
10886
10887 if (CollapseLoopCountExpr) {
10888 // Found 'collapse' clause - calculate collapse number.
10890 if (!CollapseLoopCountExpr->isInstantiationDependent() &&
10891 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
10892 NestedLoopCount = Result.Val.getInt().getLimitedValue();
10893
10894 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
10895 FVDF.TraverseStmt(AStmt);
10896 } else {
10897 Built.clear(/*Size=*/1);
10898 return 1;
10899 }
10900 }
10901 unsigned OrderedLoopCount = 1;
10902 if (OrderedLoopCountExpr) {
10903 // Found 'ordered' clause - calculate collapse number.
10904 Expr::EvalResult EVResult;
10905 if (!OrderedLoopCountExpr->isInstantiationDependent() &&
10906 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
10907 SemaRef.getASTContext())) {
10908 llvm::APSInt Result = EVResult.Val.getInt();
10909 if (Result.getLimitedValue() < NestedLoopCount) {
10910 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
10911 diag::err_omp_wrong_ordered_loop_count)
10912 << OrderedLoopCountExpr->getSourceRange();
10913 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
10914 diag::note_collapse_loop_count)
10915 << CollapseLoopCountExpr->getSourceRange();
10916 }
10917 OrderedLoopCount = Result.getLimitedValue();
10918 } else {
10919 Built.clear(/*Size=*/1);
10920 return 1;
10921 }
10922 }
10923 // This is helper routine for loop directives (e.g., 'for', 'simd',
10924 // 'for simd', etc.).
10925 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
10926 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
10927 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
10928 if (!OMPLoopBasedDirective::doForAllLoops(
10929 AStmt->IgnoreContainers(
10931 SupportsNonPerfectlyNested, NumLoops,
10932 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10933 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10934 &IterSpaces, &Captures, &CollapsedLoopVarDecls,
10935 &CollapsedLoopInductionVars](unsigned Cnt, Stmt *Loop,
10936 Stmt *HintWrapper) {
10937 Stmt *CurStmt = HintWrapper ? HintWrapper : Loop;
10939 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
10940 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10941 VarsWithImplicitDSA, IterSpaces, Captures,
10942 CollapsedLoopVarDecls, CollapsedLoopInductionVars))
10943 return true;
10944 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10945 IterSpaces[Cnt].CounterVar) {
10946 // Handle initialization of captured loop iterator variables.
10947 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
10948 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
10949 Captures[DRE] = DRE;
10950 }
10951 }
10952 return false;
10953 },
10954 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
10955 Stmt *DependentPreInits = Transform->getPreInits();
10956 if (!DependentPreInits)
10957 return;
10958
10959 // Search for pre-init declared variables that need to be captured
10960 // to be referenceable inside the directive.
10961 SmallVector<Stmt *> Constituents;
10962 appendFlattenedStmtList(Constituents, DependentPreInits);
10963 for (Stmt *S : Constituents) {
10964 if (auto *DC = dyn_cast<DeclStmt>(S)) {
10965 for (Decl *C : DC->decls()) {
10966 auto *D = cast<VarDecl>(C);
10968 SemaRef, D, D->getType().getNonReferenceType(),
10969 cast<OMPExecutableDirective>(Transform->getDirective())
10970 ->getBeginLoc());
10971 Captures[Ref] = Ref;
10972 }
10973 }
10974 }
10975 }))
10976 return 0;
10977
10978 Built.clear(/*size=*/NestedLoopCount);
10979
10980 if (SemaRef.CurContext->isDependentContext())
10981 return NestedLoopCount;
10982
10983 // An example of what is generated for the following code:
10984 //
10985 // #pragma omp simd collapse(2) ordered(2)
10986 // for (i = 0; i < NI; ++i)
10987 // for (k = 0; k < NK; ++k)
10988 // for (j = J0; j < NJ; j+=2) {
10989 // <loop body>
10990 // }
10991 //
10992 // We generate the code below.
10993 // Note: the loop body may be outlined in CodeGen.
10994 // Note: some counters may be C++ classes, operator- is used to find number of
10995 // iterations and operator+= to calculate counter value.
10996 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10997 // or i64 is currently supported).
10998 //
10999 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
11000 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
11001 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
11002 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
11003 // // similar updates for vars in clauses (e.g. 'linear')
11004 // <loop body (using local i and j)>
11005 // }
11006 // i = NI; // assign final values of counters
11007 // j = NJ;
11008 //
11009
11010 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
11011 // the iteration counts of the collapsed for loops.
11012 // Precondition tests if there is at least one iteration (all conditions are
11013 // true).
11014 auto PreCond = ExprResult(IterSpaces[0].PreCond);
11015 ASTContext &C = SemaRef.Context;
11016 unsigned FirstCountBits =
11017 C.getTypeSize(IterSpaces[0].NumIterations->getType());
11018 bool AllCountsNeedLessThan32Bits = FirstCountBits < 32;
11019
11020 Scope *CurScope = DSA.getCurScope();
11021 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
11022 if (PreCond.isUsable()) {
11023 PreCond =
11024 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
11025 PreCond.get(), IterSpaces[Cnt].PreCond);
11026 }
11027 Expr *N = IterSpaces[Cnt].NumIterations;
11028 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
11029 }
11030
11031 auto BuildLastIteration = [&](unsigned Bits) -> ExprResult {
11033 for (unsigned Cnt : llvm::seq<unsigned>(NestedLoopCount)) {
11034 Expr *N = IterSpaces[Cnt].NumIterations;
11036 Bits,
11037 SemaRef
11038 .PerformImplicitConversion(N->IgnoreImpCasts(), N->getType(),
11040 /*AllowExplicit=*/true)
11041 .get(),
11042 SemaRef);
11043 if (!Count.isUsable())
11044 return ExprError();
11045 if (Cnt == 0)
11046 Result = Count;
11047 else
11048 Result = SemaRef.BuildBinOp(CurScope, N->getExprLoc(), BO_Mul,
11049 Result.get(), Count.get());
11050 if (!Result.isUsable())
11051 return ExprError();
11052 }
11053 return Result;
11054 };
11055
11056 // Build the 32-bit tree immediately only when it is always selected.
11057 // Otherwise, build the 64-bit tree first and build the 32-bit tree only when
11058 // the constant product may fit.
11059 ExprResult LastIteration;
11060 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
11061 AllCountsNeedLessThan32Bits ||
11062 (NestedLoopCount == 1 && FirstCountBits == 32)) {
11063 LastIteration = BuildLastIteration(/*Bits=*/32);
11064 } else {
11065 ExprResult LastIteration64 = BuildLastIteration(/*Bits=*/64);
11066 if (!LastIteration64.isUsable())
11067 return NestedLoopCount;
11068 LastIteration = LastIteration64;
11069 if (LastIteration64.get()->isIntegerConstantExpr(C)) {
11070 ExprResult LastIteration32 = BuildLastIteration(/*Bits=*/32);
11071 if (LastIteration32.isUsable() &&
11072 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
11073 fitsInto(
11074 /*Bits=*/32,
11075 LastIteration32.get()
11076 ->getType()
11078 LastIteration64.get(), SemaRef))
11079 LastIteration = LastIteration32;
11080 }
11081 }
11082 if (!LastIteration.isUsable())
11083 return NestedLoopCount;
11084
11085 QualType VType = LastIteration.get()->getType();
11086 QualType RealVType = VType;
11087 QualType StrideVType = VType;
11088 if (isOpenMPTaskLoopDirective(DKind)) {
11089 VType =
11090 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
11091 StrideVType =
11092 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
11093 }
11094
11095 // Save the number of iterations.
11096 ExprResult NumIterations = LastIteration;
11097 {
11098 LastIteration = SemaRef.BuildBinOp(
11099 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
11100 LastIteration.get(),
11101 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
11102 if (!LastIteration.isUsable())
11103 return 0;
11104 }
11105
11106 // Calculate the last iteration number beforehand instead of doing this on
11107 // each iteration. Do not do this if the number of iterations may be kfold-ed.
11108 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
11109 ExprResult CalcLastIteration;
11110 if (!IsConstant) {
11111 ExprResult SaveRef =
11112 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
11113 LastIteration = SaveRef;
11114
11115 // Prepare SaveRef + 1.
11116 NumIterations = SemaRef.BuildBinOp(
11117 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
11118 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
11119 if (!NumIterations.isUsable())
11120 return 0;
11121 }
11122
11123 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
11124
11125 // Build variables passed into runtime, necessary for worksharing directives.
11126 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
11131 // Lower bound variable, initialized with zero.
11132 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
11133 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
11134 SemaRef.AddInitializerToDecl(LBDecl,
11135 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
11136 /*DirectInit=*/false);
11137
11138 // Upper bound variable, initialized with last iteration number.
11139 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
11140 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
11141 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
11142 /*DirectInit=*/false);
11143
11144 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
11145 // This will be used to implement clause 'lastprivate'.
11146 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
11147 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
11148 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
11149 SemaRef.AddInitializerToDecl(ILDecl,
11150 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
11151 /*DirectInit=*/false);
11152
11153 // Stride variable returned by runtime (we initialize it to 1 by default).
11154 VarDecl *STDecl =
11155 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
11156 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
11157 SemaRef.AddInitializerToDecl(STDecl,
11158 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
11159 /*DirectInit=*/false);
11160
11161 // Build expression: UB = min(UB, LastIteration)
11162 // It is necessary for CodeGen of directives with static scheduling.
11163 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
11164 UB.get(), LastIteration.get());
11165 ExprResult CondOp = SemaRef.ActOnConditionalOp(
11166 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
11167 LastIteration.get(), UB.get());
11168 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
11169 CondOp.get());
11170 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
11171
11172 // If we have a combined directive that combines 'distribute', 'for' or
11173 // 'simd' we need to be able to access the bounds of the schedule of the
11174 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
11175 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
11177 // Lower bound variable, initialized with zero.
11178 VarDecl *CombLBDecl =
11179 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
11180 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
11181 SemaRef.AddInitializerToDecl(
11182 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
11183 /*DirectInit=*/false);
11184
11185 // Upper bound variable, initialized with last iteration number.
11186 VarDecl *CombUBDecl =
11187 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
11188 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
11189 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
11190 /*DirectInit=*/false);
11191
11192 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
11193 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
11194 ExprResult CombCondOp =
11195 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
11196 LastIteration.get(), CombUB.get());
11197 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
11198 CombCondOp.get());
11199 CombEUB =
11200 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
11201
11202 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
11203 // We expect to have at least 2 more parameters than the 'parallel'
11204 // directive does - the lower and upper bounds of the previous schedule.
11205 assert(CD->getNumParams() >= 4 &&
11206 "Unexpected number of parameters in loop combined directive");
11207
11208 // Set the proper type for the bounds given what we learned from the
11209 // enclosed loops.
11210 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
11211 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
11212
11213 // Previous lower and upper bounds are obtained from the region
11214 // parameters.
11215 PrevLB =
11216 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
11217 PrevUB =
11218 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
11219 }
11220 }
11221
11222 // Build the iteration variable and its initialization before loop.
11223 ExprResult IV;
11224 ExprResult Init, CombInit;
11225 {
11226 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
11227 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
11228 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
11233 ? LB.get()
11234 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
11235 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
11236 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
11237
11239 Expr *CombRHS =
11244 ? CombLB.get()
11245 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
11246 CombInit =
11247 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
11248 CombInit =
11249 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
11250 }
11251 }
11252
11253 bool UseStrictCompare =
11254 RealVType->hasUnsignedIntegerRepresentation() &&
11255 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
11256 return LIS.IsStrictCompare;
11257 });
11258 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
11259 // unsigned IV)) for worksharing loops.
11260 SourceLocation CondLoc = AStmt->getBeginLoc();
11261 Expr *BoundUB = UB.get();
11262 if (UseStrictCompare) {
11263 BoundUB =
11264 SemaRef
11265 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
11266 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
11267 .get();
11268 BoundUB =
11269 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
11270 }
11271 ExprResult Cond =
11276 ? SemaRef.BuildBinOp(CurScope, CondLoc,
11277 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
11278 BoundUB)
11279 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
11280 NumIterations.get());
11281 ExprResult CombDistCond;
11283 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
11284 NumIterations.get());
11285 }
11286
11287 ExprResult CombCond;
11289 Expr *BoundCombUB = CombUB.get();
11290 if (UseStrictCompare) {
11291 BoundCombUB =
11292 SemaRef
11293 .BuildBinOp(
11294 CurScope, CondLoc, BO_Add, BoundCombUB,
11295 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
11296 .get();
11297 BoundCombUB =
11298 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
11299 .get();
11300 }
11301 CombCond =
11302 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
11303 IV.get(), BoundCombUB);
11304 }
11305 // Loop increment (IV = IV + 1)
11306 SourceLocation IncLoc = AStmt->getBeginLoc();
11307 ExprResult Inc =
11308 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
11309 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
11310 if (!Inc.isUsable())
11311 return 0;
11312 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
11313 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
11314 if (!Inc.isUsable())
11315 return 0;
11316
11317 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
11318 // Used for directives with static scheduling.
11319 // In combined construct, add combined version that use CombLB and CombUB
11320 // base variables for the update
11321 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
11326 // LB + ST
11327 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
11328 if (!NextLB.isUsable())
11329 return 0;
11330 // LB = LB + ST
11331 NextLB =
11332 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
11333 NextLB =
11334 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
11335 if (!NextLB.isUsable())
11336 return 0;
11337 // UB + ST
11338 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
11339 if (!NextUB.isUsable())
11340 return 0;
11341 // UB = UB + ST
11342 NextUB =
11343 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
11344 NextUB =
11345 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
11346 if (!NextUB.isUsable())
11347 return 0;
11349 CombNextLB =
11350 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
11351 if (!NextLB.isUsable())
11352 return 0;
11353 // LB = LB + ST
11354 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
11355 CombNextLB.get());
11356 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
11357 /*DiscardedValue=*/false);
11358 if (!CombNextLB.isUsable())
11359 return 0;
11360 // UB + ST
11361 CombNextUB =
11362 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
11363 if (!CombNextUB.isUsable())
11364 return 0;
11365 // UB = UB + ST
11366 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
11367 CombNextUB.get());
11368 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
11369 /*DiscardedValue=*/false);
11370 if (!CombNextUB.isUsable())
11371 return 0;
11372 }
11373 }
11374
11375 // Create increment expression for distribute loop when combined in a same
11376 // directive with for as IV = IV + ST; ensure upper bound expression based
11377 // on PrevUB instead of NumIterations - used to implement 'for' when found
11378 // in combination with 'distribute', like in 'distribute parallel for'
11379 SourceLocation DistIncLoc = AStmt->getBeginLoc();
11380 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
11382 DistCond = SemaRef.BuildBinOp(
11383 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
11384 assert(DistCond.isUsable() && "distribute cond expr was not built");
11385
11386 DistInc =
11387 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
11388 assert(DistInc.isUsable() && "distribute inc expr was not built");
11389 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
11390 DistInc.get());
11391 DistInc =
11392 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
11393 assert(DistInc.isUsable() && "distribute inc expr was not built");
11394
11395 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
11396 // construct
11397 ExprResult NewPrevUB = PrevUB;
11398 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
11399 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
11400 PrevUB.get()->getType())) {
11401 NewPrevUB = SemaRef.BuildCStyleCastExpr(
11402 DistEUBLoc,
11404 DistEUBLoc, NewPrevUB.get());
11405 if (!NewPrevUB.isUsable())
11406 return 0;
11407 }
11408 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
11409 UB.get(), NewPrevUB.get());
11410 ExprResult CondOp = SemaRef.ActOnConditionalOp(
11411 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
11412 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
11413 CondOp.get());
11414 PrevEUB =
11415 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
11416
11417 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
11418 // parallel for is in combination with a distribute directive with
11419 // schedule(static, 1)
11420 Expr *BoundPrevUB = PrevUB.get();
11421 if (UseStrictCompare) {
11422 BoundPrevUB =
11423 SemaRef
11424 .BuildBinOp(
11425 CurScope, CondLoc, BO_Add, BoundPrevUB,
11426 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
11427 .get();
11428 BoundPrevUB =
11429 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
11430 .get();
11431 }
11432 ParForInDistCond =
11433 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
11434 IV.get(), BoundPrevUB);
11435 }
11436
11437 // Build updates and final values of the loop counters.
11438 bool HasErrors = false;
11439 Built.Counters.resize(NestedLoopCount);
11440 Built.Inits.resize(NestedLoopCount);
11441 Built.Updates.resize(NestedLoopCount);
11442 Built.Finals.resize(NestedLoopCount);
11443 Built.DependentCounters.resize(NestedLoopCount);
11444 Built.DependentInits.resize(NestedLoopCount);
11445 Built.FinalsConditions.resize(NestedLoopCount);
11446 {
11447 // We implement the following algorithm for obtaining the
11448 // original loop iteration variable values based on the
11449 // value of the collapsed loop iteration variable IV.
11450 //
11451 // Let n+1 be the number of collapsed loops in the nest.
11452 // Iteration variables (I0, I1, .... In)
11453 // Iteration counts (N0, N1, ... Nn)
11454 //
11455 // Acc = IV;
11456 //
11457 // To compute Ik for loop k, 0 <= k <= n, generate:
11458 // Prod = N(k+1) * N(k+2) * ... * Nn;
11459 // Ik = Acc / Prod;
11460 // Acc -= Ik * Prod;
11461 //
11462 ExprResult Acc = IV;
11463 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
11464 LoopIterationSpace &IS = IterSpaces[Cnt];
11465 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
11466 ExprResult Iter;
11467
11468 // Compute prod
11469 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
11470 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
11471 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
11472 IterSpaces[K].NumIterations);
11473
11474 // Iter = Acc / Prod
11475 // If there is at least one more inner loop to avoid
11476 // multiplication by 1.
11477 if (Cnt + 1 < NestedLoopCount)
11478 Iter =
11479 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
11480 else
11481 Iter = Acc;
11482 if (!Iter.isUsable()) {
11483 HasErrors = true;
11484 break;
11485 }
11486
11487 // Update Acc:
11488 // Acc -= Iter * Prod
11489 // Check if there is at least one more inner loop to avoid
11490 // multiplication by 1.
11491 if (Cnt + 1 < NestedLoopCount)
11492 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
11493 Prod.get());
11494 else
11495 Prod = Iter;
11496 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
11497
11498 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
11499 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
11500 DeclRefExpr *CounterVar = buildDeclRefExpr(
11501 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
11502 /*RefersToCapture=*/true);
11504 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
11505 IS.CounterInit, IS.IsNonRectangularLB, Captures);
11506 if (!Init.isUsable()) {
11507 HasErrors = true;
11508 break;
11509 }
11511 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
11512 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
11513 if (!Update.isUsable()) {
11514 HasErrors = true;
11515 break;
11516 }
11517
11518 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
11519 ExprResult Final =
11520 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
11521 IS.CounterInit, IS.NumIterations, IS.CounterStep,
11522 IS.Subtract, IS.IsNonRectangularLB, &Captures);
11523 if (!Final.isUsable()) {
11524 HasErrors = true;
11525 break;
11526 }
11527
11528 if (!Update.isUsable() || !Final.isUsable()) {
11529 HasErrors = true;
11530 break;
11531 }
11532 // Save results
11533 Built.Counters[Cnt] = IS.CounterVar;
11534 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
11535 Built.Inits[Cnt] = Init.get();
11536 Built.Updates[Cnt] = Update.get();
11537 Built.Finals[Cnt] = Final.get();
11538 Built.DependentCounters[Cnt] = nullptr;
11539 Built.DependentInits[Cnt] = nullptr;
11540 // Transfer the body-guard condition: the loop condition for
11541 // non-rectangular loops, the overshoot predicate for reinterpreted tiles,
11542 // null otherwise.
11543 Built.FinalsConditions[Cnt] = IS.FinalCondition;
11544 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
11545 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
11546 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
11547 }
11548 }
11549 }
11550
11551 if (HasErrors)
11552 return 0;
11553
11554 // Save results
11555 Built.IterationVarRef = IV.get();
11556 Built.LastIteration = LastIteration.get();
11557 Built.NumIterations = NumIterations.get();
11558 Built.CalcLastIteration = SemaRef
11559 .ActOnFinishFullExpr(CalcLastIteration.get(),
11560 /*DiscardedValue=*/false)
11561 .get();
11562 Built.PreCond = PreCond.get();
11563 Built.PreInits = buildPreInits(C, Captures);
11564 Built.Cond = Cond.get();
11565 Built.Init = Init.get();
11566 Built.Inc = Inc.get();
11567 Built.LB = LB.get();
11568 Built.UB = UB.get();
11569 Built.IL = IL.get();
11570 Built.ST = ST.get();
11571 Built.EUB = EUB.get();
11572 Built.NLB = NextLB.get();
11573 Built.NUB = NextUB.get();
11574 Built.PrevLB = PrevLB.get();
11575 Built.PrevUB = PrevUB.get();
11576 Built.DistInc = DistInc.get();
11577 Built.PrevEUB = PrevEUB.get();
11578 Built.DistCombinedFields.LB = CombLB.get();
11579 Built.DistCombinedFields.UB = CombUB.get();
11580 Built.DistCombinedFields.EUB = CombEUB.get();
11581 Built.DistCombinedFields.Init = CombInit.get();
11582 Built.DistCombinedFields.Cond = CombCond.get();
11583 Built.DistCombinedFields.NLB = CombNextLB.get();
11584 Built.DistCombinedFields.NUB = CombNextUB.get();
11585 Built.DistCombinedFields.DistCond = CombDistCond.get();
11586 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
11587
11588 return NestedLoopCount;
11589}
11590
11592 auto CollapseClauses =
11593 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
11594 if (CollapseClauses.begin() != CollapseClauses.end())
11595 return (*CollapseClauses.begin())->getNumForLoops();
11596 return nullptr;
11597}
11598
11600 auto OrderedClauses =
11601 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
11602 if (OrderedClauses.begin() != OrderedClauses.end())
11603 return (*OrderedClauses.begin())->getNumForLoops();
11604 return nullptr;
11605}
11606
11608 const ArrayRef<OMPClause *> Clauses) {
11609 const OMPSafelenClause *Safelen = nullptr;
11610 const OMPSimdlenClause *Simdlen = nullptr;
11611
11612 for (const OMPClause *Clause : Clauses) {
11613 if (Clause->getClauseKind() == OMPC_safelen)
11614 Safelen = cast<OMPSafelenClause>(Clause);
11615 else if (Clause->getClauseKind() == OMPC_simdlen)
11616 Simdlen = cast<OMPSimdlenClause>(Clause);
11617 if (Safelen && Simdlen)
11618 break;
11619 }
11620
11621 if (Simdlen && Safelen) {
11622 const Expr *SimdlenLength = Simdlen->getSimdlen();
11623 const Expr *SafelenLength = Safelen->getSafelen();
11624 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
11625 SimdlenLength->isInstantiationDependent() ||
11626 SimdlenLength->containsUnexpandedParameterPack())
11627 return false;
11628 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
11629 SafelenLength->isInstantiationDependent() ||
11630 SafelenLength->containsUnexpandedParameterPack())
11631 return false;
11632 Expr::EvalResult SimdlenResult, SafelenResult;
11633 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
11634 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
11635 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
11636 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
11637 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
11638 // If both simdlen and safelen clauses are specified, the value of the
11639 // simdlen parameter must be less than or equal to the value of the safelen
11640 // parameter.
11641 if (llvm::APSInt::compareValues(SimdlenRes, SafelenRes) > 0) {
11642 S.Diag(SimdlenLength->getExprLoc(),
11643 diag::err_omp_wrong_simdlen_safelen_values)
11644 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
11645 return true;
11646 }
11647 }
11648 return false;
11649}
11650
11652 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11653 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11654 if (!AStmt)
11655 return StmtError();
11656
11657 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
11658
11659 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11660 OMPLoopBasedDirective::HelperExprs B;
11661 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11662 // define the nested loops number.
11663 unsigned NestedLoopCount = checkOpenMPLoop(
11664 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
11665 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
11666 if (NestedLoopCount == 0)
11667 return StmtError();
11668
11669 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11670 return StmtError();
11671
11673 return StmtError();
11674
11675 auto *SimdDirective = OMPSimdDirective::Create(
11676 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11677 return SimdDirective;
11678}
11679
11681 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11682 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11683 if (!AStmt)
11684 return StmtError();
11685
11686 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11687 OMPLoopBasedDirective::HelperExprs B;
11688 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11689 // define the nested loops number.
11690 unsigned NestedLoopCount = checkOpenMPLoop(
11691 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
11692 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
11693 if (NestedLoopCount == 0)
11694 return StmtError();
11695
11696 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11697 return StmtError();
11698
11699 auto *ForDirective = OMPForDirective::Create(
11700 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11701 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11702 return ForDirective;
11703}
11704
11706 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11707 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11708 if (!AStmt)
11709 return StmtError();
11710
11711 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
11712
11713 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11714 OMPLoopBasedDirective::HelperExprs B;
11715 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11716 // define the nested loops number.
11717 unsigned NestedLoopCount =
11718 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
11719 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11720 VarsWithImplicitDSA, B);
11721 if (NestedLoopCount == 0)
11722 return StmtError();
11723
11724 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11725 return StmtError();
11726
11728 return StmtError();
11729
11730 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
11731 NestedLoopCount, Clauses, AStmt, B);
11732}
11733
11735 Stmt *AStmt, DSAStackTy *Stack) {
11736 if (!AStmt)
11737 return true;
11738
11739 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11740 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
11741 auto BaseStmt = AStmt;
11742 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
11743 BaseStmt = CS->getCapturedStmt();
11744 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
11745 auto S = C->children();
11746 if (S.begin() == S.end())
11747 return true;
11748 // All associated statements must be '#pragma omp section' except for
11749 // the first one.
11750 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
11751 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
11752 if (SectionStmt)
11753 SemaRef.Diag(SectionStmt->getBeginLoc(),
11754 diag::err_omp_sections_substmt_not_section)
11755 << getOpenMPDirectiveName(DKind, OMPVersion);
11756 return true;
11757 }
11758 cast<OMPSectionDirective>(SectionStmt)
11759 ->setHasCancel(Stack->isCancelRegion());
11760 }
11761 } else {
11762 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
11763 << getOpenMPDirectiveName(DKind, OMPVersion);
11764 return true;
11765 }
11766 return false;
11767}
11768
11771 Stmt *AStmt, SourceLocation StartLoc,
11772 SourceLocation EndLoc) {
11773 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
11774 return StmtError();
11775
11776 SemaRef.setFunctionHasBranchProtectedScope();
11777
11779 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11780 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11781}
11782
11784 SourceLocation StartLoc,
11785 SourceLocation EndLoc) {
11786 if (!AStmt)
11787 return StmtError();
11788
11789 SemaRef.setFunctionHasBranchProtectedScope();
11790 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
11791
11792 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
11793 DSAStack->isCancelRegion());
11794}
11795
11797 E = E->IgnoreParenCasts()->IgnoreImplicit();
11798 if (auto *CE = dyn_cast<CallExpr>(E))
11799 if (CE->getDirectCallee())
11800 return E;
11801 return nullptr;
11802}
11803
11806 Stmt *AStmt, SourceLocation StartLoc,
11807 SourceLocation EndLoc) {
11808 if (!AStmt)
11809 return StmtError();
11810
11811 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
11812
11813 // 5.1 OpenMP
11814 // expression-stmt : an expression statement with one of the following forms:
11815 // expression = target-call ( [expression-list] );
11816 // target-call ( [expression-list] );
11817
11818 SourceLocation TargetCallLoc;
11819
11820 if (!SemaRef.CurContext->isDependentContext()) {
11821 Expr *TargetCall = nullptr;
11822
11823 auto *E = dyn_cast<Expr>(S);
11824 if (!E) {
11825 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
11826 return StmtError();
11827 }
11828
11829 E = E->IgnoreParenCasts()->IgnoreImplicit();
11830
11831 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
11832 if (BO->getOpcode() == BO_Assign)
11833 TargetCall = getDirectCallExpr(BO->getRHS());
11834 } else {
11835 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
11836 if (COCE->getOperator() == OO_Equal)
11837 TargetCall = getDirectCallExpr(COCE->getArg(1));
11838 if (!TargetCall)
11839 TargetCall = getDirectCallExpr(E);
11840 }
11841 if (!TargetCall) {
11842 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
11843 return StmtError();
11844 }
11845 TargetCallLoc = TargetCall->getExprLoc();
11846 }
11847
11848 SemaRef.setFunctionHasBranchProtectedScope();
11849
11850 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
11851 Clauses, AStmt, TargetCallLoc);
11852}
11853
11856 DSAStackTy *Stack) {
11857 bool ErrorFound = false;
11858 for (OMPClause *C : Clauses) {
11859 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
11860 for (Expr *RefExpr : LPC->varlist()) {
11861 SourceLocation ELoc;
11862 SourceRange ERange;
11863 Expr *SimpleRefExpr = RefExpr;
11864 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
11865 if (ValueDecl *D = Res.first) {
11866 auto &&Info = Stack->isLoopControlVariable(D);
11867 if (!Info.first) {
11868 llvm::omp::Version OMPVersion = S.getLangOpts().getOpenMPVersion();
11869 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
11870 << getOpenMPDirectiveName(K, OMPVersion);
11871 ErrorFound = true;
11872 }
11873 }
11874 }
11875 }
11876 }
11877 return ErrorFound;
11878}
11879
11881 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11882 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11883 if (!AStmt)
11884 return StmtError();
11885
11886 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11887 // A list item may not appear in a lastprivate clause unless it is the
11888 // loop iteration variable of a loop that is associated with the construct.
11889 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
11890 return StmtError();
11891
11892 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
11893
11894 OMPLoopDirective::HelperExprs B;
11895 // In presence of clause 'collapse', it will define the nested loops number.
11896 unsigned NestedLoopCount = checkOpenMPLoop(
11897 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
11898 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
11899 if (NestedLoopCount == 0)
11900 return StmtError();
11901
11902 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11903 "omp loop exprs were not built");
11904
11905 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
11906 NestedLoopCount, Clauses, AStmt, B);
11907}
11908
11909/// Check the number of expressions specified in a multidimensional clause and
11910/// return whether an error was encountered.
11912 SemaBase &SemaRef, OpenMPClauseKind ClauseKind,
11913 SourceLocation ClauseBeginLoc, ArrayRef<const Expr *> ClauseVarList,
11914 const Expr *DimsModifierExpr, const OMPXBareClause *BareClause = nullptr) {
11915 const uint64_t NumVars = ClauseVarList.size();
11916
11917 // The ompx_bare clause allows up to three expressions.
11918 if (BareClause) {
11919 if (NumVars > 3) {
11920 SemaRef.Diag(ClauseBeginLoc,
11921 diag::err_ompx_more_than_three_expr_not_allowed)
11922 << getOpenMPClauseName(ClauseKind);
11923 return true;
11924 }
11925 return false;
11926 }
11927
11928 // By default, only one expression accepted.
11929 uint64_t MaxExprs = 1;
11930 if (DimsModifierExpr) {
11931 // Cannot verify the expected size yet.
11932 if (DimsModifierExpr->isInstantiationDependent())
11933 return false;
11934
11935 // The dims modifier determines the exact number of expressions.
11936 MaxExprs = DimsModifierExpr->EvaluateKnownConstInt(SemaRef.getASTContext())
11937 .getExtValue();
11938 }
11939
11940 if (NumVars != MaxExprs) {
11941 SemaRef.Diag(ClauseBeginLoc, diag::err_omp_unexpected_num_exprs)
11942 << getOpenMPClauseName(ClauseKind) << MaxExprs << NumVars;
11943 return true;
11944 }
11945 if (NumVars > 3) {
11946 SemaRef.Diag(ClauseBeginLoc, diag::err_omp_max_three_exprs)
11947 << getOpenMPClauseName(ClauseKind);
11948 return true;
11949 }
11950 return false;
11951}
11952
11953/// Check the number of expressions specified in a multidimensional clause and
11954/// return whether an error was encountered.
11955template <typename ClauseT>
11957 const ClauseT *Clause,
11958 const OMPXBareClause *BareClause) {
11959 if (!Clause)
11960 return false;
11962 SemaRef, Clause->getClauseKind(), Clause->getBeginLoc(),
11963 Clause->getVarRefs(), Clause->getDimsModifierExpr(), BareClause);
11964}
11965
11966/// Check the number of expressions specified in clauses that can contain
11967/// multidimensional values, e.g., num_teams and thread_limit. The function
11968/// returns true on error.
11970 ArrayRef<OMPClause *> Clauses,
11971 bool MayHaveBareClause = false) {
11972 auto BareClauseIt =
11973 MayHaveBareClause ? llvm::find_if(Clauses, llvm::IsaPred<OMPXBareClause>)
11974 : Clauses.end();
11975 auto ThreadLimitIt =
11976 llvm::find_if(Clauses, llvm::IsaPred<OMPThreadLimitClause>);
11977 auto NumTeamsIt = llvm::find_if(Clauses, llvm::IsaPred<OMPNumTeamsClause>);
11978
11979 const auto *BareClause = BareClauseIt != Clauses.end()
11980 ? cast<OMPXBareClause>(*BareClauseIt)
11981 : nullptr;
11982 const auto *ThreadLimitClause =
11983 ThreadLimitIt != Clauses.end()
11984 ? cast<OMPThreadLimitClause>(*ThreadLimitIt)
11985 : nullptr;
11986 const auto *NumTeamsClause = NumTeamsIt != Clauses.end()
11987 ? cast<OMPNumTeamsClause>(*NumTeamsIt)
11988 : nullptr;
11989
11990 if (BareClause) {
11991 if (!NumTeamsClause || !ThreadLimitClause) {
11992 SemaRef.Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
11993 return true;
11994 }
11995 if (ThreadLimitClause->getModifier() == OMPC_THREADLIMIT_dims ||
11996 NumTeamsClause->getModifier() == OMPC_NUMTEAMS_dims) {
11997 SemaRef.Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_dims);
11998 return true;
11999 }
12000 }
12001 return validateMultidimClauseExprs(SemaRef, ThreadLimitClause, BareClause) ||
12002 validateMultidimClauseExprs(SemaRef, NumTeamsClause, BareClause);
12003}
12004
12006 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12007 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12008 if (!AStmt)
12009 return StmtError();
12010
12011 if (validateMultidimClauses(*this, Clauses))
12012 return StmtError();
12013
12014 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_teams_loop, Clauses))
12015 return StmtError();
12016
12017 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
12018 // A list item may not appear in a lastprivate clause unless it is the
12019 // loop iteration variable of a loop that is associated with the construct.
12020 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
12021 return StmtError();
12022
12023 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
12024
12025 OMPLoopDirective::HelperExprs B;
12026 // In presence of clause 'collapse', it will define the nested loops number.
12027 unsigned NestedLoopCount =
12028 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
12029 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
12030 VarsWithImplicitDSA, B);
12031 if (NestedLoopCount == 0)
12032 return StmtError();
12033
12034 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
12035 "omp loop exprs were not built");
12036
12037 DSAStack->setParentTeamsRegionLoc(StartLoc);
12038
12040 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
12041}
12042
12044 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12045 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12046 if (!AStmt)
12047 return StmtError();
12048
12049 if (validateMultidimClauses(*this, Clauses))
12050 return StmtError();
12051
12052 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
12053 // A list item may not appear in a lastprivate clause unless it is the
12054 // loop iteration variable of a loop that is associated with the construct.
12055 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
12056 DSAStack))
12057 return StmtError();
12058
12059 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_target_teams_loop,
12060 Clauses))
12061 return StmtError();
12062
12064 return StmtError();
12065
12066 CapturedStmt *CS =
12067 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
12068
12069 OMPLoopDirective::HelperExprs B;
12070 // In presence of clause 'collapse', it will define the nested loops number.
12071 unsigned NestedLoopCount =
12072 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
12073 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
12074 VarsWithImplicitDSA, B);
12075 if (NestedLoopCount == 0)
12076 return StmtError();
12077
12078 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
12079 "omp loop exprs were not built");
12080
12082 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12084}
12085
12087 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12088 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12089 if (!AStmt)
12090 return StmtError();
12091
12092 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
12093 // A list item may not appear in a lastprivate clause unless it is the
12094 // loop iteration variable of a loop that is associated with the construct.
12095 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
12096 DSAStack))
12097 return StmtError();
12098
12099 CapturedStmt *CS =
12100 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
12101
12102 OMPLoopDirective::HelperExprs B;
12103 // In presence of clause 'collapse', it will define the nested loops number.
12104 unsigned NestedLoopCount =
12105 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
12106 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
12107 VarsWithImplicitDSA, B);
12108 if (NestedLoopCount == 0)
12109 return StmtError();
12110
12111 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
12112 "omp loop exprs were not built");
12113
12115 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
12116}
12117
12119 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12120 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12121 if (!AStmt)
12122 return StmtError();
12123
12124 if (validateMultidimClauses(*this, Clauses))
12125 return StmtError();
12126
12127 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_target_parallel_loop,
12128 Clauses))
12129 return StmtError();
12130
12132 return StmtError();
12133
12134 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
12135 // A list item may not appear in a lastprivate clause unless it is the
12136 // loop iteration variable of a loop that is associated with the construct.
12137 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
12138 DSAStack))
12139 return StmtError();
12140
12141 CapturedStmt *CS =
12142 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
12143
12144 OMPLoopDirective::HelperExprs B;
12145 // In presence of clause 'collapse', it will define the nested loops number.
12146 unsigned NestedLoopCount =
12147 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
12148 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
12149 VarsWithImplicitDSA, B);
12150 if (NestedLoopCount == 0)
12151 return StmtError();
12152
12153 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
12154 "omp loop exprs were not built");
12155
12157 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
12158}
12159
12161 Stmt *AStmt,
12162 SourceLocation StartLoc,
12163 SourceLocation EndLoc) {
12164 if (!AStmt)
12165 return StmtError();
12166
12167 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12168
12169 SemaRef.setFunctionHasBranchProtectedScope();
12170
12171 // OpenMP [2.7.3, single Construct, Restrictions]
12172 // The copyprivate clause must not be used with the nowait clause.
12173 const OMPClause *Nowait = nullptr;
12174 const OMPClause *Copyprivate = nullptr;
12175 for (const OMPClause *Clause : Clauses) {
12176 if (Clause->getClauseKind() == OMPC_nowait)
12177 Nowait = Clause;
12178 else if (Clause->getClauseKind() == OMPC_copyprivate)
12179 Copyprivate = Clause;
12180 if (Copyprivate && Nowait) {
12181 Diag(Copyprivate->getBeginLoc(),
12182 diag::err_omp_single_copyprivate_with_nowait);
12183 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
12184 return StmtError();
12185 }
12186 }
12187
12188 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12189 AStmt);
12190}
12191
12193 SourceLocation StartLoc,
12194 SourceLocation EndLoc) {
12195 if (!AStmt)
12196 return StmtError();
12197
12198 SemaRef.setFunctionHasBranchProtectedScope();
12199
12200 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
12201}
12202
12204 Stmt *AStmt,
12205 SourceLocation StartLoc,
12206 SourceLocation EndLoc) {
12207 if (!AStmt)
12208 return StmtError();
12209
12210 SemaRef.setFunctionHasBranchProtectedScope();
12211
12212 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12213 AStmt);
12214}
12215
12217 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
12218 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
12219 if (!AStmt)
12220 return StmtError();
12221
12222 bool ErrorFound = false;
12223 llvm::APSInt Hint;
12224 SourceLocation HintLoc;
12225 bool DependentHint = false;
12226 for (const OMPClause *C : Clauses) {
12227 if (C->getClauseKind() == OMPC_hint) {
12228 if (!DirName.getName()) {
12229 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
12230 ErrorFound = true;
12231 }
12232 Expr *E = cast<OMPHintClause>(C)->getHint();
12233 if (E->isTypeDependent() || E->isValueDependent() ||
12235 DependentHint = true;
12236 } else {
12238 HintLoc = C->getBeginLoc();
12239 }
12240 }
12241 }
12242 if (ErrorFound)
12243 return StmtError();
12244 const auto Pair = DSAStack->getCriticalWithHint(DirName);
12245 if (Pair.first && DirName.getName() && !DependentHint) {
12246 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
12247 Diag(StartLoc, diag::err_omp_critical_with_hint);
12248 if (HintLoc.isValid())
12249 Diag(HintLoc, diag::note_omp_critical_hint_here)
12250 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
12251 else
12252 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
12253 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
12254 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
12255 << 1
12256 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
12257 /*Radix=*/10, /*Signed=*/false);
12258 } else {
12259 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
12260 }
12261 }
12262 }
12263
12264 SemaRef.setFunctionHasBranchProtectedScope();
12265
12266 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
12267 EndLoc, Clauses, AStmt);
12268 if (!Pair.first && DirName.getName() && !DependentHint)
12269 DSAStack->addCriticalWithHint(Dir, Hint);
12270 return Dir;
12271}
12272
12274 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12275 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12276 if (!AStmt)
12277 return StmtError();
12278
12279 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
12280
12281 OMPLoopBasedDirective::HelperExprs B;
12282 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12283 // define the nested loops number.
12284 unsigned NestedLoopCount =
12285 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
12286 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
12287 VarsWithImplicitDSA, B);
12288 if (NestedLoopCount == 0)
12289 return StmtError();
12290
12291 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
12292 return StmtError();
12293
12295 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
12296 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12297}
12298
12300 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12301 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
12302 if (!AStmt)
12303 return StmtError();
12304
12305 CapturedStmt *CS =
12306 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
12307
12308 OMPLoopBasedDirective::HelperExprs B;
12309 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
12310 // define the nested loops number.
12311 unsigned NestedLoopCount =
12312 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
12313 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
12314 VarsWithImplicitDSA, B);
12315 if (NestedLoopCount == 0)
12316 return StmtError();
12317
12318 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
12319 return StmtError();
12320
12322 return StmtError();
12323
12325 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
12326}
12327
12329 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12330 SourceLocation EndLoc) {
12331 if (!AStmt)
12332 return StmtError();
12333
12334 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
12335
12337 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12338 DSAStack->getTaskgroupReductionRef());
12339}
12340
12342 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12343 SourceLocation EndLoc) {
12344 if (!AStmt)
12345 return StmtError();
12346
12347 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
12348
12350 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12351 DSAStack->getTaskgroupReductionRef());
12352}
12353
12355 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
12356 SourceLocation EndLoc) {
12357 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
12358 return StmtError();
12359
12360 SemaRef.setFunctionHasBranchProtectedScope();
12361
12363 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
12364 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
12365}
12366
12367/// Find and diagnose mutually exclusive clause kinds.
12369 Sema &S, ArrayRef<OMPClause *> Clauses,
12370 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
12371 const OMPClause *PrevClause = nullptr;
12372 bool ErrorFound = false;
12373 for (const OMPClause *C : Clauses) {
12374 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
12375 if (!PrevClause) {
12376 PrevClause = C;
12377 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
12378 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
12379 << getOpenMPClauseNameForDiag(C->getClauseKind())
12380 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
12381 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
12382 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
12383 ErrorFound = true;
12384 }
12385 }
12386 }
12387 return ErrorFound;
12388}
12389
12391 Stmt *AStmt,
12392 SourceLocation StartLoc,
12393 SourceLocation EndLoc) {
12394 if (!AStmt)
12395 return StmtError();
12396
12397 // OpenMP 5.0, 2.10.1 task Construct
12398 // If a detach clause appears on the directive, then a mergeable clause cannot
12399 // appear on the same directive.
12401 {OMPC_detach, OMPC_mergeable}))
12402 return StmtError();
12403
12404 // Check for conflicting capture kinds on structured bindings.
12405 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_task, Clauses, AStmt))
12406 return StmtError();
12407
12408 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
12409
12410 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
12411 AStmt, DSAStack->isCancelRegion());
12412}
12413
12418
12423
12425 SourceLocation StartLoc,
12426 SourceLocation EndLoc,
12427 bool InExContext) {
12428 const OMPAtClause *AtC =
12429 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
12430
12431 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
12432 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
12433 return StmtError();
12434 }
12435
12436 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
12437 const OMPSeverityClause *SeverityC =
12438 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
12439 const OMPMessageClause *MessageC =
12440 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
12441 std::optional<std::string> SL =
12442 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
12443
12444 if (MessageC && !SL)
12445 Diag(MessageC->getMessageString()->getBeginLoc(),
12446 diag::warn_clause_expected_string)
12447 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
12448 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
12449 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
12450 << SL.value_or("WARNING");
12451 else
12452 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
12453 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
12454 return StmtError();
12455 }
12456
12457 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
12458}
12459
12462 SourceLocation StartLoc,
12463 SourceLocation EndLoc) {
12464 const OMPNowaitClause *NowaitC =
12465 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
12466 bool HasDependC =
12467 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
12468 .empty();
12469 if (NowaitC && !HasDependC) {
12470 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
12471 return StmtError();
12472 }
12473
12474 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
12475 Clauses);
12476}
12477
12480 Stmt *AStmt, SourceLocation StartLoc,
12481 SourceLocation EndLoc) {
12482 if (!AStmt)
12483 return StmtError();
12484
12485 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12486
12487 SemaRef.setFunctionHasBranchProtectedScope();
12488
12489 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
12490 Clauses, AStmt,
12491 DSAStack->getTaskgroupReductionRef());
12492}
12493
12495 SourceLocation StartLoc,
12496 SourceLocation EndLoc) {
12497 OMPFlushClause *FC = nullptr;
12498 OMPClause *OrderClause = nullptr;
12499 for (OMPClause *C : Clauses) {
12500 if (C->getClauseKind() == OMPC_flush)
12501 FC = cast<OMPFlushClause>(C);
12502 else
12503 OrderClause = C;
12504 }
12505 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
12506 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12507 SourceLocation MemOrderLoc;
12508 for (const OMPClause *C : Clauses) {
12509 if (C->getClauseKind() == OMPC_acq_rel ||
12510 C->getClauseKind() == OMPC_acquire ||
12511 C->getClauseKind() == OMPC_release ||
12512 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
12513 if (MemOrderKind != OMPC_unknown) {
12514 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12515 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
12516 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12517 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12518 << getOpenMPClauseNameForDiag(MemOrderKind);
12519 } else {
12520 MemOrderKind = C->getClauseKind();
12521 MemOrderLoc = C->getBeginLoc();
12522 }
12523 }
12524 }
12525 if (FC && OrderClause) {
12526 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
12527 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
12528 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
12529 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
12530 return StmtError();
12531 }
12532 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
12533}
12534
12536 SourceLocation StartLoc,
12537 SourceLocation EndLoc) {
12538 if (Clauses.empty()) {
12539 Diag(StartLoc, diag::err_omp_depobj_expected);
12540 return StmtError();
12541 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
12542 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
12543 return StmtError();
12544 }
12545 // Only depobj expression and another single clause is allowed.
12546 if (Clauses.size() > 2) {
12547 Diag(Clauses[2]->getBeginLoc(),
12548 diag::err_omp_depobj_single_clause_expected);
12549 return StmtError();
12550 } else if (Clauses.size() < 1) {
12551 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
12552 return StmtError();
12553 }
12554 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
12555}
12556
12558 SourceLocation StartLoc,
12559 SourceLocation EndLoc) {
12560 // Check that exactly one clause is specified.
12561 if (Clauses.size() != 1) {
12562 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
12563 diag::err_omp_scan_single_clause_expected);
12564 return StmtError();
12565 }
12566 // Check that scan directive is used in the scope of the OpenMP loop body.
12567 if (Scope *S = DSAStack->getCurScope()) {
12568 Scope *ParentS = S->getParent();
12569 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
12570 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
12571 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
12572 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
12573 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
12574 }
12575 }
12576 // Check that only one instance of scan directives is used in the same outer
12577 // region.
12578 if (DSAStack->doesParentHasScanDirective()) {
12579 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
12580 Diag(DSAStack->getParentScanDirectiveLoc(),
12581 diag::note_omp_previous_directive)
12582 << "scan";
12583 return StmtError();
12584 }
12585 DSAStack->setParentHasScanDirective(StartLoc);
12586 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
12587}
12588
12591 Stmt *AStmt, SourceLocation StartLoc,
12592 SourceLocation EndLoc) {
12593 const OMPClause *DependFound = nullptr;
12594 const OMPClause *DependSourceClause = nullptr;
12595 const OMPClause *DependSinkClause = nullptr;
12596 const OMPClause *DoacrossFound = nullptr;
12597 const OMPClause *DoacrossSourceClause = nullptr;
12598 const OMPClause *DoacrossSinkClause = nullptr;
12599 bool ErrorFound = false;
12600 const OMPThreadsClause *TC = nullptr;
12601 const OMPSIMDClause *SC = nullptr;
12602 for (const OMPClause *C : Clauses) {
12603 auto DOC = dyn_cast<OMPDoacrossClause>(C);
12604 auto DC = dyn_cast<OMPDependClause>(C);
12605 if (DC || DOC) {
12606 DependFound = DC ? C : nullptr;
12607 DoacrossFound = DOC ? C : nullptr;
12608 OMPDoacrossKind ODK;
12609 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
12610 (DOC && (ODK.isSource(DOC)))) {
12611 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
12612 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
12613 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
12614 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
12615 OMPVersion)
12616 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
12617 << 2;
12618 ErrorFound = true;
12619 } else {
12620 if (DC)
12621 DependSourceClause = C;
12622 else
12623 DoacrossSourceClause = C;
12624 }
12625 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
12626 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
12627 << (DC ? "depend" : "doacross") << 0;
12628 ErrorFound = true;
12629 }
12630 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
12631 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
12632 if (DependSourceClause || DoacrossSourceClause) {
12633 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
12634 << (DC ? "depend" : "doacross") << 1;
12635 ErrorFound = true;
12636 }
12637 if (DC)
12638 DependSinkClause = C;
12639 else
12640 DoacrossSinkClause = C;
12641 }
12642 } else if (C->getClauseKind() == OMPC_threads) {
12644 } else if (C->getClauseKind() == OMPC_simd) {
12645 SC = cast<OMPSIMDClause>(C);
12646 }
12647 }
12648 if (!ErrorFound && !SC &&
12649 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
12650 // OpenMP [2.8.1,simd Construct, Restrictions]
12651 // An ordered construct with the simd clause is the only OpenMP construct
12652 // that can appear in the simd region.
12653 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
12654 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
12655 ErrorFound = true;
12656 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
12657 SourceLocation Loc =
12658 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
12659 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
12660 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
12661 << getOpenMPClauseNameForDiag(TC ? TC->getClauseKind()
12662 : SC->getClauseKind());
12663 ErrorFound = true;
12664 } else if ((DependFound || DoacrossFound) &&
12665 !DSAStack->getParentOrderedRegionParam().first) {
12666 SourceLocation Loc =
12667 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
12668 Diag(Loc, diag::err_omp_ordered_directive_without_param)
12669 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
12670 : OMPC_doacross);
12671 ErrorFound = true;
12672 } else if (TC || Clauses.empty()) {
12673 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
12674 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
12675 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
12676 << (TC != nullptr);
12677 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
12678 ErrorFound = true;
12679 }
12680 }
12681 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
12682 return StmtError();
12683
12684 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
12685 // During execution of an iteration of a worksharing-loop or a loop nest
12686 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
12687 // must not execute more than one ordered region corresponding to an ordered
12688 // construct without a depend clause.
12689 if (!DependFound && !DoacrossFound) {
12690 if (DSAStack->doesParentHasOrderedDirective()) {
12691 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
12692 Diag(DSAStack->getParentOrderedDirectiveLoc(),
12693 diag::note_omp_previous_directive)
12694 << "ordered";
12695 return StmtError();
12696 }
12697 DSAStack->setParentHasOrderedDirective(StartLoc);
12698 }
12699
12700 if (AStmt) {
12701 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
12702
12703 SemaRef.setFunctionHasBranchProtectedScope();
12704 }
12705
12706 if (!AStmt)
12708 EndLoc, Clauses);
12710 EndLoc, Clauses, AStmt);
12711}
12712
12713namespace {
12714/// Helper class for checking expression in 'omp atomic [update]'
12715/// construct.
12716class OpenMPAtomicUpdateChecker {
12717 /// Error results for atomic update expressions.
12718 enum ExprAnalysisErrorCode {
12719 /// A statement is not an expression statement.
12720 NotAnExpression,
12721 /// Expression is not builtin binary or unary operation.
12722 NotABinaryOrUnaryExpression,
12723 /// Unary operation is not post-/pre- increment/decrement operation.
12724 NotAnUnaryIncDecExpression,
12725 /// An expression is not of scalar type.
12726 NotAScalarType,
12727 /// A binary operation is not an assignment operation.
12728 NotAnAssignmentOp,
12729 /// RHS part of the binary operation is not a binary expression.
12730 NotABinaryExpression,
12731 /// RHS part is not additive/multiplicative/shift/bitwise binary
12732 /// expression.
12733 NotABinaryOperator,
12734 /// RHS binary operation does not have reference to the updated LHS
12735 /// part.
12736 NotAnUpdateExpression,
12737 /// An expression contains semantical error not related to
12738 /// 'omp atomic [update]'
12739 NotAValidExpression,
12740 /// No errors is found.
12741 NoError
12742 };
12743 /// Reference to Sema.
12744 Sema &SemaRef;
12745 /// A location for note diagnostics (when error is found).
12746 SourceLocation NoteLoc;
12747 /// 'x' lvalue part of the source atomic expression.
12748 Expr *X;
12749 /// 'expr' rvalue part of the source atomic expression.
12750 Expr *E;
12751 /// Helper expression of the form
12752 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
12753 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
12754 Expr *UpdateExpr;
12755 /// Is 'x' a LHS in a RHS part of full update expression. It is
12756 /// important for non-associative operations.
12757 bool IsXLHSInRHSPart;
12759 SourceLocation OpLoc;
12760 /// true if the source expression is a postfix unary operation, false
12761 /// if it is a prefix unary operation.
12762 bool IsPostfixUpdate;
12763
12764public:
12765 OpenMPAtomicUpdateChecker(Sema &SemaRef)
12766 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
12767 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
12768 /// Check specified statement that it is suitable for 'atomic update'
12769 /// constructs and extract 'x', 'expr' and Operation from the original
12770 /// expression. If DiagId and NoteId == 0, then only check is performed
12771 /// without error notification.
12772 /// \param DiagId Diagnostic which should be emitted if error is found.
12773 /// \param NoteId Diagnostic note for the main error message.
12774 /// \return true if statement is not an update expression, false otherwise.
12775 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
12776 /// Return the 'x' lvalue part of the source atomic expression.
12777 Expr *getX() const { return X; }
12778 /// Return the 'expr' rvalue part of the source atomic expression.
12779 Expr *getExpr() const { return E; }
12780 /// Return the update expression used in calculation of the updated
12781 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
12782 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
12783 Expr *getUpdateExpr() const { return UpdateExpr; }
12784 /// Return true if 'x' is LHS in RHS part of full update expression,
12785 /// false otherwise.
12786 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
12787
12788 /// true if the source expression is a postfix unary operation, false
12789 /// if it is a prefix unary operation.
12790 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12791
12792private:
12793 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
12794 unsigned NoteId = 0);
12795};
12796
12797bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
12798 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
12799 ExprAnalysisErrorCode ErrorFound = NoError;
12800 SourceLocation ErrorLoc, NoteLoc;
12801 SourceRange ErrorRange, NoteRange;
12802 // Allowed constructs are:
12803 // x = x binop expr;
12804 // x = expr binop x;
12805 if (AtomicBinOp->getOpcode() == BO_Assign) {
12806 X = AtomicBinOp->getLHS();
12807 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
12808 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
12809 if (AtomicInnerBinOp->isMultiplicativeOp() ||
12810 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
12811 AtomicInnerBinOp->isBitwiseOp()) {
12812 Op = AtomicInnerBinOp->getOpcode();
12813 OpLoc = AtomicInnerBinOp->getOperatorLoc();
12814 Expr *LHS = AtomicInnerBinOp->getLHS();
12815 Expr *RHS = AtomicInnerBinOp->getRHS();
12816 llvm::FoldingSetNodeID XId, LHSId, RHSId;
12817 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
12818 /*Canonical=*/true);
12819 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
12820 /*Canonical=*/true);
12821 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
12822 /*Canonical=*/true);
12823 if (XId == LHSId) {
12824 E = RHS;
12825 IsXLHSInRHSPart = true;
12826 } else if (XId == RHSId) {
12827 E = LHS;
12828 IsXLHSInRHSPart = false;
12829 } else {
12830 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12831 ErrorRange = AtomicInnerBinOp->getSourceRange();
12832 NoteLoc = X->getExprLoc();
12833 NoteRange = X->getSourceRange();
12834 ErrorFound = NotAnUpdateExpression;
12835 }
12836 } else {
12837 ErrorLoc = AtomicInnerBinOp->getExprLoc();
12838 ErrorRange = AtomicInnerBinOp->getSourceRange();
12839 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
12840 NoteRange = SourceRange(NoteLoc, NoteLoc);
12841 ErrorFound = NotABinaryOperator;
12842 }
12843 } else {
12844 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
12845 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
12846 ErrorFound = NotABinaryExpression;
12847 }
12848 } else {
12849 ErrorLoc = AtomicBinOp->getExprLoc();
12850 ErrorRange = AtomicBinOp->getSourceRange();
12851 NoteLoc = AtomicBinOp->getOperatorLoc();
12852 NoteRange = SourceRange(NoteLoc, NoteLoc);
12853 ErrorFound = NotAnAssignmentOp;
12854 }
12855 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12856 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
12857 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
12858 return true;
12859 }
12860 if (SemaRef.CurContext->isDependentContext())
12861 E = X = UpdateExpr = nullptr;
12862 return ErrorFound != NoError;
12863}
12864
12865bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
12866 unsigned NoteId) {
12867 ExprAnalysisErrorCode ErrorFound = NoError;
12868 SourceLocation ErrorLoc, NoteLoc;
12869 SourceRange ErrorRange, NoteRange;
12870 // Allowed constructs are:
12871 // x++;
12872 // x--;
12873 // ++x;
12874 // --x;
12875 // x binop= expr;
12876 // x = x binop expr;
12877 // x = expr binop x;
12878 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
12879 AtomicBody = AtomicBody->IgnoreParenImpCasts();
12880 if (AtomicBody->getType()->isScalarType() ||
12881 AtomicBody->isInstantiationDependent()) {
12882 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
12883 AtomicBody->IgnoreParenImpCasts())) {
12884 // Check for Compound Assignment Operation
12886 AtomicCompAssignOp->getOpcode());
12887 OpLoc = AtomicCompAssignOp->getOperatorLoc();
12888 E = AtomicCompAssignOp->getRHS();
12889 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
12890 IsXLHSInRHSPart = true;
12891 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
12892 AtomicBody->IgnoreParenImpCasts())) {
12893 // Check for Binary Operation
12894 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
12895 return true;
12896 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
12897 AtomicBody->IgnoreParenImpCasts())) {
12898 // Check for Unary Operation
12899 if (AtomicUnaryOp->isIncrementDecrementOp()) {
12900 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
12901 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
12902 OpLoc = AtomicUnaryOp->getOperatorLoc();
12903 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
12904 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
12905 IsXLHSInRHSPart = true;
12906 } else {
12907 ErrorFound = NotAnUnaryIncDecExpression;
12908 ErrorLoc = AtomicUnaryOp->getExprLoc();
12909 ErrorRange = AtomicUnaryOp->getSourceRange();
12910 NoteLoc = AtomicUnaryOp->getOperatorLoc();
12911 NoteRange = SourceRange(NoteLoc, NoteLoc);
12912 }
12913 } else if (!AtomicBody->isInstantiationDependent()) {
12914 ErrorFound = NotABinaryOrUnaryExpression;
12915 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12916 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12917 } else if (AtomicBody->containsErrors()) {
12918 ErrorFound = NotAValidExpression;
12919 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
12920 NoteRange = ErrorRange = AtomicBody->getSourceRange();
12921 }
12922 } else {
12923 ErrorFound = NotAScalarType;
12924 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
12925 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12926 }
12927 } else {
12928 ErrorFound = NotAnExpression;
12929 NoteLoc = ErrorLoc = S->getBeginLoc();
12930 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12931 }
12932 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
12933 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
12934 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
12935 return true;
12936 }
12937 if (SemaRef.CurContext->isDependentContext())
12938 E = X = UpdateExpr = nullptr;
12939 if (ErrorFound == NoError && E && X && !E->containsErrors() &&
12940 !X->containsErrors()) {
12941 // Build an update expression of form 'OpaqueValueExpr(x) binop
12942 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
12943 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
12944 auto *OVEX = new (SemaRef.getASTContext())
12945 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
12946 auto *OVEExpr = new (SemaRef.getASTContext())
12949 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
12950 IsXLHSInRHSPart ? OVEExpr : OVEX);
12951 if (Update.isInvalid())
12952 return true;
12953 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
12955 if (Update.isInvalid())
12956 return true;
12957 UpdateExpr = Update.get();
12958 }
12959 return ErrorFound != NoError;
12960}
12961
12962/// Get the node id of the fixed point of an expression \a S.
12963llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
12964 llvm::FoldingSetNodeID Id;
12965 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
12966 return Id;
12967}
12968
12969/// Check if two expressions are same.
12970bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
12971 const Expr *RHS) {
12972 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
12973}
12974
12975class OpenMPAtomicCompareChecker {
12976public:
12977 /// All kinds of errors that can occur in `atomic compare`
12978 enum ErrorTy {
12979 /// Empty compound statement.
12980 NoStmt = 0,
12981 /// More than one statement in a compound statement.
12982 MoreThanOneStmt,
12983 /// Not an assignment binary operator.
12984 NotAnAssignment,
12985 /// Not a conditional operator.
12986 NotCondOp,
12987 /// Wrong false expr. According to the spec, 'x' should be at the false
12988 /// expression of a conditional expression.
12989 WrongFalseExpr,
12990 /// The condition of a conditional expression is not a binary operator.
12991 NotABinaryOp,
12992 /// Invalid binary operator (not <, >, or ==).
12993 InvalidBinaryOp,
12994 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
12995 InvalidComparison,
12996 /// X is not a lvalue.
12997 XNotLValue,
12998 /// Not a scalar.
12999 NotScalar,
13000 /// Not an integer.
13001 NotInteger,
13002 /// 'else' statement is not expected.
13003 UnexpectedElse,
13004 /// Not an equality operator.
13005 NotEQ,
13006 /// Invalid assignment (not v == x).
13007 InvalidAssignment,
13008 /// Not if statement
13009 NotIfStmt,
13010 /// More than two statements in a compound statement.
13011 MoreThanTwoStmts,
13012 /// Not a compound statement.
13013 NotCompoundStmt,
13014 /// No else statement.
13015 NoElse,
13016 /// Not 'if (r)'.
13017 InvalidCondition,
13018 /// No error.
13019 NoError,
13020 };
13021
13022 struct ErrorInfoTy {
13023 ErrorTy Error;
13024 SourceLocation ErrorLoc;
13025 SourceRange ErrorRange;
13026 SourceLocation NoteLoc;
13027 SourceRange NoteRange;
13028 };
13029
13030 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
13031
13032 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
13033 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
13034
13035 Expr *getX() const { return X; }
13036 Expr *getE() const { return E; }
13037 Expr *getD() const { return D; }
13038 Expr *getCond() const { return C; }
13039 bool isXBinopExpr() const { return IsXBinopExpr; }
13040
13041protected:
13042 /// Reference to ASTContext
13043 ASTContext &ContextRef;
13044 /// 'x' lvalue part of the source atomic expression.
13045 Expr *X = nullptr;
13046 /// 'expr' or 'e' rvalue part of the source atomic expression.
13047 Expr *E = nullptr;
13048 /// 'd' rvalue part of the source atomic expression.
13049 Expr *D = nullptr;
13050 /// 'cond' part of the source atomic expression. It is in one of the following
13051 /// forms:
13052 /// expr ordop x
13053 /// x ordop expr
13054 /// x == e
13055 /// e == x
13056 Expr *C = nullptr;
13057 /// True if the cond expr is in the form of 'x ordop expr'.
13058 bool IsXBinopExpr = true;
13059
13060 /// Check if it is a valid conditional update statement (cond-update-stmt).
13061 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
13062
13063 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
13064 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
13065
13066 /// Check if all captured values have right type.
13067 bool checkType(ErrorInfoTy &ErrorInfo) const;
13068
13069 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
13070 bool ShouldBeLValue, bool ShouldBeInteger = false) {
13071 if (E->isInstantiationDependent())
13072 return true;
13073
13074 if (ShouldBeLValue && !E->isLValue()) {
13075 ErrorInfo.Error = ErrorTy::XNotLValue;
13076 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
13077 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
13078 return false;
13079 }
13080
13081 QualType QTy = E->getType();
13082 if (!QTy->isScalarType()) {
13083 ErrorInfo.Error = ErrorTy::NotScalar;
13084 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
13085 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
13086 return false;
13087 }
13088 if (ShouldBeInteger && !QTy->isIntegerType()) {
13089 ErrorInfo.Error = ErrorTy::NotInteger;
13090 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
13091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
13092 return false;
13093 }
13094
13095 return true;
13096 }
13097};
13098
13099bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
13100 ErrorInfoTy &ErrorInfo) {
13101 auto *Then = S->getThen();
13102 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
13103 if (CS->body_empty()) {
13104 ErrorInfo.Error = ErrorTy::NoStmt;
13105 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13106 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13107 return false;
13108 }
13109 if (CS->size() > 1) {
13110 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13111 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13112 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
13113 return false;
13114 }
13115 Then = CS->body_front();
13116 }
13117
13118 auto *BO = dyn_cast<BinaryOperator>(Then);
13119 if (!BO) {
13120 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13121 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
13122 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
13123 return false;
13124 }
13125 if (BO->getOpcode() != BO_Assign) {
13126 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13127 ErrorInfo.ErrorLoc = BO->getExprLoc();
13128 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13129 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13130 return false;
13131 }
13132
13133 X = BO->getLHS();
13134
13135 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
13136 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
13137 Expr *LHS = nullptr;
13138 Expr *RHS = nullptr;
13139 if (Cond) {
13140 LHS = Cond->getLHS();
13141 RHS = Cond->getRHS();
13142 } else if (Call) {
13143 LHS = Call->getArg(0);
13144 RHS = Call->getArg(1);
13145 } else {
13146 ErrorInfo.Error = ErrorTy::NotABinaryOp;
13147 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13148 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
13149 return false;
13150 }
13151
13152 if ((Cond && Cond->getOpcode() == BO_EQ) ||
13153 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
13154 C = S->getCond();
13155 D = BO->getRHS();
13156 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
13157 E = RHS;
13158 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
13159 E = LHS;
13160 } else {
13161 ErrorInfo.Error = ErrorTy::InvalidComparison;
13162 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13163 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13164 S->getCond()->getSourceRange();
13165 return false;
13166 }
13167 } else if ((Cond &&
13168 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
13169 (Call &&
13170 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
13171 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
13172 E = BO->getRHS();
13173 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
13174 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
13175 C = S->getCond();
13176 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
13177 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
13178 C = S->getCond();
13179 IsXBinopExpr = false;
13180 } else {
13181 ErrorInfo.Error = ErrorTy::InvalidComparison;
13182 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13183 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13184 S->getCond()->getSourceRange();
13185 return false;
13186 }
13187 } else {
13188 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
13189 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13190 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
13191 return false;
13192 }
13193
13194 if (S->getElse()) {
13195 ErrorInfo.Error = ErrorTy::UnexpectedElse;
13196 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
13197 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
13198 return false;
13199 }
13200
13201 return true;
13202}
13203
13204bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
13205 ErrorInfoTy &ErrorInfo) {
13206 auto *BO = dyn_cast<BinaryOperator>(S);
13207 if (!BO) {
13208 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13209 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
13210 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
13211 return false;
13212 }
13213 if (BO->getOpcode() != BO_Assign) {
13214 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13215 ErrorInfo.ErrorLoc = BO->getExprLoc();
13216 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13218 return false;
13219 }
13220
13221 X = BO->getLHS();
13222
13223 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
13224 if (!CO) {
13225 ErrorInfo.Error = ErrorTy::NotCondOp;
13226 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
13227 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
13228 return false;
13229 }
13230
13231 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
13232 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
13233 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
13234 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13235 CO->getFalseExpr()->getSourceRange();
13236 return false;
13237 }
13238
13239 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
13240 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
13241 Expr *LHS = nullptr;
13242 Expr *RHS = nullptr;
13243 if (Cond) {
13244 LHS = Cond->getLHS();
13245 RHS = Cond->getRHS();
13246 } else if (Call) {
13247 LHS = Call->getArg(0);
13248 RHS = Call->getArg(1);
13249 } else {
13250 ErrorInfo.Error = ErrorTy::NotABinaryOp;
13251 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13252 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13253 CO->getCond()->getSourceRange();
13254 return false;
13255 }
13256
13257 if ((Cond && Cond->getOpcode() == BO_EQ) ||
13258 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
13259 C = CO->getCond();
13260 D = CO->getTrueExpr();
13261 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
13262 E = RHS;
13263 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
13264 E = LHS;
13265 } else {
13266 ErrorInfo.Error = ErrorTy::InvalidComparison;
13267 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13268 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13269 CO->getCond()->getSourceRange();
13270 return false;
13271 }
13272 } else if ((Cond &&
13273 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
13274 (Call &&
13275 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
13276 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
13277
13278 E = CO->getTrueExpr();
13279 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
13280 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
13281 C = CO->getCond();
13282 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
13283 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
13284 C = CO->getCond();
13285 IsXBinopExpr = false;
13286 } else {
13287 ErrorInfo.Error = ErrorTy::InvalidComparison;
13288 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13289 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13290 CO->getCond()->getSourceRange();
13291 return false;
13292 }
13293 } else {
13294 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
13295 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
13296 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13297 CO->getCond()->getSourceRange();
13298 return false;
13299 }
13300
13301 return true;
13302}
13303
13304bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
13305 // 'x' and 'e' cannot be nullptr
13306 assert(X && E && "X and E cannot be nullptr");
13307
13308 if (!CheckValue(X, ErrorInfo, true))
13309 return false;
13310
13311 if (!CheckValue(E, ErrorInfo, false))
13312 return false;
13313
13314 if (D && !CheckValue(D, ErrorInfo, false))
13315 return false;
13316
13317 return true;
13318}
13319
13320bool OpenMPAtomicCompareChecker::checkStmt(
13321 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
13322 auto *CS = dyn_cast<CompoundStmt>(S);
13323 if (CS) {
13324 if (CS->body_empty()) {
13325 ErrorInfo.Error = ErrorTy::NoStmt;
13326 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13327 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13328 return false;
13329 }
13330
13331 if (CS->size() != 1) {
13332 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13333 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13334 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13335 return false;
13336 }
13337 S = CS->body_front();
13338 }
13339
13340 auto Res = false;
13341
13342 if (auto *IS = dyn_cast<IfStmt>(S)) {
13343 // Check if the statement is in one of the following forms
13344 // (cond-update-stmt):
13345 // if (expr ordop x) { x = expr; }
13346 // if (x ordop expr) { x = expr; }
13347 // if (x == e) { x = d; }
13348 Res = checkCondUpdateStmt(IS, ErrorInfo);
13349 } else {
13350 // Check if the statement is in one of the following forms (cond-expr-stmt):
13351 // x = expr ordop x ? expr : x;
13352 // x = x ordop expr ? expr : x;
13353 // x = x == e ? d : x;
13354 Res = checkCondExprStmt(S, ErrorInfo);
13355 }
13356
13357 if (!Res)
13358 return false;
13359
13360 return checkType(ErrorInfo);
13361}
13362
13363class OpenMPAtomicCompareCaptureChecker final
13364 : public OpenMPAtomicCompareChecker {
13365public:
13366 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
13367
13368 Expr *getV() const { return V; }
13369 Expr *getR() const { return R; }
13370 bool isFailOnly() const { return IsFailOnly; }
13371 bool isPostfixUpdate() const { return IsPostfixUpdate; }
13372
13373 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
13374 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
13375
13376private:
13377 bool checkType(ErrorInfoTy &ErrorInfo);
13378
13379 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
13380 // form of 'conditional-update-capture-atomic' structured block on the v5.2
13381 // spec p.p. 82:
13382 // (1) { v = x; cond-update-stmt }
13383 // (2) { cond-update-stmt v = x; }
13384 // (3) if(x == e) { x = d; } else { v = x; }
13385 // (4) { r = x == e; if(r) { x = d; } }
13386 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
13387
13388 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
13389 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
13390
13391 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
13392 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
13393 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
13394
13395 /// 'v' lvalue part of the source atomic expression.
13396 Expr *V = nullptr;
13397 /// 'r' lvalue part of the source atomic expression.
13398 Expr *R = nullptr;
13399 /// If 'v' is only updated when the comparison fails.
13400 bool IsFailOnly = false;
13401 /// If original value of 'x' must be stored in 'v', not an updated one.
13402 bool IsPostfixUpdate = false;
13403};
13404
13405bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
13406 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
13407 return false;
13408
13409 if (V && !CheckValue(V, ErrorInfo, true))
13410 return false;
13411
13412 if (R && !CheckValue(R, ErrorInfo, true, true))
13413 return false;
13414
13415 return true;
13416}
13417
13418bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
13419 ErrorInfoTy &ErrorInfo) {
13420 IsFailOnly = true;
13421
13422 auto *Then = S->getThen();
13423 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
13424 if (CS->body_empty()) {
13425 ErrorInfo.Error = ErrorTy::NoStmt;
13426 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13427 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13428 return false;
13429 }
13430 if (CS->size() > 1) {
13431 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13432 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13433 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13434 return false;
13435 }
13436 Then = CS->body_front();
13437 }
13438
13439 auto *BO = dyn_cast<BinaryOperator>(Then);
13440 if (!BO) {
13441 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13442 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
13443 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
13444 return false;
13445 }
13446 if (BO->getOpcode() != BO_Assign) {
13447 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13448 ErrorInfo.ErrorLoc = BO->getExprLoc();
13449 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13451 return false;
13452 }
13453
13454 X = BO->getLHS();
13455 D = BO->getRHS();
13456
13457 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
13458 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
13459 Expr *LHS = nullptr;
13460 Expr *RHS = nullptr;
13461 if (Cond) {
13462 LHS = Cond->getLHS();
13463 RHS = Cond->getRHS();
13464 } else if (Call) {
13465 LHS = Call->getArg(0);
13466 RHS = Call->getArg(1);
13467 } else {
13468 ErrorInfo.Error = ErrorTy::NotABinaryOp;
13469 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13470 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
13471 return false;
13472 }
13473 if ((Cond && Cond->getOpcode() != BO_EQ) ||
13474 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
13475 ErrorInfo.Error = ErrorTy::NotEQ;
13476 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13477 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
13478 return false;
13479 }
13480
13481 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
13482 E = RHS;
13483 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
13484 E = LHS;
13485 } else {
13486 ErrorInfo.Error = ErrorTy::InvalidComparison;
13487 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
13488 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
13489 return false;
13490 }
13491
13492 C = S->getCond();
13493
13494 if (!S->getElse()) {
13495 ErrorInfo.Error = ErrorTy::NoElse;
13496 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
13497 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
13498 return false;
13499 }
13500
13501 auto *Else = S->getElse();
13502 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
13503 if (CS->body_empty()) {
13504 ErrorInfo.Error = ErrorTy::NoStmt;
13505 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13506 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13507 return false;
13508 }
13509 if (CS->size() > 1) {
13510 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13511 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13512 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
13513 return false;
13514 }
13515 Else = CS->body_front();
13516 }
13517
13518 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
13519 if (!ElseBO) {
13520 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13521 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
13522 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
13523 return false;
13524 }
13525 if (ElseBO->getOpcode() != BO_Assign) {
13526 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13527 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
13528 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
13529 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
13530 return false;
13531 }
13532
13533 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
13534 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13535 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
13536 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13537 ElseBO->getRHS()->getSourceRange();
13538 return false;
13539 }
13540
13541 V = ElseBO->getLHS();
13542
13543 return checkType(ErrorInfo);
13544}
13545
13546bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
13547 ErrorInfoTy &ErrorInfo) {
13548 // We don't check here as they should be already done before call this
13549 // function.
13550 auto *CS = cast<CompoundStmt>(S);
13551 assert(CS->size() == 2 && "CompoundStmt size is not expected");
13552 auto *S1 = cast<BinaryOperator>(CS->body_front());
13553 auto *S2 = cast<IfStmt>(CS->body_back());
13554 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
13555
13556 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
13557 ErrorInfo.Error = ErrorTy::InvalidCondition;
13558 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
13559 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
13560 return false;
13561 }
13562
13563 R = S1->getLHS();
13564
13565 auto *Then = S2->getThen();
13566 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
13567 if (ThenCS->body_empty()) {
13568 ErrorInfo.Error = ErrorTy::NoStmt;
13569 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
13570 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
13571 return false;
13572 }
13573 if (ThenCS->size() > 1) {
13574 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13575 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
13576 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
13577 return false;
13578 }
13579 Then = ThenCS->body_front();
13580 }
13581
13582 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
13583 if (!ThenBO) {
13584 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13585 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
13586 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
13587 return false;
13588 }
13589 if (ThenBO->getOpcode() != BO_Assign) {
13590 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13591 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
13592 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
13593 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
13594 return false;
13595 }
13596
13597 X = ThenBO->getLHS();
13598 D = ThenBO->getRHS();
13599
13600 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
13601 if (BO->getOpcode() != BO_EQ) {
13602 ErrorInfo.Error = ErrorTy::NotEQ;
13603 ErrorInfo.ErrorLoc = BO->getExprLoc();
13604 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13605 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13606 return false;
13607 }
13608
13609 C = BO;
13610
13611 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
13612 E = BO->getRHS();
13613 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
13614 E = BO->getLHS();
13615 } else {
13616 ErrorInfo.Error = ErrorTy::InvalidComparison;
13617 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
13618 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13619 return false;
13620 }
13621
13622 if (S2->getElse()) {
13623 IsFailOnly = true;
13624
13625 auto *Else = S2->getElse();
13626 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
13627 if (ElseCS->body_empty()) {
13628 ErrorInfo.Error = ErrorTy::NoStmt;
13629 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
13630 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
13631 return false;
13632 }
13633 if (ElseCS->size() > 1) {
13634 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
13635 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
13636 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
13637 return false;
13638 }
13639 Else = ElseCS->body_front();
13640 }
13641
13642 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
13643 if (!ElseBO) {
13644 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13645 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
13646 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
13647 return false;
13648 }
13649 if (ElseBO->getOpcode() != BO_Assign) {
13650 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13651 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
13652 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
13653 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
13654 return false;
13655 }
13656 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
13657 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13658 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
13659 ErrorInfo.NoteLoc = X->getExprLoc();
13660 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
13661 ErrorInfo.NoteRange = X->getSourceRange();
13662 return false;
13663 }
13664
13665 V = ElseBO->getLHS();
13666 }
13667
13668 return checkType(ErrorInfo);
13669}
13670
13671bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
13672 ErrorInfoTy &ErrorInfo) {
13673 // if(x == e) { x = d; } else { v = x; }
13674 if (auto *IS = dyn_cast<IfStmt>(S))
13675 return checkForm3(IS, ErrorInfo);
13676
13677 auto *CS = dyn_cast<CompoundStmt>(S);
13678 if (!CS) {
13679 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
13680 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
13681 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
13682 return false;
13683 }
13684 if (CS->body_empty()) {
13685 ErrorInfo.Error = ErrorTy::NoStmt;
13686 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13687 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13688 return false;
13689 }
13690
13691 // { if(x == e) { x = d; } else { v = x; } }
13692 if (CS->size() == 1) {
13693 auto *IS = dyn_cast<IfStmt>(CS->body_front());
13694 if (!IS) {
13695 ErrorInfo.Error = ErrorTy::NotIfStmt;
13696 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
13697 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
13698 CS->body_front()->getSourceRange();
13699 return false;
13700 }
13701
13702 return checkForm3(IS, ErrorInfo);
13703 } else if (CS->size() == 2) {
13704 auto *S1 = CS->body_front();
13705 auto *S2 = CS->body_back();
13706
13707 Stmt *UpdateStmt = nullptr;
13708 Stmt *CondUpdateStmt = nullptr;
13709 Stmt *CondExprStmt = nullptr;
13710
13711 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
13712 // It could be one of the following cases:
13713 // { v = x; cond-update-stmt }
13714 // { v = x; cond-expr-stmt }
13715 // { cond-expr-stmt; v = x; }
13716 // form 45
13717 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
13718 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
13719 // check if form 45
13720 if (isa<IfStmt>(S2))
13721 return checkForm45(CS, ErrorInfo);
13722 // { cond-expr-stmt; v = x; }
13723 CondExprStmt = S1;
13724 UpdateStmt = S2;
13725 } else {
13726 IsPostfixUpdate = true;
13727 UpdateStmt = S1;
13728 if (isa<IfStmt>(S2)) {
13729 // { v = x; cond-update-stmt }
13730 CondUpdateStmt = S2;
13731 } else {
13732 // { v = x; cond-expr-stmt }
13733 CondExprStmt = S2;
13734 }
13735 }
13736 } else {
13737 // { cond-update-stmt v = x; }
13738 UpdateStmt = S2;
13739 CondUpdateStmt = S1;
13740 }
13741
13742 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
13743 auto *IS = dyn_cast<IfStmt>(CUS);
13744 if (!IS) {
13745 ErrorInfo.Error = ErrorTy::NotIfStmt;
13746 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
13747 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
13748 return false;
13749 }
13750
13751 return checkCondUpdateStmt(IS, ErrorInfo);
13752 };
13753
13754 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
13755 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
13756 auto *BO = dyn_cast<BinaryOperator>(US);
13757 if (!BO) {
13758 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13759 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
13760 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
13761 return false;
13762 }
13763 if (BO->getOpcode() != BO_Assign) {
13764 ErrorInfo.Error = ErrorTy::NotAnAssignment;
13765 ErrorInfo.ErrorLoc = BO->getExprLoc();
13766 ErrorInfo.NoteLoc = BO->getOperatorLoc();
13767 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
13768 return false;
13769 }
13770 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
13771 ErrorInfo.Error = ErrorTy::InvalidAssignment;
13772 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
13773 ErrorInfo.NoteLoc = this->X->getExprLoc();
13774 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
13775 ErrorInfo.NoteRange = this->X->getSourceRange();
13776 return false;
13777 }
13778
13779 this->V = BO->getLHS();
13780
13781 return true;
13782 };
13783
13784 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
13785 return false;
13786 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
13787 return false;
13788 if (!CheckUpdateStmt(UpdateStmt))
13789 return false;
13790 } else {
13791 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
13792 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
13793 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
13794 return false;
13795 }
13796
13797 return checkType(ErrorInfo);
13798}
13799} // namespace
13800
13802 Stmt *AStmt,
13803 SourceLocation StartLoc,
13804 SourceLocation EndLoc) {
13805 ASTContext &Context = getASTContext();
13806 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
13807 // Register location of the first atomic directive.
13808 DSAStack->addAtomicDirectiveLoc(StartLoc);
13809 if (!AStmt)
13810 return StmtError();
13811
13812 // 1.2.2 OpenMP Language Terminology
13813 // Structured block - An executable statement with a single entry at the
13814 // top and a single exit at the bottom.
13815 // The point of exit cannot be a branch out of the structured block.
13816 // longjmp() and throw() must not violate the entry/exit criteria.
13817 OpenMPClauseKind AtomicKind = OMPC_unknown;
13818 SourceLocation AtomicKindLoc;
13819 OpenMPClauseKind MemOrderKind = OMPC_unknown;
13820 SourceLocation MemOrderLoc;
13821 bool MutexClauseEncountered = false;
13822 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
13823 for (const OMPClause *C : Clauses) {
13824 switch (C->getClauseKind()) {
13825 case OMPC_read:
13826 case OMPC_write:
13827 case OMPC_update:
13828 MutexClauseEncountered = true;
13829 [[fallthrough]];
13830 case OMPC_capture:
13831 case OMPC_compare: {
13832 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
13833 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
13834 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13835 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
13836 << getOpenMPClauseNameForDiag(AtomicKind);
13837 } else {
13838 AtomicKind = C->getClauseKind();
13839 AtomicKindLoc = C->getBeginLoc();
13840 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
13841 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
13842 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13843 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
13844 << getOpenMPClauseNameForDiag(AtomicKind);
13845 }
13846 }
13847 break;
13848 }
13849 case OMPC_weak:
13850 case OMPC_fail: {
13851 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
13852 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
13853 << getOpenMPClauseNameForDiag(C->getClauseKind())
13854 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13855 return StmtError();
13856 }
13857 break;
13858 }
13859 case OMPC_seq_cst:
13860 case OMPC_acq_rel:
13861 case OMPC_acquire:
13862 case OMPC_release:
13863 case OMPC_relaxed: {
13864 if (MemOrderKind != OMPC_unknown) {
13865 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
13866 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
13867 << SourceRange(C->getBeginLoc(), C->getEndLoc());
13868 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
13869 << getOpenMPClauseNameForDiag(MemOrderKind);
13870 } else {
13871 MemOrderKind = C->getClauseKind();
13872 MemOrderLoc = C->getBeginLoc();
13873 }
13874 break;
13875 }
13876 // The following clauses are allowed, but we don't need to do anything here.
13877 case OMPC_hint:
13878 break;
13879 default:
13880 llvm_unreachable("unknown clause is encountered");
13881 }
13882 }
13883 bool IsCompareCapture = false;
13884 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
13885 EncounteredAtomicKinds.contains(OMPC_capture)) {
13886 IsCompareCapture = true;
13887 AtomicKind = OMPC_compare;
13888 }
13889 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
13890 // If atomic-clause is read then memory-order-clause must not be acq_rel or
13891 // release.
13892 // If atomic-clause is write then memory-order-clause must not be acq_rel or
13893 // acquire.
13894 // If atomic-clause is update or not present then memory-order-clause must not
13895 // be acq_rel or acquire.
13896 if ((AtomicKind == OMPC_read &&
13897 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
13898 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
13899 AtomicKind == OMPC_unknown) &&
13900 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
13901 SourceLocation Loc = AtomicKindLoc;
13902 if (AtomicKind == OMPC_unknown)
13903 Loc = StartLoc;
13904 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
13905 << getOpenMPClauseNameForDiag(AtomicKind)
13906 << (AtomicKind == OMPC_unknown ? 1 : 0)
13907 << getOpenMPClauseNameForDiag(MemOrderKind);
13908 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
13909 << getOpenMPClauseNameForDiag(MemOrderKind);
13910 }
13911
13912 Stmt *Body = AStmt;
13913 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
13914 Body = EWC->getSubExpr();
13915
13916 Expr *X = nullptr;
13917 Expr *V = nullptr;
13918 Expr *E = nullptr;
13919 Expr *UE = nullptr;
13920 Expr *D = nullptr;
13921 Expr *CE = nullptr;
13922 Expr *R = nullptr;
13923 bool IsXLHSInRHSPart = false;
13924 bool IsPostfixUpdate = false;
13925 bool IsFailOnly = false;
13926 // OpenMP [2.12.6, atomic Construct]
13927 // In the next expressions:
13928 // * x and v (as applicable) are both l-value expressions with scalar type.
13929 // * During the execution of an atomic region, multiple syntactic
13930 // occurrences of x must designate the same storage location.
13931 // * Neither of v and expr (as applicable) may access the storage location
13932 // designated by x.
13933 // * Neither of x and expr (as applicable) may access the storage location
13934 // designated by v.
13935 // * expr is an expression with scalar type.
13936 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
13937 // * binop, binop=, ++, and -- are not overloaded operators.
13938 // * The expression x binop expr must be numerically equivalent to x binop
13939 // (expr). This requirement is satisfied if the operators in expr have
13940 // precedence greater than binop, or by using parentheses around expr or
13941 // subexpressions of expr.
13942 // * The expression expr binop x must be numerically equivalent to (expr)
13943 // binop x. This requirement is satisfied if the operators in expr have
13944 // precedence equal to or greater than binop, or by using parentheses around
13945 // expr or subexpressions of expr.
13946 // * For forms that allow multiple occurrences of x, the number of times
13947 // that x is evaluated is unspecified.
13948 if (AtomicKind == OMPC_read) {
13949 enum {
13950 NotAnExpression,
13951 NotAnAssignmentOp,
13952 NotAScalarType,
13953 NotAnLValue,
13954 NoError
13955 } ErrorFound = NoError;
13956 SourceLocation ErrorLoc, NoteLoc;
13957 SourceRange ErrorRange, NoteRange;
13958 // If clause is read:
13959 // v = x;
13960 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13961 const auto *AtomicBinOp =
13962 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13963 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13964 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13965 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
13966 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
13967 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
13968 if (!X->isLValue() || !V->isLValue()) {
13969 const Expr *NotLValueExpr = X->isLValue() ? V : X;
13970 ErrorFound = NotAnLValue;
13971 ErrorLoc = AtomicBinOp->getExprLoc();
13972 ErrorRange = AtomicBinOp->getSourceRange();
13973 NoteLoc = NotLValueExpr->getExprLoc();
13974 NoteRange = NotLValueExpr->getSourceRange();
13975 }
13976 } else if (!X->isInstantiationDependent() ||
13977 !V->isInstantiationDependent()) {
13978 const Expr *NotScalarExpr =
13979 (X->isInstantiationDependent() || X->getType()->isScalarType())
13980 ? V
13981 : X;
13982 ErrorFound = NotAScalarType;
13983 ErrorLoc = AtomicBinOp->getExprLoc();
13984 ErrorRange = AtomicBinOp->getSourceRange();
13985 NoteLoc = NotScalarExpr->getExprLoc();
13986 NoteRange = NotScalarExpr->getSourceRange();
13987 }
13988 } else if (!AtomicBody->isInstantiationDependent()) {
13989 ErrorFound = NotAnAssignmentOp;
13990 ErrorLoc = AtomicBody->getExprLoc();
13991 ErrorRange = AtomicBody->getSourceRange();
13992 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13993 : AtomicBody->getExprLoc();
13994 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13995 : AtomicBody->getSourceRange();
13996 }
13997 } else {
13998 ErrorFound = NotAnExpression;
13999 NoteLoc = ErrorLoc = Body->getBeginLoc();
14000 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
14001 }
14002 if (ErrorFound != NoError) {
14003 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
14004 << ErrorRange;
14005 Diag(NoteLoc, diag::note_omp_atomic_read_write)
14006 << ErrorFound << NoteRange;
14007 return StmtError();
14008 }
14009 if (SemaRef.CurContext->isDependentContext())
14010 V = X = nullptr;
14011 } else if (AtomicKind == OMPC_write) {
14012 enum {
14013 NotAnExpression,
14014 NotAnAssignmentOp,
14015 NotAScalarType,
14016 NotAnLValue,
14017 NoError
14018 } ErrorFound = NoError;
14019 SourceLocation ErrorLoc, NoteLoc;
14020 SourceRange ErrorRange, NoteRange;
14021 // If clause is write:
14022 // x = expr;
14023 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
14024 const auto *AtomicBinOp =
14025 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
14026 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
14027 X = AtomicBinOp->getLHS();
14028 E = AtomicBinOp->getRHS();
14029 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
14030 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
14031 if (!X->isLValue()) {
14032 ErrorFound = NotAnLValue;
14033 ErrorLoc = AtomicBinOp->getExprLoc();
14034 ErrorRange = AtomicBinOp->getSourceRange();
14035 NoteLoc = X->getExprLoc();
14036 NoteRange = X->getSourceRange();
14037 }
14038 } else if (!X->isInstantiationDependent() ||
14040 const Expr *NotScalarExpr =
14041 (X->isInstantiationDependent() || X->getType()->isScalarType())
14042 ? E
14043 : X;
14044 ErrorFound = NotAScalarType;
14045 ErrorLoc = AtomicBinOp->getExprLoc();
14046 ErrorRange = AtomicBinOp->getSourceRange();
14047 NoteLoc = NotScalarExpr->getExprLoc();
14048 NoteRange = NotScalarExpr->getSourceRange();
14049 }
14050 } else if (!AtomicBody->isInstantiationDependent()) {
14051 ErrorFound = NotAnAssignmentOp;
14052 ErrorLoc = AtomicBody->getExprLoc();
14053 ErrorRange = AtomicBody->getSourceRange();
14054 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
14055 : AtomicBody->getExprLoc();
14056 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
14057 : AtomicBody->getSourceRange();
14058 }
14059 } else {
14060 ErrorFound = NotAnExpression;
14061 NoteLoc = ErrorLoc = Body->getBeginLoc();
14062 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
14063 }
14064 if (ErrorFound != NoError) {
14065 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
14066 << ErrorRange;
14067 Diag(NoteLoc, diag::note_omp_atomic_read_write)
14068 << ErrorFound << NoteRange;
14069 return StmtError();
14070 }
14071 if (SemaRef.CurContext->isDependentContext())
14072 E = X = nullptr;
14073 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
14074 // If clause is update:
14075 // x++;
14076 // x--;
14077 // ++x;
14078 // --x;
14079 // x binop= expr;
14080 // x = x binop expr;
14081 // x = expr binop x;
14082 OpenMPAtomicUpdateChecker Checker(SemaRef);
14083 if (Checker.checkStatement(
14084 Body,
14085 (AtomicKind == OMPC_update)
14086 ? diag::err_omp_atomic_update_not_expression_statement
14087 : diag::err_omp_atomic_not_expression_statement,
14088 diag::note_omp_atomic_update))
14089 return StmtError();
14090 if (!SemaRef.CurContext->isDependentContext()) {
14091 E = Checker.getExpr();
14092 X = Checker.getX();
14093 UE = Checker.getUpdateExpr();
14094 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
14095 }
14096 } else if (AtomicKind == OMPC_capture) {
14097 enum {
14098 NotAnAssignmentOp,
14099 NotACompoundStatement,
14100 NotTwoSubstatements,
14101 NotASpecificExpression,
14102 NoError
14103 } ErrorFound = NoError;
14104 SourceLocation ErrorLoc, NoteLoc;
14105 SourceRange ErrorRange, NoteRange;
14106 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
14107 // If clause is a capture:
14108 // v = x++;
14109 // v = x--;
14110 // v = ++x;
14111 // v = --x;
14112 // v = x binop= expr;
14113 // v = x = x binop expr;
14114 // v = x = expr binop x;
14115 const auto *AtomicBinOp =
14116 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
14117 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
14118 V = AtomicBinOp->getLHS();
14119 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
14120 OpenMPAtomicUpdateChecker Checker(SemaRef);
14121 if (Checker.checkStatement(
14122 Body, diag::err_omp_atomic_capture_not_expression_statement,
14123 diag::note_omp_atomic_update))
14124 return StmtError();
14125 E = Checker.getExpr();
14126 X = Checker.getX();
14127 UE = Checker.getUpdateExpr();
14128 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
14129 IsPostfixUpdate = Checker.isPostfixUpdate();
14130 } else if (!AtomicBody->isInstantiationDependent()) {
14131 ErrorLoc = AtomicBody->getExprLoc();
14132 ErrorRange = AtomicBody->getSourceRange();
14133 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
14134 : AtomicBody->getExprLoc();
14135 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
14136 : AtomicBody->getSourceRange();
14137 ErrorFound = NotAnAssignmentOp;
14138 }
14139 if (ErrorFound != NoError) {
14140 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
14141 << ErrorRange;
14142 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
14143 return StmtError();
14144 }
14145 if (SemaRef.CurContext->isDependentContext())
14146 UE = V = E = X = nullptr;
14147 } else {
14148 // If clause is a capture:
14149 // { v = x; x = expr; }
14150 // { v = x; x++; }
14151 // { v = x; x--; }
14152 // { v = x; ++x; }
14153 // { v = x; --x; }
14154 // { v = x; x binop= expr; }
14155 // { v = x; x = x binop expr; }
14156 // { v = x; x = expr binop x; }
14157 // { x++; v = x; }
14158 // { x--; v = x; }
14159 // { ++x; v = x; }
14160 // { --x; v = x; }
14161 // { x binop= expr; v = x; }
14162 // { x = x binop expr; v = x; }
14163 // { x = expr binop x; v = x; }
14164 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
14165 // Check that this is { expr1; expr2; }
14166 if (CS->size() == 2) {
14167 Stmt *First = CS->body_front();
14168 Stmt *Second = CS->body_back();
14169 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
14170 First = EWC->getSubExpr()->IgnoreParenImpCasts();
14171 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
14172 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
14173 // Need to find what subexpression is 'v' and what is 'x'.
14174 OpenMPAtomicUpdateChecker Checker(SemaRef);
14175 bool IsUpdateExprFound = !Checker.checkStatement(Second);
14176 BinaryOperator *BinOp = nullptr;
14177 if (IsUpdateExprFound) {
14178 BinOp = dyn_cast<BinaryOperator>(First);
14179 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
14180 }
14181 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
14182 // { v = x; x++; }
14183 // { v = x; x--; }
14184 // { v = x; ++x; }
14185 // { v = x; --x; }
14186 // { v = x; x binop= expr; }
14187 // { v = x; x = x binop expr; }
14188 // { v = x; x = expr binop x; }
14189 // Check that the first expression has form v = x.
14190 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
14191 llvm::FoldingSetNodeID XId, PossibleXId;
14192 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
14193 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
14194 IsUpdateExprFound = XId == PossibleXId;
14195 if (IsUpdateExprFound) {
14196 V = BinOp->getLHS();
14197 X = Checker.getX();
14198 E = Checker.getExpr();
14199 UE = Checker.getUpdateExpr();
14200 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
14201 IsPostfixUpdate = true;
14202 }
14203 }
14204 if (!IsUpdateExprFound) {
14205 IsUpdateExprFound = !Checker.checkStatement(First);
14206 BinOp = nullptr;
14207 if (IsUpdateExprFound) {
14208 BinOp = dyn_cast<BinaryOperator>(Second);
14209 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
14210 }
14211 if (IsUpdateExprFound &&
14212 !SemaRef.CurContext->isDependentContext()) {
14213 // { x++; v = x; }
14214 // { x--; v = x; }
14215 // { ++x; v = x; }
14216 // { --x; v = x; }
14217 // { x binop= expr; v = x; }
14218 // { x = x binop expr; v = x; }
14219 // { x = expr binop x; v = x; }
14220 // Check that the second expression has form v = x.
14221 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
14222 llvm::FoldingSetNodeID XId, PossibleXId;
14223 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
14224 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
14225 IsUpdateExprFound = XId == PossibleXId;
14226 if (IsUpdateExprFound) {
14227 V = BinOp->getLHS();
14228 X = Checker.getX();
14229 E = Checker.getExpr();
14230 UE = Checker.getUpdateExpr();
14231 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
14232 IsPostfixUpdate = false;
14233 }
14234 }
14235 }
14236 if (!IsUpdateExprFound) {
14237 // { v = x; x = expr; }
14238 auto *FirstExpr = dyn_cast<Expr>(First);
14239 auto *SecondExpr = dyn_cast<Expr>(Second);
14240 if (!FirstExpr || !SecondExpr ||
14241 !(FirstExpr->isInstantiationDependent() ||
14242 SecondExpr->isInstantiationDependent())) {
14243 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
14244 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
14245 ErrorFound = NotAnAssignmentOp;
14246 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
14247 : First->getBeginLoc();
14248 NoteRange = ErrorRange = FirstBinOp
14249 ? FirstBinOp->getSourceRange()
14250 : SourceRange(ErrorLoc, ErrorLoc);
14251 } else {
14252 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
14253 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
14254 ErrorFound = NotAnAssignmentOp;
14255 NoteLoc = ErrorLoc = SecondBinOp
14256 ? SecondBinOp->getOperatorLoc()
14257 : Second->getBeginLoc();
14258 NoteRange = ErrorRange =
14259 SecondBinOp ? SecondBinOp->getSourceRange()
14260 : SourceRange(ErrorLoc, ErrorLoc);
14261 } else {
14262 Expr *PossibleXRHSInFirst =
14263 FirstBinOp->getRHS()->IgnoreParenImpCasts();
14264 Expr *PossibleXLHSInSecond =
14265 SecondBinOp->getLHS()->IgnoreParenImpCasts();
14266 llvm::FoldingSetNodeID X1Id, X2Id;
14267 PossibleXRHSInFirst->Profile(X1Id, Context,
14268 /*Canonical=*/true);
14269 PossibleXLHSInSecond->Profile(X2Id, Context,
14270 /*Canonical=*/true);
14271 IsUpdateExprFound = X1Id == X2Id;
14272 if (IsUpdateExprFound) {
14273 V = FirstBinOp->getLHS();
14274 X = SecondBinOp->getLHS();
14275 E = SecondBinOp->getRHS();
14276 UE = nullptr;
14277 IsXLHSInRHSPart = false;
14278 IsPostfixUpdate = true;
14279 } else {
14280 ErrorFound = NotASpecificExpression;
14281 ErrorLoc = FirstBinOp->getExprLoc();
14282 ErrorRange = FirstBinOp->getSourceRange();
14283 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
14284 NoteRange = SecondBinOp->getRHS()->getSourceRange();
14285 }
14286 }
14287 }
14288 }
14289 }
14290 } else {
14291 NoteLoc = ErrorLoc = Body->getBeginLoc();
14292 NoteRange = ErrorRange =
14293 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
14294 ErrorFound = NotTwoSubstatements;
14295 }
14296 } else {
14297 NoteLoc = ErrorLoc = Body->getBeginLoc();
14298 NoteRange = ErrorRange =
14299 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
14300 ErrorFound = NotACompoundStatement;
14301 }
14302 }
14303 if (ErrorFound != NoError) {
14304 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
14305 << ErrorRange;
14306 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
14307 return StmtError();
14308 }
14309 if (SemaRef.CurContext->isDependentContext())
14310 UE = V = E = X = nullptr;
14311 } else if (AtomicKind == OMPC_compare) {
14312 if (IsCompareCapture) {
14313 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
14314 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
14315 if (!Checker.checkStmt(Body, ErrorInfo)) {
14316 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
14317 << ErrorInfo.ErrorRange;
14318 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
14319 << ErrorInfo.Error << ErrorInfo.NoteRange;
14320 return StmtError();
14321 }
14322 X = Checker.getX();
14323 E = Checker.getE();
14324 D = Checker.getD();
14325 CE = Checker.getCond();
14326 V = Checker.getV();
14327 R = Checker.getR();
14328 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
14329 IsXLHSInRHSPart = Checker.isXBinopExpr();
14330 IsFailOnly = Checker.isFailOnly();
14331 IsPostfixUpdate = Checker.isPostfixUpdate();
14332 } else {
14333 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
14334 OpenMPAtomicCompareChecker Checker(SemaRef);
14335 if (!Checker.checkStmt(Body, ErrorInfo)) {
14336 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
14337 << ErrorInfo.ErrorRange;
14338 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
14339 << ErrorInfo.Error << ErrorInfo.NoteRange;
14340 return StmtError();
14341 }
14342 X = Checker.getX();
14343 E = Checker.getE();
14344 D = Checker.getD();
14345 CE = Checker.getCond();
14346 // The weak clause may only appear if the resulting atomic operation is
14347 // an atomic conditional update for which the comparison tests for
14348 // equality. It was not possible to do this check in
14349 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
14350 // could not be performed (Clauses are not available).
14351 auto *It = find_if(Clauses, [](OMPClause *C) {
14352 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
14353 });
14354 if (It != Clauses.end()) {
14355 auto *Cond = dyn_cast<BinaryOperator>(CE);
14356 if (Cond->getOpcode() != BO_EQ) {
14357 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
14358 ErrorInfo.ErrorLoc = Cond->getExprLoc();
14359 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
14360 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
14361
14362 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
14363 << ErrorInfo.ErrorRange;
14364 return StmtError();
14365 }
14366 }
14367 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
14368 IsXLHSInRHSPart = Checker.isXBinopExpr();
14369 }
14370 }
14371
14372 SemaRef.setFunctionHasBranchProtectedScope();
14373
14375 Context, StartLoc, EndLoc, Clauses, AStmt,
14376 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
14377}
14378
14380 Stmt *AStmt,
14381 SourceLocation StartLoc,
14382 SourceLocation EndLoc) {
14383 if (!AStmt)
14384 return StmtError();
14385
14386 if (validateMultidimClauses(*this, Clauses))
14387 return StmtError();
14388
14389 // Check for conflicting capture kinds on structured bindings.
14390 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_target, Clauses))
14391 return StmtError();
14392
14394 return StmtError();
14395
14396 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
14397
14398 // OpenMP [2.16, Nesting of Regions]
14399 // If specified, a teams construct must be contained within a target
14400 // construct. That target construct must contain no statements or directives
14401 // outside of the teams construct.
14402 if (DSAStack->hasInnerTeamsRegion()) {
14403 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
14404 bool OMPTeamsFound = true;
14405 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
14406 auto I = CS->body_begin();
14407 while (I != CS->body_end()) {
14408 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
14409 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
14410 if (!IsTeams || I != CS->body_begin()) {
14411 OMPTeamsFound = false;
14412 if (IsTeams && I != CS->body_begin()) {
14413 // This is the two teams case. Since the InnerTeamsRegionLoc will
14414 // point to this second one reset the iterator to the other teams.
14415 --I;
14416 }
14417 break;
14418 }
14419 ++I;
14420 }
14421 assert(I != CS->body_end() && "Not found statement");
14422 S = *I;
14423 } else {
14424 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
14425 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
14426 }
14427 if (!OMPTeamsFound) {
14428 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
14429 Diag(DSAStack->getInnerTeamsRegionLoc(),
14430 diag::note_omp_nested_teams_construct_here);
14431 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
14433 return StmtError();
14434 }
14435 }
14436
14437 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
14438 AStmt);
14439}
14440
14442 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14443 SourceLocation EndLoc) {
14444 if (!AStmt)
14445 return StmtError();
14446
14447 if (validateMultidimClauses(*this, Clauses))
14448 return StmtError();
14449
14450 // Check for conflicting capture kinds on structured bindings.
14451 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_target_parallel,
14452 Clauses))
14453 return StmtError();
14454
14456 return StmtError();
14457
14458 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
14459
14461 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
14462 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14463}
14464
14466 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14467 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14468 if (!AStmt)
14469 return StmtError();
14470
14471 if (validateMultidimClauses(*this, Clauses))
14472 return StmtError();
14473
14474 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_target_parallel_for,
14475 Clauses))
14476 return StmtError();
14477
14479 return StmtError();
14480
14481 CapturedStmt *CS =
14482 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
14483
14484 OMPLoopBasedDirective::HelperExprs B;
14485 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14486 // define the nested loops number.
14487 unsigned NestedLoopCount =
14488 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
14489 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14490 VarsWithImplicitDSA, B);
14491 if (NestedLoopCount == 0)
14492 return StmtError();
14493
14494 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14495 return StmtError();
14496
14498 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14499 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14500}
14501
14502/// Check for existence of a map clause in the list of clauses.
14504 const OpenMPClauseKind K) {
14505 return llvm::any_of(
14506 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
14507}
14508
14509template <typename... Params>
14511 const Params... ClauseTypes) {
14512 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
14513}
14514
14515/// Check if the variables in the mapping clause are externally visible.
14517 for (const OMPClause *C : Clauses) {
14518 if (auto *TC = dyn_cast<OMPToClause>(C))
14519 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
14520 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
14521 (VD->isExternallyVisible() &&
14522 VD->getVisibility() != HiddenVisibility);
14523 });
14524 else if (auto *FC = dyn_cast<OMPFromClause>(C))
14525 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
14526 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
14527 (VD->isExternallyVisible() &&
14528 VD->getVisibility() != HiddenVisibility);
14529 });
14530 }
14531
14532 return true;
14533}
14534
14537 Stmt *AStmt, SourceLocation StartLoc,
14538 SourceLocation EndLoc) {
14539 if (!AStmt)
14540 return StmtError();
14541
14542 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14543
14544 // OpenMP [2.12.2, target data Construct, Restrictions]
14545 // At least one map, use_device_addr or use_device_ptr clause must appear on
14546 // the directive.
14547 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
14548 (getLangOpts().OpenMP < 50 ||
14549 !hasClauses(Clauses, OMPC_use_device_addr))) {
14550 StringRef Expected;
14551 if (getLangOpts().OpenMP < 50)
14552 Expected = "'map' or 'use_device_ptr'";
14553 else
14554 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
14555 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
14556 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
14557 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
14558 return StmtError();
14559 }
14560
14561 SemaRef.setFunctionHasBranchProtectedScope();
14562
14563 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
14564 Clauses, AStmt);
14565}
14566
14568 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
14569 SourceLocation EndLoc, Stmt *AStmt) {
14570 if (!AStmt)
14571 return StmtError();
14572
14573 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
14574
14575 // OpenMP [2.10.2, Restrictions, p. 99]
14576 // At least one map clause must appear on the directive.
14577 if (!hasClauses(Clauses, OMPC_map)) {
14578 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
14579 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
14580 << "'map'"
14581 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
14582 return StmtError();
14583 }
14584
14585 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
14586 Clauses, AStmt);
14587}
14588
14590 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
14591 SourceLocation EndLoc, Stmt *AStmt) {
14592 if (!AStmt)
14593 return StmtError();
14594
14595 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
14596
14597 // OpenMP [2.10.3, Restrictions, p. 102]
14598 // At least one map clause must appear on the directive.
14599 if (!hasClauses(Clauses, OMPC_map)) {
14600 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
14601 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
14602 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
14603 return StmtError();
14604 }
14605
14606 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
14607 Clauses, AStmt);
14608}
14609
14611 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
14612 SourceLocation EndLoc, Stmt *AStmt) {
14613 if (!AStmt)
14614 return StmtError();
14615
14616 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
14617
14618 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
14619 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
14620 return StmtError();
14621 }
14622
14623 if (!isClauseMappable(Clauses)) {
14624 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
14625 return StmtError();
14626 }
14627
14628 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
14629 Clauses, AStmt);
14630}
14631
14633 Stmt *AStmt,
14634 SourceLocation StartLoc,
14635 SourceLocation EndLoc) {
14636 if (!AStmt)
14637 return StmtError();
14638
14639 if (validateMultidimClauses(*this, Clauses))
14640 return StmtError();
14641
14642 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_teams, Clauses))
14643 return StmtError();
14644
14645 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
14646 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
14647 Diag(StartLoc, diag::warn_hip_omp_target_directives);
14648
14649 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
14650
14651 DSAStack->setParentTeamsRegionLoc(StartLoc);
14652
14653 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
14654 AStmt);
14655}
14656
14658 SourceLocation StartLoc, SourceLocation EndLoc,
14659 OpenMPDirectiveKind CancelRegion) {
14660 if (DSAStack->isParentNowaitRegion()) {
14661 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
14662 return StmtError();
14663 }
14664 if (DSAStack->isParentOrderedRegion()) {
14665 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
14666 return StmtError();
14667 }
14669 EndLoc, CancelRegion);
14670}
14671
14673 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
14674 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
14675 if (DSAStack->isParentNowaitRegion()) {
14676 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
14677 return StmtError();
14678 }
14679 if (DSAStack->isParentOrderedRegion()) {
14680 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
14681 return StmtError();
14682 }
14683 DSAStack->setParentCancelRegion(/*Cancel=*/true);
14684 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
14685 CancelRegion);
14686}
14687
14689 ArrayRef<OMPClause *> Clauses) {
14690 const OMPClause *ReductionClause = nullptr;
14691 const OMPClause *NogroupClause = nullptr;
14692 for (const OMPClause *C : Clauses) {
14693 if (C->getClauseKind() == OMPC_reduction) {
14694 ReductionClause = C;
14695 if (NogroupClause)
14696 break;
14697 continue;
14698 }
14699 if (C->getClauseKind() == OMPC_nogroup) {
14700 NogroupClause = C;
14701 if (ReductionClause)
14702 break;
14703 continue;
14704 }
14705 }
14706 if (ReductionClause && NogroupClause) {
14707 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
14708 << SourceRange(NogroupClause->getBeginLoc(),
14709 NogroupClause->getEndLoc());
14710 return true;
14711 }
14712 return false;
14713}
14714
14716 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14717 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14718 if (!AStmt)
14719 return StmtError();
14720
14721 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14722 OMPLoopBasedDirective::HelperExprs B;
14723 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14724 // define the nested loops number.
14725 unsigned NestedLoopCount =
14726 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
14727 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14728 *DSAStack, VarsWithImplicitDSA, B);
14729 if (NestedLoopCount == 0)
14730 return StmtError();
14731
14732 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14733 "omp for loop exprs were not built");
14734
14735 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14736 // The grainsize clause and num_tasks clause are mutually exclusive and may
14737 // not appear on the same taskloop directive.
14739 {OMPC_grainsize, OMPC_num_tasks}))
14740 return StmtError();
14741 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14742 // If a reduction clause is present on the taskloop directive, the nogroup
14743 // clause must not be specified.
14745 return StmtError();
14746
14747 SemaRef.setFunctionHasBranchProtectedScope();
14748 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
14749 NestedLoopCount, Clauses, AStmt, B,
14750 DSAStack->isCancelRegion());
14751}
14752
14754 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14755 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14756 if (!AStmt)
14757 return StmtError();
14758
14759 CapturedStmt *CS =
14760 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
14761
14762 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14763 OMPLoopBasedDirective::HelperExprs B;
14764 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14765 // define the nested loops number.
14766 unsigned NestedLoopCount =
14767 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
14768 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14769 VarsWithImplicitDSA, B);
14770 if (NestedLoopCount == 0)
14771 return StmtError();
14772
14773 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14774 return StmtError();
14775
14776 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14777 // The grainsize clause and num_tasks clause are mutually exclusive and may
14778 // not appear on the same taskloop directive.
14780 {OMPC_grainsize, OMPC_num_tasks}))
14781 return StmtError();
14782 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14783 // If a reduction clause is present on the taskloop directive, the nogroup
14784 // clause must not be specified.
14786 return StmtError();
14788 return StmtError();
14789
14790 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14791 NestedLoopCount, Clauses, AStmt, B);
14792}
14793
14795 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14796 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14797 if (!AStmt)
14798 return StmtError();
14799
14800 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14801 OMPLoopBasedDirective::HelperExprs B;
14802 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14803 // define the nested loops number.
14804 unsigned NestedLoopCount =
14805 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
14806 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14807 *DSAStack, VarsWithImplicitDSA, B);
14808 if (NestedLoopCount == 0)
14809 return StmtError();
14810
14811 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14812 "omp for loop exprs were not built");
14813
14814 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14815 // The grainsize clause and num_tasks clause are mutually exclusive and may
14816 // not appear on the same taskloop directive.
14818 {OMPC_grainsize, OMPC_num_tasks}))
14819 return StmtError();
14820 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14821 // If a reduction clause is present on the taskloop directive, the nogroup
14822 // clause must not be specified.
14824 return StmtError();
14825
14826 SemaRef.setFunctionHasBranchProtectedScope();
14827 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
14828 NestedLoopCount, Clauses, AStmt, B,
14829 DSAStack->isCancelRegion());
14830}
14831
14833 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14834 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14835 if (!AStmt)
14836 return StmtError();
14837
14838 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14839 OMPLoopBasedDirective::HelperExprs B;
14840 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14841 // define the nested loops number.
14842 unsigned NestedLoopCount =
14843 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
14844 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
14845 *DSAStack, VarsWithImplicitDSA, B);
14846 if (NestedLoopCount == 0)
14847 return StmtError();
14848
14849 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14850 "omp for loop exprs were not built");
14851
14852 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14853 // The grainsize clause and num_tasks clause are mutually exclusive and may
14854 // not appear on the same taskloop directive.
14856 {OMPC_grainsize, OMPC_num_tasks}))
14857 return StmtError();
14858 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14859 // If a reduction clause is present on the taskloop directive, the nogroup
14860 // clause must not be specified.
14862 return StmtError();
14863
14864 SemaRef.setFunctionHasBranchProtectedScope();
14865 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
14866 NestedLoopCount, Clauses, AStmt, B,
14867 DSAStack->isCancelRegion());
14868}
14869
14871 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14872 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14873 if (!AStmt)
14874 return StmtError();
14875
14876 CapturedStmt *CS =
14877 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
14878
14879 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14880 OMPLoopBasedDirective::HelperExprs B;
14881 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14882 // define the nested loops number.
14883 unsigned NestedLoopCount =
14884 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
14885 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14886 VarsWithImplicitDSA, B);
14887 if (NestedLoopCount == 0)
14888 return StmtError();
14889
14890 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14891 return StmtError();
14892
14893 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14894 // The grainsize clause and num_tasks clause are mutually exclusive and may
14895 // not appear on the same taskloop directive.
14897 {OMPC_grainsize, OMPC_num_tasks}))
14898 return StmtError();
14899 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14900 // If a reduction clause is present on the taskloop directive, the nogroup
14901 // clause must not be specified.
14903 return StmtError();
14905 return StmtError();
14906
14908 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14909}
14910
14912 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14913 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14914 if (!AStmt)
14915 return StmtError();
14916
14917 CapturedStmt *CS =
14918 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
14919
14920 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14921 OMPLoopBasedDirective::HelperExprs B;
14922 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14923 // define the nested loops number.
14924 unsigned NestedLoopCount =
14925 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14926 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14927 VarsWithImplicitDSA, B);
14928 if (NestedLoopCount == 0)
14929 return StmtError();
14930
14931 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14932 return StmtError();
14933
14934 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14935 // The grainsize clause and num_tasks clause are mutually exclusive and may
14936 // not appear on the same taskloop directive.
14938 {OMPC_grainsize, OMPC_num_tasks}))
14939 return StmtError();
14940 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14941 // If a reduction clause is present on the taskloop directive, the nogroup
14942 // clause must not be specified.
14944 return StmtError();
14946 return StmtError();
14947
14949 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14950}
14951
14953 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14954 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14955 if (!AStmt)
14956 return StmtError();
14957
14958 CapturedStmt *CS =
14959 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
14960
14961 OMPLoopBasedDirective::HelperExprs B;
14962 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14963 // define the nested loops number.
14964 unsigned NestedLoopCount = checkOpenMPLoop(
14965 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
14966 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14967 VarsWithImplicitDSA, B);
14968 if (NestedLoopCount == 0)
14969 return StmtError();
14970
14971 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14972 "omp for loop exprs were not built");
14973
14974 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14975 // The grainsize clause and num_tasks clause are mutually exclusive and may
14976 // not appear on the same taskloop directive.
14978 {OMPC_grainsize, OMPC_num_tasks}))
14979 return StmtError();
14980 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14981 // If a reduction clause is present on the taskloop directive, the nogroup
14982 // clause must not be specified.
14984 return StmtError();
14985
14987 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14988 DSAStack->isCancelRegion());
14989}
14990
14992 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14993 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14994 if (!AStmt)
14995 return StmtError();
14996
14997 CapturedStmt *CS =
14998 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
14999
15000 OMPLoopBasedDirective::HelperExprs B;
15001 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
15002 // define the nested loops number.
15003 unsigned NestedLoopCount = checkOpenMPLoop(
15004 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
15005 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
15006 VarsWithImplicitDSA, B);
15007 if (NestedLoopCount == 0)
15008 return StmtError();
15009
15010 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15011 "omp for loop exprs were not built");
15012
15013 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
15014 // The grainsize clause and num_tasks clause are mutually exclusive and may
15015 // not appear on the same taskloop directive.
15017 {OMPC_grainsize, OMPC_num_tasks}))
15018 return StmtError();
15019 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
15020 // If a reduction clause is present on the taskloop directive, the nogroup
15021 // clause must not be specified.
15023 return StmtError();
15024
15026 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15027 DSAStack->isCancelRegion());
15028}
15029
15031 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15032 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15033 if (!AStmt)
15034 return StmtError();
15035
15037 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
15038
15039 OMPLoopBasedDirective::HelperExprs B;
15040 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
15041 // define the nested loops number.
15042 unsigned NestedLoopCount = checkOpenMPLoop(
15043 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
15044 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
15045 VarsWithImplicitDSA, B);
15046 if (NestedLoopCount == 0)
15047 return StmtError();
15048
15049 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15050 return StmtError();
15051
15052 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
15053 // The grainsize clause and num_tasks clause are mutually exclusive and may
15054 // not appear on the same taskloop directive.
15056 {OMPC_grainsize, OMPC_num_tasks}))
15057 return StmtError();
15058 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
15059 // If a reduction clause is present on the taskloop directive, the nogroup
15060 // clause must not be specified.
15062 return StmtError();
15064 return StmtError();
15065
15067 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15068}
15069
15071 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15072 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15073 if (!AStmt)
15074 return StmtError();
15075
15077 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
15078
15079 OMPLoopBasedDirective::HelperExprs B;
15080 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
15081 // define the nested loops number.
15082 unsigned NestedLoopCount = checkOpenMPLoop(
15083 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
15084 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
15085 VarsWithImplicitDSA, B);
15086 if (NestedLoopCount == 0)
15087 return StmtError();
15088
15089 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15090 return StmtError();
15091
15092 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
15093 // The grainsize clause and num_tasks clause are mutually exclusive and may
15094 // not appear on the same taskloop directive.
15096 {OMPC_grainsize, OMPC_num_tasks}))
15097 return StmtError();
15098 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
15099 // If a reduction clause is present on the taskloop directive, the nogroup
15100 // clause must not be specified.
15102 return StmtError();
15104 return StmtError();
15105
15107 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15108}
15109
15111 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15112 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15113 if (!AStmt)
15114 return StmtError();
15115
15116 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
15117 OMPLoopBasedDirective::HelperExprs B;
15118 // In presence of clause 'collapse' with number of loops, it will
15119 // define the nested loops number.
15120 unsigned NestedLoopCount =
15121 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
15122 nullptr /*ordered not a clause on distribute*/, AStmt,
15123 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
15124 if (NestedLoopCount == 0)
15125 return StmtError();
15126
15127 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15128 "omp for loop exprs were not built");
15129
15130 SemaRef.setFunctionHasBranchProtectedScope();
15131 auto *DistributeDirective = OMPDistributeDirective::Create(
15132 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15133 return DistributeDirective;
15134}
15135
15137 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15138 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15139 if (!AStmt)
15140 return StmtError();
15141
15142 CapturedStmt *CS =
15143 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
15144
15145 OMPLoopBasedDirective::HelperExprs B;
15146 // In presence of clause 'collapse' with number of loops, it will
15147 // define the nested loops number.
15148 unsigned NestedLoopCount = checkOpenMPLoop(
15149 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
15150 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15151 VarsWithImplicitDSA, B);
15152 if (NestedLoopCount == 0)
15153 return StmtError();
15154
15155 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15156 "omp for loop exprs were not built");
15157
15159 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15160 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
15161}
15162
15164 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15165 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15166 if (!AStmt)
15167 return StmtError();
15168
15170 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
15171
15172 OMPLoopBasedDirective::HelperExprs B;
15173 // In presence of clause 'collapse' with number of loops, it will
15174 // define the nested loops number.
15175 unsigned NestedLoopCount = checkOpenMPLoop(
15176 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
15177 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15178 VarsWithImplicitDSA, B);
15179 if (NestedLoopCount == 0)
15180 return StmtError();
15181
15182 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15183 return StmtError();
15184
15186 return StmtError();
15187
15189 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15190}
15191
15193 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15194 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15195 if (!AStmt)
15196 return StmtError();
15197
15198 CapturedStmt *CS =
15199 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
15200
15201 OMPLoopBasedDirective::HelperExprs B;
15202 // In presence of clause 'collapse' with number of loops, it will
15203 // define the nested loops number.
15204 unsigned NestedLoopCount =
15205 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
15206 nullptr /*ordered not a clause on distribute*/, CS,
15207 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
15208 if (NestedLoopCount == 0)
15209 return StmtError();
15210
15211 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15212 return StmtError();
15213
15215 return StmtError();
15216
15217 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
15218 NestedLoopCount, Clauses, AStmt, B);
15219}
15220
15222 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15223 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15224 if (!AStmt)
15225 return StmtError();
15226
15227 if (validateMultidimClauses(*this, Clauses))
15228 return StmtError();
15229
15231 SemaRef, OMPD_target_parallel_for_simd, Clauses))
15232 return StmtError();
15233
15235 return StmtError();
15236
15237 CapturedStmt *CS =
15238 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
15239
15240 OMPLoopBasedDirective::HelperExprs B;
15241 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
15242 // define the nested loops number.
15243 unsigned NestedLoopCount = checkOpenMPLoop(
15244 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
15245 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
15246 VarsWithImplicitDSA, B);
15247 if (NestedLoopCount == 0)
15248 return StmtError();
15249
15250 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15251 return StmtError();
15252
15254 return StmtError();
15255
15257 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15258}
15259
15261 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15262 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15263 if (!AStmt)
15264 return StmtError();
15265
15266 if (validateMultidimClauses(*this, Clauses))
15267 return StmtError();
15268
15269 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_target_simd, Clauses))
15270 return StmtError();
15271
15273 return StmtError();
15274
15275 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
15276
15277 OMPLoopBasedDirective::HelperExprs B;
15278 // In presence of clause 'collapse' with number of loops, it will define the
15279 // nested loops number.
15280 unsigned NestedLoopCount =
15281 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
15282 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
15283 VarsWithImplicitDSA, B);
15284 if (NestedLoopCount == 0)
15285 return StmtError();
15286
15287 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15288 return StmtError();
15289
15291 return StmtError();
15292
15293 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
15294 NestedLoopCount, Clauses, AStmt, B);
15295}
15296
15298 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15299 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15300 if (!AStmt)
15301 return StmtError();
15302
15303 if (validateMultidimClauses(*this, Clauses))
15304 return StmtError();
15305
15306 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_teams_distribute,
15307 Clauses))
15308 return StmtError();
15309
15310 CapturedStmt *CS =
15311 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
15312
15313 OMPLoopBasedDirective::HelperExprs B;
15314 // In presence of clause 'collapse' with number of loops, it will
15315 // define the nested loops number.
15316 unsigned NestedLoopCount =
15317 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
15318 nullptr /*ordered not a clause on distribute*/, CS,
15319 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
15320 if (NestedLoopCount == 0)
15321 return StmtError();
15322
15323 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15324 "omp teams distribute loop exprs were not built");
15325
15326 DSAStack->setParentTeamsRegionLoc(StartLoc);
15327
15329 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15330}
15331
15333 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15334 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15335 if (!AStmt)
15336 return StmtError();
15337
15338 if (validateMultidimClauses(*this, Clauses))
15339 return StmtError();
15340 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_teams_distribute_simd,
15341 Clauses))
15342 return StmtError();
15343
15344 CapturedStmt *CS =
15345 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
15346
15347 OMPLoopBasedDirective::HelperExprs B;
15348 // In presence of clause 'collapse' with number of loops, it will
15349 // define the nested loops number.
15350 unsigned NestedLoopCount = checkOpenMPLoop(
15351 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
15352 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15353 VarsWithImplicitDSA, B);
15354 if (NestedLoopCount == 0)
15355 return StmtError();
15356
15357 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15358 return StmtError();
15359
15361 return StmtError();
15362
15363 DSAStack->setParentTeamsRegionLoc(StartLoc);
15364
15366 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15367}
15368
15370 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15371 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15372 if (!AStmt)
15373 return StmtError();
15374
15375 if (validateMultidimClauses(*this, Clauses))
15376 return StmtError();
15377
15379 SemaRef, OMPD_teams_distribute_parallel_for_simd, Clauses))
15380 return StmtError();
15381
15383 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
15384
15385 OMPLoopBasedDirective::HelperExprs B;
15386 // In presence of clause 'collapse' with number of loops, it will
15387 // define the nested loops number.
15388 unsigned NestedLoopCount = checkOpenMPLoop(
15389 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
15390 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15391 VarsWithImplicitDSA, B);
15392 if (NestedLoopCount == 0)
15393 return StmtError();
15394
15395 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15396 return StmtError();
15397
15399 return StmtError();
15400
15401 DSAStack->setParentTeamsRegionLoc(StartLoc);
15402
15404 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15405}
15406
15408 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15409 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15410 if (!AStmt)
15411 return StmtError();
15412
15413 if (validateMultidimClauses(*this, Clauses))
15414 return StmtError();
15415
15417 SemaRef, OMPD_teams_distribute_parallel_for, Clauses))
15418 return StmtError();
15419
15421 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
15422
15423 OMPLoopBasedDirective::HelperExprs B;
15424 // In presence of clause 'collapse' with number of loops, it will
15425 // define the nested loops number.
15426 unsigned NestedLoopCount = checkOpenMPLoop(
15427 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
15428 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15429 VarsWithImplicitDSA, B);
15430
15431 if (NestedLoopCount == 0)
15432 return StmtError();
15433
15434 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15435 "omp for loop exprs were not built");
15436
15437 DSAStack->setParentTeamsRegionLoc(StartLoc);
15438
15440 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15441 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
15442}
15443
15445 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15446 SourceLocation EndLoc) {
15447 if (!AStmt)
15448 return StmtError();
15449
15450 if (checkClausesForDecompositionConflicts(SemaRef, OMPD_target_teams,
15451 Clauses))
15452 return StmtError();
15453
15455 return StmtError();
15456
15457 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
15458
15459 if (validateMultidimClauses(*this, Clauses, /*MayHaveBareClause=*/true))
15460 return StmtError();
15461
15462 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
15463 Clauses, AStmt);
15464}
15465
15467 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15468 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15469 if (!AStmt)
15470 return StmtError();
15471
15472 if (validateMultidimClauses(*this, Clauses))
15473 return StmtError();
15474
15476 SemaRef, OMPD_target_teams_distribute, Clauses))
15477 return StmtError();
15478
15480 return StmtError();
15481
15482 CapturedStmt *CS =
15483 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
15484
15485 OMPLoopBasedDirective::HelperExprs B;
15486 // In presence of clause 'collapse' with number of loops, it will
15487 // define the nested loops number.
15488 unsigned NestedLoopCount = checkOpenMPLoop(
15489 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
15490 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15491 VarsWithImplicitDSA, B);
15492 if (NestedLoopCount == 0)
15493 return StmtError();
15494
15495 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
15496 "omp target teams distribute loop exprs were not built");
15497
15499 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15500}
15501
15503 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15504 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15505 if (!AStmt)
15506 return StmtError();
15507
15508 if (validateMultidimClauses(*this, Clauses))
15509 return StmtError();
15510
15512 SemaRef, OMPD_target_teams_distribute_parallel_for, Clauses))
15513 return StmtError();
15514
15516 return StmtError();
15517
15519 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
15520
15521 OMPLoopBasedDirective::HelperExprs B;
15522 // In presence of clause 'collapse' with number of loops, it will
15523 // define the nested loops number.
15524 unsigned NestedLoopCount = checkOpenMPLoop(
15525 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
15526 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15527 VarsWithImplicitDSA, B);
15528 if (NestedLoopCount == 0)
15529 return StmtError();
15530
15531 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15532 return StmtError();
15533
15535 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
15536 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
15537}
15538
15540 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15541 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15542 if (!AStmt)
15543 return StmtError();
15544
15545 if (validateMultidimClauses(*this, Clauses))
15546 return StmtError();
15547
15549 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, Clauses))
15550 return StmtError();
15551
15553 return StmtError();
15554
15556 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
15557
15558 OMPLoopBasedDirective::HelperExprs B;
15559 // In presence of clause 'collapse' with number of loops, it will
15560 // define the nested loops number.
15561 unsigned NestedLoopCount =
15562 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
15563 getCollapseNumberExpr(Clauses),
15564 nullptr /*ordered not a clause on distribute*/, CS,
15565 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
15566 if (NestedLoopCount == 0)
15567 return StmtError();
15568
15569 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15570 return StmtError();
15571
15573 return StmtError();
15574
15576 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15577}
15578
15580 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15581 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
15582 if (!AStmt)
15583 return StmtError();
15584
15585 if (validateMultidimClauses(*this, Clauses))
15586 return StmtError();
15587
15589 SemaRef, OMPD_target_teams_distribute_simd, Clauses))
15590 return StmtError();
15591
15593 return StmtError();
15594
15596 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
15597
15598 OMPLoopBasedDirective::HelperExprs B;
15599 // In presence of clause 'collapse' with number of loops, it will
15600 // define the nested loops number.
15601 unsigned NestedLoopCount = checkOpenMPLoop(
15602 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
15603 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
15604 VarsWithImplicitDSA, B);
15605 if (NestedLoopCount == 0)
15606 return StmtError();
15607
15608 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
15609 return StmtError();
15610
15612 return StmtError();
15613
15615 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
15616}
15617
15618/// Updates OriginalInits by checking Transform against loop transformation
15619/// directives and appending their pre-inits if a match is found.
15621 SmallVectorImpl<Stmt *> &PreInits) {
15622 Stmt *Dir = Transform->getDirective();
15623 switch (Dir->getStmtClass()) {
15624#define STMT(CLASS, PARENT)
15625#define ABSTRACT_STMT(CLASS)
15626#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
15627 case Stmt::CLASS##Class: \
15628 appendFlattenedStmtList(PreInits, \
15629 static_cast<const CLASS *>(Dir)->getPreInits()); \
15630 break;
15631#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
15632 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
15633#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
15634 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
15635#include "clang/AST/StmtNodes.inc"
15636#undef COMMON_OMP_LOOP_TRANSFORMATION
15637 default:
15638 llvm_unreachable("Not a loop transformation");
15639 }
15640}
15641
15642bool SemaOpenMP::checkTransformableLoopNest(
15643 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
15645 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits,
15646 SmallVectorImpl<Stmt *> *NestedFinals) {
15647 if (NestedFinals)
15648 NestedFinals->assign(NumLoops, nullptr);
15649 OriginalInits.emplace_back();
15650 // Only tile and stripe re-emit the statements before the nested loop in a
15651 // nested transformation's generated loop (see appendStmtsBeforeNestedLoop);
15652 // other constructs would silently drop them.
15654 Kind == OMPD_tile || Kind == OMPD_stripe;
15655 bool Result = OMPLoopBasedDirective::doForAllLoops(
15656 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
15657 [this, &LoopHelpers, &Body, &OriginalInits,
15658 Kind](unsigned Cnt, Stmt *CurStmt, Stmt *HintWrapper) {
15659 // The start of this loop is a floor set in the enclosing tile's body.
15660 // Loop analysis reads a start only once, so the nest would repeat the
15661 // first tile. Reject instead of emitting wrong loops.
15662 if (HintWrapper) {
15663 SemaRef.Diag(CurStmt->getBeginLoc(),
15664 diag::err_omp_collapse_stacked_tile)
15665 << /*LoopTransform=*/1;
15666 return true;
15667 }
15669 unsigned SingleNumLoops =
15670 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
15671 TmpDSA, LoopHelpers[Cnt]);
15672 if (SingleNumLoops == 0)
15673 return true;
15674 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
15675 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
15676 OriginalInits.back().push_back(For->getInit());
15677 Body = For->getBody();
15678 } else {
15679 assert(isa<CXXForRangeStmt>(CurStmt) &&
15680 "Expected canonical for or range-based for loops.");
15681 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
15682 OriginalInits.back().push_back(CXXFor->getBeginStmt());
15683 Body = CXXFor->getBody();
15684 }
15685 OriginalInits.emplace_back();
15686 return false;
15687 },
15688 [&OriginalInits,
15689 NestedFinals](OMPLoopTransformationDirective *Transform) {
15690 updatePreInits(Transform, OriginalInits.back());
15691 if (NestedFinals)
15692 if (Stmt *Finals = Transform->getFinals()) {
15693 assert(!(*NestedFinals)[OriginalInits.size() - 1] &&
15694 "Expected one nested transformation per loop");
15695 (*NestedFinals)[OriginalInits.size() - 1] = Finals;
15696 }
15697 },
15699 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
15700 OriginalInits.pop_back();
15701 return Result;
15702}
15703
15704/// Counts the total number of OpenMP canonical nested loops, including the
15705/// outermost loop (the original loop). PRECONDITION of this visitor is that it
15706/// must be invoked from the original loop to be analyzed. The traversal stops
15707/// for Decl's and Expr's given that they may contain inner loops that must not
15708/// be counted.
15709///
15710/// Example AST structure for the code:
15711///
15712/// int main() {
15713/// #pragma omp fuse
15714/// {
15715/// for (int i = 0; i < 100; i++) { <-- Outer loop
15716/// []() {
15717/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
15718/// };
15719/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
15720/// }
15721/// for (int r = 0; i < 100; i++) { <-- Outer loop
15722/// struct LocalClass {
15723/// void bar() {
15724/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
15725/// }
15726/// };
15727/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
15728/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
15729/// }
15730/// }
15731/// }
15732/// (1) because in a different function (here: a lambda)
15733/// (2) because in a different function (here: class method)
15734/// (3) because considered to be intervening-code of non-perfectly nested loop
15735/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
15737private:
15738 unsigned NestedLoopCount = 0;
15739
15740public:
15741 explicit NestedLoopCounterVisitor() = default;
15742
15743 unsigned getNestedLoopCount() const { return NestedLoopCount; }
15744
15745 bool VisitForStmt(ForStmt *FS) override {
15746 ++NestedLoopCount;
15747 return true;
15748 }
15749
15751 ++NestedLoopCount;
15752 return true;
15753 }
15754
15755 bool TraverseStmt(Stmt *S) override {
15756 if (!S)
15757 return true;
15758
15759 // Skip traversal of all expressions, including special cases like
15760 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
15761 // may contain inner statements (and even loops), but they are not part
15762 // of the syntactic body of the surrounding loop structure.
15763 // Therefore must not be counted.
15764 if (isa<Expr>(S))
15765 return true;
15766
15767 // Only recurse into CompoundStmt (block {}) and loop bodies.
15770 }
15771
15772 // Stop traversal of the rest of statements, that break perfect
15773 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
15774 return true;
15775 }
15776
15777 bool TraverseDecl(Decl *D) override {
15778 // Stop in the case of finding a declaration, it is not important
15779 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
15780 // FunctionDecl...).
15781 return true;
15782 }
15783};
15784
15785bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
15786 LoopSequenceAnalysis &SeqAnalysis,
15787 ASTContext &Context,
15789 bool IsGeneratedSequence) {
15791 // Helper Lambda to handle storing initialization and body statements for
15792 // both ForStmt and CXXForRangeStmt.
15793 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
15794 if (auto *For = dyn_cast<ForStmt>(LoopStmt)) {
15795 Analysis.OriginalInits.push_back(For->getInit());
15796 Analysis.TheForStmt = For;
15797 } else {
15798 auto *CXXFor = cast<CXXForRangeStmt>(LoopStmt);
15799 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
15800 Analysis.TheForStmt = CXXFor;
15801 }
15802 };
15803
15804 // Helper lambda functions to encapsulate the processing of different
15805 // derivations of the canonical loop sequence grammar
15806 // Modularized code for handling loop generation and transformations.
15807 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
15808 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Child);
15809 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
15810 unsigned NumGeneratedTopLevelLoops =
15811 LoopTransform->getNumGeneratedTopLevelLoops();
15812 // Handle the case where transformed statement is not available due to
15813 // dependent contexts
15814 if (!TransformedStmt) {
15815 if (NumGeneratedTopLevelLoops > 0) {
15816 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
15817 return true;
15818 }
15819 // Unroll full (0 loops produced)
15820 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
15821 << 0 << getOpenMPDirectiveName(Kind);
15822 return false;
15823 }
15824 // Handle loop transformations with multiple loop nests
15825 // Unroll full
15826 if (!NumGeneratedTopLevelLoops) {
15827 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
15828 << 0 << getOpenMPDirectiveName(Kind);
15829 return false;
15830 }
15831 // Loop transformatons such as split or loopranged fuse
15832 if (NumGeneratedTopLevelLoops > 1) {
15833 // Get the preinits related to this loop sequence generating
15834 // loop transformation (i.e loopranged fuse, split...)
15835 // These preinits differ slightly from regular inits/pre-inits related
15836 // to single loop generating loop transformations (interchange, unroll)
15837 // given that they are not bounded to a particular loop nest
15838 // so they need to be treated independently
15839 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
15840 if (!analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind,
15841 /*IsGeneratedSequence=*/true))
15842 return false;
15843 // Finals follow the last generated loop; looprange fuse inlines its own.
15844 if (Stmt *Finals = LoopTransform->getFinals()) {
15845 assert(!SeqAnalysis.Loops.back().TransformFinals &&
15846 "Generated loop already has Finals");
15847 SeqAnalysis.Loops.back().TransformFinals = Finals;
15848 }
15849 return true;
15850 }
15851 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
15852 // Process the transformed loop statement
15853 LoopAnalysis &NewTransformedSingleLoop =
15854 SeqAnalysis.Loops.emplace_back(Child);
15855 unsigned IsCanonical = checkOpenMPLoop(
15856 Kind, nullptr, nullptr, TransformedStmt, SemaRef, *DSAStack, TmpDSA,
15857 NewTransformedSingleLoop.HelperExprs);
15858
15859 if (!IsCanonical)
15860 return false;
15861
15862 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
15863 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
15864 NewTransformedSingleLoop.TransformFinals = LoopTransform->getFinals();
15865
15866 SeqAnalysis.LoopSeqSize++;
15867 return true;
15868 };
15869
15870 // Modularized code for handling regular canonical loops.
15871 auto AnalyzeRegularLoop = [&](Stmt *Child) {
15872 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
15873 unsigned IsCanonical =
15874 checkOpenMPLoop(Kind, nullptr, nullptr, Child, SemaRef, *DSAStack,
15875 TmpDSA, NewRegularLoop.HelperExprs);
15876
15877 if (!IsCanonical)
15878 return false;
15879
15880 StoreLoopStatements(NewRegularLoop, Child);
15881 NestedLoopCounterVisitor NLCV;
15882 NLCV.TraverseStmt(Child);
15883 return true;
15884 };
15885
15886 // High level grammar validation.
15887 for (Stmt *Child : LoopSeqStmt->children()) {
15888 if (!Child)
15889 continue;
15890 // A sequence-generating transformation (e.g. looprange fuse) emits each
15891 // out-of-range loop transformation as `{ Loop; Finals }` so its loop
15892 // variables are finalized right after the loop. Analyze the loop and carry
15893 // its Finals along so the enclosing directive can place them.
15894 if (IsGeneratedSequence) {
15895 auto *CS = dyn_cast<CompoundStmt>(Child);
15896 if (CS && CS->size() == 2 &&
15897 LoopAnalysis::isRegularLoop(CS->body_front()) &&
15898 !LoopAnalysis::isRegularLoop(CS->body_back())) {
15899 if (!AnalyzeRegularLoop(CS->body_front()))
15900 return false;
15901 SeqAnalysis.Loops.back().TransformFinals = CS->body_back();
15902 SeqAnalysis.LoopSeqSize++;
15903 continue;
15904 }
15905 }
15906 // Skip over non-loop-sequence statements.
15907 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
15908 Child = Child->IgnoreContainers();
15909 // Ignore empty compound statement.
15910 if (!Child)
15911 continue;
15912 // In the case of a nested loop sequence ignoring containers would not
15913 // be enough, a recurisve transversal of the loop sequence is required.
15914 if (isa<CompoundStmt>(Child)) {
15915 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind,
15916 IsGeneratedSequence))
15917 return false;
15918 // Already been treated, skip this children
15919 continue;
15920 }
15921 }
15922 // Regular loop sequence handling.
15923 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
15924 if (LoopAnalysis::isLoopTransformation(Child)) {
15925 if (!AnalyzeLoopGeneration(Child))
15926 return false;
15927 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
15928 } else {
15929 if (!AnalyzeRegularLoop(Child))
15930 return false;
15931 SeqAnalysis.LoopSeqSize++;
15932 }
15933 } else {
15934 // Report error for invalid statement inside canonical loop sequence.
15935 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
15936 << 0 << getOpenMPDirectiveName(Kind);
15937 return false;
15938 }
15939 }
15940 return true;
15941}
15942
15943bool SemaOpenMP::checkTransformableLoopSequence(
15944 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
15945 ASTContext &Context) {
15946 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
15947 // the grammar:
15948 //
15949 // canonical-loop-sequence:
15950 // {
15951 // loop-sequence+
15952 // }
15953 // where loop-sequence can be any of the following:
15954 // 1. canonical-loop-sequence
15955 // 2. loop-nest
15956 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
15957 //
15958 // To recognise and traverse this structure the helper function
15959 // analyzeLoopSequence serves as the recurisve entry point
15960 // and tries to match the input AST to the canonical loop sequence grammar
15961 // structure. This function will perform both a semantic and syntactical
15962 // analysis of the given statement according to OpenMP 6.0 definition of
15963 // the aforementioned canonical loop sequence.
15964
15965 // We expect an outer compound statement.
15966 if (!isa<CompoundStmt>(AStmt)) {
15967 Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
15968 << getOpenMPDirectiveName(Kind);
15969 return false;
15970 }
15971
15972 // Recursive entry point to process the main loop sequence
15973 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
15974 return false;
15975
15976 // Diagnose an empty loop sequence.
15977 if (!SeqAnalysis.LoopSeqSize) {
15978 Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
15979 << getOpenMPDirectiveName(Kind);
15980 return false;
15981 }
15982 return true;
15983}
15984
15985/// Add preinit statements that need to be propagated from the selected loop.
15986static void addLoopPreInits(ASTContext &Context,
15987 OMPLoopBasedDirective::HelperExprs &LoopHelper,
15988 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
15989 SmallVectorImpl<Stmt *> &PreInits) {
15990
15991 // For range-based for-statements, ensure that their syntactic sugar is
15992 // executed by adding them as pre-init statements.
15993 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
15994 Stmt *RangeInit = CXXRangeFor->getInit();
15995 if (RangeInit)
15996 PreInits.push_back(RangeInit);
15997
15998 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
15999 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
16000 RangeStmt->getBeginLoc(),
16001 RangeStmt->getEndLoc()));
16002
16003 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
16004 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
16005 RangeEnd->getBeginLoc(),
16006 RangeEnd->getEndLoc()));
16007 }
16008
16009 llvm::append_range(PreInits, OriginalInit);
16010
16011 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
16012 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
16013 PreInits.push_back(new (Context) DeclStmt(
16014 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
16015 }
16016
16017 // Gather declarations for the data members used as counters.
16018 for (Expr *CounterRef : LoopHelper.Counters) {
16019 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
16020 if (isa<OMPCapturedExprDecl>(CounterDecl))
16021 PreInits.push_back(new (Context) DeclStmt(
16022 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
16023 }
16024}
16025
16026/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
16027/// loop of a construct.
16028static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts,
16029 bool RelaxNestForPeeledTransformation = false) {
16030 size_t NumLoops = LoopStmts.size();
16031 OMPLoopBasedDirective::doForAllLoops(
16032 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
16033 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
16034 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
16035 LoopStmts[Cnt] = CurStmt;
16036 return false;
16037 },
16039 assert(!is_contained(LoopStmts, nullptr) &&
16040 "Expecting a loop statement for each affected loop");
16041}
16042
16043/// A non-innermost affected loop generated by a nested loop transformation
16044/// (e.g. `omp reverse`) computes the user counter in statements ahead of the
16045/// next loop. A construct that rebuilds the nest only keeps the innermost
16046/// body, so it must re-emit these statements in the matching loop.
16047static void appendStmtsBeforeNestedLoop(Stmt *LoopStmt,
16048 SmallVectorImpl<Stmt *> &BodyParts) {
16049 Stmt *Body = isa<ForStmt>(LoopStmt)
16050 ? cast<ForStmt>(LoopStmt)->getBody()
16051 : cast<CXXForRangeStmt>(LoopStmt)->getBody();
16052 llvm::append_range(BodyParts,
16053 OMPLoopBasedDirective::getStmtsBeforeNestedLoop(Body));
16054}
16055
16056/// Build and return a DeclRefExpr for the floor induction variable using the
16057/// SemaRef and the provided parameters.
16058static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
16059 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
16060 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
16061 OrigCntVar->getExprLoc());
16062}
16063
16064/// Whether \p Counter is dead after \p LoopStmt: compiler generated (e.g. a
16065/// fuse index) or declared by the loop's own init statement.
16066static bool isDeadAfterLoop(const Expr *Counter, const Stmt *LoopStmt) {
16067 const auto *DRE = dyn_cast<DeclRefExpr>(Counter);
16068 const auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
16069 if (!VD)
16070 return false;
16071 if (VD->isImplicit())
16072 return !isa<OMPCapturedExprDecl>(VD);
16073 const auto *For = dyn_cast<ForStmt>(LoopStmt);
16074 const auto *Init = For ? dyn_cast_or_null<DeclStmt>(For->getInit()) : nullptr;
16075 return Init && llvm::is_contained(Init->decls(), VD);
16076}
16077
16078/// Wrap \p S so it runs only if every loop in \p Loops has iterations.
16079static Stmt *
16082 Stmt *S) {
16083 for (const auto &Loop : llvm::reverse(Loops))
16085 nullptr, nullptr, Loop.PreCond, SourceLocation(),
16086 SourceLocation(), S, SourceLocation(), nullptr);
16087 return S;
16088}
16089
16090/// Run loop \p I's inits only if all enclosing loops have iterations.
16091/// Declarations are left as is.
16092static void
16095 unsigned I, SmallVectorImpl<Stmt *> &OriginalInit) {
16096 if (I == 0)
16097 return;
16098 for (Stmt *&Init : OriginalInit)
16099 if (Init && !isa<DeclStmt>(Init))
16100 Init = guardByLoopPreConds(Context, LoopHelpers.take_front(I), Init);
16101}
16102
16103/// Build loop variable finalization statement from HelperExprs.Finals.
16104/// Each Final runs only if its loop and all enclosing loops have iterations;
16105/// \p NestedFinals[I] is emitted with loop I's.
16106/// Returns nullptr if there is nothing to finalize.
16107/// Counters that are dead after their loop and class-type iterators are
16108/// skipped.
16109static Stmt *
16112 ArrayRef<Stmt *> LoopStmts,
16113 ArrayRef<Stmt *> NestedFinals = {}) {
16114 assert(LoopStmts.size() == LoopHelpers.size() &&
16115 "Expected one loop statement per loop");
16116 auto GetFinals = [](const OMPLoopBasedDirective::HelperExprs &Helper,
16117 const Stmt *LoopStmt) {
16119 for (auto [Counter, Final] :
16120 llvm::zip_equal(Helper.Counters, Helper.Finals)) {
16121 if (isDeadAfterLoop(Counter, LoopStmt))
16122 continue;
16123 // FIXME: finalize class-type iterators too (random-access arithmetic
16124 // is available per the canonical loop form).
16125 QualType CounterTy = Counter->getType();
16126 if (Final &&
16127 (CounterTy->isArithmeticType() || CounterTy->isPointerType()))
16128 Finals.push_back(Final);
16129 }
16130 return Finals;
16131 };
16132 auto MakeCompound = [&Context](ArrayRef<Stmt *> Stmts) -> Stmt * {
16133 return CompoundStmt::Create(Context, Stmts, FPOptionsOverride(),
16135 };
16136
16137 auto GetNestedFinals = [&](size_t I) -> Stmt * {
16138 return I < NestedFinals.size() ? NestedFinals[I] : nullptr;
16139 };
16140
16141 // if (P0) { F0; if (P1) { F1; ... } }, built from the innermost loop out.
16142 Stmt *Nested = nullptr;
16143 for (size_t I = LoopHelpers.size(); I-- > 0;) {
16144 SmallVector<Stmt *, 2> Body = GetFinals(LoopHelpers[I], LoopStmts[I]);
16145 if (Stmt *F = GetNestedFinals(I))
16146 Body.push_back(F);
16147 if (Nested)
16148 Body.push_back(Nested);
16149 if (Body.empty())
16150 continue;
16151 Nested = guardByLoopPreConds(Context, LoopHelpers[I],
16152 Body.size() == 1 ? Body.front()
16153 : MakeCompound(Body));
16154 }
16155 return Nested;
16156}
16157
16159 Stmt *AStmt,
16160 SourceLocation StartLoc,
16161 SourceLocation EndLoc) {
16162 ASTContext &Context = getASTContext();
16163 Scope *CurScope = SemaRef.getCurScope();
16164
16165 const auto *SizesClause =
16166 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
16167 if (!SizesClause ||
16168 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
16169 return StmtError();
16170 unsigned NumLoops = SizesClause->getNumSizes();
16171
16172 // Empty statement should only be possible if there already was an error.
16173 if (!AStmt)
16174 return StmtError();
16175
16176 // Verify and diagnose loop nest.
16178 Stmt *Body = nullptr;
16179 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
16180 SmallVector<Stmt *, 4> NestedFinals;
16181 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
16182 OriginalInits, &NestedFinals))
16183 return StmtError();
16184
16185 // Delay tiling to when template is completely instantiated.
16186 if (SemaRef.CurContext->isDependentContext())
16187 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
16188 NumLoops, AStmt, nullptr, nullptr, nullptr);
16189
16190 assert(LoopHelpers.size() == NumLoops &&
16191 "Expecting loop iteration space dimensionality to match number of "
16192 "affected loops");
16193 assert(OriginalInits.size() == NumLoops &&
16194 "Expecting loop iteration space dimensionality to match number of "
16195 "affected loops");
16196
16197 // Collect all affected loop statements.
16198 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
16199 collectLoopStmts(AStmt, LoopStmts, /*RelaxNestForPeeledTransformation=*/true);
16200
16201 SmallVector<Stmt *, 4> PreInits;
16202 CaptureVars CopyTransformer(SemaRef);
16203
16204 // Create iteration variables for the generated loops.
16205 SmallVector<VarDecl *, 4> FloorIndVars;
16206 SmallVector<VarDecl *, 4> TileIndVars;
16207 FloorIndVars.resize(NumLoops);
16208 TileIndVars.resize(NumLoops);
16209 for (unsigned I = 0; I < NumLoops; ++I) {
16210 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16211
16212 assert(LoopHelper.Counters.size() == 1 &&
16213 "Expect single-dimensional loop iteration space");
16214 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
16215 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16216 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
16217 QualType CntTy = IterVarRef->getType();
16218
16219 // Iteration variable for the floor (i.e. outer) loop.
16220 {
16221 std::string FloorCntName =
16222 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
16223 VarDecl *FloorCntDecl =
16224 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
16225 FloorIndVars[I] = FloorCntDecl;
16226 }
16227
16228 // Iteration variable for the tile (i.e. inner) loop.
16229 {
16230 std::string TileCntName =
16231 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
16232
16233 // Reuse the iteration variable created by checkOpenMPLoop. It is also
16234 // used by the expressions to derive the original iteration variable's
16235 // value from the logical iteration number.
16236 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
16237 TileCntDecl->setDeclName(
16238 &SemaRef.PP.getIdentifierTable().get(TileCntName));
16239 TileIndVars[I] = TileCntDecl;
16240 }
16241
16242 guardNestedLoopInit(Context, LoopHelpers, I, OriginalInits[I]);
16243 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
16244 PreInits);
16245 }
16246
16247 // Once the original iteration values are set, append the innermost body.
16248 Stmt *Inner = Body;
16249
16250 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
16251 SizesClause, CurScope](int I) -> Expr * {
16252 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
16253
16254 if (DimTileSizeExpr->containsErrors())
16255 return nullptr;
16256
16257 if (isa<ConstantExpr>(DimTileSizeExpr))
16258 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
16259
16260 // When the tile size is not a constant but a variable, it is possible to
16261 // pass non-positive numbers. For instance:
16262 // \code{c}
16263 // int a = 0;
16264 // #pragma omp tile sizes(a)
16265 // for (int i = 0; i < 42; ++i)
16266 // body(i);
16267 // \endcode
16268 // Although there is no meaningful interpretation of the tile size, the body
16269 // should still be executed 42 times to avoid surprises. To preserve the
16270 // invariant that every loop iteration is executed exactly once and not
16271 // cause an infinite loop, apply a minimum tile size of one.
16272 // Build expr:
16273 // \code{c}
16274 // (TS <= 0) ? 1 : TS
16275 // \endcode
16276 QualType DimTy = DimTileSizeExpr->getType();
16277 unsigned DimWidth = Context.getIntWidth(DimTy);
16279 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
16280 IntegerLiteral *One =
16281 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
16282 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
16283 CurScope, {}, BO_LE,
16284 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
16285 Expr *MinOne = new (Context) ConditionalOperator(
16286 Cond, {}, One, {},
16287 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
16289 return MinOne;
16290 };
16291
16292 // Create tile loops from the inside to the outside.
16293 //
16294 // Each intra-tile loop is emitted in its natural min-bounded form, which has
16295 // no per-iteration body predicate and vectorizes well when run directly:
16296 // for (.tile.iv = .floor.iv; .tile.iv < min(.floor.iv + T, N); ++.tile.iv)
16297 //
16298 // A loop-associated directive that *consumes* this loop (e.g. `collapse`)
16299 // instead needs a constant, floor-independent trip count to linearize the
16300 // nest, which the min() bound cannot give it. Rather than change the
16301 // emitted loop, we attach a droppable OMPInvariantPredicateBoundAttr hint
16302 // below carrying an equivalent rectangular reinterpretation:
16303 // RectCond : .tile.iv < .floor.iv + T -- rectangular bound, analyzed by
16304 // checkOpenMPIterationSpace in place of the stored condition
16305 // TileSize : T -- constant per-tile trip count
16306 // Predicate : .tile.iv < N -- remainder-tile overshoot,
16307 // applied as a body guard instead of shortening the trip count;
16308 // omitted when N is known to be a multiple of T, as there is
16309 // then no partial tile to guard against
16310 // Because the reinterpreted lower bound is still `.floor.iv`,
16311 // checkOpenMPIterationSpace sets IsNonRectangularLB on the matching floor
16312 // counter, so a collapsed `.tile.iv` re-reads the floor's current value
16313 // instead of a stale preheader snapshot. Collapsing through stacked tiles
16314 // (tile-of-tile) is not supported: the inner floor is not itself a collapsed
16315 // counter.
16316 for (int I = NumLoops - 1; I >= 0; --I) {
16317 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16318 Expr *NumIterations = LoopHelper.NumIterations;
16319 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
16320 QualType IVTy = NumIterations->getType();
16321 Stmt *LoopStmt = LoopStmts[I];
16322
16323 // Commonly used variables. One of the constraints of an AST is that every
16324 // node object must appear at most once, hence we define a lambda that
16325 // creates a new AST node at every use.
16326 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
16327 OrigCntVar]() {
16328 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
16329 OrigCntVar->getExprLoc());
16330 };
16331
16332 // For init-statement: auto .tile.iv = .floor.iv
16333 SemaRef.AddInitializerToDecl(
16334 TileIndVars[I],
16335 SemaRef
16336 .DefaultLvalueConversion(
16337 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
16338 .get(),
16339 /*DirectInit=*/false);
16340 Decl *CounterDecl = TileIndVars[I];
16341 StmtResult InitStmt = new (Context)
16342 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
16343 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16344 if (!InitStmt.isUsable())
16345 return StmtError();
16346
16347 // For cond-expression:
16348 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
16349 Expr *DimTileSize = MakeDimTileSize(I);
16350 if (!DimTileSize)
16351 return StmtError();
16352 ExprResult EndOfTile = SemaRef.BuildBinOp(
16353 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
16354 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16355 DimTileSize);
16356 if (!EndOfTile.isUsable())
16357 return StmtError();
16358 ExprResult IsPartialTile =
16359 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16360 NumIterations, EndOfTile.get());
16361 if (!IsPartialTile.isUsable())
16362 return StmtError();
16363 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
16364 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
16365 IsPartialTile.get(), NumIterations, EndOfTile.get());
16366 if (!MinTileAndIterSpace.isUsable())
16367 return StmtError();
16368 ExprResult CondExpr =
16369 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16370 MakeTileIVRef(), MinTileAndIterSpace.get());
16371 if (!CondExpr.isUsable())
16372 return StmtError();
16373
16374 // For incr-statement: ++.tile.iv
16375 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
16376 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
16377 if (!IncrStmt.isUsable())
16378 return StmtError();
16379
16380 // Build OMPInvariantPredicateBoundAttr hint (RectCond, TileSize,
16381 // Predicate).
16382 Expr *RectDimTileSize = MakeDimTileSize(I);
16383 if (!RectDimTileSize)
16384 return StmtError();
16385 ExprResult RectEndOfTile = SemaRef.BuildBinOp(
16386 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
16387 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16388 RectDimTileSize);
16389 if (!RectEndOfTile.isUsable())
16390 return StmtError();
16391 ExprResult RectCond =
16392 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16393 MakeTileIVRef(), RectEndOfTile.get());
16394 Expr *TileSizeExpr = MakeDimTileSize(I);
16395 if (!TileSizeExpr)
16396 return StmtError();
16397 ExprResult TileSize = SemaRef.PerformImplicitConversion(
16398 TileSizeExpr, IVTy, AssignmentAction::Converting,
16399 /*AllowExplicit=*/true);
16400 if (!RectCond.isUsable() || !TileSize.isUsable())
16401 return StmtError();
16402
16403 // The overshoot guard is only needed if the last tile can be partial. When
16404 // both the trip count and the tile size are known at compile time and the
16405 // former is a multiple of the latter, every tile is full, so leave the
16406 // predicate out. A dependent or run-time value makes
16407 // the evaluation fail, which keeps the guard.
16408 bool NoPartialTile = false;
16409 Expr::EvalResult TileSizeVal, NumIterationsVal;
16410 if (TileSizeExpr->EvaluateAsInt(TileSizeVal, Context) &&
16411 NumIterations->EvaluateAsInt(NumIterationsVal, Context)) {
16412 llvm::APSInt TS = TileSizeVal.Val.getInt();
16413 llvm::APSInt N = NumIterationsVal.Val.getInt();
16414 unsigned Width = std::max(TS.getBitWidth(), N.getBitWidth());
16415 TS = TS.extend(Width);
16416 N = N.extend(Width);
16417 NoPartialTile =
16418 TS.isStrictlyPositive() && N.isStrictlyPositive() && N.urem(TS) == 0;
16419 }
16420
16421 ExprResult Predicate;
16422 if (!NoPartialTile) {
16423 Predicate = SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(),
16424 BO_LT, MakeTileIVRef(), NumIterations);
16425 if (!Predicate.isUsable())
16426 return StmtError();
16427 }
16428
16429 // Statements to set the original iteration variable's value from the
16430 // logical iteration number.
16431 // Generated for loop is:
16432 // \code
16433 // Original_for_init;
16434 // for (auto .tile.iv = .floor.iv;
16435 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
16436 // ++.tile.iv) {
16437 // Original_Body;
16438 // Original_counter_update;
16439 // }
16440 // \endcode
16441 // FIXME: If the innermost body is an loop itself, inserting these
16442 // statements stops it being recognized as a perfectly nested loop (e.g.
16443 // for applying tiling again). If this is the case, sink the expressions
16444 // further into the inner loop.
16445 SmallVector<Stmt *, 4> BodyParts;
16446 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
16447 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
16448 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16449 if (static_cast<unsigned>(I) + 1 < NumLoops)
16450 appendStmtsBeforeNestedLoop(LoopStmt, BodyParts);
16451 BodyParts.push_back(Inner);
16452 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
16453 Inner->getBeginLoc(), Inner->getEndLoc());
16454 Inner = new (Context)
16455 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16456 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
16457 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16458
16459 // Attach the droppable reinterpretation attribute to the intra-tile loop.
16460 auto *Hint = OMPInvariantPredicateBoundAttr::CreateImplicit(
16461 Context, RectCond.get(), TileSize.get(),
16462 Predicate.isUsable() ? Predicate.get() : nullptr,
16463 Inner->getSourceRange());
16464 Inner =
16465 AttributedStmt::Create(Context, Inner->getBeginLoc(), {Hint}, Inner);
16466 }
16467
16468 // Create floor loops from the inside to the outside.
16469 for (int I = NumLoops - 1; I >= 0; --I) {
16470 auto &LoopHelper = LoopHelpers[I];
16471 Expr *NumIterations = LoopHelper.NumIterations;
16472 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
16473 QualType IVTy = NumIterations->getType();
16474
16475 // For init-statement: auto .floor.iv = 0
16476 SemaRef.AddInitializerToDecl(
16477 FloorIndVars[I],
16478 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
16479 /*DirectInit=*/false);
16480 Decl *CounterDecl = FloorIndVars[I];
16481 StmtResult InitStmt = new (Context)
16482 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
16483 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16484 if (!InitStmt.isUsable())
16485 return StmtError();
16486
16487 // For cond-expression: .floor.iv < NumIterations
16488 ExprResult CondExpr = SemaRef.BuildBinOp(
16489 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16490 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16491 NumIterations);
16492 if (!CondExpr.isUsable())
16493 return StmtError();
16494
16495 // For incr-statement: .floor.iv += DimTileSize
16496 Expr *DimTileSize = MakeDimTileSize(I);
16497 if (!DimTileSize)
16498 return StmtError();
16499 ExprResult IncrStmt = SemaRef.BuildBinOp(
16500 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
16501 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16502 DimTileSize);
16503 if (!IncrStmt.isUsable())
16504 return StmtError();
16505
16506 Inner = new (Context)
16507 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16508 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
16509 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16510 }
16511
16513 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, Inner,
16514 buildPreInits(Context, PreInits),
16515 buildLoopFinalization(Context, LoopHelpers, LoopStmts, NestedFinals));
16516}
16517
16519 Stmt *AStmt,
16520 SourceLocation StartLoc,
16521 SourceLocation EndLoc) {
16522 ASTContext &Context = getASTContext();
16523 Scope *CurScope = SemaRef.getCurScope();
16524
16525 const auto *SizesClause =
16526 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
16527 if (!SizesClause ||
16528 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
16529 return !SizeExpr || SizeExpr->containsErrors();
16530 }))
16531 return StmtError();
16532 unsigned NumLoops = SizesClause->getNumSizes();
16533
16534 // Empty statement should only be possible if there already was an error.
16535 if (!AStmt)
16536 return StmtError();
16537
16538 // Verify and diagnose loop nest.
16540 Stmt *Body = nullptr;
16541 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
16542 SmallVector<Stmt *, 4> NestedFinals;
16543 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
16544 Body, OriginalInits, &NestedFinals))
16545 return StmtError();
16546
16547 // Delay striping to when template is completely instantiated.
16548 if (SemaRef.CurContext->isDependentContext())
16549 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
16550 NumLoops, AStmt, nullptr, nullptr,
16551 nullptr);
16552
16553 assert(LoopHelpers.size() == NumLoops &&
16554 "Expecting loop iteration space dimensionality to match number of "
16555 "affected loops");
16556 assert(OriginalInits.size() == NumLoops &&
16557 "Expecting loop iteration space dimensionality to match number of "
16558 "affected loops");
16559
16560 // Collect all affected loop statements.
16561 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
16562 collectLoopStmts(AStmt, LoopStmts, /*RelaxNestForPeeledTransformation=*/true);
16563
16564 SmallVector<Stmt *, 4> PreInits;
16565 CaptureVars CopyTransformer(SemaRef);
16566
16567 // Create iteration variables for the generated loops.
16568 SmallVector<VarDecl *, 4> FloorIndVars;
16569 SmallVector<VarDecl *, 4> StripeIndVars;
16570 FloorIndVars.resize(NumLoops);
16571 StripeIndVars.resize(NumLoops);
16572 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
16573 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16574
16575 assert(LoopHelper.Counters.size() == 1 &&
16576 "Expect single-dimensional loop iteration space");
16577 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
16578 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
16579 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
16580 QualType CntTy = IterVarRef->getType();
16581
16582 // Iteration variable for the stripe (i.e. outer) loop.
16583 {
16584 std::string FloorCntName =
16585 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
16586 VarDecl *FloorCntDecl =
16587 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
16588 FloorIndVars[I] = FloorCntDecl;
16589 }
16590
16591 // Iteration variable for the stripe (i.e. inner) loop.
16592 {
16593 std::string StripeCntName =
16594 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
16595
16596 // Reuse the iteration variable created by checkOpenMPLoop. It is also
16597 // used by the expressions to derive the original iteration variable's
16598 // value from the logical iteration number.
16599 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
16600 StripeCntDecl->setDeclName(
16601 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
16602 StripeIndVars[I] = StripeCntDecl;
16603 }
16604
16605 guardNestedLoopInit(Context, LoopHelpers, I, OriginalInits[I]);
16606 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
16607 PreInits);
16608 }
16609
16610 // Once the original iteration values are set, append the innermost body.
16611 Stmt *Inner = Body;
16612
16613 auto MakeDimStripeSize = [&](int I) -> Expr * {
16614 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
16615 if (isa<ConstantExpr>(DimStripeSizeExpr))
16616 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
16617
16618 // When the stripe size is not a constant but a variable, it is possible to
16619 // pass non-positive numbers. For instance:
16620 // \code{c}
16621 // int a = 0;
16622 // #pragma omp stripe sizes(a)
16623 // for (int i = 0; i < 42; ++i)
16624 // body(i);
16625 // \endcode
16626 // Although there is no meaningful interpretation of the stripe size, the
16627 // body should still be executed 42 times to avoid surprises. To preserve
16628 // the invariant that every loop iteration is executed exactly once and not
16629 // cause an infinite loop, apply a minimum stripe size of one.
16630 // Build expr:
16631 // \code{c}
16632 // (TS <= 0) ? 1 : TS
16633 // \endcode
16634 QualType DimTy = DimStripeSizeExpr->getType();
16635 unsigned DimWidth = Context.getIntWidth(DimTy);
16637 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
16638 IntegerLiteral *One =
16639 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
16640 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
16641 CurScope, {}, BO_LE,
16642 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
16643 Expr *MinOne = new (Context) ConditionalOperator(
16644 Cond, {}, One, {},
16645 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
16647 return MinOne;
16648 };
16649
16650 // Create stripe loops from the inside to the outside.
16651 for (int I = NumLoops - 1; I >= 0; --I) {
16652 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
16653 Expr *NumIterations = LoopHelper.NumIterations;
16654 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
16655 QualType IVTy = NumIterations->getType();
16656 Stmt *LoopStmt = LoopStmts[I];
16657
16658 // For init-statement: auto .stripe.iv = .floor.iv
16659 SemaRef.AddInitializerToDecl(
16660 StripeIndVars[I],
16661 SemaRef
16662 .DefaultLvalueConversion(
16663 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
16664 .get(),
16665 /*DirectInit=*/false);
16666 Decl *CounterDecl = StripeIndVars[I];
16667 StmtResult InitStmt = new (Context)
16668 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
16669 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16670 if (!InitStmt.isUsable())
16671 return StmtError();
16672
16673 // For cond-expression:
16674 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
16675 ExprResult EndOfStripe = SemaRef.BuildBinOp(
16676 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
16677 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16678 MakeDimStripeSize(I));
16679 if (!EndOfStripe.isUsable())
16680 return StmtError();
16681 ExprResult IsPartialStripe =
16682 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16683 NumIterations, EndOfStripe.get());
16684 if (!IsPartialStripe.isUsable())
16685 return StmtError();
16686 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
16687 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
16688 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
16689 if (!MinStripeAndIterSpace.isUsable())
16690 return StmtError();
16691 ExprResult CondExpr = SemaRef.BuildBinOp(
16692 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16693 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
16694 MinStripeAndIterSpace.get());
16695 if (!CondExpr.isUsable())
16696 return StmtError();
16697
16698 // For incr-statement: ++.stripe.iv
16699 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
16700 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
16701 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
16702 if (!IncrStmt.isUsable())
16703 return StmtError();
16704
16705 // Statements to set the original iteration variable's value from the
16706 // logical iteration number.
16707 // Generated for loop is:
16708 // \code
16709 // Original_for_init;
16710 // for (auto .stripe.iv = .floor.iv;
16711 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
16712 // ++.stripe.iv) {
16713 // Original_Body;
16714 // Original_counter_update;
16715 // }
16716 // \endcode
16717 // FIXME: If the innermost body is a loop itself, inserting these
16718 // statements stops it being recognized as a perfectly nested loop (e.g.
16719 // for applying another loop transformation). If this is the case, sink the
16720 // expressions further into the inner loop.
16721 SmallVector<Stmt *, 4> BodyParts;
16722 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
16723 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
16724 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16725 if (static_cast<unsigned>(I) + 1 < NumLoops)
16726 appendStmtsBeforeNestedLoop(LoopStmt, BodyParts);
16727 BodyParts.push_back(Inner);
16728 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
16729 Inner->getBeginLoc(), Inner->getEndLoc());
16730 Inner = new (Context)
16731 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16732 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
16733 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16734 }
16735
16736 // Create grid loops from the inside to the outside.
16737 for (int I = NumLoops - 1; I >= 0; --I) {
16738 auto &LoopHelper = LoopHelpers[I];
16739 Expr *NumIterations = LoopHelper.NumIterations;
16740 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
16741 QualType IVTy = NumIterations->getType();
16742
16743 // For init-statement: auto .grid.iv = 0
16744 SemaRef.AddInitializerToDecl(
16745 FloorIndVars[I],
16746 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
16747 /*DirectInit=*/false);
16748 Decl *CounterDecl = FloorIndVars[I];
16749 StmtResult InitStmt = new (Context)
16750 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
16751 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
16752 if (!InitStmt.isUsable())
16753 return StmtError();
16754
16755 // For cond-expression: .floor.iv < NumIterations
16756 ExprResult CondExpr = SemaRef.BuildBinOp(
16757 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16758 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16759 NumIterations);
16760 if (!CondExpr.isUsable())
16761 return StmtError();
16762
16763 // For incr-statement: .floor.iv += DimStripeSize
16764 ExprResult IncrStmt = SemaRef.BuildBinOp(
16765 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
16766 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
16767 MakeDimStripeSize(I));
16768 if (!IncrStmt.isUsable())
16769 return StmtError();
16770
16771 Inner = new (Context)
16772 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
16773 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
16774 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
16775 }
16776
16778 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, Inner,
16779 buildPreInits(Context, PreInits),
16780 buildLoopFinalization(Context, LoopHelpers, LoopStmts, NestedFinals));
16781}
16782
16784 Stmt *AStmt,
16785 SourceLocation StartLoc,
16786 SourceLocation EndLoc) {
16787 ASTContext &Context = getASTContext();
16788 Scope *CurScope = SemaRef.getCurScope();
16789 // Empty statement should only be possible if there already was an error.
16790 if (!AStmt)
16791 return StmtError();
16792
16794 {OMPC_partial, OMPC_full}))
16795 return StmtError();
16796
16797 const OMPFullClause *FullClause =
16798 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
16799 const OMPPartialClause *PartialClause =
16800 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
16801 assert(!(FullClause && PartialClause) &&
16802 "mutual exclusivity must have been checked before");
16803
16804 constexpr unsigned NumLoops = 1;
16805 Stmt *Body = nullptr;
16807 NumLoops);
16808 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
16809 SmallVector<Stmt *, 4> NestedFinals;
16810 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
16811 Body, OriginalInits, &NestedFinals))
16812 return StmtError();
16813
16814 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
16815
16816 // Delay unrolling to when template is completely instantiated.
16817 if (SemaRef.CurContext->isDependentContext())
16818 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
16819 NumGeneratedTopLevelLoops, nullptr,
16820 nullptr, nullptr);
16821
16822 assert(LoopHelpers.size() == NumLoops &&
16823 "Expecting a single-dimensional loop iteration space");
16824 assert(OriginalInits.size() == NumLoops &&
16825 "Expecting a single-dimensional loop iteration space");
16826 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
16827
16828 if (FullClause) {
16830 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
16831 /*SuppressExprDiags=*/true)
16832 .isUsable()) {
16833 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
16834 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
16835 << "#pragma omp unroll full";
16836 return StmtError();
16837 }
16838 }
16839
16840 // The generated loop may only be passed to other loop-associated directive
16841 // when a partial clause is specified. Without the requirement it is
16842 // sufficient to generate loop unroll metadata at code-generation.
16843 if (NumGeneratedTopLevelLoops == 0)
16844 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
16845 NumGeneratedTopLevelLoops, nullptr,
16846 nullptr, nullptr);
16847
16848 // Otherwise, we need to provide a de-sugared/transformed AST that can be
16849 // associated with another loop directive.
16850 //
16851 // The canonical loop analysis return by checkTransformableLoopNest assumes
16852 // the following structure to be the same loop without transformations or
16853 // directives applied: \code OriginalInits; LoopHelper.PreInits;
16854 // LoopHelper.Counters;
16855 // for (; IV < LoopHelper.NumIterations; ++IV) {
16856 // LoopHelper.Updates;
16857 // Body;
16858 // }
16859 // \endcode
16860 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
16861 // and referenced by LoopHelper.IterationVarRef.
16862 //
16863 // The unrolling directive transforms this into the following loop:
16864 // \code
16865 // OriginalInits; \
16866 // LoopHelper.PreInits; > NewPreInits
16867 // LoopHelper.Counters; /
16868 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
16869 // #pragma clang loop unroll_count(Factor)
16870 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
16871 // {
16872 // LoopHelper.Updates;
16873 // Body;
16874 // }
16875 // }
16876 // \endcode
16877 // where UIV is a new logical iteration counter. IV must be the same VarDecl
16878 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
16879 // references it. If the partially unrolled loop is associated with another
16880 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
16881 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
16882 // OpenMP canonical loop. The inner loop is not an associable canonical loop
16883 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
16884 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
16885 // property of the OMPLoopBasedDirective instead of statements in
16886 // CompoundStatement. This is to allow the loop to become a non-outermost loop
16887 // of a canonical loop nest where these PreInits are emitted before the
16888 // outermost directive.
16889
16890 // Find the loop statement.
16891 Stmt *LoopStmt = nullptr;
16892 collectLoopStmts(AStmt, {LoopStmt});
16893
16894 // Determine the PreInit declarations.
16895 SmallVector<Stmt *, 4> PreInits;
16896 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
16897
16898 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
16899 QualType IVTy = IterationVarRef->getType();
16900 assert(LoopHelper.Counters.size() == 1 &&
16901 "Expecting a single-dimensional loop iteration space");
16902 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
16903
16904 // Determine the unroll factor.
16905 uint64_t Factor;
16906 SourceLocation FactorLoc;
16907 if (Expr *FactorVal = PartialClause->getFactor();
16908 FactorVal && !FactorVal->containsErrors()) {
16909 Factor = FactorVal->getIntegerConstantExpr(Context)->getLimitedValue();
16910 FactorLoc = FactorVal->getExprLoc();
16911 } else {
16912 // TODO: Use a better profitability model.
16913 Factor = 2;
16914 }
16915 assert(Factor > 0 && "Expected positive unroll factor");
16916 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
16918 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
16919 IVTy, FactorLoc);
16920 };
16921
16922 // Iteration variable SourceLocations.
16923 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
16924 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
16925 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
16926
16927 // Internal variable names.
16928 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
16929 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
16930 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
16931
16932 // Create the iteration variable for the unrolled loop.
16933 VarDecl *OuterIVDecl =
16934 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
16935 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
16936 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
16937 };
16938
16939 // Iteration variable for the inner loop: Reuse the iteration variable created
16940 // by checkOpenMPLoop.
16941 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
16942 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
16943 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
16944 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
16945 };
16946
16947 // Make a copy of the NumIterations expression for each use: By the AST
16948 // constraints, every expression object in a DeclContext must be unique.
16949 CaptureVars CopyTransformer(SemaRef);
16950 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
16951 return AssertSuccess(
16952 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
16953 };
16954
16955 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
16956 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
16957 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
16958 /*DirectInit=*/false);
16959 StmtResult InnerInit = new (Context)
16960 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
16961 if (!InnerInit.isUsable())
16962 return StmtError();
16963
16964 // Inner For cond-expression:
16965 // \code
16966 // .unroll_inner.iv < .unrolled.iv + Factor &&
16967 // .unroll_inner.iv < NumIterations
16968 // \endcode
16969 // This conjunction of two conditions allows ScalarEvolution to derive the
16970 // maximum trip count of the inner loop.
16971 ExprResult EndOfTile =
16972 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
16973 MakeOuterRef(), MakeFactorExpr());
16974 if (!EndOfTile.isUsable())
16975 return StmtError();
16976 ExprResult InnerCond1 =
16977 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16978 MakeInnerRef(), EndOfTile.get());
16979 if (!InnerCond1.isUsable())
16980 return StmtError();
16981 ExprResult InnerCond2 =
16982 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
16983 MakeInnerRef(), MakeNumIterations());
16984 if (!InnerCond2.isUsable())
16985 return StmtError();
16986 ExprResult InnerCond =
16987 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
16988 InnerCond1.get(), InnerCond2.get());
16989 if (!InnerCond.isUsable())
16990 return StmtError();
16991
16992 // Inner For incr-statement: ++.unroll_inner.iv
16993 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
16994 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
16995 if (!InnerIncr.isUsable())
16996 return StmtError();
16997
16998 // Inner For statement.
16999 SmallVector<Stmt *> InnerBodyStmts;
17000 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
17001 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
17002 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
17003 InnerBodyStmts.push_back(Body);
17004 CompoundStmt *InnerBody =
17006 Body->getBeginLoc(), Body->getEndLoc());
17007 ForStmt *InnerFor = new (Context)
17008 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
17009 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
17010 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17011
17012 // Unroll metadata for the inner loop.
17013 // This needs to take into account the remainder portion of the unrolled loop,
17014 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
17015 // supports multiple loop exits. Instead, unroll using a factor equivalent to
17016 // the maximum trip count, which will also generate a remainder loop. Just
17017 // `unroll(enable)` (which could have been useful if the user has not
17018 // specified a concrete factor; even though the outer loop cannot be
17019 // influenced anymore, would avoid more code bloat than necessary) will refuse
17020 // the loop because "Won't unroll; remainder loop could not be generated when
17021 // assuming runtime trip count". Even if it did work, it must not choose a
17022 // larger unroll factor than the maximum loop length, or it would always just
17023 // execute the remainder loop.
17024 LoopHintAttr *UnrollHintAttr =
17025 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
17026 LoopHintAttr::Numeric, MakeFactorExpr());
17027 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
17028 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
17029
17030 // Outer For init-statement: auto .unrolled.iv = 0
17031 SemaRef.AddInitializerToDecl(
17032 OuterIVDecl,
17033 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
17034 /*DirectInit=*/false);
17035 StmtResult OuterInit = new (Context)
17036 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
17037 if (!OuterInit.isUsable())
17038 return StmtError();
17039
17040 // Outer For cond-expression: .unrolled.iv < NumIterations
17041 ExprResult OuterConde =
17042 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
17043 MakeOuterRef(), MakeNumIterations());
17044 if (!OuterConde.isUsable())
17045 return StmtError();
17046
17047 // Outer For incr-statement: .unrolled.iv += Factor
17048 ExprResult OuterIncr =
17049 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
17050 MakeOuterRef(), MakeFactorExpr());
17051 if (!OuterIncr.isUsable())
17052 return StmtError();
17053
17054 // Outer For statement.
17055 ForStmt *OuterFor = new (Context)
17056 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
17057 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
17058 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17059
17061 Context, StartLoc, EndLoc, Clauses, AStmt, NumGeneratedTopLevelLoops,
17062 OuterFor, buildPreInits(Context, PreInits),
17063 buildLoopFinalization(Context, LoopHelpers, LoopStmt, NestedFinals));
17064}
17065
17067 SourceLocation StartLoc,
17068 SourceLocation EndLoc) {
17069 ASTContext &Context = getASTContext();
17070 Scope *CurScope = SemaRef.getCurScope();
17071
17072 // Empty statement should only be possible if there already was an error.
17073 if (!AStmt)
17074 return StmtError();
17075
17076 constexpr unsigned NumLoops = 1;
17077 Stmt *Body = nullptr;
17079 NumLoops);
17080 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
17081 SmallVector<Stmt *, 4> NestedFinals;
17082 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
17083 Body, OriginalInits, &NestedFinals))
17084 return StmtError();
17085
17086 // Delay applying the transformation to when template is completely
17087 // instantiated.
17088 if (SemaRef.CurContext->isDependentContext())
17089 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
17090 NumLoops, nullptr, nullptr, nullptr);
17091
17092 assert(LoopHelpers.size() == NumLoops &&
17093 "Expecting a single-dimensional loop iteration space");
17094 assert(OriginalInits.size() == NumLoops &&
17095 "Expecting a single-dimensional loop iteration space");
17096 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
17097
17098 // Find the loop statement.
17099 Stmt *LoopStmt = nullptr;
17100 collectLoopStmts(AStmt, {LoopStmt});
17101
17102 // Determine the PreInit declarations.
17103 SmallVector<Stmt *> PreInits;
17104 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
17105
17106 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
17107 QualType IVTy = IterationVarRef->getType();
17108 uint64_t IVWidth = Context.getTypeSize(IVTy);
17109 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
17110
17111 // Iteration variable SourceLocations.
17112 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
17113 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
17114 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
17115
17116 // Locations pointing to the transformation.
17117 SourceLocation TransformLoc = StartLoc;
17118 SourceLocation TransformLocBegin = StartLoc;
17119 SourceLocation TransformLocEnd = EndLoc;
17120
17121 // Internal variable names.
17122 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
17123 SmallString<64> ForwardIVName(".forward.iv.");
17124 ForwardIVName += OrigVarName;
17125 SmallString<64> ReversedIVName(".reversed.iv.");
17126 ReversedIVName += OrigVarName;
17127
17128 // LoopHelper.Updates will read the logical iteration number from
17129 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
17130 // that logical iteration from it, then assign it to the user loop counter
17131 // variable. We cannot directly use LoopHelper.IterationVarRef as the
17132 // induction variable of the generated loop because it may cause an underflow:
17133 // \code{.c}
17134 // for (unsigned i = 0; i < n; ++i)
17135 // body(i);
17136 // \endcode
17137 //
17138 // Naive reversal:
17139 // \code{.c}
17140 // for (unsigned i = n-1; i >= 0; --i)
17141 // body(i);
17142 // \endcode
17143 //
17144 // Instead, we introduce a new iteration variable representing the logical
17145 // iteration counter of the original loop, convert it to the logical iteration
17146 // number of the reversed loop, then let LoopHelper.Updates compute the user's
17147 // loop iteration variable from it.
17148 // \code{.cpp}
17149 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
17150 // auto .reversed.iv = n - .forward.iv - 1;
17151 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
17152 // body(i); // Body
17153 // }
17154 // \endcode
17155
17156 // Subexpressions with more than one use. One of the constraints of an AST is
17157 // that every node object must appear at most once, hence we define a lambda
17158 // that creates a new AST node at every use.
17159 CaptureVars CopyTransformer(SemaRef);
17160 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
17161 return AssertSuccess(
17162 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
17163 };
17164
17165 // Create the iteration variable for the forward loop (from 0 to n-1).
17166 VarDecl *ForwardIVDecl =
17167 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
17168 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
17169 OrigVarLoc]() {
17170 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
17171 };
17172
17173 // Iteration variable for the reversed induction variable (from n-1 downto 0):
17174 // Reuse the iteration variable created by checkOpenMPLoop.
17175 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
17176 ReversedIVDecl->setDeclName(
17177 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
17178
17179 // For init-statement:
17180 // \code{.cpp}
17181 // auto .forward.iv = 0;
17182 // \endcode
17183 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
17184 ForwardIVDecl->getType(), OrigVarLoc);
17185 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
17186 StmtResult Init = new (Context)
17187 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
17188 if (!Init.isUsable())
17189 return StmtError();
17190
17191 // Forward iv cond-expression:
17192 // \code{.cpp}
17193 // .forward.iv < MakeNumIterations()
17194 // \endcode
17195 ExprResult Cond =
17196 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
17197 MakeForwardRef(), MakeNumIterations());
17198 if (!Cond.isUsable())
17199 return StmtError();
17200
17201 // Forward incr-statement:
17202 // \code{.c}
17203 // ++.forward.iv
17204 // \endcode
17205 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
17206 UO_PreInc, MakeForwardRef());
17207 if (!Incr.isUsable())
17208 return StmtError();
17209
17210 // Reverse the forward-iv:
17211 // \code{.cpp}
17212 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
17213 // \endcode
17214 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
17215 TransformLoc);
17216 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
17217 MakeNumIterations(), One);
17218 if (!Minus.isUsable())
17219 return StmtError();
17220 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
17221 MakeForwardRef());
17222 if (!Minus.isUsable())
17223 return StmtError();
17224 StmtResult InitReversed = new (Context) DeclStmt(
17225 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
17226 if (!InitReversed.isUsable())
17227 return StmtError();
17228 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
17229 /*DirectInit=*/false);
17230
17231 // The new loop body.
17232 SmallVector<Stmt *, 4> BodyStmts;
17233 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
17234 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
17235 BodyStmts.push_back(InitReversed.get());
17236 llvm::append_range(BodyStmts, LoopHelper.Updates);
17237 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
17238 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
17239 BodyStmts.push_back(Body);
17240 auto *ReversedBody =
17241 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
17242 Body->getBeginLoc(), Body->getEndLoc());
17243
17244 // Finally create the reversed For-statement.
17245 auto *ReversedFor = new (Context)
17246 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
17247 ReversedBody, LoopHelper.Init->getBeginLoc(),
17248 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17250 Context, StartLoc, EndLoc, AStmt, NumLoops, ReversedFor,
17251 buildPreInits(Context, PreInits),
17252 buildLoopFinalization(Context, LoopHelpers, LoopStmt, NestedFinals));
17253}
17254
17255/// Build the AST for \#pragma omp split counts(c1, c2, ...).
17256///
17257/// Splits the single associated loop into N consecutive loops, where N is the
17258/// number of count expressions.
17260 Stmt *AStmt,
17261 SourceLocation StartLoc,
17262 SourceLocation EndLoc) {
17263 ASTContext &Context = getASTContext();
17264 Scope *CurScope = SemaRef.getCurScope();
17265
17266 // Empty statement should only be possible if there already was an error.
17267 if (!AStmt)
17268 return StmtError();
17269
17270 const auto *CountsClause =
17271 OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
17272 if (!CountsClause)
17273 return StmtError();
17274
17275 // Split applies to a single loop; check it is transformable and get helpers.
17276 constexpr unsigned NumLoops = 1;
17277 Stmt *Body = nullptr;
17279 NumLoops);
17280 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
17281 SmallVector<Stmt *, 4> NestedFinals;
17282 if (!checkTransformableLoopNest(OMPD_split, AStmt, NumLoops, LoopHelpers,
17283 Body, OriginalInits, &NestedFinals))
17284 return StmtError();
17285
17286 // Delay applying the transformation to when template is completely
17287 // instantiated.
17288 if (SemaRef.CurContext->isDependentContext())
17289 return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
17290 NumLoops, AStmt, nullptr, nullptr,
17291 nullptr);
17292
17293 assert(LoopHelpers.size() == NumLoops &&
17294 "Expecting a single-dimensional loop iteration space");
17295 assert(OriginalInits.size() == NumLoops &&
17296 "Expecting a single-dimensional loop iteration space");
17297 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
17298
17299 // Find the loop statement.
17300 Stmt *LoopStmt = nullptr;
17301 collectLoopStmts(AStmt, {LoopStmt});
17302
17303 // Determine the PreInit declarations.
17304 SmallVector<Stmt *> PreInits;
17305 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
17306
17307 // Type and name of the original loop variable; we create one IV per segment
17308 // and assign it to the original var so the body sees the same name.
17309 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
17310 QualType IVTy = IterationVarRef->getType();
17311 uint64_t IVWidth = Context.getTypeSize(IVTy);
17312 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
17313
17314 // Iteration variable SourceLocations.
17315 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
17316 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
17317 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
17318 // Internal variable names.
17319 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
17320
17321 if (!CountsClause->hasOmpFill())
17322 return StmtError();
17323 unsigned FillIdx = *CountsClause->getOmpFillIndex();
17324
17325 unsigned NumItems = CountsClause->getNumCounts();
17326 SmallVector<uint64_t, 4> CountValues(NumItems, 0);
17327 ArrayRef<Expr *> Refs = CountsClause->getCountsRefs();
17328 for (unsigned I = 0; I < NumItems; ++I) {
17329 if (I == FillIdx)
17330 continue;
17331 Expr *CountExpr = Refs[I];
17332 if (!CountExpr)
17333 return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
17334 NumLoops, AStmt, nullptr, nullptr,
17335 nullptr);
17336 std::optional<llvm::APSInt> OptVal =
17337 CountExpr->getIntegerConstantExpr(Context);
17338 if (!OptVal || OptVal->isNegative())
17339 return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
17340 NumLoops, AStmt, nullptr, nullptr,
17341 nullptr);
17342 CountValues[I] = OptVal->getLimitedValue();
17343 }
17344
17345 Expr *NumIterExpr = LoopHelper.NumIterations;
17346
17347 uint64_t RightSum = 0;
17348 for (unsigned I = FillIdx + 1; I < NumItems; ++I)
17349 RightSum += CountValues[I];
17350
17351 auto MakeIntLit = [&](uint64_t Val) {
17352 return IntegerLiteral::Create(Context, llvm::APInt(IVWidth, Val), IVTy,
17353 OrigVarLoc);
17354 };
17355
17356 size_t NumSegments = NumItems;
17357 SmallVector<Stmt *, 4> SplitLoops;
17358
17359 auto *IterVarDecl = cast<VarDecl>(IterationVarRef->getDecl());
17360 SplitLoops.push_back(new (Context) DeclStmt(DeclGroupRef(IterVarDecl),
17361 IterationVarRef->getBeginLoc(),
17362 IterationVarRef->getEndLoc()));
17363
17364 uint64_t LeftAccum = 0;
17365 uint64_t RightRemaining = RightSum;
17366
17367 for (size_t Seg = 0; Seg < NumSegments; ++Seg) {
17368 Expr *StartExpr = nullptr;
17369 Expr *EndExpr = nullptr;
17370
17371 if (Seg < FillIdx) {
17372 StartExpr = MakeIntLit(LeftAccum);
17373 LeftAccum += CountValues[Seg];
17374 EndExpr = MakeIntLit(LeftAccum);
17375 } else if (Seg == FillIdx) {
17376 StartExpr = MakeIntLit(LeftAccum);
17377 if (RightRemaining == 0) {
17378 EndExpr = NumIterExpr;
17379 } else {
17380 ExprResult Sub =
17381 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
17382 MakeIntLit(RightRemaining));
17383 if (!Sub.isUsable())
17384 return StmtError();
17385 EndExpr = Sub.get();
17386 }
17387 } else {
17388 if (RightRemaining == RightSum) {
17389 if (RightSum == 0)
17390 StartExpr = NumIterExpr;
17391 else {
17392 ExprResult Sub =
17393 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
17394 MakeIntLit(RightRemaining));
17395 if (!Sub.isUsable())
17396 return StmtError();
17397 StartExpr = Sub.get();
17398 }
17399 } else {
17400 ExprResult Sub =
17401 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
17402 MakeIntLit(RightRemaining));
17403 if (!Sub.isUsable())
17404 return StmtError();
17405 StartExpr = Sub.get();
17406 }
17407 RightRemaining -= CountValues[Seg];
17408 if (RightRemaining == 0)
17409 EndExpr = NumIterExpr;
17410 else {
17411 ExprResult Sub =
17412 SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
17413 MakeIntLit(RightRemaining));
17414 if (!Sub.isUsable())
17415 return StmtError();
17416 EndExpr = Sub.get();
17417 }
17418 }
17419
17420 SmallString<64> IVName(".split.iv.");
17421 IVName += (Twine(Seg) + "." + OrigVarName).str();
17422 VarDecl *IVDecl = buildVarDecl(SemaRef, {}, IVTy, IVName, nullptr, OrigVar);
17423 auto MakeIVRef = [&SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
17424 return buildDeclRefExpr(SemaRef, IVDecl, IVTy, OrigVarLoc);
17425 };
17426
17427 SemaRef.AddInitializerToDecl(IVDecl, StartExpr, /*DirectInit=*/false);
17428 StmtResult InitStmt = new (Context)
17429 DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
17430 if (!InitStmt.isUsable())
17431 return StmtError();
17432
17433 ExprResult CondExpr = SemaRef.BuildBinOp(
17434 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeIVRef(), EndExpr);
17435 if (!CondExpr.isUsable())
17436 return StmtError();
17437
17438 ExprResult IncrExpr = SemaRef.BuildUnaryOp(
17439 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeIVRef());
17440 if (!IncrExpr.isUsable())
17441 return StmtError();
17442
17443 ExprResult IVAssign = SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Assign,
17444 IterationVarRef, MakeIVRef());
17445 if (!IVAssign.isUsable())
17446 return StmtError();
17447
17448 SmallVector<Stmt *, 4> BodyStmts;
17449 BodyStmts.push_back(IVAssign.get());
17450 BodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
17451 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
17452 if (Seg == 0) {
17453 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
17454 } else {
17455 VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
17457 SemaRef, LoopVar, LoopVar->getType().getNonReferenceType(),
17458 OrigVarLoc);
17459 ExprResult LVAssign = SemaRef.BuildBinOp(
17460 CurScope, OrigVarLoc, BO_Assign, LVRef, LoopVar->getInit());
17461 if (!LVAssign.isUsable())
17462 return StmtError();
17463 BodyStmts.push_back(LVAssign.get());
17464 }
17465 }
17466 BodyStmts.push_back(Body);
17467
17468 auto *LoopBody =
17469 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
17470 Body->getBeginLoc(), Body->getEndLoc());
17471
17472 auto *For = new (Context)
17473 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
17474 IncrExpr.get(), LoopBody, LoopHelper.Init->getBeginLoc(),
17475 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
17476 SplitLoops.push_back(For);
17477 }
17478
17479 auto *SplitStmt = CompoundStmt::Create(
17480 Context, SplitLoops, FPOptionsOverride(),
17481 SplitLoops.front()->getBeginLoc(), SplitLoops.back()->getEndLoc());
17482
17484 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, SplitStmt,
17485 buildPreInits(Context, PreInits),
17486 buildLoopFinalization(Context, LoopHelpers, LoopStmt, NestedFinals));
17487}
17488
17490 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
17491 SourceLocation EndLoc) {
17492 ASTContext &Context = getASTContext();
17493 DeclContext *CurContext = SemaRef.CurContext;
17494 Scope *CurScope = SemaRef.getCurScope();
17495
17496 // Empty statement should only be possible if there already was an error.
17497 if (!AStmt)
17498 return StmtError();
17499
17500 // interchange without permutation clause swaps two loops.
17501 const OMPPermutationClause *PermutationClause =
17502 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
17503 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
17504
17505 // Verify and diagnose loop nest.
17507 Stmt *Body = nullptr;
17508 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
17509 SmallVector<Stmt *, 4> NestedFinals;
17510 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
17511 LoopHelpers, Body, OriginalInits,
17512 &NestedFinals))
17513 return StmtError();
17514
17515 // Delay interchange to when template is completely instantiated.
17516 if (CurContext->isDependentContext())
17517 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
17518 NumLoops, AStmt, nullptr, nullptr,
17519 nullptr);
17520
17521 // An invalid expression in the permutation clause is set to nullptr in
17522 // ActOnOpenMPPermutationClause.
17523 if (PermutationClause &&
17524 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
17525 return StmtError();
17526
17527 assert(LoopHelpers.size() == NumLoops &&
17528 "Expecting loop iteration space dimensionaly to match number of "
17529 "affected loops");
17530 assert(OriginalInits.size() == NumLoops &&
17531 "Expecting loop iteration space dimensionaly to match number of "
17532 "affected loops");
17533
17534 // Decode the permutation clause.
17535 SmallVector<uint64_t, 2> Permutation;
17536 if (!PermutationClause) {
17537 Permutation = {1, 0};
17538 } else {
17539 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
17540 llvm::BitVector Flags(PermArgs.size());
17541 for (Expr *PermArg : PermArgs) {
17542 std::optional<llvm::APSInt> PermCstExpr =
17543 PermArg->getIntegerConstantExpr(Context);
17544 if (!PermCstExpr)
17545 continue;
17546 uint64_t PermInt = PermCstExpr->getLimitedValue();
17547 assert(1 <= PermInt && PermInt <= NumLoops &&
17548 "Must be a permutation; diagnostic emitted in "
17549 "ActOnOpenMPPermutationClause");
17550 if (Flags[PermInt - 1]) {
17551 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
17552 Diag(PermArg->getExprLoc(),
17553 diag::err_omp_interchange_permutation_value_repeated)
17554 << PermInt << ExprRange;
17555 continue;
17556 }
17557 Flags[PermInt - 1] = true;
17558
17559 Permutation.push_back(PermInt - 1);
17560 }
17561
17562 if (Permutation.size() != NumLoops)
17563 return StmtError();
17564 }
17565
17566 // Nothing to transform with trivial permutation.
17567 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
17568 auto [Idx, Arg] = P;
17569 return Idx == Arg;
17570 }))
17571 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
17572 NumLoops, AStmt, AStmt, nullptr,
17573 nullptr);
17574
17575 // Find the affected loops.
17576 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
17577 collectLoopStmts(AStmt, LoopStmts);
17578
17579 // Collect pre-init statements on the order before the permuation.
17580 SmallVector<Stmt *> PreInits;
17581 for (auto I : llvm::seq<int>(NumLoops)) {
17582 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
17583
17584 assert(LoopHelper.Counters.size() == 1 &&
17585 "Single-dimensional loop iteration space expected");
17586
17587 guardNestedLoopInit(Context, LoopHelpers, I, OriginalInits[I]);
17588 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
17589 PreInits);
17590 }
17591
17592 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
17593 CaptureVars CopyTransformer(SemaRef);
17594
17595 // True if no loop of the nest has a zero trip count.
17596 auto MakeNotEmpty = [&]() -> Expr * {
17597 Expr *NotEmpty = nullptr;
17598 for (const OMPLoopBasedDirective::HelperExprs &Helper : LoopHelpers) {
17599 Expr *NumIters =
17600 AssertSuccess(CopyTransformer.TransformExpr(Helper.NumIterations));
17601 Expr *HasIters = AssertSuccess(SemaRef.BuildBinOp(
17602 CurScope, NumIters->getExprLoc(), BO_NE, NumIters,
17603 SemaRef.ActOnIntegerConstant(NumIters->getExprLoc(), 0).get()));
17604 NotEmpty = NotEmpty ? AssertSuccess(SemaRef.BuildBinOp(
17605 CurScope, HasIters->getExprLoc(), BO_LAnd,
17606 NotEmpty, HasIters))
17607 : HasIters;
17608 }
17609 return NotEmpty;
17610 };
17611
17612 // Create the permuted loops from the inside to the outside of the
17613 // interchanged loop nest. Body of the innermost new loop is the original
17614 // innermost body.
17615 Stmt *Inner = Body;
17616 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
17617 // Get the original loop that belongs to this new position.
17618 uint64_t SourceIdx = Permutation[TargetIdx];
17619 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
17620 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
17621 assert(SourceHelper.Counters.size() == 1 &&
17622 "Single-dimensional loop iteration space expected");
17623 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
17624
17625 // Normalized loop counter variable: From 0 to n-1, always an integer type.
17626 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
17627 QualType IVTy = IterVarRef->getType();
17628 assert(IVTy->isIntegerType() &&
17629 "Expected the logical iteration counter to be an integer");
17630
17631 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
17632 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
17633
17634 // Make a copy of the NumIterations expression for each use: By the AST
17635 // constraints, every expression object in a DeclContext must be unique.
17636 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
17637 return AssertSuccess(
17638 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
17639 };
17640
17641 // Iteration variable for the permuted loop. Reuse the one from
17642 // checkOpenMPLoop which will also be used to update the original loop
17643 // variable.
17644 SmallString<64> PermutedCntName(".permuted_");
17645 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
17646 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
17647 PermutedCntDecl->setDeclName(
17648 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
17649 PermutedIndVars[TargetIdx] = PermutedCntDecl;
17650 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
17651 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
17652 };
17653
17654 // For init-statement:
17655 // \code
17656 // auto .permuted_{target}.iv = 0
17657 // \endcode
17658 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
17659 if (!Zero.isUsable())
17660 return StmtError();
17661 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
17662 /*DirectInit=*/false);
17663 StmtResult InitStmt = new (Context)
17664 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
17665 OrigCntVar->getEndLoc());
17666 if (!InitStmt.isUsable())
17667 return StmtError();
17668
17669 // For cond-expression:
17670 // \code
17671 // .permuted_{target}.iv < MakeNumIterations()
17672 // \endcode
17673 Expr *UpperBound = MakeNumIterations();
17674 // The outermost loop runs only if the iteration space is not empty, so
17675 // that no loop variable is assigned when an original loop has none.
17676 if (TargetIdx == 0) {
17677 ExprResult NoIterations = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
17678 ExprResult Guarded =
17679 SemaRef.ActOnConditionalOp(OrigVarLoc, OrigVarLoc, MakeNotEmpty(),
17680 UpperBound, NoIterations.get());
17681 if (!Guarded.isUsable())
17682 return StmtError();
17683 UpperBound = Guarded.get();
17684 }
17685 ExprResult CondExpr =
17686 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
17687 MakePermutedRef(), UpperBound);
17688 if (!CondExpr.isUsable())
17689 return StmtError();
17690
17691 // For incr-statement:
17692 // \code
17693 // ++.tile.iv
17694 // \endcode
17695 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
17696 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
17697 if (!IncrStmt.isUsable())
17698 return StmtError();
17699
17700 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
17701 SourceHelper.Updates.end());
17702 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
17703 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
17704 BodyParts.push_back(Inner);
17705 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
17706 Inner->getBeginLoc(), Inner->getEndLoc());
17707 Inner = new (Context) ForStmt(
17708 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
17709 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
17710 SourceHelper.Inc->getEndLoc());
17711 }
17712
17714 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, Inner,
17715 buildPreInits(Context, PreInits),
17716 buildLoopFinalization(Context, LoopHelpers, LoopStmts, NestedFinals));
17717}
17718
17721 Stmt *AStmt, SourceLocation StartLoc,
17722 SourceLocation EndLoc) {
17723 ASTContext &Context = getASTContext();
17724 DeclContext *CurContext = SemaRef.CurContext;
17725 Scope *CurScope = SemaRef.getCurScope();
17726
17727 // Empty statement should only be possible if there already was an error.
17728 if (!AStmt)
17729 return StmtError();
17730
17731 // flatten without 'depth' clause combines two loops; 'depth(k)' selects k.
17732 unsigned NumLoops = 2;
17733 bool DepthIsDependent = false;
17734 const auto *DepthClause =
17735 OMPExecutableDirective::getSingleClause<OMPDepthClause>(Clauses);
17736 if (DepthClause) {
17737 Expr *DepthExpr = DepthClause->getDepth();
17738 if (DepthExpr && DepthExpr->isInstantiationDependent()) {
17739 DepthIsDependent = true;
17740 } else if (DepthExpr) {
17741 Expr::EvalResult EvalResult;
17742 if (DepthExpr->EvaluateAsInt(EvalResult, Context))
17743 NumLoops = EvalResult.Val.getInt().getLimitedValue(
17744 std::numeric_limits<unsigned>::max());
17745 }
17746 }
17747
17748 // Count perfectly nested loops with doForAllLoops. When 'depth' is present,
17749 // walk NumLoops iterations to diagnose an insufficient nest. When it is
17750 // omitted, walk one extra loop (3 total) so we can warn that default
17751 // flatten only combines 2 of a deeper nest.
17752 if (!DepthIsDependent) {
17753 unsigned WalkLimit = DepthClause ? NumLoops : 3;
17754 unsigned Found = 0;
17755 bool Enough = OMPLoopBasedDirective::doForAllLoops(
17756 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false,
17757 WalkLimit, [&](unsigned Cnt, Stmt *S) {
17758 if (!isa<ForStmt>(S) && !isa<CXXForRangeStmt>(S))
17759 return true;
17760 Found = Cnt + 1;
17761 return false;
17762 });
17763 if (DepthClause && !Enough) {
17764 Diag(AStmt->getBeginLoc(), diag::err_omp_not_for)
17765 << /*expected N for loops form=*/1
17766 << getOpenMPDirectiveName(OMPD_flatten) << NumLoops << (Found > 0)
17767 << Found;
17768 return StmtError();
17769 }
17770 if (!DepthClause && Found >= 3) {
17771 Diag(StartLoc, diag::warn_omp_flatten_omitted_depth);
17772 if (SemaRef.getLangOpts().OpenMP >= 61)
17773 Diag(StartLoc, diag::note_omp_flatten_insert_depth)
17774 << FixItHint::CreateInsertion(EndLoc, " depth(2)");
17775 }
17776 }
17777
17778 // Defer when 'depth' is instantiation-dependent (concrete k unknown until
17779 // instantiation).
17780 if (DepthIsDependent)
17781 return OMPFlattenDirective::Create(Context, StartLoc, EndLoc, Clauses,
17782 NumLoops, AStmt, nullptr, nullptr,
17783 nullptr);
17784
17785 // Verify and diagnose loop nest.
17787 Stmt *Body = nullptr;
17788 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
17789 SmallVector<Stmt *, 4> NestedFinals;
17790 if (!checkTransformableLoopNest(OMPD_flatten, AStmt, NumLoops, LoopHelpers,
17791 Body, OriginalInits, &NestedFinals))
17792 return StmtError();
17793
17794 // Delay flattening to when template is completely instantiated.
17795 if (CurContext->isDependentContext())
17796 return OMPFlattenDirective::Create(Context, StartLoc, EndLoc, Clauses,
17797 NumLoops, AStmt, nullptr, nullptr,
17798 nullptr);
17799
17800 assert(LoopHelpers.size() == NumLoops &&
17801 "Expecting loop iteration space dimensionality to match number of "
17802 "affected loops");
17803 assert(OriginalInits.size() == NumLoops &&
17804 "Expecting loop iteration space dimensionality to match number of "
17805 "affected loops");
17806
17807 // Find the affected loops.
17808 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
17809 collectLoopStmts(AStmt, LoopStmts);
17810
17811 // Collect pre-init statements in outer-to-inner order.
17812 SmallVector<Stmt *> PreInits;
17813 for (auto I : llvm::seq<unsigned>(NumLoops)) {
17814 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
17815 assert(LoopHelper.Counters.size() == 1 &&
17816 "Single-dimensional loop iteration space expected");
17817 guardNestedLoopInit(Context, LoopHelpers, I, OriginalInits[I]);
17818 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
17819 PreInits);
17820 }
17821
17822 CaptureVars CopyTransformer(SemaRef);
17823 // Convert a non-integer trip count. Width matches buildNumIterations.
17824 // Signedness follows an integer loop variable so a float count stays signed.
17825 auto MakeNumIterations = [&CopyTransformer, &LoopHelpers, &Context,
17826 &SemaRef =
17827 this->SemaRef](unsigned I) -> ExprResult {
17828 ExprResult N = CopyTransformer.TransformExpr(LoopHelpers[I].NumIterations);
17829 if (!N.isUsable())
17830 return ExprError();
17831 QualType Type = N.get()->getType();
17832 if (Type->isIntegerType())
17833 return N;
17834 const auto *Counter = cast<DeclRefExpr>(LoopHelpers[I].Counters.front());
17835 QualType VarType = Counter->getType().getNonReferenceType();
17836 bool VarIsInt = VarType->hasIntegerRepresentation();
17837 bool UseVarWidth =
17838 VarIsInt && Context.getTypeSize(Type) > Context.getTypeSize(VarType);
17839 unsigned NewSize =
17840 UseVarWidth ? Context.getTypeSize(VarType) : Context.getTypeSize(Type);
17841 bool IsSigned = VarIsInt ? VarType->hasSignedIntegerRepresentation()
17843 QualType IntTy = getIntTypeForBitwidthOrBitInt(Context, NewSize, IsSigned);
17844 N = SemaRef.PerformImplicitConversion(
17845 N.get(), IntTy, AssignmentAction::Converting, /*AllowExplicit=*/true);
17846 if (!N.isUsable())
17847 return ExprError();
17848 return N;
17849 };
17850
17851 OMPLoopBasedDirective::HelperExprs &OutermostHelper = LoopHelpers[0];
17852 auto *OutermostCntVar = cast<DeclRefExpr>(OutermostHelper.Counters.front());
17853 SourceLocation OrigVarLoc = OutermostCntVar->getExprLoc();
17854 SourceLocation OrigVarLocBegin = OutermostCntVar->getBeginLoc();
17855 SourceLocation OrigVarLocEnd = OutermostCntVar->getEndLoc();
17856 SourceLocation CondLoc = OutermostHelper.Cond->getExprLoc();
17857
17858 // Product of trip counts; mirror 'collapse' IV-width selection to avoid
17859 // overflow when several counts are multiplied.
17860 auto BuildTripCount = [&](unsigned Bits) -> ExprResult {
17861 ExprResult Product;
17862 for (unsigned I = 0; I < NumLoops; ++I) {
17863 ExprResult N = MakeNumIterations(I);
17864 if (!N.isUsable())
17865 return ExprError();
17866 N = widenIterationCount(Bits, N.get(), SemaRef);
17867 if (!N.isUsable())
17868 return ExprError();
17869 if (I == 0)
17870 Product = N;
17871 else
17872 Product = SemaRef.BuildBinOp(CurScope, CondLoc, BO_Mul, Product.get(),
17873 N.get());
17874 if (!Product.isUsable())
17875 return ExprError();
17876 }
17877 return Product;
17878 };
17879
17880 bool AllCountsLessThan32Bits =
17881 llvm::all_of(llvm::seq<unsigned>(NumLoops), [&](unsigned I) {
17882 return Context.getTypeSize(LoopHelpers[I].NumIterations->getType()) <
17883 32;
17884 });
17885
17886 ExprResult TripCount;
17887 if (AllCountsLessThan32Bits || NumLoops == 1) {
17888 TripCount = BuildTripCount(/*Bits=*/32);
17889 } else {
17890 ExprResult TripCount64 = BuildTripCount(/*Bits=*/64);
17891 if (!TripCount64.isUsable())
17892 return StmtError();
17893 TripCount = TripCount64;
17894 if (TripCount64.get()->isIntegerConstantExpr(Context)) {
17895 ExprResult TripCount32 = BuildTripCount(/*Bits=*/32);
17896 if (TripCount32.isUsable() &&
17897 Context.getTypeSize(TripCount32.get()->getType()) == 32 &&
17898 fitsInto(
17899 /*Bits=*/32,
17900 TripCount32.get()->getType()->hasSignedIntegerRepresentation(),
17901 TripCount64.get(), SemaRef))
17902 TripCount = TripCount32;
17903 }
17904 }
17905 if (!TripCount.isUsable())
17906 return StmtError();
17907
17908 QualType IVTy = TripCount.get()->getType();
17909 uint64_t IVWidth = Context.getTypeSize(IVTy);
17910
17911 // Build a condition that is true if the outermost \p Count loops all have at
17912 // least one iteration.
17913 auto BuildHasIterations = [&](unsigned Count) -> ExprResult {
17915 for (unsigned I = 0; I < Count; ++I) {
17916 ExprResult LoopPreCond =
17917 CopyTransformer.TransformExpr(LoopHelpers[I].PreCond);
17918 if (!LoopPreCond.isUsable())
17919 return ExprError();
17920 if (I == 0)
17921 Result = LoopPreCond;
17922 else
17923 Result = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LAnd, Result.get(),
17924 LoopPreCond.get());
17925 if (!Result.isUsable())
17926 return ExprError();
17927 }
17928 return Result;
17929 };
17930
17931 // NumIterations may wrap or overflow when an empty loop has extreme runtime
17932 // bounds. Test whether every original loop has at least one iteration before
17933 // evaluating their product.
17934 ExprResult HasIterations = BuildHasIterations(NumLoops);
17935 if (!HasIterations.isUsable())
17936 return StmtError();
17937 Expr *ZeroTripCount = IntegerLiteral::Create(
17938 Context, llvm::APInt::getZero(IVWidth), IVTy, CondLoc);
17939 TripCount = SemaRef.ActOnConditionalOp(CondLoc, CondLoc, HasIterations.get(),
17940 TripCount.get(), ZeroTripCount);
17941 if (!TripCount.isUsable())
17942 return StmtError();
17943
17944 auto MakeNumIterationsInIVTy = [&](unsigned I) -> ExprResult {
17945 ExprResult N = MakeNumIterations(I);
17946 if (!N.isUsable())
17947 return ExprError();
17948 return SemaRef.PerformImplicitConversion(
17949 N.get(), IVTy, AssignmentAction::Converting, /*AllowExplicit=*/true);
17950 };
17951
17952 // Divisors in index recovery use (N == 0 ? 1 : N) so a zero trip count does
17953 // not warn.
17954 auto MakeDivisorInIVTy = [&](unsigned I) -> ExprResult {
17955 ExprResult N = MakeNumIterationsInIVTy(I);
17956 ExprResult NCmp = MakeNumIterationsInIVTy(I);
17957 if (!N.isUsable() || !NCmp.isUsable())
17958 return ExprError();
17959 auto MakeCst = [&](uint64_t V) -> Expr * {
17960 return IntegerLiteral::Create(Context, llvm::APInt(IVWidth, V), IVTy,
17961 CondLoc);
17962 };
17963 ExprResult IsZero =
17964 SemaRef.BuildBinOp(CurScope, CondLoc, BO_EQ, NCmp.get(), MakeCst(0));
17965 if (!IsZero.isUsable())
17966 return N;
17967 return SemaRef.ActOnConditionalOp(CondLoc, CondLoc, IsZero.get(),
17968 MakeCst(1), N.get());
17969 };
17970
17971 // \code{.cpp}
17972 // for (auto .flatten.iv = 0; .flatten.iv < n0 * n1 * ...; ++.flatten.iv) {
17973 // .flatten.iv.0 = .flatten.iv / (n1 * ...);
17974 // i0 = ...; // Updates[0]
17975 // .flatten.iv.1 = (.flatten.iv / ...) % n1;
17976 // i1 = ...; // Updates[1]
17977 // ...
17978 // body(i0, i1, ...);
17979 // }
17980 // \endcode
17981 SmallString<64> FlattenedIVName(".flatten.iv");
17982 VarDecl *FlattenedIVDecl = buildVarDecl(SemaRef, {}, IVTy, FlattenedIVName,
17983 nullptr, OutermostCntVar);
17984 auto MakeFlattenedRef = [&SemaRef = this->SemaRef, FlattenedIVDecl, IVTy,
17985 OrigVarLoc]() {
17986 return buildDeclRefExpr(SemaRef, FlattenedIVDecl, IVTy, OrigVarLoc);
17987 };
17988
17989 // For init-statement:
17990 // \code{.cpp}
17991 // auto .flatten.iv = 0;
17992 // \endcode
17993 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
17994 IVTy, OrigVarLoc);
17995 SemaRef.AddInitializerToDecl(FlattenedIVDecl, Zero, /*DirectInit=*/false);
17996 StmtResult Init = new (Context)
17997 DeclStmt(DeclGroupRef(FlattenedIVDecl), OrigVarLocBegin, OrigVarLocEnd);
17998 if (!Init.isUsable())
17999 return StmtError();
18000
18001 // For cond-expression:
18002 // \code{.cpp}
18003 // .flatten.iv < n0 * n1 * ... * n(k-1)
18004 // \endcode
18005 ExprResult Cond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT,
18006 MakeFlattenedRef(), TripCount.get());
18007 if (!Cond.isUsable())
18008 return StmtError();
18009
18010 // For incr-statement:
18011 // \code{.cpp}
18012 // ++.flatten.iv
18013 // \endcode
18014 ExprResult Incr =
18015 SemaRef.BuildUnaryOp(CurScope, OutermostHelper.Inc->getExprLoc(),
18016 UO_PreInc, MakeFlattenedRef());
18017 if (!Incr.isUsable())
18018 return StmtError();
18019
18020 // Recover each logical iteration counter via mixed-radix div/mod; reuse the
18021 // iteration variables from checkOpenMPLoop so Updates compute user counters.
18022 SmallVector<Stmt *, 8> BodyStmts;
18023 for (unsigned I = 0; I < NumLoops; ++I) {
18024 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
18025 auto *IVRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
18026 auto *IVDecl = cast<VarDecl>(IVRef->getDecl());
18027 std::string IVName = (".flatten.iv." + llvm::Twine(I)).str();
18028 IVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(IVName));
18029
18030 ExprResult Value = MakeFlattenedRef();
18031 if (I + 1 < NumLoops) {
18032 ExprResult Divisor = MakeDivisorInIVTy(I + 1);
18033 if (!Divisor.isUsable())
18034 return StmtError();
18035 for (unsigned J = I + 2; J < NumLoops; ++J) {
18036 ExprResult Next = MakeDivisorInIVTy(J);
18037 if (!Next.isUsable())
18038 return StmtError();
18039 Divisor = SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Mul,
18040 Divisor.get(), Next.get());
18041 if (!Divisor.isUsable())
18042 return StmtError();
18043 }
18044 Value = SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Div, Value.get(),
18045 Divisor.get());
18046 if (!Value.isUsable())
18047 return StmtError();
18048 }
18049 if (I > 0) {
18050 ExprResult RemDivisor = MakeDivisorInIVTy(I);
18051 if (!RemDivisor.isUsable())
18052 return StmtError();
18053 Value = SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Rem, Value.get(),
18054 RemDivisor.get());
18055 if (!Value.isUsable())
18056 return StmtError();
18057 }
18058
18059 SemaRef.AddInitializerToDecl(IVDecl, Value.get(), /*DirectInit=*/false);
18060 StmtResult IVStmt = new (Context)
18061 DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
18062 if (!IVStmt.isUsable())
18063 return StmtError();
18064
18065 BodyStmts.push_back(IVStmt.get());
18066 llvm::append_range(BodyStmts, LoopHelper.Updates);
18067 if (auto *CXXFor = dyn_cast<CXXForRangeStmt>(LoopStmts[I]))
18068 BodyStmts.push_back(CXXFor->getLoopVarStmt());
18069 }
18070 BodyStmts.push_back(Body);
18071 auto *FlattenedBody =
18072 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
18073 Body->getBeginLoc(), Body->getEndLoc());
18074
18075 auto *FlattenedFor = new (Context) ForStmt(
18076 Context, Init.get(), Cond.get(), nullptr, Incr.get(), FlattenedBody,
18077 OutermostHelper.Init->getBeginLoc(), OutermostHelper.Init->getBeginLoc(),
18078 OutermostHelper.Inc->getEndLoc());
18079
18080 // A counter only reaches its final value if its own loop and all enclosing
18081 // loops execute at least one iteration; otherwise it keeps the value assigned
18082 // by the pre-inits. Guarding also avoids evaluating 'start + n * step' for an
18083 // empty loop, whose trip count may have wrapped.
18085 for (unsigned I = 0; I < NumLoops; ++I) {
18086 assert(LoopHelpers[I].Finals.size() == 1 &&
18087 "Single-dimensional loop iteration space expected");
18088 ExprResult Final =
18089 CopyTransformer.TransformExpr(LoopHelpers[I].Finals.front());
18090 if (!Final.isUsable())
18091 return StmtError();
18092 ExprResult FinalCond = BuildHasIterations(/*Count=*/I + 1);
18093 if (!FinalCond.isUsable())
18094 return StmtError();
18095 // If the loop has its own directive (e.g. reverse), restore its variable.
18096 Stmt *Then = Final.get();
18097 if (Stmt *Nested = NestedFinals[I])
18098 Then = CompoundStmt::Create(Context, {Then, Nested}, FPOptionsOverride(),
18099 CondLoc, CondLoc);
18100 Finals.push_back(IfStmt::Create(Context, CondLoc, IfStatementKind::Ordinary,
18101 nullptr, nullptr, FinalCond.get(), CondLoc,
18102 CondLoc, Then, SourceLocation(), nullptr));
18103 }
18104 Stmt *FinalsStmt = CompoundStmt::Create(Context, Finals, FPOptionsOverride(),
18105 FlattenedFor->getBeginLoc(),
18106 FlattenedFor->getEndLoc());
18107
18109 Context, StartLoc, EndLoc, Clauses, NumLoops, AStmt, FlattenedFor,
18110 buildPreInits(Context, PreInits), FinalsStmt);
18111}
18112
18114 Stmt *AStmt,
18115 SourceLocation StartLoc,
18116 SourceLocation EndLoc) {
18117
18118 ASTContext &Context = getASTContext();
18119 DeclContext *CurrContext = SemaRef.CurContext;
18120 Scope *CurScope = SemaRef.getCurScope();
18121 CaptureVars CopyTransformer(SemaRef);
18122
18123 // Ensure the structured block is not empty
18124 if (!AStmt)
18125 return StmtError();
18126
18127 if (const auto *DepthC =
18128 OMPExecutableDirective::getSingleClause<OMPDepthClause>(Clauses)) {
18129 Diag(DepthC->getBeginLoc(), diag::err_omp_clause_not_supported_yet)
18130 << "depth" << getOpenMPDirectiveName(OMPD_fuse);
18131 return StmtError();
18132 }
18133
18134 // Defer transformation in dependent contexts
18135 // The NumLoopNests argument is set to a placeholder 1 (even though
18136 // using looprange fuse could yield up to 3 top level loop nests)
18137 // because a dependent context could prevent determining its true value
18138 if (CurrContext->isDependentContext())
18139 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
18140 /* NumLoops */ 1, AStmt, nullptr, nullptr,
18141 nullptr);
18142
18143 // Validate that the potential loop sequence is transformable for fusion
18144 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
18145 LoopSequenceAnalysis SeqAnalysis;
18146 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
18147 return StmtError();
18148
18149 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
18150 // otherwise it must be the same as SeqAnalysis.Loops.size().
18151 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
18152 "Inconsistent size of the loop sequence and the number of loops "
18153 "found in the sequence");
18154
18155 // Handle clauses, which can be any of the following: [looprange, apply]
18156 const auto *LRC =
18157 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
18158
18159 // The clause arguments are invalidated if any error arises
18160 // such as non-constant or non-positive arguments
18161 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
18162 return StmtError();
18163
18164 // Delayed semantic check of LoopRange constraint
18165 // Evaluates the loop range arguments and returns the first and count values
18166 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
18167 uint64_t &FirstVal,
18168 uint64_t &CountVal) {
18169 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context);
18170 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
18171 FirstVal = FirstInt.getLimitedValue();
18172 CountVal = CountInt.getLimitedValue();
18173 };
18174
18175 // OpenMP [6.0, Restrictions]
18176 // first + count - 1 must not evaluate to a value greater than the
18177 // loop sequence length of the associated canonical loop sequence.
18178 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
18179 unsigned NumLoops) -> bool {
18180 return FirstVal + CountVal - 1 <= NumLoops;
18181 };
18182 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
18183
18184 // Validates the loop range after evaluating the semantic information
18185 // and ensures that the range is valid for the given loop sequence size.
18186 // Expressions are evaluated at compile time to obtain constant values.
18187 if (LRC) {
18188 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
18189 CountVal);
18190 if (CountVal == 1)
18191 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
18192 << getOpenMPDirectiveName(OMPD_fuse);
18193
18194 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
18195 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
18196 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
18197 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
18198 return StmtError();
18199 }
18200
18201 LastVal = FirstVal + CountVal - 1;
18202 }
18203
18204 // Complete fusion generates a single canonical loop nest
18205 // However looprange clause may generate several loop nests
18206 unsigned NumGeneratedTopLevelLoops =
18207 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
18208
18209 // Emit a warning for redundant loop fusion when the sequence contains only
18210 // one loop.
18211 if (SeqAnalysis.LoopSeqSize == 1)
18212 SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion)
18213 << getOpenMPDirectiveName(OMPD_fuse);
18214
18215 // Select the type with the largest bit width among all induction variables
18216 QualType IVType =
18217 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
18218 for (unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
18219 QualType CurrentIVType =
18220 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
18221 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
18222 IVType = CurrentIVType;
18223 }
18224 }
18225 uint64_t IVBitWidth = Context.getIntWidth(IVType);
18226
18227 // Create pre-init declarations for all loops lower bounds, upper bounds,
18228 // strides and num-iterations for every top level loop in the fusion
18229 SmallVector<VarDecl *, 4> LBVarDecls;
18230 SmallVector<VarDecl *, 4> STVarDecls;
18231 SmallVector<VarDecl *, 4> NIVarDecls;
18232 SmallVector<VarDecl *, 4> IVVarDecls;
18233
18234 // Helper lambda to create variables for bounds, strides, and other
18235 // expressions. Generates both the variable declaration and the corresponding
18236 // initialization statement.
18237 auto CreateHelperVarAndStmt =
18238 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
18239 unsigned I, bool NeedsNewVD = false) {
18240 Expr *TransformedExpr =
18241 AssertSuccess(CopyTransformer.TransformExpr(ExprToCopy));
18242 if (!TransformedExpr)
18243 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
18244
18245 auto Name = (Twine(".omp.") + BaseName + std::to_string(I)).str();
18246
18247 VarDecl *VD;
18248 if (NeedsNewVD) {
18249 VD = buildVarDecl(SemaRef, SourceLocation(), IVType, Name);
18250 SemaRef.AddInitializerToDecl(VD, TransformedExpr, false);
18251 } else {
18252 // Create a unique variable name
18253 DeclRefExpr *DRE = cast<DeclRefExpr>(TransformedExpr);
18254 VD = cast<VarDecl>(DRE->getDecl());
18255 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
18256 }
18257 // Create the corresponding declaration statement
18258 StmtResult DeclStmt = new (Context) class DeclStmt(
18260 return std::make_pair(VD, DeclStmt);
18261 };
18262
18263 // PreInits hold a sequence of variable declarations that must be executed
18264 // before the fused loop begins. These include bounds, strides, and other
18265 // helper variables required for the transformation. Other loop transforms
18266 // also contain their own preinits
18267 SmallVector<Stmt *> PreInits;
18268
18269 // Update the general preinits using the preinits generated by loop sequence
18270 // generating loop transformations. These preinits differ slightly from
18271 // single-loop transformation preinits, as they can be detached from a
18272 // specific loop inside multiple generated loop nests. This happens
18273 // because certain helper variables, like '.omp.fuse.max', are introduced to
18274 // handle fused iteration spaces and may not be directly tied to a single
18275 // original loop. The preinit structure must ensure that hidden variables
18276 // like '.omp.fuse.max' are still properly handled.
18277 // Transformations that apply this concept: Loopranged Fuse, Split
18278 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
18279
18280 // Process each single loop to generate and collect declarations
18281 // and statements for all helper expressions related to
18282 // particular single loop nests
18283
18284 // Also In the case of the fused loops, we keep track of their original
18285 // inits by appending them to their preinits statement, and in the case of
18286 // transformations, also append their preinits (which contain the original
18287 // loop initialization statement or other statements)
18288
18289 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
18290 if (SeqAnalysis.Loops[I].isRegularLoop()) {
18291 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
18292 SeqAnalysis.Loops[I].TheForStmt,
18293 SeqAnalysis.Loops[I].OriginalInits, PreInits);
18294 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
18295 // For transformed loops, insert both pre-inits and original inits.
18296 // Order matters: pre-inits may define variables used in the original
18297 // inits such as upper bounds...
18298 llvm::append_range(PreInits, SeqAnalysis.Loops[I].TransformsPreInits);
18299
18300 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
18301 SeqAnalysis.Loops[I].TheForStmt,
18302 SeqAnalysis.Loops[I].OriginalInits, PreInits);
18303 }
18304 auto [LBVD, LBDStmt] =
18305 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
18306 auto [STVD, STDStmt] =
18307 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
18308 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
18309 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
18310 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
18311 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
18312
18313 assert(LBVD && STVD && NIVD && IVVD &&
18314 "OpenMP Fuse Helper variables creation failed");
18315
18316 LBVarDecls.push_back(LBVD);
18317 STVarDecls.push_back(STVD);
18318 NIVarDecls.push_back(NIVD);
18319 IVVarDecls.push_back(IVVD);
18320
18321 PreInits.push_back(LBDStmt.get());
18322 PreInits.push_back(STDStmt.get());
18323 PreInits.push_back(NIDStmt.get());
18324 PreInits.push_back(IVDStmt.get());
18325 }
18326
18327 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
18328 return buildDeclRefExpr(SemaRef, VD, VD->getType(), VD->getLocation(),
18329 false);
18330 };
18331
18332 // Following up the creation of the final fused loop will be performed
18333 // which has the following shape (considering the selected loops):
18334 //
18335 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
18336 // if (fuse.index < ni0){
18337 // iv0 = lb0 + st0 * fuse.index;
18338 // original.index0 = iv0
18339 // body(0);
18340 // }
18341 // if (fuse.index < ni1){
18342 // iv1 = lb1 + st1 * fuse.index;
18343 // original.index1 = iv1
18344 // body(1);
18345 // }
18346 //
18347 // ...
18348 //
18349 // if (fuse.index < nik){
18350 // ivk = lbk + stk * fuse.index;
18351 // original.indexk = ivk
18352 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
18353 // llvm::APInt(IVWidth, 0),
18354 // }
18355
18356 // 1. Create the initialized fuse index
18357 StringRef IndexName = ".omp.fuse.index";
18358 Expr *InitVal = IntegerLiteral::Create(Context, llvm::APInt(IVBitWidth, 0),
18359 IVType, SourceLocation());
18360 VarDecl *IndexDecl =
18361 buildVarDecl(SemaRef, {}, IVType, IndexName, nullptr, nullptr);
18362 SemaRef.AddInitializerToDecl(IndexDecl, InitVal, false);
18363 StmtResult InitStmt = new (Context)
18365
18366 if (!InitStmt.isUsable())
18367 return StmtError();
18368
18369 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
18370 Loc = InitVal->getExprLoc()]() {
18371 return buildDeclRefExpr(SemaRef, IndexDecl, IVType, Loc, false);
18372 };
18373
18374 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
18375 // ..., NI_k)
18376 //
18377 // This loop accumulates the maximum value across multiple expressions,
18378 // ensuring each step constructs a unique AST node for correctness. By using
18379 // intermediate temporary variables and conditional operators, we maintain
18380 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
18381 // omp.temp0 = max(a, b)
18382 // omp.temp1 = max(omp.temp0, c)
18383 // omp.fuse.max = max(omp.temp1, omp.temp0)
18384
18385 ExprResult MaxExpr;
18386 // I is the range of loops in the sequence that we fuse.
18387 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
18388 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
18389 QualType NITy = NIRef->getType();
18390
18391 if (MaxExpr.isUnset()) {
18392 // Initialize MaxExpr with the first NI expression
18393 MaxExpr = NIRef;
18394 } else {
18395 // Create a new acummulator variable t_i = MaxExpr
18396 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
18397 VarDecl *TempDecl =
18398 buildVarDecl(SemaRef, {}, NITy, TempName, nullptr, nullptr);
18399 TempDecl->setInit(MaxExpr.get());
18400 DeclRefExpr *TempRef =
18401 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
18402 DeclRefExpr *TempRef2 =
18403 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
18404 // Add a DeclStmt to PreInits to ensure the variable is declared.
18405 StmtResult TempStmt = new (Context)
18407
18408 if (!TempStmt.isUsable())
18409 return StmtError();
18410 PreInits.push_back(TempStmt.get());
18411
18412 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
18414 SemaRef.BuildBinOp(nullptr, SourceLocation(), BO_GT, TempRef, NIRef);
18415 // Handle any errors in Comparison creation
18416 if (!Comparison.isUsable())
18417 return StmtError();
18418
18419 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
18420 // Update MaxExpr using a conditional expression to hold the max value
18421 MaxExpr = new (Context) ConditionalOperator(
18422 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
18423 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
18424
18425 if (!MaxExpr.isUsable())
18426 return StmtError();
18427 }
18428 }
18429 if (!MaxExpr.isUsable())
18430 return StmtError();
18431
18432 // 3. Declare the max variable
18433 const std::string MaxName = Twine(".omp.fuse.max").str();
18434 VarDecl *MaxDecl =
18435 buildVarDecl(SemaRef, {}, IVType, MaxName, nullptr, nullptr);
18436 MaxDecl->setInit(MaxExpr.get());
18437 DeclRefExpr *MaxRef = buildDeclRefExpr(SemaRef, MaxDecl, IVType, {}, false);
18438 StmtResult MaxStmt = new (Context)
18440
18441 if (MaxStmt.isInvalid())
18442 return StmtError();
18443 PreInits.push_back(MaxStmt.get());
18444
18445 // 4. Create condition Expr: index < n_max
18446 ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT,
18447 MakeIVRef(), MaxRef);
18448 if (!CondExpr.isUsable())
18449 return StmtError();
18450
18451 // 5. Increment Expr: ++index
18452 ExprResult IncrExpr =
18453 SemaRef.BuildUnaryOp(CurScope, SourceLocation(), UO_PreInc, MakeIVRef());
18454 if (!IncrExpr.isUsable())
18455 return StmtError();
18456
18457 // 6. Build the Fused Loop Body
18458 // The final fused loop iterates over the maximum logical range. Inside the
18459 // loop, each original loop's index is calculated dynamically, and its body
18460 // is executed conditionally.
18461 //
18462 // Each sub-loop's body is guarded by a conditional statement to ensure
18463 // it executes only within its logical iteration range:
18464 //
18465 // if (fuse.index < ni_k){
18466 // iv_k = lb_k + st_k * fuse.index;
18467 // original.index = iv_k
18468 // body(k);
18469 // }
18470
18471 CompoundStmt *FusedBody = nullptr;
18472 SmallVector<Stmt *, 4> FusedBodyStmts;
18473 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
18474 // Assingment of the original sub-loop index to compute the logical index
18475 // IV_k = LB_k + omp.fuse.index * ST_k
18476 ExprResult IdxExpr =
18477 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
18478 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
18479 if (!IdxExpr.isUsable())
18480 return StmtError();
18481 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Add,
18482 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.get());
18483
18484 if (!IdxExpr.isUsable())
18485 return StmtError();
18486 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Assign,
18487 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.get());
18488 if (!IdxExpr.isUsable())
18489 return StmtError();
18490
18491 // Update the original i_k = IV_k
18492 SmallVector<Stmt *, 4> BodyStmts;
18493 BodyStmts.push_back(IdxExpr.get());
18494 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
18495
18496 // If the loop is a CXXForRangeStmt then the iterator variable is needed
18497 if (auto *SourceCXXFor =
18498 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
18499 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
18500
18501 Stmt *Body =
18502 (isa<ForStmt>(SeqAnalysis.Loops[I].TheForStmt))
18503 ? cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
18504 : cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody();
18505 BodyStmts.push_back(Body);
18506
18507 CompoundStmt *CombinedBody =
18508 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
18511 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT, MakeIVRef(),
18512 MakeVarDeclRef(NIVarDecls[J]));
18513
18514 if (!Condition.isUsable())
18515 return StmtError();
18516
18517 IfStmt *IfStatement = IfStmt::Create(
18518 Context, SourceLocation(), IfStatementKind::Ordinary, nullptr, nullptr,
18519 Condition.get(), SourceLocation(), SourceLocation(), CombinedBody,
18520 SourceLocation(), nullptr);
18521
18522 FusedBodyStmts.push_back(IfStatement);
18523 }
18524 FusedBody = CompoundStmt::Create(Context, FusedBodyStmts, FPOptionsOverride(),
18526
18527 // 7. Construct the final fused loop
18528 ForStmt *FusedForStmt = new (Context)
18529 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
18530 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
18531 IncrExpr.get()->getEndLoc());
18532
18533 // 8. Finals of the fused loops, in sequence order. Out-of-range loops keep
18534 // theirs inline.
18535 SmallVector<Stmt *, 4> AllFinalsStmts;
18536 for (unsigned I : llvm::seq<unsigned>(FirstVal - 1, LastVal)) {
18537 const LoopAnalysis &Loop = SeqAnalysis.Loops[I];
18538 if (Loop.isRegularLoop())
18539 if (Stmt *Own =
18540 buildLoopFinalization(Context, Loop.HelperExprs, Loop.TheForStmt))
18541 AllFinalsStmts.push_back(Own);
18542 if (Loop.TransformFinals)
18543 AllFinalsStmts.push_back(Loop.TransformFinals);
18544 }
18545 Stmt *CombinedFinals = nullptr;
18546 if (AllFinalsStmts.size() == 1)
18547 CombinedFinals = AllFinalsStmts.front();
18548 else if (!AllFinalsStmts.empty())
18549 CombinedFinals =
18550 CompoundStmt::Create(Context, AllFinalsStmts, FPOptionsOverride(),
18552
18553 // In the case of looprange, the result of fuse won't simply
18554 // be a single loop (ForStmt), but rather a loop sequence
18555 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
18556 // and the post-fusion loops, preserving its original order.
18557 //
18558 // Note: If looprange clause produces a single fused loop nest then
18559 // this compound statement wrapper is unnecessary (Therefore this
18560 // treatment is skipped)
18561
18562 auto WithFinals = [&](Stmt *Loop, Stmt *Finals) -> Stmt * {
18563 return Finals ? CompoundStmt::Create(Context, {Loop, Finals},
18566 : Loop;
18567 };
18568 Stmt *FusionStmt = FusedForStmt;
18569 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
18570 SmallVector<Stmt *, 4> FinalLoops;
18571
18572 // Collect all non-fused loops before and after the fused region.
18573 // Pre-fusion and post-fusion loops are inserted in order exploiting their
18574 // symmetry, along with their corresponding transformation pre-inits if
18575 // needed. The fused loop is added between the two regions.
18576 for (unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
18577 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1)
18578 continue;
18579
18580 // Out-of-range transformations still need their pre-inits.
18581 if (SeqAnalysis.Loops[I].isLoopTransformation())
18582 llvm::append_range(PreInits, SeqAnalysis.Loops[I].TransformsPreInits);
18583
18584 // For out-of-range loop-transformations, emit their finalization inline
18585 // right after the transformed loop so that IVs are restored as if the
18586 // transformation had not been present (OpenMP 6.0 finalization rule).
18587 FinalLoops.push_back(WithFinals(SeqAnalysis.Loops[I].TheForStmt,
18588 SeqAnalysis.Loops[I].TransformFinals));
18589 }
18590
18591 // Insert the fused loop with its Finals between the pre- and post-fusion
18592 // loops.
18593 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1),
18594 WithFinals(FusedForStmt, CombinedFinals));
18595 CombinedFinals = nullptr; // emitted inline
18596 FusionStmt = CompoundStmt::Create(Context, FinalLoops, FPOptionsOverride(),
18598 }
18600 Context, StartLoc, EndLoc, Clauses, NumGeneratedTopLevelLoops, AStmt,
18601 FusionStmt, buildPreInits(Context, PreInits), CombinedFinals);
18602}
18603
18605 Expr *Expr,
18606 SourceLocation StartLoc,
18607 SourceLocation LParenLoc,
18608 SourceLocation EndLoc) {
18609 OMPClause *Res = nullptr;
18610 switch (Kind) {
18611 case OMPC_final:
18612 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
18613 break;
18614 case OMPC_safelen:
18615 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
18616 break;
18617 case OMPC_simdlen:
18618 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
18619 break;
18620 case OMPC_allocator:
18621 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
18622 break;
18623 case OMPC_collapse:
18624 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
18625 break;
18626 case OMPC_ordered:
18627 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
18628 break;
18629 case OMPC_nowait:
18630 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Expr);
18631 break;
18632 case OMPC_priority:
18633 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
18634 break;
18635 case OMPC_hint:
18636 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
18637 break;
18638 case OMPC_depobj:
18639 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
18640 break;
18641 case OMPC_detach:
18642 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
18643 break;
18644 case OMPC_novariants:
18645 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
18646 break;
18647 case OMPC_nocontext:
18648 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
18649 break;
18650 case OMPC_filter:
18651 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
18652 break;
18653 case OMPC_partial:
18654 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
18655 break;
18656 case OMPC_depth:
18657 Res = ActOnOpenMPDepthClause(Expr, StartLoc, LParenLoc, EndLoc);
18658 break;
18659 case OMPC_message:
18660 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
18661 break;
18662 case OMPC_align:
18663 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
18664 break;
18665 case OMPC_ompx_dyn_cgroup_mem:
18666 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
18667 break;
18668 case OMPC_holds:
18669 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
18670 break;
18671 case OMPC_transparent:
18672 Res = ActOnOpenMPTransparentClause(Expr, StartLoc, LParenLoc, EndLoc);
18673 break;
18674 case OMPC_dyn_groupprivate:
18675 case OMPC_grainsize:
18676 case OMPC_num_tasks:
18677 case OMPC_num_threads:
18678 case OMPC_device:
18679 case OMPC_if:
18680 case OMPC_default:
18681 case OMPC_proc_bind:
18682 case OMPC_schedule:
18683 case OMPC_private:
18684 case OMPC_firstprivate:
18685 case OMPC_lastprivate:
18686 case OMPC_shared:
18687 case OMPC_reduction:
18688 case OMPC_task_reduction:
18689 case OMPC_in_reduction:
18690 case OMPC_linear:
18691 case OMPC_aligned:
18692 case OMPC_copyin:
18693 case OMPC_copyprivate:
18694 case OMPC_untied:
18695 case OMPC_mergeable:
18696 case OMPC_threadprivate:
18697 case OMPC_groupprivate:
18698 case OMPC_sizes:
18699 case OMPC_allocate:
18700 case OMPC_flush:
18701 case OMPC_read:
18702 case OMPC_write:
18703 case OMPC_update:
18704 case OMPC_capture:
18705 case OMPC_compare:
18706 case OMPC_seq_cst:
18707 case OMPC_acq_rel:
18708 case OMPC_acquire:
18709 case OMPC_release:
18710 case OMPC_relaxed:
18711 case OMPC_depend:
18712 case OMPC_threads:
18713 case OMPC_simd:
18714 case OMPC_map:
18715 case OMPC_nogroup:
18716 case OMPC_dist_schedule:
18717 case OMPC_defaultmap:
18718 case OMPC_unknown:
18719 case OMPC_uniform:
18720 case OMPC_to:
18721 case OMPC_from:
18722 case OMPC_use_device_ptr:
18723 case OMPC_use_device_addr:
18724 case OMPC_is_device_ptr:
18725 case OMPC_unified_address:
18726 case OMPC_unified_shared_memory:
18727 case OMPC_reverse_offload:
18728 case OMPC_dynamic_allocators:
18729 case OMPC_atomic_default_mem_order:
18730 case OMPC_self_maps:
18731 case OMPC_device_type:
18732 case OMPC_match:
18733 case OMPC_nontemporal:
18734 case OMPC_order:
18735 case OMPC_at:
18736 case OMPC_severity:
18737 case OMPC_destroy:
18738 case OMPC_inclusive:
18739 case OMPC_exclusive:
18740 case OMPC_uses_allocators:
18741 case OMPC_affinity:
18742 case OMPC_when:
18743 case OMPC_bind:
18744 case OMPC_num_teams:
18745 case OMPC_thread_limit:
18746 default:
18747 llvm_unreachable("Clause is not allowed.");
18748 }
18749 return Res;
18750}
18751
18752// An OpenMP directive such as 'target parallel' has two captured regions:
18753// for the 'target' and 'parallel' respectively. This function returns
18754// the region in which to capture expressions associated with a clause.
18755// A return value of OMPD_unknown signifies that the expression should not
18756// be captured.
18759 llvm::omp::Version OMPVersion,
18760 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
18761 assert(isAllowedClauseForDirective(DKind, CKind, OMPVersion) &&
18762 "Invalid directive with CKind-clause");
18763
18764 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
18765 if (NameModifier != OMPD_unknown &&
18766 !isAllowedClauseForDirective(NameModifier, CKind, OMPVersion))
18767 return OMPD_unknown;
18768
18769 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
18770
18771 // [5.2:341:24-30]
18772 // If the clauses have expressions on them, such as for various clauses where
18773 // the argument of the clause is an expression, or lower-bound, length, or
18774 // stride expressions inside array sections (or subscript and stride
18775 // expressions in subscript-triplet for Fortran), or linear-step or alignment
18776 // expressions, the expressions are evaluated immediately before the construct
18777 // to which the clause has been split or duplicated per the above rules
18778 // (therefore inside of the outer leaf constructs). However, the expressions
18779 // inside the num_teams and thread_limit clauses are always evaluated before
18780 // the outermost leaf construct.
18781
18782 // Process special cases first.
18783 switch (CKind) {
18784 case OMPC_if:
18785 switch (DKind) {
18786 case OMPD_teams_loop:
18787 case OMPD_target_teams_loop:
18788 // For [target] teams loop, assume capture region is 'teams' so it's
18789 // available for codegen later to use if/when necessary.
18790 return OMPD_teams;
18791 case OMPD_target_update:
18792 case OMPD_target_enter_data:
18793 case OMPD_target_exit_data:
18794 return OMPD_task;
18795 default:
18796 break;
18797 }
18798 break;
18799 case OMPC_num_teams:
18800 case OMPC_thread_limit:
18801 case OMPC_ompx_dyn_cgroup_mem:
18802 case OMPC_dyn_groupprivate:
18803 // TODO: This may need to consider teams too.
18804 if (Leafs[0] == OMPD_target)
18805 return OMPD_target;
18806 break;
18807 case OMPC_device:
18808 if (Leafs[0] == OMPD_target ||
18809 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
18810 OMPD_target_enter_data, OMPD_target_exit_data},
18811 DKind))
18812 return OMPD_task;
18813 break;
18814 case OMPC_novariants:
18815 case OMPC_nocontext:
18816 if (DKind == OMPD_dispatch)
18817 return OMPD_task;
18818 break;
18819 case OMPC_when:
18820 if (DKind == OMPD_metadirective)
18821 return OMPD_metadirective;
18822 break;
18823 case OMPC_filter:
18824 return OMPD_unknown;
18825 default:
18826 break;
18827 }
18828
18829 // If none of the special cases above applied, and DKind is a capturing
18830 // directive, find the innermost enclosing leaf construct that allows the
18831 // clause, and returns the corresponding capture region.
18832
18833 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
18834 // Find the index in "Leafs" of the last leaf that allows the given
18835 // clause. The search will only include indexes [0, EndIdx).
18836 // EndIdx may be set to the index of the NameModifier, if present.
18837 int InnermostIdx = [&]() {
18838 for (int I = EndIdx - 1; I >= 0; --I) {
18839 if (isAllowedClauseForDirective(Leafs[I], Clause, OMPVersion))
18840 return I;
18841 }
18842 return -1;
18843 }();
18844
18845 // Find the nearest enclosing capture region.
18847 for (int I = InnermostIdx - 1; I >= 0; --I) {
18848 if (!isOpenMPCapturingDirective(Leafs[I]))
18849 continue;
18850 Regions.clear();
18851 getOpenMPCaptureRegions(Regions, Leafs[I]);
18852 if (Regions[0] != OMPD_unknown)
18853 return Regions.back();
18854 }
18855 return OMPD_unknown;
18856 };
18857
18858 if (isOpenMPCapturingDirective(DKind)) {
18859 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
18860 for (int I = 0, E = Leafs.size(); I != E; ++I) {
18861 if (Leafs[I] == Dir)
18862 return I + 1;
18863 }
18864 return 0;
18865 };
18866
18867 int End = NameModifier == OMPD_unknown ? Leafs.size()
18868 : GetLeafIndex(NameModifier);
18869 return GetEnclosingRegion(End, CKind);
18870 }
18871
18872 return OMPD_unknown;
18873}
18874
18876 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
18877 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
18878 SourceLocation ColonLoc, SourceLocation EndLoc) {
18879 Expr *ValExpr = Condition;
18880 Stmt *HelperValStmt = nullptr;
18881 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18882 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18883 !Condition->isInstantiationDependent() &&
18884 !Condition->containsUnexpandedParameterPack()) {
18885 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18886 if (Val.isInvalid())
18887 return nullptr;
18888
18889 ValExpr = Val.get();
18890
18891 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18892 CaptureRegion = getOpenMPCaptureRegionForClause(
18893 DKind, OMPC_if, getLangOpts().getOpenMPVersion(), NameModifier);
18894 if (CaptureRegion != OMPD_unknown &&
18895 !SemaRef.CurContext->isDependentContext()) {
18896 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18897 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18898 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18899 HelperValStmt = buildPreInits(getASTContext(), Captures);
18900 }
18901 }
18902
18903 return new (getASTContext())
18904 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
18905 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
18906}
18907
18909 SourceLocation StartLoc,
18910 SourceLocation LParenLoc,
18911 SourceLocation EndLoc) {
18912 Expr *ValExpr = Condition;
18913 Stmt *HelperValStmt = nullptr;
18914 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18915 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18916 !Condition->isInstantiationDependent() &&
18917 !Condition->containsUnexpandedParameterPack()) {
18918 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18919 if (Val.isInvalid())
18920 return nullptr;
18921
18922 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18923
18924 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18925 CaptureRegion = getOpenMPCaptureRegionForClause(
18926 DKind, OMPC_final, getLangOpts().getOpenMPVersion());
18927 if (CaptureRegion != OMPD_unknown &&
18928 !SemaRef.CurContext->isDependentContext()) {
18929 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18930 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18931 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18932 HelperValStmt = buildPreInits(getASTContext(), Captures);
18933 }
18934 }
18935
18936 return new (getASTContext()) OMPFinalClause(
18937 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18938}
18939
18942 Expr *Op) {
18943 if (!Op)
18944 return ExprError();
18945
18946 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
18947 public:
18948 IntConvertDiagnoser()
18949 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
18950 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
18951 QualType T) override {
18952 return S.Diag(Loc, diag::err_omp_not_integral) << T;
18953 }
18954 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
18955 QualType T) override {
18956 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
18957 }
18958 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
18959 QualType T,
18960 QualType ConvTy) override {
18961 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
18962 }
18963 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
18964 QualType ConvTy) override {
18965 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
18966 << ConvTy->isEnumeralType() << ConvTy;
18967 }
18968 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
18969 QualType T) override {
18970 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
18971 }
18972 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
18973 QualType ConvTy) override {
18974 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
18975 << ConvTy->isEnumeralType() << ConvTy;
18976 }
18977 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
18978 QualType) override {
18979 llvm_unreachable("conversion functions are permitted");
18980 }
18981 } ConvertDiagnoser;
18982 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
18983}
18984
18985static bool
18987 bool StrictlyPositive, bool BuildCapture = false,
18988 OpenMPDirectiveKind DKind = OMPD_unknown,
18989 OpenMPDirectiveKind *CaptureRegion = nullptr,
18990 Stmt **HelperValStmt = nullptr) {
18991 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
18992 !ValExpr->isInstantiationDependent()) {
18993 SourceLocation Loc = ValExpr->getExprLoc();
18995 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
18996 if (Value.isInvalid())
18997 return false;
18998
18999 ValExpr = Value.get();
19000 // The expression must evaluate to a non-negative integer value.
19001 if (std::optional<llvm::APSInt> Result =
19002 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
19003 if (Result->isSigned() &&
19004 !((!StrictlyPositive && Result->isNonNegative()) ||
19005 (StrictlyPositive && Result->isStrictlyPositive()))) {
19006 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
19007 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
19008 << ValExpr->getSourceRange();
19009 return false;
19010 }
19011 }
19012 if (!BuildCapture)
19013 return true;
19014 *CaptureRegion = getOpenMPCaptureRegionForClause(
19015 DKind, CKind, SemaRef.getLangOpts().getOpenMPVersion());
19016 if (*CaptureRegion != OMPD_unknown &&
19017 !SemaRef.CurContext->isDependentContext()) {
19018 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
19019 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19020 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
19021 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
19022 }
19023 }
19024 return true;
19025}
19026
19027static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
19028 unsigned Last,
19029 ArrayRef<unsigned> Exclude = {}) {
19030 SmallString<256> Buffer;
19031 llvm::raw_svector_ostream Out(Buffer);
19032 unsigned Skipped = Exclude.size();
19033 for (unsigned I = First; I < Last; ++I) {
19034 if (llvm::is_contained(Exclude, I)) {
19035 --Skipped;
19036 continue;
19037 }
19038 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
19039 if (I + Skipped + 2 == Last)
19040 Out << " or ";
19041 else if (I + Skipped + 1 != Last)
19042 Out << ", ";
19043 }
19044 return std::string(Out.str());
19045}
19046
19048 ArrayRef<Expr *> VarList, OpenMPNumThreadsClauseModifier SimpleModifier,
19049 SourceLocation SimpleModifierLoc,
19050 OpenMPNumThreadsClauseModifier ComplexModifier, Expr *ComplexModifierExpr,
19051 SourceLocation ComplexModifierLoc, SourceLocation StartLoc,
19052 SourceLocation LParenLoc, SourceLocation EndLoc) {
19053 // Check that modifiers were correctly specified.
19054 if (ComplexModifierLoc.isValid() &&
19055 (ComplexModifier != OMPC_NUMTHREADS_dims || !ComplexModifierExpr)) {
19056 Diag(ComplexModifierLoc, diag::err_omp_malformed_complex_modifier)
19057 << getOpenMPSimpleClauseTypeName(OMPC_num_threads, OMPC_NUMTHREADS_dims)
19058 << getOpenMPClauseName(OMPC_num_threads);
19059 return nullptr;
19060 }
19061 if (SimpleModifierLoc.isValid() && SimpleModifier == OMPC_NUMTHREADS_dims) {
19062 Diag(SimpleModifierLoc, diag::err_omp_malformed_complex_modifier)
19063 << getOpenMPSimpleClauseTypeName(OMPC_num_threads, OMPC_NUMTHREADS_dims)
19064 << getOpenMPClauseName(OMPC_num_threads);
19065 return nullptr;
19066 }
19067 if (SimpleModifierLoc.isValid() && SimpleModifier != OMPC_NUMTHREADS_strict) {
19068 Diag(SimpleModifierLoc, diag::err_omp_unexpected_clause_value)
19069 << getOpenMPSimpleClauseTypeName(OMPC_num_threads,
19070 OMPC_NUMTHREADS_strict)
19071 << getOpenMPClauseName(OMPC_num_threads);
19072 return nullptr;
19073 }
19074
19075 if (VarList.empty())
19076 return nullptr;
19077
19078 SmallVector<Expr *, 3> Vars(VarList.begin(), VarList.end());
19079 for (Expr *&ValExpr : Vars) {
19080 // OpenMP [2.5, Restrictions]
19081 // The num_threads expression must evaluate to a positive integer value.
19082 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
19083 /*StrictlyPositive=*/true))
19084 return nullptr;
19085 }
19086
19087 if (ComplexModifier == OMPC_NUMTHREADS_dims) {
19088 ExprResult Res = ActOnOpenMPDimsModifier(OMPC_num_threads, ComplexModifier,
19089 ComplexModifierExpr,
19090 ComplexModifierLoc, Vars, EndLoc);
19091 if (Res.isInvalid())
19092 return nullptr;
19093 ComplexModifierExpr = Res.get();
19094
19095 if (validateMultidimClauseExprs(*this, OMPC_num_threads, StartLoc, Vars,
19096 ComplexModifierExpr))
19097 return nullptr;
19098 }
19099 if (SimpleModifier == OMPC_NUMTHREADS_strict && getLangOpts().OpenMP < 60) {
19100 Diag(SimpleModifierLoc, diag::err_omp_modifier_requires_version)
19101 << getOpenMPSimpleClauseTypeName(OMPC_num_threads, SimpleModifier)
19102 << getOpenMPClauseName(OMPC_num_threads) << "6.0";
19103 return nullptr;
19104 }
19105
19106 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19108 DKind, OMPC_num_threads, getLangOpts().getOpenMPVersion());
19109 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
19111 getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, Vars,
19112 SimpleModifier, ComplexModifier, SimpleModifierLoc, ComplexModifierLoc,
19113 ComplexModifierExpr, /*PreInit=*/nullptr);
19114
19115 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19116 for (Expr *&ValExpr : Vars) {
19117 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
19118 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
19119 }
19120 if (ComplexModifierExpr) {
19121 ComplexModifierExpr = SemaRef.MakeFullExpr(ComplexModifierExpr).get();
19122 ComplexModifierExpr =
19123 tryBuildCapture(SemaRef, ComplexModifierExpr, Captures).get();
19124 }
19125 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
19126
19128 getASTContext(), CaptureRegion, StartLoc, LParenLoc, EndLoc, Vars,
19129 SimpleModifier, ComplexModifier, SimpleModifierLoc, ComplexModifierLoc,
19130 ComplexModifierExpr, PreInit);
19131}
19132
19134 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
19135 bool SuppressExprDiags) {
19136 if (!E)
19137 return ExprError();
19138 if (E->isValueDependent() || E->isTypeDependent() ||
19140 return E;
19141
19142 llvm::APSInt Result;
19143 ExprResult ICE;
19144 if (SuppressExprDiags) {
19145 // Use a custom diagnoser that suppresses 'note' diagnostics about the
19146 // expression.
19147 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
19148 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
19150 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
19151 llvm_unreachable("Diagnostic suppressed");
19152 }
19153 } Diagnoser;
19154 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
19156 } else {
19157 ICE =
19158 SemaRef.VerifyIntegerConstantExpression(E, &Result,
19159 /*FIXME*/ AllowFoldKind::Allow);
19160 }
19161 if (ICE.isInvalid())
19162 return ExprError();
19163
19164 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
19165 (!StrictlyPositive && !Result.isNonNegative())) {
19166 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
19167 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
19168 << E->getSourceRange();
19169 return ExprError();
19170 }
19171 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
19172 CKind == OMPC_allocate) &&
19173 !Result.isPowerOf2()) {
19174 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
19175 << E->getSourceRange();
19176 return ExprError();
19177 }
19178
19179 if (!Result.isRepresentableByInt64()) {
19180 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
19182 return ExprError();
19183 }
19184
19185 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
19186 DSAStack->setAssociatedLoops(Result.getExtValue());
19187 else if (CKind == OMPC_ordered)
19188 DSAStack->setAssociatedLoops(Result.getExtValue());
19189 return ICE;
19190}
19191
19192void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
19193
19194void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
19195
19196int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
19197
19199 llvm::APSInt Result;
19200 Expr::EvalResult EvalResult;
19201 // Evaluate the expression to an integer value
19202 if (!DeviceNumExpr->isValueDependent() &&
19203 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
19204 // The device expression must evaluate to a non-negative integer value.
19205 Result = EvalResult.Val.getInt();
19206 if (Result.isNonNegative()) {
19207 setOpenMPDeviceNum(Result.getZExtValue());
19208 } else {
19209 Diag(DeviceNumExpr->getExprLoc(),
19210 diag::err_omp_negative_expression_in_clause)
19211 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
19212 }
19213 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
19214 // Check if the expression is an identifier
19215 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
19216 if (IdInfo) {
19217 setOpenMPDeviceNumID(IdInfo->getName());
19218 }
19219 } else {
19220 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
19221 }
19222}
19223
19225 SourceLocation StartLoc,
19226 SourceLocation LParenLoc,
19227 SourceLocation EndLoc) {
19228 // OpenMP [2.8.1, simd construct, Description]
19229 // The parameter of the safelen clause must be a constant
19230 // positive integer expression.
19231 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
19232 if (Safelen.isInvalid())
19233 return nullptr;
19234 return new (getASTContext())
19235 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
19236}
19237
19239 SourceLocation StartLoc,
19240 SourceLocation LParenLoc,
19241 SourceLocation EndLoc) {
19242 // OpenMP [2.8.1, simd construct, Description]
19243 // The parameter of the simdlen clause must be a constant
19244 // positive integer expression.
19245 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
19246 if (Simdlen.isInvalid())
19247 return nullptr;
19248 return new (getASTContext())
19249 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
19250}
19251
19252/// Tries to find omp_allocator_handle_t type.
19254 DSAStackTy *Stack) {
19255 if (!Stack->getOMPAllocatorHandleT().isNull())
19256 return true;
19257
19258 // Set the allocator handle type.
19259 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
19260 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
19261 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
19262 S.Diag(Loc, diag::err_omp_implied_type_not_found)
19263 << "omp_allocator_handle_t";
19264 return false;
19265 }
19266 QualType AllocatorHandleEnumTy = PT.get();
19267 AllocatorHandleEnumTy.addConst();
19268
19269 // Fill the predefined allocator map.
19270 bool ErrorFound = false;
19271 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
19272 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
19273 StringRef Allocator =
19274 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
19275 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
19276 auto *VD = dyn_cast_or_null<ValueDecl>(
19277 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
19278 if (!VD) {
19279 ErrorFound = true;
19280 break;
19281 }
19282 QualType AllocatorType =
19284 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
19285 if (!Res.isUsable()) {
19286 ErrorFound = true;
19287 break;
19288 }
19289 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
19291 /*AllowExplicit=*/true);
19292 if (!Res.isUsable()) {
19293 ErrorFound = true;
19294 break;
19295 }
19296 Stack->setAllocator(AllocatorKind, Res.get());
19297 }
19298 if (ErrorFound) {
19299 S.Diag(Loc, diag::err_omp_implied_type_not_found)
19300 << "omp_allocator_handle_t";
19301 return false;
19302 }
19303
19304 // Record the type only now. It is what tells a later call that the map above
19305 // is ready to be read, so setting it before the map is filled would let that
19306 // call proceed on a map this one gave up on halfway through.
19307 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
19308
19309 return true;
19310}
19311
19313 SourceLocation StartLoc,
19314 SourceLocation LParenLoc,
19315 SourceLocation EndLoc) {
19316 // OpenMP [2.11.3, allocate Directive, Description]
19317 // allocator is an expression of omp_allocator_handle_t type.
19319 return nullptr;
19320
19321 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
19322 if (Allocator.isInvalid())
19323 return nullptr;
19324 Allocator = SemaRef.PerformImplicitConversion(
19325 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
19327 /*AllowExplicit=*/true);
19328 if (Allocator.isInvalid())
19329 return nullptr;
19330 return new (getASTContext())
19331 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
19332}
19333
19335 SourceLocation StartLoc,
19336 SourceLocation LParenLoc,
19337 SourceLocation EndLoc) {
19338 // OpenMP [2.7.1, loop construct, Description]
19339 // OpenMP [2.8.1, simd construct, Description]
19340 // OpenMP [2.9.6, distribute construct, Description]
19341 // The parameter of the collapse clause must be a constant
19342 // positive integer expression.
19343 ExprResult NumForLoopsResult =
19344 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
19345 if (NumForLoopsResult.isInvalid())
19346 return nullptr;
19347 return new (getASTContext())
19348 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
19349}
19350
19352 SourceLocation EndLoc,
19353 SourceLocation LParenLoc,
19354 Expr *NumForLoops) {
19355 // OpenMP [2.7.1, loop construct, Description]
19356 // OpenMP [2.8.1, simd construct, Description]
19357 // OpenMP [2.9.6, distribute construct, Description]
19358 // The parameter of the ordered clause must be a constant
19359 // positive integer expression if any.
19360 if (NumForLoops && LParenLoc.isValid()) {
19361 ExprResult NumForLoopsResult =
19362 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
19363 if (NumForLoopsResult.isInvalid())
19364 return nullptr;
19365 NumForLoops = NumForLoopsResult.get();
19366 } else {
19367 NumForLoops = nullptr;
19368 }
19369 auto *Clause =
19370 OMPOrderedClause::Create(getASTContext(), NumForLoops,
19371 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
19372 StartLoc, LParenLoc, EndLoc);
19373 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
19374 return Clause;
19375}
19376
19378 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
19379 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
19380 OMPClause *Res = nullptr;
19381 switch (Kind) {
19382 case OMPC_proc_bind:
19383 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
19384 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19385 break;
19386 case OMPC_atomic_default_mem_order:
19388 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
19389 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19390 break;
19391 case OMPC_fail:
19392 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
19393 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19394 break;
19395 case OMPC_update_depend_objects:
19397 static_cast<OpenMPDependClauseKind>(Argument), ArgumentLoc, StartLoc,
19398 LParenLoc, EndLoc);
19399 break;
19400 case OMPC_bind:
19401 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
19402 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19403 break;
19404 case OMPC_at:
19405 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
19406 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19407 break;
19408 case OMPC_severity:
19410 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
19411 LParenLoc, EndLoc);
19412 break;
19413 case OMPC_threadset:
19414 Res = ActOnOpenMPThreadsetClause(static_cast<OpenMPThreadsetKind>(Argument),
19415 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
19416 break;
19417 case OMPC_if:
19418 case OMPC_final:
19419 case OMPC_num_threads:
19420 case OMPC_safelen:
19421 case OMPC_simdlen:
19422 case OMPC_sizes:
19423 case OMPC_depth:
19424 case OMPC_allocator:
19425 case OMPC_collapse:
19426 case OMPC_schedule:
19427 case OMPC_private:
19428 case OMPC_firstprivate:
19429 case OMPC_lastprivate:
19430 case OMPC_shared:
19431 case OMPC_reduction:
19432 case OMPC_task_reduction:
19433 case OMPC_in_reduction:
19434 case OMPC_linear:
19435 case OMPC_aligned:
19436 case OMPC_copyin:
19437 case OMPC_copyprivate:
19438 case OMPC_ordered:
19439 case OMPC_nowait:
19440 case OMPC_untied:
19441 case OMPC_mergeable:
19442 case OMPC_threadprivate:
19443 case OMPC_groupprivate:
19444 case OMPC_allocate:
19445 case OMPC_flush:
19446 case OMPC_depobj:
19447 case OMPC_read:
19448 case OMPC_write:
19449 case OMPC_capture:
19450 case OMPC_compare:
19451 case OMPC_update:
19452 case OMPC_seq_cst:
19453 case OMPC_acq_rel:
19454 case OMPC_acquire:
19455 case OMPC_release:
19456 case OMPC_relaxed:
19457 case OMPC_depend:
19458 case OMPC_device:
19459 case OMPC_threads:
19460 case OMPC_simd:
19461 case OMPC_map:
19462 case OMPC_num_teams:
19463 case OMPC_thread_limit:
19464 case OMPC_priority:
19465 case OMPC_grainsize:
19466 case OMPC_nogroup:
19467 case OMPC_num_tasks:
19468 case OMPC_hint:
19469 case OMPC_dist_schedule:
19470 case OMPC_default:
19471 case OMPC_defaultmap:
19472 case OMPC_unknown:
19473 case OMPC_uniform:
19474 case OMPC_to:
19475 case OMPC_from:
19476 case OMPC_use_device_ptr:
19477 case OMPC_use_device_addr:
19478 case OMPC_is_device_ptr:
19479 case OMPC_has_device_addr:
19480 case OMPC_unified_address:
19481 case OMPC_unified_shared_memory:
19482 case OMPC_reverse_offload:
19483 case OMPC_dynamic_allocators:
19484 case OMPC_self_maps:
19485 case OMPC_device_type:
19486 case OMPC_match:
19487 case OMPC_nontemporal:
19488 case OMPC_destroy:
19489 case OMPC_novariants:
19490 case OMPC_nocontext:
19491 case OMPC_detach:
19492 case OMPC_inclusive:
19493 case OMPC_exclusive:
19494 case OMPC_uses_allocators:
19495 case OMPC_affinity:
19496 case OMPC_when:
19497 case OMPC_message:
19498 default:
19499 llvm_unreachable("Clause is not allowed.");
19500 }
19501 return Res;
19502}
19503
19505 llvm::omp::DefaultKind M, SourceLocation MLoc,
19507 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
19508 if (M == OMP_DEFAULT_unknown) {
19509 Diag(MLoc, diag::err_omp_unexpected_clause_value)
19510 << getListOfPossibleValues(OMPC_default, /*First=*/0,
19511 /*Last=*/unsigned(OMP_DEFAULT_unknown))
19512 << getOpenMPClauseNameForDiag(OMPC_default);
19513 return nullptr;
19514 }
19515 if (VCKind == OMPC_DEFAULT_VC_unknown) {
19516 Diag(VCKindLoc, diag::err_omp_default_vc)
19517 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
19518 return nullptr;
19519 }
19520
19521 bool IsTargetDefault =
19522 getLangOpts().OpenMP >= 60 &&
19523 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
19524
19525 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
19526 // If data-sharing-attribute is shared then the clause has no effect
19527 // on a target construct;
19528 if (IsTargetDefault && M == OMP_DEFAULT_shared)
19529 return nullptr;
19530
19531 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
19534 OpenMPDefaultmapClauseKind DefMapKind;
19535 // default data-sharing-attribute
19536 switch (M) {
19537 case OMP_DEFAULT_none:
19538 if (IsTargetDefault)
19539 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
19540 else
19541 DSAStack->setDefaultDSANone(MLoc);
19542 break;
19543 case OMP_DEFAULT_firstprivate:
19544 if (IsTargetDefault)
19545 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
19546 else
19547 DSAStack->setDefaultDSAFirstPrivate(MLoc);
19548 break;
19549 case OMP_DEFAULT_private:
19550 if (IsTargetDefault)
19551 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
19552 else
19553 DSAStack->setDefaultDSAPrivate(MLoc);
19554 break;
19555 case OMP_DEFAULT_shared:
19556 assert(!IsTargetDefault && "DSA shared invalid with target directive");
19557 DSAStack->setDefaultDSAShared(MLoc);
19558 break;
19559 default:
19560 llvm_unreachable("unexpected DSA in OpenMP default clause");
19561 }
19562 // default variable-category
19563 switch (VCKind) {
19564 case OMPC_DEFAULT_VC_aggregate:
19565 if (IsTargetDefault)
19566 DefMapKind = OMPC_DEFAULTMAP_aggregate;
19567 else
19568 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
19569 break;
19570 case OMPC_DEFAULT_VC_pointer:
19571 if (IsTargetDefault)
19572 DefMapKind = OMPC_DEFAULTMAP_pointer;
19573 else
19574 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
19575 break;
19576 case OMPC_DEFAULT_VC_scalar:
19577 if (IsTargetDefault)
19578 DefMapKind = OMPC_DEFAULTMAP_scalar;
19579 else
19580 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
19581 break;
19582 case OMPC_DEFAULT_VC_all:
19583 if (IsTargetDefault)
19584 DefMapKind = OMPC_DEFAULTMAP_all;
19585 else
19586 DSAStack->setDefaultDSAVCAll(VCKindLoc);
19587 break;
19588 default:
19589 llvm_unreachable("unexpected variable category in OpenMP default clause");
19590 }
19591 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
19592 // otherwise, its effect on a target construct is equivalent to
19593 // specifying the defaultmap clause with the same data-sharing-attribute
19594 // and variable-category.
19595 //
19596 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
19597 // is/was set as before.
19598 if (IsTargetDefault) {
19599 if (DefMapKind == OMPC_DEFAULTMAP_all) {
19600 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
19601 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
19602 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
19603 } else {
19604 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
19605 }
19606 }
19607 };
19608
19609 SetDefaultClauseAttrs(M, VCKind);
19610 return new (getASTContext())
19611 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
19612}
19613
19615 SourceLocation KindLoc,
19616 SourceLocation StartLoc,
19617 SourceLocation LParenLoc,
19618 SourceLocation EndLoc) {
19619 if (Kind == OMPC_THREADSET_unknown) {
19620 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
19621 << getListOfPossibleValues(OMPC_threadset, /*First=*/0,
19622 /*Last=*/unsigned(OMPC_THREADSET_unknown))
19623 << getOpenMPClauseName(OMPC_threadset);
19624 return nullptr;
19625 }
19626
19627 return new (getASTContext())
19628 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
19629}
19630
19631static OMPClause *
19632createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg,
19633 Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion,
19634 SourceLocation StartLoc, SourceLocation LParenLoc,
19635 SourceLocation EndLoc) {
19636 ExprResult ER = SemaRef.DefaultLvalueConversion(ImpexTypeArg);
19637 if (ER.isInvalid())
19638 return nullptr;
19639
19640 return new (Ctx) OMPTransparentClause(ER.get(), HelperValStmt, CaptureRegion,
19641 StartLoc, LParenLoc, EndLoc);
19642}
19643
19645 SourceLocation StartLoc,
19646 SourceLocation LParenLoc,
19647 SourceLocation EndLoc) {
19648 Stmt *HelperValStmt = nullptr;
19649 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19651 DKind, OMPC_transparent, getLangOpts().getOpenMPVersion());
19652 if (CaptureRegion != OMPD_unknown &&
19653 !SemaRef.CurContext->isDependentContext()) {
19654 Expr *ValExpr = SemaRef.MakeFullExpr(ImpexTypeArg).get();
19655 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19656 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
19657 HelperValStmt = buildPreInits(getASTContext(), Captures);
19658 }
19659 if (!ImpexTypeArg) {
19660 return new (getASTContext())
19661 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19662 StartLoc, LParenLoc, EndLoc);
19663 }
19664 QualType Ty = ImpexTypeArg->getType();
19665
19666 if (const auto *TT = Ty->getAs<TypedefType>()) {
19667 const TypedefNameDecl *TypedefDecl = TT->getDecl();
19668 llvm::StringRef TypedefName = TypedefDecl->getName();
19669 IdentifierInfo &II = SemaRef.PP.getIdentifierTable().get(TypedefName);
19670 ParsedType ImpexTy =
19671 SemaRef.getTypeName(II, StartLoc, SemaRef.getCurScope());
19672 if (!ImpexTy.getAsOpaquePtr() || ImpexTy.get().isNull()) {
19673 SemaRef.Diag(StartLoc, diag::err_omp_implied_type_not_found)
19674 << TypedefName;
19675 return nullptr;
19676 }
19677 return new (getASTContext())
19678 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19679 StartLoc, LParenLoc, EndLoc);
19680 }
19681
19682 if (Ty->isEnumeralType())
19683 return createTransparentClause(SemaRef, getASTContext(), ImpexTypeArg,
19684 HelperValStmt, CaptureRegion, StartLoc,
19685 LParenLoc, EndLoc);
19686 if (Ty->isIntegerType()) {
19687 if (isNonNegativeIntegerValue(ImpexTypeArg, SemaRef, OMPC_transparent,
19688 /*StrictlyPositive=*/false)) {
19690 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(StartLoc,
19691 ImpexTypeArg);
19692 if (std::optional<llvm::APSInt> Result =
19693 Value.get()->getIntegerConstantExpr(SemaRef.Context)) {
19694 if (Result->isNegative() ||
19695 Result >
19696 static_cast<int64_t>(SemaOpenMP::OpenMPImpexType::OMP_Export))
19697 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_value);
19698 }
19699 return new (getASTContext())
19700 OMPTransparentClause(ImpexTypeArg, HelperValStmt, CaptureRegion,
19701 StartLoc, LParenLoc, EndLoc);
19702 }
19703 }
19704 if (!isNonNegativeIntegerValue(ImpexTypeArg, SemaRef, OMPC_transparent,
19705 /*StrictlyPositive=*/true))
19706 return nullptr;
19707 return new (getASTContext()) OMPTransparentClause(
19708 ImpexTypeArg, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19709}
19710
19712 SourceLocation KindKwLoc,
19713 SourceLocation StartLoc,
19714 SourceLocation LParenLoc,
19715 SourceLocation EndLoc) {
19716 if (Kind == OMP_PROC_BIND_unknown) {
19717 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19718 << getListOfPossibleValues(OMPC_proc_bind,
19719 /*First=*/unsigned(OMP_PROC_BIND_master),
19720 /*Last=*/
19721 unsigned(getLangOpts().OpenMP > 50
19722 ? OMP_PROC_BIND_primary
19723 : OMP_PROC_BIND_spread) +
19724 1)
19725 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
19726 return nullptr;
19727 }
19728 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
19729 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19730 << getListOfPossibleValues(OMPC_proc_bind,
19731 /*First=*/unsigned(OMP_PROC_BIND_master),
19732 /*Last=*/
19733 unsigned(OMP_PROC_BIND_spread) + 1)
19734 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
19735 return new (getASTContext())
19736 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19737}
19738
19741 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
19743 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19745 OMPC_atomic_default_mem_order, /*First=*/0,
19747 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
19748 return nullptr;
19749 }
19750 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
19751 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19752}
19753
19755 SourceLocation KindKwLoc,
19756 SourceLocation StartLoc,
19757 SourceLocation LParenLoc,
19758 SourceLocation EndLoc) {
19759 if (Kind == OMPC_AT_unknown) {
19760 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19761 << getListOfPossibleValues(OMPC_at, /*First=*/0,
19762 /*Last=*/OMPC_AT_unknown)
19763 << getOpenMPClauseNameForDiag(OMPC_at);
19764 return nullptr;
19765 }
19766 return new (getASTContext())
19767 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19768}
19769
19771 SourceLocation KindKwLoc,
19772 SourceLocation StartLoc,
19773 SourceLocation LParenLoc,
19774 SourceLocation EndLoc) {
19775 if (Kind == OMPC_SEVERITY_unknown) {
19776 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19777 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
19778 /*Last=*/OMPC_SEVERITY_unknown)
19779 << getOpenMPClauseNameForDiag(OMPC_severity);
19780 return nullptr;
19781 }
19782 return new (getASTContext())
19783 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
19784}
19785
19787 SourceLocation StartLoc,
19788 SourceLocation LParenLoc,
19789 SourceLocation EndLoc) {
19790 assert(ME && "NULL expr in Message clause");
19791 QualType Type = ME->getType();
19792 if ((!Type->isPointerType() && !Type->isArrayType()) ||
19794 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
19795 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
19796 return nullptr;
19797 }
19798
19799 Stmt *HelperValStmt = nullptr;
19800
19801 // Depending on whether this clause appears in an executable context or not,
19802 // we may or may not build a capture.
19803 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
19804 OpenMPDirectiveKind CaptureRegion =
19805 DKind == OMPD_unknown
19806 ? OMPD_unknown
19807 : getOpenMPCaptureRegionForClause(DKind, OMPC_message,
19808 getLangOpts().getOpenMPVersion());
19809 if (CaptureRegion != OMPD_unknown &&
19810 !SemaRef.CurContext->isDependentContext()) {
19811 ME = SemaRef.MakeFullExpr(ME).get();
19812 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
19813 ME = tryBuildCapture(SemaRef, ME, Captures).get();
19814 HelperValStmt = buildPreInits(getASTContext(), Captures);
19815 }
19816
19817 // Convert array type to pointer type if needed.
19818 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
19819
19820 return new (getASTContext()) OMPMessageClause(
19821 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
19822}
19823
19826 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
19827 SourceLocation KindLoc, SourceLocation EndLoc) {
19828 if (Kind != OMPC_ORDER_concurrent ||
19829 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
19830 // Kind should be concurrent,
19831 // Modifiers introduced in OpenMP 5.1
19832 static_assert(OMPC_ORDER_unknown > 0,
19833 "OMPC_ORDER_unknown not greater than 0");
19834
19835 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
19836 << getListOfPossibleValues(OMPC_order,
19837 /*First=*/0,
19838 /*Last=*/OMPC_ORDER_unknown)
19839 << getOpenMPClauseNameForDiag(OMPC_order);
19840 return nullptr;
19841 }
19842 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
19843 MLoc.isValid()) {
19844 Diag(MLoc, diag::err_omp_unexpected_clause_value)
19845 << getListOfPossibleValues(OMPC_order,
19846 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
19847 /*Last=*/OMPC_ORDER_MODIFIER_last)
19848 << getOpenMPClauseNameForDiag(OMPC_order);
19849 } else if (getLangOpts().OpenMP >= 50) {
19850 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
19851 if (DSAStack->getCurScope()) {
19852 // mark the current scope with 'order' flag
19853 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
19854 DSAStack->getCurScope()->setFlags(existingFlags |
19856 }
19857 }
19858 return new (getASTContext()) OMPOrderClause(
19859 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
19860}
19861
19863 OpenMPDependClauseKind Kind, SourceLocation KindKwLoc,
19864 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
19865 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
19866 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
19867 SmallVector<unsigned> Except = {
19868 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
19869 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
19870 if (getLangOpts().OpenMP < 51)
19871 Except.push_back(OMPC_DEPEND_inoutset);
19872 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
19873 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
19874 /*Last=*/OMPC_DEPEND_unknown, Except)
19875 << getOpenMPClauseNameForDiag(OMPC_update_depend_objects);
19876 return nullptr;
19877 }
19878 return OMPUpdateDependObjectsClause::Create(
19879 getASTContext(), StartLoc, LParenLoc, KindKwLoc, Kind, EndLoc);
19880}
19881
19883 SourceLocation StartLoc,
19884 SourceLocation LParenLoc,
19885 SourceLocation EndLoc) {
19886 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
19887
19888 for (Expr *&SizeExpr : SanitizedSizeExprs) {
19889 // Skip if already sanitized, e.g. during a partial template instantiation.
19890 if (!SizeExpr)
19891 continue;
19892
19893 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
19894 /*StrictlyPositive=*/true);
19895
19896 // isNonNegativeIntegerValue returns true for non-integral types (but still
19897 // emits error diagnostic), so check for the expected type explicitly.
19898 QualType SizeTy = SizeExpr->getType();
19899 if (!SizeTy->isIntegerType())
19900 IsValid = false;
19901
19902 // Handling in templates is tricky. There are four possibilities to
19903 // consider:
19904 //
19905 // 1a. The expression is valid and we are in a instantiated template or not
19906 // in a template:
19907 // Pass valid expression to be further analysed later in Sema.
19908 // 1b. The expression is valid and we are in a template (including partial
19909 // instantiation):
19910 // isNonNegativeIntegerValue skipped any checks so there is no
19911 // guarantee it will be correct after instantiation.
19912 // ActOnOpenMPSizesClause will be called again at instantiation when
19913 // it is not in a dependent context anymore. This may cause warnings
19914 // to be emitted multiple times.
19915 // 2a. The expression is invalid and we are in an instantiated template or
19916 // not in a template:
19917 // Invalidate the expression with a clearly wrong value (nullptr) so
19918 // later in Sema we do not have to do the same validity analysis again
19919 // or crash from unexpected data. Error diagnostics have already been
19920 // emitted.
19921 // 2b. The expression is invalid and we are in a template (including partial
19922 // instantiation):
19923 // Pass the invalid expression as-is, template instantiation may
19924 // replace unexpected types/values with valid ones. The directives
19925 // with this clause must not try to use these expressions in dependent
19926 // contexts, but delay analysis until full instantiation.
19927 if (!SizeExpr->isInstantiationDependent() && !IsValid)
19928 SizeExpr = nullptr;
19929 }
19930
19931 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19932 SanitizedSizeExprs);
19933}
19934
19936 SourceLocation StartLoc,
19937 SourceLocation LParenLoc,
19938 SourceLocation EndLoc,
19939 std::optional<unsigned> FillIdx,
19940 SourceLocation FillLoc,
19941 unsigned FillCount) {
19942 SmallVector<Expr *> SanitizedCountExprs(CountExprs);
19943
19944 // OpenMP 6.0: each list item in counts(...) is either the omp_fill keyword
19945 // or an integral constant expression (non-negative). Runtime variables are
19946 // not permitted; this matches split codegen, which needs segment sizes at
19947 // compile time.
19948 for (unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
19949 Expr *&CountExpr = SanitizedCountExprs[I];
19950 if (FillIdx && I == *FillIdx)
19951 continue;
19952 if (!CountExpr)
19953 continue;
19954
19956 CountExpr, OMPC_counts, /*StrictlyPositive=*/false);
19957 if (Verified.isInvalid())
19958 CountExpr = nullptr;
19959 else
19960 CountExpr = Verified.get();
19961 }
19962
19963 if (FillCount != 1) {
19964 Diag(FillCount == 0 ? StartLoc : FillLoc,
19965 diag::err_omp_split_counts_not_one_omp_fill);
19966 }
19967
19968 return OMPCountsClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19969 SanitizedCountExprs, FillIdx, FillLoc);
19970}
19971
19973 SourceLocation StartLoc,
19974 SourceLocation LParenLoc,
19975 SourceLocation EndLoc) {
19976 size_t NumLoops = PermExprs.size();
19977 SmallVector<Expr *> SanitizedPermExprs;
19978 llvm::append_range(SanitizedPermExprs, PermExprs);
19979
19980 for (Expr *&PermExpr : SanitizedPermExprs) {
19981 // Skip if template-dependent or already sanitized, e.g. during a partial
19982 // template instantiation.
19983 if (!PermExpr || PermExpr->isInstantiationDependent())
19984 continue;
19985
19986 llvm::APSInt PermVal;
19987 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
19988 PermExpr, &PermVal, AllowFoldKind::Allow);
19989 bool IsValid = PermEvalExpr.isUsable();
19990 if (IsValid)
19991 PermExpr = PermEvalExpr.get();
19992
19993 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
19994 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
19995 PermEvalExpr.get()->getEndLoc());
19996 Diag(PermEvalExpr.get()->getExprLoc(),
19997 diag::err_omp_interchange_permutation_value_range)
19998 << NumLoops << ExprRange;
19999 IsValid = false;
20000 }
20001
20002 if (!PermExpr->isInstantiationDependent() && !IsValid)
20003 PermExpr = nullptr;
20004 }
20005
20006 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
20007 EndLoc, SanitizedPermExprs);
20008}
20009
20011 SourceLocation EndLoc) {
20012 return new (getASTContext()) OMPFullClause(StartLoc, EndLoc);
20013}
20014
20016 SourceLocation StartLoc,
20017 SourceLocation LParenLoc,
20018 SourceLocation EndLoc) {
20019 if (FactorExpr) {
20020 // If an argument is specified, it must be a constant (or an unevaluated
20021 // template expression).
20023 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
20024 if (FactorResult.isInvalid())
20025 return nullptr;
20026 FactorExpr = FactorResult.get();
20027 }
20028
20029 return new (getASTContext())
20030 OMPPartialClause(StartLoc, LParenLoc, EndLoc, FactorExpr);
20031}
20032
20034 SourceLocation StartLoc,
20035 SourceLocation LParenLoc,
20036 SourceLocation EndLoc) {
20037 // The depth-expr must be a positive integer constant expression and
20038 // not greater than the number of loops in the associated loop nest.
20040 DepthExpr, OMPC_depth, /*StrictlyPositive=*/true);
20041 if (DepthResult.isInvalid())
20042 return nullptr;
20043 DepthExpr = DepthResult.get();
20044
20045 return new (getASTContext())
20046 OMPDepthClause(StartLoc, LParenLoc, EndLoc, DepthExpr);
20047}
20048
20050 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
20051 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
20052
20053 // OpenMP [6.0, Restrictions]
20054 // First and Count must be integer expressions with positive value
20055 ExprResult FirstVal =
20057 if (FirstVal.isInvalid())
20058 First = nullptr;
20059
20060 ExprResult CountVal =
20061 VerifyPositiveIntegerConstantInClause(Count, OMPC_looprange);
20062 if (CountVal.isInvalid())
20063 Count = nullptr;
20064
20065 // OpenMP [6.0, Restrictions]
20066 // first + count - 1 must not evaluate to a value greater than the
20067 // loop sequence length of the associated canonical loop sequence.
20068 // This check must be performed afterwards due to the delayed
20069 // parsing and computation of the associated loop sequence
20070 return new (getASTContext()) OMPLoopRangeClause(
20071 StartLoc, LParenLoc, FirstLoc, CountLoc, EndLoc, First, Count);
20072}
20073
20075 SourceLocation LParenLoc,
20076 SourceLocation EndLoc) {
20077 ExprResult AlignVal;
20078 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
20079 if (AlignVal.isInvalid())
20080 return nullptr;
20081 return new (getASTContext())
20082 OMPAlignClause(AlignVal.get(), StartLoc, LParenLoc, EndLoc);
20083}
20084
20087 SourceLocation StartLoc, SourceLocation LParenLoc,
20088 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
20089 SourceLocation EndLoc) {
20090 OMPClause *Res = nullptr;
20091 switch (Kind) {
20092 case OMPC_schedule: {
20093 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
20094 assert(Argument.size() == NumberOfElements &&
20095 ArgumentLoc.size() == NumberOfElements);
20097 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
20098 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
20099 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
20100 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
20101 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
20102 break;
20103 }
20104 case OMPC_if:
20105 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
20106 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
20107 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
20108 DelimLoc, EndLoc);
20109 break;
20110 case OMPC_dist_schedule:
20112 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
20113 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
20114 break;
20115 case OMPC_default:
20116 enum { DefaultModifier, DefaultVarCategory };
20118 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
20119 ArgumentLoc[DefaultModifier],
20121 Argument[DefaultVarCategory]),
20122 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
20123 break;
20124 case OMPC_defaultmap:
20125 enum { Modifier, DefaultmapKind };
20127 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
20128 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
20129 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
20130 EndLoc);
20131 break;
20132 case OMPC_order:
20133 enum { OrderModifier, OrderKind };
20135 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
20136 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
20137 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
20138 break;
20139 case OMPC_device:
20140 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
20142 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
20143 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
20144 break;
20145 case OMPC_grainsize:
20146 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
20147 "Modifier for grainsize clause and its location are expected.");
20149 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
20150 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
20151 break;
20152 case OMPC_num_tasks:
20153 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
20154 "Modifier for num_tasks clause and its location are expected.");
20156 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
20157 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
20158 break;
20159 case OMPC_dyn_groupprivate: {
20160 enum { Modifier1, Modifier2, NumberOfElements };
20161 assert(Argument.size() == NumberOfElements &&
20162 ArgumentLoc.size() == NumberOfElements &&
20163 "Modifiers for dyn_groupprivate clause and their locations are "
20164 "expected.");
20166 static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
20168 Argument[Modifier2]),
20169 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
20170 ArgumentLoc[Modifier2], EndLoc);
20171 break;
20172 }
20173 case OMPC_final:
20174 case OMPC_safelen:
20175 case OMPC_simdlen:
20176 case OMPC_sizes:
20177 case OMPC_depth:
20178 case OMPC_allocator:
20179 case OMPC_collapse:
20180 case OMPC_proc_bind:
20181 case OMPC_private:
20182 case OMPC_firstprivate:
20183 case OMPC_lastprivate:
20184 case OMPC_shared:
20185 case OMPC_reduction:
20186 case OMPC_task_reduction:
20187 case OMPC_in_reduction:
20188 case OMPC_linear:
20189 case OMPC_aligned:
20190 case OMPC_copyin:
20191 case OMPC_copyprivate:
20192 case OMPC_ordered:
20193 case OMPC_nowait:
20194 case OMPC_untied:
20195 case OMPC_mergeable:
20196 case OMPC_threadprivate:
20197 case OMPC_groupprivate:
20198 case OMPC_allocate:
20199 case OMPC_flush:
20200 case OMPC_depobj:
20201 case OMPC_read:
20202 case OMPC_write:
20203 case OMPC_update:
20204 case OMPC_capture:
20205 case OMPC_compare:
20206 case OMPC_seq_cst:
20207 case OMPC_acq_rel:
20208 case OMPC_acquire:
20209 case OMPC_release:
20210 case OMPC_relaxed:
20211 case OMPC_depend:
20212 case OMPC_threads:
20213 case OMPC_simd:
20214 case OMPC_map:
20215 case OMPC_num_teams:
20216 case OMPC_thread_limit:
20217 case OMPC_priority:
20218 case OMPC_nogroup:
20219 case OMPC_hint:
20220 case OMPC_unknown:
20221 case OMPC_uniform:
20222 case OMPC_to:
20223 case OMPC_from:
20224 case OMPC_use_device_ptr:
20225 case OMPC_use_device_addr:
20226 case OMPC_is_device_ptr:
20227 case OMPC_has_device_addr:
20228 case OMPC_unified_address:
20229 case OMPC_unified_shared_memory:
20230 case OMPC_reverse_offload:
20231 case OMPC_dynamic_allocators:
20232 case OMPC_atomic_default_mem_order:
20233 case OMPC_self_maps:
20234 case OMPC_device_type:
20235 case OMPC_match:
20236 case OMPC_nontemporal:
20237 case OMPC_at:
20238 case OMPC_severity:
20239 case OMPC_message:
20240 case OMPC_destroy:
20241 case OMPC_novariants:
20242 case OMPC_nocontext:
20243 case OMPC_detach:
20244 case OMPC_inclusive:
20245 case OMPC_exclusive:
20246 case OMPC_uses_allocators:
20247 case OMPC_affinity:
20248 case OMPC_when:
20249 case OMPC_bind:
20250 default:
20251 llvm_unreachable("Clause is not allowed.");
20252 }
20253 return Res;
20254}
20255
20258 SourceLocation M1Loc, SourceLocation M2Loc) {
20259 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
20260 SmallVector<unsigned, 2> Excluded;
20262 Excluded.push_back(M2);
20263 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
20264 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
20265 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
20266 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
20267 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
20268 << getListOfPossibleValues(OMPC_schedule,
20269 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
20271 Excluded)
20272 << getOpenMPClauseNameForDiag(OMPC_schedule);
20273 return true;
20274 }
20275 return false;
20276}
20277
20280 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
20281 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
20282 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
20283 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
20284 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
20285 return nullptr;
20286 // OpenMP, 2.7.1, Loop Construct, Restrictions
20287 // Either the monotonic modifier or the nonmonotonic modifier can be specified
20288 // but not both.
20289 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
20290 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
20291 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
20292 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
20293 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
20294 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
20295 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
20296 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
20297 return nullptr;
20298 }
20299 if (Kind == OMPC_SCHEDULE_unknown) {
20300 std::string Values;
20301 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
20302 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
20303 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
20305 Exclude);
20306 } else {
20307 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
20308 /*Last=*/OMPC_SCHEDULE_unknown);
20309 }
20310 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
20311 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
20312 return nullptr;
20313 }
20314 // OpenMP, 2.7.1, Loop Construct, Restrictions
20315 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
20316 // schedule(guided).
20317 // OpenMP 5.0 does not have this restriction.
20318 if (getLangOpts().OpenMP < 50 &&
20319 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
20320 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
20321 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
20322 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
20323 diag::err_omp_schedule_nonmonotonic_static);
20324 return nullptr;
20325 }
20326 Expr *ValExpr = ChunkSize;
20327 Stmt *HelperValStmt = nullptr;
20328 if (ChunkSize) {
20329 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
20330 !ChunkSize->isInstantiationDependent() &&
20331 !ChunkSize->containsUnexpandedParameterPack()) {
20332 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
20333 ExprResult Val =
20334 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
20335 if (Val.isInvalid())
20336 return nullptr;
20337
20338 ValExpr = Val.get();
20339
20340 // OpenMP [2.7.1, Restrictions]
20341 // chunk_size must be a loop invariant integer expression with a positive
20342 // value.
20343 if (std::optional<llvm::APSInt> Result =
20345 if (Result->isSigned() && !Result->isStrictlyPositive()) {
20346 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
20347 << "schedule" << 1 << ChunkSize->getSourceRange();
20348 return nullptr;
20349 }
20351 DSAStack->getCurrentDirective(), OMPC_schedule,
20352 getLangOpts().getOpenMPVersion()) != OMPD_unknown &&
20353 !SemaRef.CurContext->isDependentContext()) {
20354 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20355 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20356 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20357 HelperValStmt = buildPreInits(getASTContext(), Captures);
20358 }
20359 }
20360 }
20361
20362 return new (getASTContext())
20363 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
20364 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
20365}
20366
20368 SourceLocation StartLoc,
20369 SourceLocation EndLoc) {
20370 OMPClause *Res = nullptr;
20371 switch (Kind) {
20372 case OMPC_ordered:
20373 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
20374 break;
20375 case OMPC_nowait:
20376 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
20377 /*LParenLoc=*/SourceLocation(),
20378 /*Condition=*/nullptr);
20379 break;
20380 case OMPC_untied:
20381 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
20382 break;
20383 case OMPC_mergeable:
20384 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
20385 break;
20386 case OMPC_read:
20387 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
20388 break;
20389 case OMPC_write:
20390 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
20391 break;
20392 case OMPC_update:
20393 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
20394 break;
20395 case OMPC_capture:
20396 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
20397 break;
20398 case OMPC_compare:
20399 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
20400 break;
20401 case OMPC_fail:
20402 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
20403 break;
20404 case OMPC_seq_cst:
20405 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
20406 break;
20407 case OMPC_acq_rel:
20408 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
20409 break;
20410 case OMPC_acquire:
20411 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
20412 break;
20413 case OMPC_release:
20414 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
20415 break;
20416 case OMPC_relaxed:
20417 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
20418 break;
20419 case OMPC_weak:
20420 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
20421 break;
20422 case OMPC_threads:
20423 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
20424 break;
20425 case OMPC_simd:
20426 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
20427 break;
20428 case OMPC_nogroup:
20429 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
20430 break;
20431 case OMPC_unified_address:
20432 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
20433 break;
20434 case OMPC_unified_shared_memory:
20435 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
20436 break;
20437 case OMPC_reverse_offload:
20438 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
20439 break;
20440 case OMPC_dynamic_allocators:
20441 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
20442 break;
20443 case OMPC_self_maps:
20444 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
20445 break;
20446 case OMPC_destroy:
20447 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
20448 /*LParenLoc=*/SourceLocation(),
20449 /*VarLoc=*/SourceLocation(), EndLoc);
20450 break;
20451 case OMPC_full:
20452 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
20453 break;
20454 case OMPC_partial:
20455 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
20456 break;
20457 case OMPC_ompx_bare:
20458 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
20459 break;
20460 case OMPC_if:
20461 case OMPC_final:
20462 case OMPC_num_threads:
20463 case OMPC_safelen:
20464 case OMPC_simdlen:
20465 case OMPC_sizes:
20466 case OMPC_depth:
20467 case OMPC_allocator:
20468 case OMPC_collapse:
20469 case OMPC_schedule:
20470 case OMPC_private:
20471 case OMPC_firstprivate:
20472 case OMPC_lastprivate:
20473 case OMPC_shared:
20474 case OMPC_reduction:
20475 case OMPC_task_reduction:
20476 case OMPC_in_reduction:
20477 case OMPC_linear:
20478 case OMPC_aligned:
20479 case OMPC_copyin:
20480 case OMPC_copyprivate:
20481 case OMPC_default:
20482 case OMPC_proc_bind:
20483 case OMPC_threadprivate:
20484 case OMPC_groupprivate:
20485 case OMPC_allocate:
20486 case OMPC_flush:
20487 case OMPC_depobj:
20488 case OMPC_depend:
20489 case OMPC_device:
20490 case OMPC_map:
20491 case OMPC_num_teams:
20492 case OMPC_thread_limit:
20493 case OMPC_priority:
20494 case OMPC_grainsize:
20495 case OMPC_num_tasks:
20496 case OMPC_hint:
20497 case OMPC_dist_schedule:
20498 case OMPC_defaultmap:
20499 case OMPC_unknown:
20500 case OMPC_uniform:
20501 case OMPC_to:
20502 case OMPC_from:
20503 case OMPC_use_device_ptr:
20504 case OMPC_use_device_addr:
20505 case OMPC_is_device_ptr:
20506 case OMPC_has_device_addr:
20507 case OMPC_atomic_default_mem_order:
20508 case OMPC_device_type:
20509 case OMPC_match:
20510 case OMPC_nontemporal:
20511 case OMPC_order:
20512 case OMPC_at:
20513 case OMPC_severity:
20514 case OMPC_message:
20515 case OMPC_novariants:
20516 case OMPC_nocontext:
20517 case OMPC_detach:
20518 case OMPC_inclusive:
20519 case OMPC_exclusive:
20520 case OMPC_uses_allocators:
20521 case OMPC_affinity:
20522 case OMPC_when:
20523 case OMPC_ompx_dyn_cgroup_mem:
20524 case OMPC_dyn_groupprivate:
20525 default:
20526 llvm_unreachable("Clause is not allowed.");
20527 }
20528 return Res;
20529}
20530
20532 SourceLocation EndLoc,
20533 SourceLocation LParenLoc,
20534 Expr *Condition) {
20535 Expr *ValExpr = Condition;
20536 if (Condition && LParenLoc.isValid()) {
20537 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
20538 !Condition->isInstantiationDependent() &&
20539 !Condition->containsUnexpandedParameterPack()) {
20540 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
20541 if (Val.isInvalid())
20542 return nullptr;
20543
20544 ValExpr = Val.get();
20545 }
20546 }
20547 DSAStack->setNowaitRegion();
20548 return new (getASTContext())
20549 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
20550}
20551
20553 SourceLocation EndLoc) {
20554 DSAStack->setUntiedRegion();
20555 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
20556}
20557
20559 SourceLocation EndLoc) {
20560 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
20561}
20562
20564 SourceLocation EndLoc) {
20565 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
20566}
20567
20569 SourceLocation EndLoc) {
20570 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
20571}
20572
20574 SourceLocation EndLoc) {
20575 return new (getASTContext()) OMPUpdateClause(StartLoc, EndLoc);
20576}
20577
20579 SourceLocation EndLoc) {
20580 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
20581}
20582
20584 SourceLocation EndLoc) {
20585 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
20586}
20587
20589 SourceLocation EndLoc) {
20590 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
20591}
20592
20594 SourceLocation KindLoc,
20595 SourceLocation StartLoc,
20596 SourceLocation LParenLoc,
20597 SourceLocation EndLoc) {
20598
20600 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
20601 return nullptr;
20602 }
20603 return new (getASTContext())
20604 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
20605}
20606
20608 SourceLocation EndLoc) {
20609 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
20610}
20611
20613 SourceLocation EndLoc) {
20614 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
20615}
20616
20618 SourceLocation EndLoc) {
20619 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
20620}
20621
20623 SourceLocation EndLoc) {
20624 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
20625}
20626
20628 SourceLocation EndLoc) {
20629 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
20630}
20631
20633 SourceLocation EndLoc) {
20634 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
20635}
20636
20638 SourceLocation EndLoc) {
20639 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
20640}
20641
20643 SourceLocation EndLoc) {
20644 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
20645}
20646
20648 SourceLocation EndLoc) {
20649 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
20650}
20651
20653 SourceLocation EndLoc) {
20654 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
20655}
20656
20657OMPClause *
20659 SourceLocation EndLoc) {
20660 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
20661}
20662
20664 SourceLocation EndLoc) {
20665 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
20666}
20667
20668OMPClause *
20670 SourceLocation EndLoc) {
20671 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
20672}
20673
20675 SourceLocation EndLoc) {
20676 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
20677}
20678
20681 SourceLocation StartLoc,
20682 SourceLocation EndLoc) {
20683
20684 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
20685 // At least one action-clause must appear on a directive.
20686 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
20687 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
20688 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
20689 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
20690 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
20691 return StmtError();
20692 }
20693
20694 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
20695 // A depend clause can only appear on the directive if a targetsync
20696 // interop-type is present or the interop-var was initialized with
20697 // the targetsync interop-type.
20698
20699 // If there is any 'init' clause diagnose if there is no 'init' clause with
20700 // interop-type of 'targetsync'. Cases involving other directives cannot be
20701 // diagnosed.
20702 const OMPDependClause *DependClause = nullptr;
20703 bool HasInitClause = false;
20704 bool IsTargetSync = false;
20705 for (const OMPClause *C : Clauses) {
20706 if (IsTargetSync)
20707 break;
20708 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
20709 HasInitClause = true;
20710 if (InitClause->getIsTargetSync())
20711 IsTargetSync = true;
20712 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
20713 DependClause = DC;
20714 }
20715 }
20716 if (DependClause && HasInitClause && !IsTargetSync) {
20717 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
20718 return StmtError();
20719 }
20720
20721 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
20722 // Each interop-var may be specified for at most one action-clause of each
20723 // interop construct.
20725 for (OMPClause *C : Clauses) {
20726 OpenMPClauseKind ClauseKind = C->getClauseKind();
20727 std::pair<ValueDecl *, bool> DeclResult;
20728 SourceLocation ELoc;
20729 SourceRange ERange;
20730
20731 if (ClauseKind == OMPC_init) {
20732 auto *E = cast<OMPInitClause>(C)->getInteropVar();
20733 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
20734 } else if (ClauseKind == OMPC_use) {
20735 auto *E = cast<OMPUseClause>(C)->getInteropVar();
20736 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
20737 } else if (ClauseKind == OMPC_destroy) {
20738 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
20739 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
20740 }
20741
20742 if (DeclResult.first) {
20743 if (!InteropVars.insert(DeclResult.first).second) {
20744 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
20745 << DeclResult.first;
20746 return StmtError();
20747 }
20748 }
20749 }
20750
20751 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
20752 Clauses);
20753}
20754
20755static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
20756 SourceLocation VarLoc,
20757 OpenMPClauseKind Kind) {
20758 SourceLocation ELoc;
20759 SourceRange ERange;
20760 Expr *RefExpr = InteropVarExpr;
20761 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
20762 /*AllowArraySection=*/false,
20763 /*AllowAssumedSizeArray=*/false,
20764 /*DiagType=*/"omp_interop_t");
20765
20766 if (Res.second) {
20767 // It will be analyzed later.
20768 return true;
20769 }
20770
20771 if (!Res.first)
20772 return false;
20773
20774 // Interop variable should be of type omp_interop_t.
20775 bool HasError = false;
20776 QualType InteropType;
20777 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
20778 VarLoc, Sema::LookupOrdinaryName);
20779 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
20780 NamedDecl *ND = Result.getFoundDecl();
20781 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
20782 InteropType = QualType(TD->getTypeForDecl(), 0);
20783 } else {
20784 HasError = true;
20785 }
20786 } else {
20787 HasError = true;
20788 }
20789
20790 if (HasError) {
20791 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
20792 << "omp_interop_t";
20793 return false;
20794 }
20795
20796 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
20797 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
20798 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
20799 return false;
20800 }
20801
20802 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
20803 // The interop-var passed to init or destroy must be non-const.
20804 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
20805 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
20806 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
20807 << /*non-const*/ 1;
20808 return false;
20809 }
20810 return true;
20811}
20812
20814 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
20815 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
20816
20817 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
20818 return nullptr;
20819
20820 if (!checkPreferTypeArgs(*this, InteropInfo))
20821 return nullptr;
20822
20823 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
20824 StartLoc, LParenLoc, VarLoc, EndLoc);
20825}
20826
20828 SourceLocation StartLoc,
20829 SourceLocation LParenLoc,
20830 SourceLocation VarLoc,
20831 SourceLocation EndLoc) {
20832
20833 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
20834 return nullptr;
20835
20836 return new (getASTContext())
20837 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
20838}
20839
20841 SourceLocation StartLoc,
20842 SourceLocation LParenLoc,
20843 SourceLocation VarLoc,
20844 SourceLocation EndLoc) {
20845 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
20846 DSAStack->getCurrentDirective() == OMPD_depobj) {
20847 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
20848 Diag(StartLoc, diag::err_omp_expected_clause_argument)
20849 << getOpenMPClauseNameForDiag(OMPC_destroy)
20850 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
20851 return nullptr;
20852 }
20853 if (InteropVar &&
20854 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
20855 return nullptr;
20856
20857 return new (getASTContext())
20858 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
20859}
20860
20862 SourceLocation StartLoc,
20863 SourceLocation LParenLoc,
20864 SourceLocation EndLoc) {
20865 Expr *ValExpr = Condition;
20866 Stmt *HelperValStmt = nullptr;
20867 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
20868 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
20869 !Condition->isInstantiationDependent() &&
20870 !Condition->containsUnexpandedParameterPack()) {
20871 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
20872 if (Val.isInvalid())
20873 return nullptr;
20874
20875 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
20876
20877 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20878 CaptureRegion = getOpenMPCaptureRegionForClause(
20879 DKind, OMPC_novariants, getLangOpts().getOpenMPVersion());
20880 if (CaptureRegion != OMPD_unknown &&
20881 !SemaRef.CurContext->isDependentContext()) {
20882 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20883 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20884 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20885 HelperValStmt = buildPreInits(getASTContext(), Captures);
20886 }
20887 }
20888
20889 return new (getASTContext()) OMPNovariantsClause(
20890 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20891}
20892
20894 SourceLocation StartLoc,
20895 SourceLocation LParenLoc,
20896 SourceLocation EndLoc) {
20897 Expr *ValExpr = Condition;
20898 Stmt *HelperValStmt = nullptr;
20899 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
20900 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
20901 !Condition->isInstantiationDependent() &&
20902 !Condition->containsUnexpandedParameterPack()) {
20903 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
20904 if (Val.isInvalid())
20905 return nullptr;
20906
20907 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
20908
20909 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20910 CaptureRegion = getOpenMPCaptureRegionForClause(
20911 DKind, OMPC_nocontext, getLangOpts().getOpenMPVersion());
20912 if (CaptureRegion != OMPD_unknown &&
20913 !SemaRef.CurContext->isDependentContext()) {
20914 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20915 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20916 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20917 HelperValStmt = buildPreInits(getASTContext(), Captures);
20918 }
20919 }
20920
20921 return new (getASTContext()) OMPNocontextClause(
20922 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20923}
20924
20926 SourceLocation StartLoc,
20927 SourceLocation LParenLoc,
20928 SourceLocation EndLoc) {
20929 Expr *ValExpr = ThreadID;
20930 Stmt *HelperValStmt = nullptr;
20931
20932 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
20934 DKind, OMPC_filter, getLangOpts().getOpenMPVersion());
20935 if (CaptureRegion != OMPD_unknown &&
20936 !SemaRef.CurContext->isDependentContext()) {
20937 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
20938 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
20939 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
20940 HelperValStmt = buildPreInits(getASTContext(), Captures);
20941 }
20942
20943 return new (getASTContext()) OMPFilterClause(
20944 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
20945}
20946
20948 ArrayRef<Expr *> VarList,
20949 const OMPVarListLocTy &Locs,
20951 SourceLocation StartLoc = Locs.StartLoc;
20952 SourceLocation LParenLoc = Locs.LParenLoc;
20953 SourceLocation EndLoc = Locs.EndLoc;
20954 OMPClause *Res = nullptr;
20955 int ExtraModifier = Data.ExtraModifier;
20956 int OriginalSharingModifier = Data.OriginalSharingModifier;
20957 Expr *ExtraModifierExpr = Data.ExtraModifierExpr;
20958 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
20959 SourceLocation ColonLoc = Data.ColonLoc;
20960 switch (Kind) {
20961 case OMPC_private:
20962 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
20963 break;
20964 case OMPC_firstprivate:
20965 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
20966 break;
20967 case OMPC_lastprivate:
20968 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
20969 "Unexpected lastprivate modifier.");
20971 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
20972 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
20973 break;
20974 case OMPC_shared:
20975 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
20976 break;
20977 case OMPC_reduction:
20978 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
20979 "Unexpected lastprivate modifier.");
20981 VarList,
20983 ExtraModifier, OriginalSharingModifier),
20984 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
20985 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
20986 break;
20987 case OMPC_task_reduction:
20989 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
20990 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
20991 break;
20992 case OMPC_in_reduction:
20994 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
20995 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
20996 break;
20997 case OMPC_linear:
20998 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
20999 "Unexpected linear modifier.");
21001 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
21002 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
21003 ColonLoc, Data.StepModifierLoc, EndLoc);
21004 break;
21005 case OMPC_aligned:
21006 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
21007 LParenLoc, ColonLoc, EndLoc);
21008 break;
21009 case OMPC_copyin:
21010 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
21011 break;
21012 case OMPC_copyprivate:
21013 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
21014 break;
21015 case OMPC_flush:
21016 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
21017 break;
21018 case OMPC_depend:
21019 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
21020 "Unexpected depend modifier.");
21022 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
21023 ColonLoc, Data.OmpAllMemoryLoc},
21024 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
21025 break;
21026 case OMPC_map:
21027 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
21028 "Unexpected map modifier.");
21030 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
21031 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
21032 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
21033 ExtraModifierLoc, ColonLoc, VarList, Locs);
21034 break;
21035 case OMPC_to:
21036 Res = ActOnOpenMPToClause(
21037 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
21038 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
21039 VarList, Locs);
21040 break;
21041 case OMPC_from:
21043 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
21044 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
21045 VarList, Locs);
21046 break;
21047 case OMPC_use_device_ptr:
21048 assert(0 <= Data.ExtraModifier &&
21049 Data.ExtraModifier <= OMPC_USE_DEVICE_PTR_FALLBACK_unknown &&
21050 "Unexpected use_device_ptr fallback modifier.");
21052 VarList, Locs,
21053 static_cast<OpenMPUseDevicePtrFallbackModifier>(Data.ExtraModifier),
21054 Data.ExtraModifierLoc);
21055 break;
21056 case OMPC_use_device_addr:
21057 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
21058 break;
21059 case OMPC_is_device_ptr:
21060 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
21061 break;
21062 case OMPC_has_device_addr:
21063 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
21064 break;
21065 case OMPC_allocate: {
21068 SourceLocation Modifier1Loc, Modifier2Loc;
21069 if (!Data.AllocClauseModifiers.empty()) {
21070 assert(Data.AllocClauseModifiers.size() <= 2 &&
21071 "More allocate modifiers than expected");
21072 Modifier1 = Data.AllocClauseModifiers[0];
21073 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
21074 if (Data.AllocClauseModifiers.size() == 2) {
21075 Modifier2 = Data.AllocClauseModifiers[1];
21076 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
21077 }
21078 }
21080 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
21081 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
21082 EndLoc);
21083 break;
21084 }
21085 case OMPC_nontemporal:
21086 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
21087 break;
21088 case OMPC_inclusive:
21089 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
21090 break;
21091 case OMPC_exclusive:
21092 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
21093 break;
21094 case OMPC_affinity:
21095 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
21096 Data.DepModOrTailExpr, VarList);
21097 break;
21098 case OMPC_doacross:
21100 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
21101 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
21102 break;
21103 case OMPC_num_teams:
21104 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_NUMTEAMS_unknown &&
21105 "Unexpected num_teams modifier.");
21107 VarList,
21108 static_cast<OpenMPNumTeamsClauseModifier>(Data.ExtraModifierArray[0]),
21109 Data.ExtraModifierExprArray[0], Data.ExtraModifierLocArray[0],
21110 static_cast<OpenMPNumTeamsClauseModifier>(Data.ExtraModifierArray[1]),
21111 Data.ExtraModifierExprArray[1], Data.ExtraModifierLocArray[1], StartLoc,
21112 LParenLoc, EndLoc);
21113 break;
21114 case OMPC_thread_limit:
21115 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_THREADLIMIT_unknown &&
21116 "Unexpected thread_limit modifier.");
21118 VarList, static_cast<OpenMPThreadLimitClauseModifier>(ExtraModifier),
21119 ExtraModifierExpr, ExtraModifierLoc, StartLoc, LParenLoc, EndLoc);
21120 break;
21121 case OMPC_num_threads:
21122 assert(0 <= Data.ExtraModifierArray[0] &&
21123 Data.ExtraModifierArray[0] <= OMPC_NUMTHREADS_unknown &&
21124 0 <= Data.ExtraModifierArray[1] &&
21125 Data.ExtraModifierArray[1] <= OMPC_NUMTHREADS_unknown &&
21126 "Unexpected num_threads modifier.");
21128 VarList,
21129 static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[0]),
21130 Data.ExtraModifierLocArray[0],
21131 static_cast<OpenMPNumThreadsClauseModifier>(Data.ExtraModifierArray[1]),
21132 Data.ExtraModifierExprArray[1], Data.ExtraModifierLocArray[1], StartLoc,
21133 LParenLoc, EndLoc);
21134 break;
21135 case OMPC_if:
21136 case OMPC_depobj:
21137 case OMPC_final:
21138 case OMPC_safelen:
21139 case OMPC_simdlen:
21140 case OMPC_sizes:
21141 case OMPC_depth:
21142 case OMPC_allocator:
21143 case OMPC_collapse:
21144 case OMPC_default:
21145 case OMPC_proc_bind:
21146 case OMPC_schedule:
21147 case OMPC_ordered:
21148 case OMPC_nowait:
21149 case OMPC_untied:
21150 case OMPC_mergeable:
21151 case OMPC_threadprivate:
21152 case OMPC_groupprivate:
21153 case OMPC_read:
21154 case OMPC_write:
21155 case OMPC_update:
21156 case OMPC_capture:
21157 case OMPC_compare:
21158 case OMPC_seq_cst:
21159 case OMPC_acq_rel:
21160 case OMPC_acquire:
21161 case OMPC_release:
21162 case OMPC_relaxed:
21163 case OMPC_device:
21164 case OMPC_threads:
21165 case OMPC_simd:
21166 case OMPC_priority:
21167 case OMPC_grainsize:
21168 case OMPC_nogroup:
21169 case OMPC_num_tasks:
21170 case OMPC_hint:
21171 case OMPC_dist_schedule:
21172 case OMPC_defaultmap:
21173 case OMPC_unknown:
21174 case OMPC_uniform:
21175 case OMPC_unified_address:
21176 case OMPC_unified_shared_memory:
21177 case OMPC_reverse_offload:
21178 case OMPC_dynamic_allocators:
21179 case OMPC_atomic_default_mem_order:
21180 case OMPC_self_maps:
21181 case OMPC_device_type:
21182 case OMPC_match:
21183 case OMPC_order:
21184 case OMPC_at:
21185 case OMPC_severity:
21186 case OMPC_message:
21187 case OMPC_destroy:
21188 case OMPC_novariants:
21189 case OMPC_nocontext:
21190 case OMPC_detach:
21191 case OMPC_uses_allocators:
21192 case OMPC_when:
21193 case OMPC_bind:
21194 default:
21195 llvm_unreachable("Clause is not allowed.");
21196 }
21197 return Res;
21198}
21199
21201 ExprObjectKind OK,
21202 SourceLocation Loc) {
21203 ExprResult Res = SemaRef.BuildDeclRefExpr(
21204 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
21205 if (!Res.isUsable())
21206 return ExprError();
21207 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
21208 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
21209 if (!Res.isUsable())
21210 return ExprError();
21211 }
21212 if (VK != VK_LValue && Res.get()->isGLValue()) {
21213 Res = SemaRef.DefaultLvalueConversion(Res.get());
21214 if (!Res.isUsable())
21215 return ExprError();
21216 }
21217 return Res;
21218}
21219
21221 SourceLocation StartLoc,
21222 SourceLocation LParenLoc,
21223 SourceLocation EndLoc) {
21225 SmallVector<Expr *, 8> PrivateCopies;
21226 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
21227 bool IsImplicitClause =
21228 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
21229 for (Expr *RefExpr : VarList) {
21230 assert(RefExpr && "NULL expr in OpenMP private clause.");
21231 SourceLocation ELoc;
21232 SourceRange ERange;
21233 Expr *SimpleRefExpr = RefExpr;
21234 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21235 if (Res.second) {
21236 // It will be analyzed later.
21237 Vars.push_back(RefExpr);
21238 PrivateCopies.push_back(nullptr);
21239 }
21240 ValueDecl *D = Res.first;
21241 if (!D)
21242 continue;
21243
21244 QualType Type = D->getType();
21245 auto *VD = dyn_cast<VarDecl>(D);
21246
21247 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
21248 // A variable that appears in a private clause must not have an incomplete
21249 // type or a reference type.
21250 if (SemaRef.RequireCompleteType(ELoc, Type,
21251 diag::err_omp_private_incomplete_type))
21252 continue;
21253 Type = Type.getNonReferenceType();
21254
21255 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
21256 // A variable that is privatized must not have a const-qualified type
21257 // unless it is of class type with a mutable member. This restriction does
21258 // not apply to the firstprivate clause.
21259 //
21260 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
21261 // A variable that appears in a private clause must not have a
21262 // const-qualified type unless it is of class type with a mutable member.
21263 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
21264 continue;
21265
21266 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
21267 // in a Construct]
21268 // Variables with the predetermined data-sharing attributes may not be
21269 // listed in data-sharing attributes clauses, except for the cases
21270 // listed below. For these exceptions only, listing a predetermined
21271 // variable in a data-sharing attribute clause is allowed and overrides
21272 // the variable's predetermined data-sharing attributes.
21273 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21274 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
21275 Diag(ELoc, diag::err_omp_wrong_dsa)
21276 << getOpenMPClauseNameForDiag(DVar.CKind)
21277 << getOpenMPClauseNameForDiag(OMPC_private);
21279 continue;
21280 }
21281
21282 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
21283 // Variably modified types are not supported for tasks.
21285 isOpenMPTaskingDirective(CurrDir)) {
21286 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21287 << getOpenMPClauseNameForDiag(OMPC_private) << Type
21288 << getOpenMPDirectiveName(CurrDir, OMPVersion);
21289 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21291 Diag(D->getLocation(),
21292 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21293 << D;
21294 continue;
21295 }
21296
21297 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21298 // A list item cannot appear in both a map clause and a data-sharing
21299 // attribute clause on the same construct
21300 //
21301 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21302 // A list item cannot appear in both a map clause and a data-sharing
21303 // attribute clause on the same construct unless the construct is a
21304 // combined construct.
21305 if ((getLangOpts().OpenMP <= 45 &&
21307 CurrDir == OMPD_target) {
21308 OpenMPClauseKind ConflictKind;
21309 if (DSAStack->checkMappableExprComponentListsForDecl(
21310 VD, /*CurrentRegionOnly=*/true,
21312 OpenMPClauseKind WhereFoundClauseKind) -> bool {
21313 ConflictKind = WhereFoundClauseKind;
21314 return true;
21315 })) {
21316 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21317 << getOpenMPClauseNameForDiag(OMPC_private)
21318 << getOpenMPClauseNameForDiag(ConflictKind)
21319 << getOpenMPDirectiveName(CurrDir, OMPVersion);
21321 continue;
21322 }
21323 }
21324
21325 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
21326 // A variable of class type (or array thereof) that appears in a private
21327 // clause requires an accessible, unambiguous default constructor for the
21328 // class type.
21329 // Generate helper private variable and initialize it with the default
21330 // value. The address of the original variable is replaced by the address of
21331 // the new private variable in CodeGen. This new variable is not added to
21332 // IdResolver, so the code in the OpenMP region uses original variable for
21333 // proper diagnostics.
21334 Type = Type.getUnqualifiedType();
21335 VarDecl *VDPrivate =
21336 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
21337 D->hasAttrs() ? &D->getAttrs() : nullptr,
21338 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
21339 SemaRef.ActOnUninitializedDecl(VDPrivate);
21340 if (VDPrivate->isInvalidDecl())
21341 continue;
21342 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
21343 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
21344
21345 DeclRefExpr *Ref = nullptr;
21346 bool IsBindingDecl = isa<BindingDecl>(D);
21347 if (!VD && !IsBindingDecl && !SemaRef.CurContext->isDependentContext()) {
21348 auto *FD = dyn_cast<FieldDecl>(D);
21349 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
21350 if (VD)
21352 RefExpr->getExprLoc());
21353 else
21354 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
21355 }
21356 if (!IsImplicitClause) {
21357 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
21358 }
21359 Vars.push_back(
21360 (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
21361 ? RefExpr->IgnoreParens()
21362 : Ref);
21363 PrivateCopies.push_back(VDPrivateRefExpr);
21364 }
21365
21366 if (Vars.empty())
21367 return nullptr;
21368
21369 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21370 Vars, PrivateCopies);
21371}
21372
21374 SourceLocation StartLoc,
21375 SourceLocation LParenLoc,
21376 SourceLocation EndLoc) {
21378 SmallVector<Expr *, 8> PrivateCopies;
21380 SmallVector<Decl *, 4> ExprCaptures;
21381 bool IsImplicitClause =
21382 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
21383 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
21384 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
21385
21386 for (Expr *RefExpr : VarList) {
21387 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
21388 SourceLocation ELoc;
21389 SourceRange ERange;
21390 Expr *SimpleRefExpr = RefExpr;
21391 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21392 if (Res.second) {
21393 // It will be analyzed later.
21394 Vars.push_back(RefExpr);
21395 PrivateCopies.push_back(nullptr);
21396 Inits.push_back(nullptr);
21397 }
21398 ValueDecl *D = Res.first;
21399 if (!D)
21400 continue;
21401
21402 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
21403 QualType Type = D->getType();
21404 auto *VD = dyn_cast<VarDecl>(D);
21405
21406 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
21407 // A variable that appears in a private clause must not have an incomplete
21408 // type or a reference type.
21409 if (SemaRef.RequireCompleteType(ELoc, Type,
21410 diag::err_omp_firstprivate_incomplete_type))
21411 continue;
21412 Type = Type.getNonReferenceType();
21413
21414 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
21415 // A variable of class type (or array thereof) that appears in a private
21416 // clause requires an accessible, unambiguous copy constructor for the
21417 // class type.
21418 QualType ElemType =
21420
21421 // If an implicit firstprivate variable found it was checked already.
21422 DSAStackTy::DSAVarData TopDVar;
21423 if (!IsImplicitClause) {
21424 DSAStackTy::DSAVarData DVar =
21425 DSAStack->getTopDSA(D, /*FromParent=*/false);
21426 TopDVar = DVar;
21427 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
21428 bool IsConstant = ElemType.isConstant(getASTContext());
21429 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
21430 // A list item that specifies a given variable may not appear in more
21431 // than one clause on the same directive, except that a variable may be
21432 // specified in both firstprivate and lastprivate clauses.
21433 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
21434 // A list item may appear in a firstprivate or lastprivate clause but not
21435 // both.
21436 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
21437 (isOpenMPDistributeDirective(CurrDir) ||
21438 DVar.CKind != OMPC_lastprivate) &&
21439 DVar.RefExpr) {
21440 Diag(ELoc, diag::err_omp_wrong_dsa)
21441 << getOpenMPClauseNameForDiag(DVar.CKind)
21442 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
21444 continue;
21445 }
21446
21447 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
21448 // in a Construct]
21449 // Variables with the predetermined data-sharing attributes may not be
21450 // listed in data-sharing attributes clauses, except for the cases
21451 // listed below. For these exceptions only, listing a predetermined
21452 // variable in a data-sharing attribute clause is allowed and overrides
21453 // the variable's predetermined data-sharing attributes.
21454 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
21455 // in a Construct, C/C++, p.2]
21456 // Variables with const-qualified type having no mutable member may be
21457 // listed in a firstprivate clause, even if they are static data members.
21458 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
21459 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
21460 Diag(ELoc, diag::err_omp_wrong_dsa)
21461 << getOpenMPClauseNameForDiag(DVar.CKind)
21462 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
21464 continue;
21465 }
21466
21467 // OpenMP [2.9.3.4, Restrictions, p.2]
21468 // A list item that is private within a parallel region must not appear
21469 // in a firstprivate clause on a worksharing construct if any of the
21470 // worksharing regions arising from the worksharing construct ever bind
21471 // to any of the parallel regions arising from the parallel construct.
21472 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
21473 // A list item that is private within a teams region must not appear in a
21474 // firstprivate clause on a distribute construct if any of the distribute
21475 // regions arising from the distribute construct ever bind to any of the
21476 // teams regions arising from the teams construct.
21477 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
21478 // A list item that appears in a reduction clause of a teams construct
21479 // must not appear in a firstprivate clause on a distribute construct if
21480 // any of the distribute regions arising from the distribute construct
21481 // ever bind to any of the teams regions arising from the teams construct.
21482 if ((isOpenMPWorksharingDirective(CurrDir) ||
21483 isOpenMPDistributeDirective(CurrDir)) &&
21484 !isOpenMPParallelDirective(CurrDir) &&
21485 !isOpenMPTeamsDirective(CurrDir)) {
21486 DVar = DSAStack->getImplicitDSA(D, true);
21487 if (DVar.CKind != OMPC_shared &&
21488 (isOpenMPParallelDirective(DVar.DKind) ||
21489 isOpenMPTeamsDirective(DVar.DKind) ||
21490 DVar.DKind == OMPD_unknown)) {
21491 Diag(ELoc, diag::err_omp_required_access)
21492 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
21493 << getOpenMPClauseNameForDiag(OMPC_shared);
21495 continue;
21496 }
21497 }
21498 // OpenMP [2.9.3.4, Restrictions, p.3]
21499 // A list item that appears in a reduction clause of a parallel construct
21500 // must not appear in a firstprivate clause on a worksharing or task
21501 // construct if any of the worksharing or task regions arising from the
21502 // worksharing or task construct ever bind to any of the parallel regions
21503 // arising from the parallel construct.
21504 // OpenMP [2.9.3.4, Restrictions, p.4]
21505 // A list item that appears in a reduction clause in worksharing
21506 // construct must not appear in a firstprivate clause in a task construct
21507 // encountered during execution of any of the worksharing regions arising
21508 // from the worksharing construct.
21509 if (isOpenMPTaskingDirective(CurrDir)) {
21510 DVar = DSAStack->hasInnermostDSA(
21511 D,
21512 [](OpenMPClauseKind C, bool AppliedToPointee) {
21513 return C == OMPC_reduction && !AppliedToPointee;
21514 },
21515 [](OpenMPDirectiveKind K) {
21516 return isOpenMPParallelDirective(K) ||
21519 },
21520 /*FromParent=*/true);
21521 if (DVar.CKind == OMPC_reduction &&
21522 (isOpenMPParallelDirective(DVar.DKind) ||
21523 isOpenMPWorksharingDirective(DVar.DKind) ||
21524 isOpenMPTeamsDirective(DVar.DKind))) {
21525 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
21526 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
21528 continue;
21529 }
21530 }
21531
21532 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
21533 // A list item cannot appear in both a map clause and a data-sharing
21534 // attribute clause on the same construct
21535 //
21536 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
21537 // A list item cannot appear in both a map clause and a data-sharing
21538 // attribute clause on the same construct unless the construct is a
21539 // combined construct.
21540 if ((getLangOpts().OpenMP <= 45 &&
21542 CurrDir == OMPD_target) {
21543 OpenMPClauseKind ConflictKind;
21544 if (DSAStack->checkMappableExprComponentListsForDecl(
21545 VD, /*CurrentRegionOnly=*/true,
21546 [&ConflictKind](
21548 OpenMPClauseKind WhereFoundClauseKind) {
21549 ConflictKind = WhereFoundClauseKind;
21550 return true;
21551 })) {
21552 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
21553 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
21554 << getOpenMPClauseNameForDiag(ConflictKind)
21555 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21556 OMPVersion);
21558 continue;
21559 }
21560 }
21561 }
21562
21563 // Variably modified types are not supported for tasks.
21565 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
21566 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21567 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
21568 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21569 OMPVersion);
21570 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21572 Diag(D->getLocation(),
21573 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21574 << D;
21575 continue;
21576 }
21577
21578 Type = Type.getUnqualifiedType();
21579
21580 // For BindingDecls, use the DecompositionDecl's type so all bindings from
21581 // the same decomposition are accessible in the privatized region. We do
21582 // this after conflict checking to preserve diagnostic errors. Don't modify
21583 // RefExpr/SimpleRefExpr to keep diagnostics working.
21584 bool IsBindingDecl = isa<BindingDecl>(D);
21585 VarDecl *PrivateVD = VD;
21586 QualType PrivateType = Type;
21587 if (IsBindingDecl) {
21588 const auto *BD = cast<BindingDecl>(D);
21589 PrivateVD = cast<VarDecl>(BD->getDecomposedDecl());
21590 // PrivateType stays as the BindingDecl's type (Type), not the
21591 // DecompositionDecl's type.
21592 }
21593
21594 // For regular arrays, pass the original var ref. For BindingDecls, don't
21595 // pass the DecompositionDecl ref since VDPrivate has the binding's type,
21596 // not the decomposition type.
21597 VarDecl *VDPrivate = buildVarDecl(SemaRef, ELoc, PrivateType, D->getName(),
21598 D->hasAttrs() ? &D->getAttrs() : nullptr,
21599 (PrivateVD && !IsBindingDecl)
21600 ? cast<DeclRefExpr>(SimpleRefExpr)
21601 : nullptr);
21602
21603 // Generate helper private variable and initialize it with the value of the
21604 // original variable. The address of the original variable is replaced by
21605 // the address of the new private variable in the CodeGen. This new variable
21606 // is not added to IdResolver, so the code in the OpenMP region uses
21607 // original variable for proper diagnostics and variable capturing.
21608 Expr *VDInitRefExpr = nullptr;
21609
21610 // For BindingDecls, VDPrivate should have the binding's type (not the
21611 // DecompositionDecl's type), and will be initialized from the binding's
21612 // field in the original DecompositionDecl.
21613 if (IsBindingDecl && !PrivateType->isArrayType()) {
21614 // For non-array bindings, create a simple copy initialization.
21615 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
21616 PrivateType, ".firstprivate.temp");
21617 VDInitRefExpr =
21618 buildDeclRefExpr(SemaRef, VDInit, PrivateType, RefExpr->getExprLoc());
21619
21620 // Initialize VDPrivate from VDInit (which will point to the field).
21621 SemaRef.AddInitializerToDecl(
21622 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
21623 /*DirectInit=*/false);
21624 } else if (Type->isArrayType()) {
21625 // For arrays generate initializer for single element and replace it by
21626 // the original array element in CodeGen.
21627 VarDecl *VDInit =
21628 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
21629 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
21630 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
21631 ElemType = ElemType.getUnqualifiedType();
21632 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
21633 ElemType, ".firstprivate.temp");
21634 InitializedEntity Entity =
21637
21638 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
21639 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
21640 if (Result.isInvalid())
21641 VDPrivate->setInvalidDecl();
21642 else
21643 VDPrivate->setInit(Result.getAs<Expr>());
21644 // Remove temp variable declaration.
21645 getASTContext().Deallocate(VDInitTemp);
21646 } else {
21647 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
21648 ".firstprivate.temp");
21649 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
21650 RefExpr->getExprLoc());
21651 SemaRef.AddInitializerToDecl(
21652 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
21653 /*DirectInit=*/false);
21654 }
21655 if (VDPrivate->isInvalidDecl()) {
21656 if (IsImplicitClause) {
21657 Diag(RefExpr->getExprLoc(),
21658 diag::note_omp_task_predetermined_firstprivate_here);
21659 }
21660 continue;
21661 }
21662 SemaRef.CurContext->addDecl(VDPrivate);
21663 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
21664 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
21665 RefExpr->getExprLoc());
21666 DeclRefExpr *Ref = nullptr;
21667 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21668 if (TopDVar.CKind == OMPC_lastprivate) {
21669 Ref = TopDVar.PrivateCopy;
21670 } else if (!IsBindingDecl) {
21671 auto *FD = dyn_cast<FieldDecl>(D);
21672 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
21673 if (VD)
21674 Ref =
21676 RefExpr->getExprLoc());
21677 else
21678 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21679 if (VD || !isOpenMPCapturedDecl(D))
21680 ExprCaptures.push_back(Ref->getDecl());
21681 }
21682 }
21683 if (!IsImplicitClause)
21684 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
21685 Vars.push_back(
21686 (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
21687 ? RefExpr->IgnoreParens()
21688 : Ref);
21689 PrivateCopies.push_back(VDPrivateRefExpr);
21690 Inits.push_back(VDInitRefExpr);
21691 }
21692
21693 if (Vars.empty())
21694 return nullptr;
21695
21696 return OMPFirstprivateClause::Create(
21697 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
21698 buildPreInits(getASTContext(), ExprCaptures));
21699}
21700
21703 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
21704 SourceLocation LParenLoc, SourceLocation EndLoc) {
21705 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
21706 assert(ColonLoc.isValid() && "Colon location must be valid.");
21707 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
21708 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
21709 /*Last=*/OMPC_LASTPRIVATE_unknown)
21710 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
21711 return nullptr;
21712 }
21713
21715 SmallVector<Expr *, 8> SrcExprs;
21716 SmallVector<Expr *, 8> DstExprs;
21717 SmallVector<Expr *, 8> AssignmentOps;
21718 SmallVector<Decl *, 4> ExprCaptures;
21719 SmallVector<Expr *, 4> ExprPostUpdates;
21720 for (Expr *RefExpr : VarList) {
21721 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
21722 SourceLocation ELoc;
21723 SourceRange ERange;
21724 Expr *SimpleRefExpr = RefExpr;
21725 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21726 if (Res.second) {
21727 // It will be analyzed later.
21728 Vars.push_back(RefExpr);
21729 SrcExprs.push_back(nullptr);
21730 DstExprs.push_back(nullptr);
21731 AssignmentOps.push_back(nullptr);
21732 }
21733 ValueDecl *D = Res.first;
21734 if (!D)
21735 continue;
21736
21737 QualType Type = D->getType();
21738 auto *VD = dyn_cast<VarDecl>(D);
21739
21740 // Structured bindings with conditional modifier are currently not
21741 // supported.
21742 if (LPKind == OMPC_LASTPRIVATE_conditional && isa<BindingDecl>(D)) {
21743 Diag(ELoc, diag::err_omp_unsupported_on_binding) << 1;
21744 Diag(D->getLocation(), diag::note_defined_here) << D;
21745 continue;
21746 }
21747
21748 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
21749 // A variable that appears in a lastprivate clause must not have an
21750 // incomplete type or a reference type.
21751 if (SemaRef.RequireCompleteType(ELoc, Type,
21752 diag::err_omp_lastprivate_incomplete_type))
21753 continue;
21754 Type = Type.getNonReferenceType();
21755
21756 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
21757 // A variable that is privatized must not have a const-qualified type
21758 // unless it is of class type with a mutable member. This restriction does
21759 // not apply to the firstprivate clause.
21760 //
21761 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
21762 // A variable that appears in a lastprivate clause must not have a
21763 // const-qualified type unless it is of class type with a mutable member.
21764 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
21765 continue;
21766
21767 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
21768 // A list item that appears in a lastprivate clause with the conditional
21769 // modifier must be a scalar variable.
21770 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
21771 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
21772 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21774 Diag(D->getLocation(),
21775 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21776 << D;
21777 continue;
21778 }
21779
21780 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
21781 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
21782 // in a Construct]
21783 // Variables with the predetermined data-sharing attributes may not be
21784 // listed in data-sharing attributes clauses, except for the cases
21785 // listed below.
21786 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
21787 // A list item may appear in a firstprivate or lastprivate clause but not
21788 // both.
21789 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21790 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
21791 (isOpenMPDistributeDirective(CurrDir) ||
21792 DVar.CKind != OMPC_firstprivate) &&
21793 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
21794 Diag(ELoc, diag::err_omp_wrong_dsa)
21795 << getOpenMPClauseNameForDiag(DVar.CKind)
21796 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
21798 continue;
21799 }
21800
21801 // OpenMP [2.14.3.5, Restrictions, p.2]
21802 // A list item that is private within a parallel region, or that appears in
21803 // the reduction clause of a parallel construct, must not appear in a
21804 // lastprivate clause on a worksharing construct if any of the corresponding
21805 // worksharing regions ever binds to any of the corresponding parallel
21806 // regions.
21807 DSAStackTy::DSAVarData TopDVar = DVar;
21808 if (isOpenMPWorksharingDirective(CurrDir) &&
21809 !isOpenMPParallelDirective(CurrDir) &&
21810 !isOpenMPTeamsDirective(CurrDir)) {
21811 DVar = DSAStack->getImplicitDSA(D, true);
21812 if (DVar.CKind != OMPC_shared) {
21813 Diag(ELoc, diag::err_omp_required_access)
21814 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
21815 << getOpenMPClauseNameForDiag(OMPC_shared);
21817 continue;
21818 }
21819 }
21820
21821 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
21822 // A variable of class type (or array thereof) that appears in a
21823 // lastprivate clause requires an accessible, unambiguous default
21824 // constructor for the class type, unless the list item is also specified
21825 // in a firstprivate clause.
21826 // A variable of class type (or array thereof) that appears in a
21827 // lastprivate clause requires an accessible, unambiguous copy assignment
21828 // operator for the class type.
21830 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
21831 Type.getUnqualifiedType(), ".lastprivate.src",
21832 D->hasAttrs() ? &D->getAttrs() : nullptr);
21833 DeclRefExpr *PseudoSrcExpr =
21834 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
21835 VarDecl *DstVD =
21836 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
21837 D->hasAttrs() ? &D->getAttrs() : nullptr);
21838 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21839 // For arrays generate assignment operation for single element and replace
21840 // it by the original array element in CodeGen.
21841 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
21842 PseudoDstExpr, PseudoSrcExpr);
21843 if (AssignmentOp.isInvalid())
21844 continue;
21845 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
21846 /*DiscardedValue=*/false);
21847 if (AssignmentOp.isInvalid())
21848 continue;
21849
21850 DeclRefExpr *Ref = nullptr;
21851 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21852 if (TopDVar.CKind == OMPC_firstprivate) {
21853 Ref = TopDVar.PrivateCopy;
21854 } else {
21855 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
21856 if (!isOpenMPCapturedDecl(D))
21857 ExprCaptures.push_back(Ref->getDecl());
21858 }
21859 if (Ref &&
21860 ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
21861 (!isOpenMPCapturedDecl(D) &&
21862 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()))) {
21863 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
21864 if (!RefRes.isUsable())
21865 continue;
21866 ExprResult PostUpdateRes =
21867 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
21868 SimpleRefExpr, RefRes.get());
21869 if (!PostUpdateRes.isUsable())
21870 continue;
21871 ExprPostUpdates.push_back(
21872 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
21873 }
21874 }
21875 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
21876 bool IsBindingDecl = isa<BindingDecl>(D);
21877 Vars.push_back(
21878 (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
21879 ? RefExpr->IgnoreParens()
21880 : Ref);
21881 SrcExprs.push_back(PseudoSrcExpr);
21882 DstExprs.push_back(PseudoDstExpr);
21883 AssignmentOps.push_back(AssignmentOp.get());
21884 }
21885
21886 if (Vars.empty())
21887 return nullptr;
21888
21889 return OMPLastprivateClause::Create(
21890 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
21891 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
21892 buildPreInits(getASTContext(), ExprCaptures),
21893 buildPostUpdate(SemaRef, ExprPostUpdates));
21894}
21895
21897 SourceLocation StartLoc,
21898 SourceLocation LParenLoc,
21899 SourceLocation EndLoc) {
21901 for (Expr *RefExpr : VarList) {
21902 assert(RefExpr && "NULL expr in OpenMP shared clause.");
21903 SourceLocation ELoc;
21904 SourceRange ERange;
21905 Expr *SimpleRefExpr = RefExpr;
21906 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21907 if (Res.second) {
21908 // It will be analyzed later.
21909 Vars.push_back(RefExpr);
21910 }
21911 ValueDecl *D = Res.first;
21912 if (!D)
21913 continue;
21914
21915 auto *VD = dyn_cast<VarDecl>(D);
21916 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
21917 // in a Construct]
21918 // Variables with the predetermined data-sharing attributes may not be
21919 // listed in data-sharing attributes clauses, except for the cases
21920 // listed below. For these exceptions only, listing a predetermined
21921 // variable in a data-sharing attribute clause is allowed and overrides
21922 // the variable's predetermined data-sharing attributes.
21923 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21924 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
21925 DVar.RefExpr) {
21926 Diag(ELoc, diag::err_omp_wrong_dsa)
21927 << getOpenMPClauseNameForDiag(DVar.CKind)
21928 << getOpenMPClauseNameForDiag(OMPC_shared);
21930 continue;
21931 }
21932
21933 DeclRefExpr *Ref = nullptr;
21934 if (!VD && isOpenMPCapturedDecl(D) &&
21935 !SemaRef.CurContext->isDependentContext())
21936 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21937 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
21938 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
21939 ? RefExpr->IgnoreParens()
21940 : Ref);
21941 }
21942
21943 if (Vars.empty())
21944 return nullptr;
21945
21946 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21947 Vars);
21948}
21949
21950namespace {
21951class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
21952 DSAStackTy *Stack;
21953
21954public:
21955 bool VisitDeclRefExpr(DeclRefExpr *E) {
21956 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
21957 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
21958 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
21959 return false;
21960 if (DVar.CKind != OMPC_unknown)
21961 return true;
21962 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
21963 VD,
21964 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
21965 return isOpenMPPrivate(C) && !AppliedToPointee;
21966 },
21967 [](OpenMPDirectiveKind) { return true; },
21968 /*FromParent=*/true);
21969 return DVarPrivate.CKind != OMPC_unknown;
21970 }
21971 return false;
21972 }
21973 bool VisitStmt(Stmt *S) {
21974 for (Stmt *Child : S->children()) {
21975 if (Child && Visit(Child))
21976 return true;
21977 }
21978 return false;
21979 }
21980 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
21981};
21982} // namespace
21983
21984namespace {
21985// Transform MemberExpression for specified FieldDecl of current class to
21986// DeclRefExpr to specified OMPCapturedExprDecl.
21987class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
21988 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
21989 ValueDecl *Field = nullptr;
21990 DeclRefExpr *CapturedExpr = nullptr;
21991
21992public:
21993 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
21994 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
21995
21996 ExprResult TransformMemberExpr(MemberExpr *E) {
21998 E->getMemberDecl() == Field) {
21999 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
22000 return CapturedExpr;
22001 }
22002 return BaseTransform::TransformMemberExpr(E);
22003 }
22004 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
22005};
22006} // namespace
22007
22008template <typename T, typename U>
22010 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
22011 for (U &Set : Lookups) {
22012 for (auto *D : Set) {
22013 if (T Res = Gen(cast<ValueDecl>(D)))
22014 return Res;
22015 }
22016 }
22017 return T();
22018}
22019
22021 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
22022
22023 for (auto *RD : D->redecls()) {
22024 // Don't bother with extra checks if we already know this one isn't visible.
22025 if (RD == D)
22026 continue;
22027
22028 auto ND = cast<NamedDecl>(RD);
22029 if (LookupResult::isVisible(SemaRef, ND))
22030 return ND;
22031 }
22032
22033 return nullptr;
22034}
22035
22036static void
22038 SourceLocation Loc, QualType Ty,
22040 // Find all of the associated namespaces and classes based on the
22041 // arguments we have.
22042 Sema::AssociatedNamespaceSet AssociatedNamespaces;
22043 Sema::AssociatedClassSet AssociatedClasses;
22044 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
22045 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
22046 AssociatedClasses);
22047
22048 // C++ [basic.lookup.argdep]p3:
22049 // Let X be the lookup set produced by unqualified lookup (3.4.1)
22050 // and let Y be the lookup set produced by argument dependent
22051 // lookup (defined as follows). If X contains [...] then Y is
22052 // empty. Otherwise Y is the set of declarations found in the
22053 // namespaces associated with the argument types as described
22054 // below. The set of declarations found by the lookup of the name
22055 // is the union of X and Y.
22056 //
22057 // Here, we compute Y and add its members to the overloaded
22058 // candidate set.
22059 for (auto *NS : AssociatedNamespaces) {
22060 // When considering an associated namespace, the lookup is the
22061 // same as the lookup performed when the associated namespace is
22062 // used as a qualifier (3.4.3.2) except that:
22063 //
22064 // -- Any using-directives in the associated namespace are
22065 // ignored.
22066 //
22067 // -- Any namespace-scope friend functions declared in
22068 // associated classes are visible within their respective
22069 // namespaces even if they are not visible during an ordinary
22070 // lookup (11.4).
22071 DeclContext::lookup_result R = NS->lookup(Id.getName());
22072 for (auto *D : R) {
22073 auto *Underlying = D;
22074 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
22075 Underlying = USD->getTargetDecl();
22076
22077 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
22078 !isa<OMPDeclareMapperDecl>(Underlying))
22079 continue;
22080
22081 if (!SemaRef.isVisible(D)) {
22082 D = findAcceptableDecl(SemaRef, D);
22083 if (!D)
22084 continue;
22085 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
22086 Underlying = USD->getTargetDecl();
22087 }
22088 Lookups.emplace_back();
22089 Lookups.back().addDecl(Underlying);
22090 }
22091 }
22092}
22093
22094static ExprResult
22096 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
22097 const DeclarationNameInfo &ReductionId, QualType Ty,
22098 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
22099 if (ReductionIdScopeSpec.isInvalid())
22100 return ExprError();
22101 SmallVector<UnresolvedSet<8>, 4> Lookups;
22102 if (S) {
22103 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
22104 Lookup.suppressDiagnostics();
22105 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
22106 /*ObjectType=*/QualType())) {
22107 NamedDecl *D = Lookup.getRepresentativeDecl();
22108 do {
22109 S = S->getParent();
22110 } while (S && !S->isDeclScope(D));
22111 if (S)
22112 S = S->getParent();
22113 Lookups.emplace_back();
22114 Lookups.back().append(Lookup.begin(), Lookup.end());
22115 Lookup.clear();
22116 }
22117 } else if (auto *ULE =
22118 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
22119 Lookups.push_back(UnresolvedSet<8>());
22120 Decl *PrevD = nullptr;
22121 for (NamedDecl *D : ULE->decls()) {
22122 if (D == PrevD)
22123 Lookups.push_back(UnresolvedSet<8>());
22124 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
22125 Lookups.back().addDecl(DRD);
22126 PrevD = D;
22127 }
22128 }
22129 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
22133 return !D->isInvalidDecl() &&
22134 (D->getType()->isDependentType() ||
22135 D->getType()->isInstantiationDependentType() ||
22136 D->getType()->containsUnexpandedParameterPack());
22137 })) {
22138 UnresolvedSet<8> ResSet;
22139 for (const UnresolvedSet<8> &Set : Lookups) {
22140 if (Set.empty())
22141 continue;
22142 ResSet.append(Set.begin(), Set.end());
22143 // The last item marks the end of all declarations at the specified scope.
22144 ResSet.addDecl(Set[Set.size() - 1]);
22145 }
22147 SemaRef.Context, /*NamingClass=*/nullptr,
22148 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
22149 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
22150 /*KnownInstantiationDependent=*/false);
22151 }
22152 // Lookup inside the classes.
22153 // C++ [over.match.oper]p3:
22154 // For a unary operator @ with an operand of a type whose
22155 // cv-unqualified version is T1, and for a binary operator @ with
22156 // a left operand of a type whose cv-unqualified version is T1 and
22157 // a right operand of a type whose cv-unqualified version is T2,
22158 // three sets of candidate functions, designated member
22159 // candidates, non-member candidates and built-in candidates, are
22160 // constructed as follows:
22161 // -- If T1 is a complete class type or a class currently being
22162 // defined, the set of member candidates is the result of the
22163 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
22164 // the set of member candidates is empty.
22165 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
22166 Lookup.suppressDiagnostics();
22167 if (Ty->isRecordType()) {
22168 // Complete the type if it can be completed.
22169 // If the type is neither complete nor being defined, bail out now.
22170 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
22171 auto *RD = Ty->castAsRecordDecl();
22172 if (IsComplete || RD->isBeingDefined()) {
22173 Lookup.clear();
22174 SemaRef.LookupQualifiedName(Lookup, RD);
22175 if (Lookup.empty()) {
22176 Lookups.emplace_back();
22177 Lookups.back().append(Lookup.begin(), Lookup.end());
22178 }
22179 }
22180 }
22181 // Perform ADL.
22182 if (SemaRef.getLangOpts().CPlusPlus)
22183 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
22185 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
22186 if (!D->isInvalidDecl() &&
22187 SemaRef.Context.hasSameType(D->getType(), Ty))
22188 return D;
22189 return nullptr;
22190 }))
22191 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
22192 VK_LValue, Loc);
22193 if (SemaRef.getLangOpts().CPlusPlus) {
22195 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
22196 if (!D->isInvalidDecl() &&
22197 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
22199 SemaRef.getASTContext()))
22200 return D;
22201 return nullptr;
22202 })) {
22203 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22204 /*DetectVirtual=*/false);
22205 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
22206 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22207 VD->getType().getUnqualifiedType()))) {
22208 if (SemaRef.CheckBaseClassAccess(
22209 Loc, VD->getType(), Ty, Paths.front(),
22210 /*DiagID=*/0) != Sema::AR_inaccessible) {
22211 SemaRef.BuildBasePathArray(Paths, BasePath);
22212 return SemaRef.BuildDeclRefExpr(
22213 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
22214 }
22215 }
22216 }
22217 }
22218 }
22219 if (ReductionIdScopeSpec.isSet()) {
22220 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
22221 << Ty << Range;
22222 return ExprError();
22223 }
22224 return ExprEmpty();
22225}
22226
22227namespace {
22228/// Data for the reduction-based clauses.
22229struct ReductionData {
22230 /// List of original reduction items.
22231 SmallVector<Expr *, 8> Vars;
22232 /// List of private copies of the reduction items.
22233 SmallVector<Expr *, 8> Privates;
22234 /// LHS expressions for the reduction_op expressions.
22235 SmallVector<Expr *, 8> LHSs;
22236 /// RHS expressions for the reduction_op expressions.
22237 SmallVector<Expr *, 8> RHSs;
22238 /// Reduction operation expression.
22239 SmallVector<Expr *, 8> ReductionOps;
22240 /// inscan copy operation expressions.
22241 SmallVector<Expr *, 8> InscanCopyOps;
22242 /// inscan copy temp array expressions for prefix sums.
22243 SmallVector<Expr *, 8> InscanCopyArrayTemps;
22244 /// inscan copy temp array element expressions for prefix sums.
22245 SmallVector<Expr *, 8> InscanCopyArrayElems;
22246 /// Taskgroup descriptors for the corresponding reduction items in
22247 /// in_reduction clauses.
22248 SmallVector<Expr *, 8> TaskgroupDescriptors;
22249 /// List of captures for clause.
22250 SmallVector<Decl *, 4> ExprCaptures;
22251 /// List of postupdate expressions.
22252 SmallVector<Expr *, 4> ExprPostUpdates;
22253 /// Reduction modifier.
22254 unsigned RedModifier = 0;
22255 /// Original modifier.
22256 unsigned OrigSharingModifier = 0;
22257 /// Private Variable Reduction
22258 SmallVector<bool, 8> IsPrivateVarReduction;
22259 ReductionData() = delete;
22260 /// Reserves required memory for the reduction data.
22261 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
22262 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
22263 Vars.reserve(Size);
22264 Privates.reserve(Size);
22265 LHSs.reserve(Size);
22266 RHSs.reserve(Size);
22267 ReductionOps.reserve(Size);
22268 IsPrivateVarReduction.reserve(Size);
22269 if (RedModifier == OMPC_REDUCTION_inscan) {
22270 InscanCopyOps.reserve(Size);
22271 InscanCopyArrayTemps.reserve(Size);
22272 InscanCopyArrayElems.reserve(Size);
22273 }
22274 TaskgroupDescriptors.reserve(Size);
22275 ExprCaptures.reserve(Size);
22276 ExprPostUpdates.reserve(Size);
22277 }
22278 /// Stores reduction item and reduction operation only (required for dependent
22279 /// reduction item).
22280 void push(Expr *Item, Expr *ReductionOp) {
22281 Vars.emplace_back(Item);
22282 Privates.emplace_back(nullptr);
22283 LHSs.emplace_back(nullptr);
22284 RHSs.emplace_back(nullptr);
22285 ReductionOps.emplace_back(ReductionOp);
22286 IsPrivateVarReduction.emplace_back(false);
22287 TaskgroupDescriptors.emplace_back(nullptr);
22288 if (RedModifier == OMPC_REDUCTION_inscan) {
22289 InscanCopyOps.push_back(nullptr);
22290 InscanCopyArrayTemps.push_back(nullptr);
22291 InscanCopyArrayElems.push_back(nullptr);
22292 }
22293 }
22294 /// Stores reduction data.
22295 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
22296 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
22297 Expr *CopyArrayElem, bool IsPrivate) {
22298 Vars.emplace_back(Item);
22299 Privates.emplace_back(Private);
22300 LHSs.emplace_back(LHS);
22301 RHSs.emplace_back(RHS);
22302 ReductionOps.emplace_back(ReductionOp);
22303 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
22304 if (RedModifier == OMPC_REDUCTION_inscan) {
22305 InscanCopyOps.push_back(CopyOp);
22306 InscanCopyArrayTemps.push_back(CopyArrayTemp);
22307 InscanCopyArrayElems.push_back(CopyArrayElem);
22308 } else {
22309 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
22310 CopyArrayElem == nullptr &&
22311 "Copy operation must be used for inscan reductions only.");
22312 }
22313 IsPrivateVarReduction.emplace_back(IsPrivate);
22314 }
22315};
22316} // namespace
22317
22319 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
22320 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
22321 const Expr *Length = OASE->getLength();
22322 if (Length == nullptr) {
22323 // For array sections of the form [1:] or [:], we would need to analyze
22324 // the lower bound...
22325 if (OASE->getColonLocFirst().isValid())
22326 return false;
22327
22328 // This is an array subscript which has implicit length 1!
22329 SingleElement = true;
22330 ArraySizes.push_back(llvm::APSInt::get(1));
22331 } else {
22333 if (!Length->EvaluateAsInt(Result, Context))
22334 return false;
22335
22336 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
22337 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
22338 ArraySizes.push_back(ConstantLengthValue);
22339 }
22340
22341 // Get the base of this array section and walk up from there.
22342 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
22343
22344 // We require length = 1 for all array sections except the right-most to
22345 // guarantee that the memory region is contiguous and has no holes in it.
22346 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
22347 Length = TempOASE->getLength();
22348 if (Length == nullptr) {
22349 // For array sections of the form [1:] or [:], we would need to analyze
22350 // the lower bound...
22351 if (OASE->getColonLocFirst().isValid())
22352 return false;
22353
22354 // This is an array subscript which has implicit length 1!
22355 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
22356 ArraySizes.push_back(ConstantOne);
22357 } else {
22359 if (!Length->EvaluateAsInt(Result, Context))
22360 return false;
22361
22362 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
22363 if (ConstantLengthValue.getSExtValue() != 1)
22364 return false;
22365
22366 ArraySizes.push_back(ConstantLengthValue);
22367 }
22368 Base = TempOASE->getBase()->IgnoreParenImpCasts();
22369 }
22370
22371 // If we have a single element, we don't need to add the implicit lengths.
22372 if (!SingleElement) {
22373 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
22374 // Has implicit length 1!
22375 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
22376 ArraySizes.push_back(ConstantOne);
22377 Base = TempASE->getBase()->IgnoreParenImpCasts();
22378 }
22379 }
22380
22381 // This array section can be privatized as a single value or as a constant
22382 // sized array.
22383 return true;
22384}
22385
22386static BinaryOperatorKind
22388 if (BOK == BO_Add)
22389 return BO_AddAssign;
22390 if (BOK == BO_Mul)
22391 return BO_MulAssign;
22392 if (BOK == BO_And)
22393 return BO_AndAssign;
22394 if (BOK == BO_Or)
22395 return BO_OrAssign;
22396 if (BOK == BO_Xor)
22397 return BO_XorAssign;
22398 return BOK;
22399}
22400
22402 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
22403 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
22404 SourceLocation ColonLoc, SourceLocation EndLoc,
22405 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
22406 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
22407 DeclarationName DN = ReductionId.getName();
22409 BinaryOperatorKind BOK = BO_Comma;
22410
22411 ASTContext &Context = S.Context;
22412 // OpenMP [2.14.3.6, reduction clause]
22413 // C
22414 // reduction-identifier is either an identifier or one of the following
22415 // operators: +, -, *, &, |, ^, && and ||
22416 // C++
22417 // reduction-identifier is either an id-expression or one of the following
22418 // operators: +, -, *, &, |, ^, && and ||
22419 switch (OOK) {
22420 case OO_Plus:
22421 BOK = BO_Add;
22422 break;
22423 case OO_Minus:
22424 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
22425 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
22426 // reduction identifier.
22427 if (S.LangOpts.OpenMP > 52)
22428 BOK = BO_Comma;
22429 else
22430 BOK = BO_Add;
22431 break;
22432 case OO_Star:
22433 BOK = BO_Mul;
22434 break;
22435 case OO_Amp:
22436 BOK = BO_And;
22437 break;
22438 case OO_Pipe:
22439 BOK = BO_Or;
22440 break;
22441 case OO_Caret:
22442 BOK = BO_Xor;
22443 break;
22444 case OO_AmpAmp:
22445 BOK = BO_LAnd;
22446 break;
22447 case OO_PipePipe:
22448 BOK = BO_LOr;
22449 break;
22450 case OO_New:
22451 case OO_Delete:
22452 case OO_Array_New:
22453 case OO_Array_Delete:
22454 case OO_Slash:
22455 case OO_Percent:
22456 case OO_Tilde:
22457 case OO_Exclaim:
22458 case OO_Equal:
22459 case OO_Less:
22460 case OO_Greater:
22461 case OO_LessEqual:
22462 case OO_GreaterEqual:
22463 case OO_PlusEqual:
22464 case OO_MinusEqual:
22465 case OO_StarEqual:
22466 case OO_SlashEqual:
22467 case OO_PercentEqual:
22468 case OO_CaretEqual:
22469 case OO_AmpEqual:
22470 case OO_PipeEqual:
22471 case OO_LessLess:
22472 case OO_GreaterGreater:
22473 case OO_LessLessEqual:
22474 case OO_GreaterGreaterEqual:
22475 case OO_EqualEqual:
22476 case OO_ExclaimEqual:
22477 case OO_Spaceship:
22478 case OO_PlusPlus:
22479 case OO_MinusMinus:
22480 case OO_Comma:
22481 case OO_ArrowStar:
22482 case OO_Arrow:
22483 case OO_Call:
22484 case OO_Subscript:
22485 case OO_Conditional:
22486 case OO_Coawait:
22488 llvm_unreachable("Unexpected reduction identifier");
22489 case OO_None:
22490 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
22491 if (II->isStr("max"))
22492 BOK = BO_GT;
22493 else if (II->isStr("min"))
22494 BOK = BO_LT;
22495 }
22496 break;
22497 }
22498
22499 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
22500 // A reduction clause with the minus (-) operator was deprecated
22501 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
22502 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
22503
22504 SourceRange ReductionIdRange;
22505 if (ReductionIdScopeSpec.isValid())
22506 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
22507 else
22508 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
22509 ReductionIdRange.setEnd(ReductionId.getEndLoc());
22510
22511 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
22512 bool FirstIter = true;
22513 for (Expr *RefExpr : VarList) {
22514 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
22515 // OpenMP [2.1, C/C++]
22516 // A list item is a variable or array section, subject to the restrictions
22517 // specified in Section 2.4 on page 42 and in each of the sections
22518 // describing clauses and directives for which a list appears.
22519 // OpenMP [2.14.3.3, Restrictions, p.1]
22520 // A variable that is part of another variable (as an array or
22521 // structure element) cannot appear in a private clause.
22522 if (!FirstIter && IR != ER)
22523 ++IR;
22524 FirstIter = false;
22525 SourceLocation ELoc;
22526 SourceRange ERange;
22527 bool IsPrivate = false;
22528 Expr *SimpleRefExpr = RefExpr;
22529 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
22530 /*AllowArraySection=*/true);
22531 if (Res.second) {
22532 // Try to find 'declare reduction' corresponding construct before using
22533 // builtin/overloaded operators.
22534 QualType Type = Context.DependentTy;
22535 CXXCastPath BasePath;
22536 ExprResult DeclareReductionRef = buildDeclareReductionRef(
22537 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
22538 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
22539 Expr *ReductionOp = nullptr;
22540 if (S.CurContext->isDependentContext() &&
22541 (DeclareReductionRef.isUnset() ||
22542 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
22543 ReductionOp = DeclareReductionRef.get();
22544 // It will be analyzed later.
22545 RD.push(RefExpr, ReductionOp);
22546 }
22547 ValueDecl *D = Res.first;
22548 if (!D)
22549 continue;
22550
22551 Expr *TaskgroupDescriptor = nullptr;
22552 QualType Type;
22553 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
22554 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
22555 if (ASE) {
22556 Type = ASE->getType().getNonReferenceType();
22557 } else if (OASE) {
22558 QualType BaseType =
22560 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
22561 Type = ATy->getElementType();
22562 else
22563 Type = BaseType->getPointeeType();
22564 Type = Type.getNonReferenceType();
22565 } else {
22566 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
22567 }
22568 auto *VD = dyn_cast<VarDecl>(D);
22569
22570 auto *BD = dyn_cast<BindingDecl>(D);
22571 if (BD) {
22572 // FIXME: reductions on bindings are rejected.
22573 S.Diag(ELoc, diag::err_omp_unsupported_on_binding) << 0;
22574 continue;
22575 }
22576
22577 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
22578 // A variable that appears in a private clause must not have an incomplete
22579 // type or a reference type.
22580 if (S.RequireCompleteType(ELoc, D->getType(),
22581 diag::err_omp_reduction_incomplete_type))
22582 continue;
22583 // OpenMP [2.14.3.6, reduction clause, Restrictions]
22584 // A list item that appears in a reduction clause must not be
22585 // const-qualified.
22586 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
22587 /*AcceptIfMutable=*/false, ASE || OASE))
22588 continue;
22589
22590 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
22591 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
22592 // If a list-item is a reference type then it must bind to the same object
22593 // for all threads of the team.
22594 if (!ASE && !OASE) {
22595 if (VD) {
22596 VarDecl *VDDef = VD->getDefinition();
22597 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
22598 DSARefChecker Check(Stack);
22599 if (Check.Visit(VDDef->getInit())) {
22600 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
22601 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
22602 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
22603 continue;
22604 }
22605 }
22606 }
22607
22608 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
22609 // in a Construct]
22610 // Variables with the predetermined data-sharing attributes may not be
22611 // listed in data-sharing attributes clauses, except for the cases
22612 // listed below. For these exceptions only, listing a predetermined
22613 // variable in a data-sharing attribute clause is allowed and overrides
22614 // the variable's predetermined data-sharing attributes.
22615 // OpenMP [2.14.3.6, Restrictions, p.3]
22616 // Any number of reduction clauses can be specified on the directive,
22617 // but a list item can appear only once in the reduction clauses for that
22618 // directive.
22619 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
22620 if (DVar.CKind == OMPC_reduction) {
22621 S.Diag(ELoc, diag::err_omp_once_referenced)
22622 << getOpenMPClauseNameForDiag(ClauseKind);
22623 if (DVar.RefExpr)
22624 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
22625 continue;
22626 }
22627 if (DVar.CKind != OMPC_unknown) {
22628 S.Diag(ELoc, diag::err_omp_wrong_dsa)
22629 << getOpenMPClauseNameForDiag(DVar.CKind)
22630 << getOpenMPClauseNameForDiag(OMPC_reduction);
22631 reportOriginalDsa(S, Stack, D, DVar);
22632 continue;
22633 }
22634
22635 // OpenMP [2.14.3.6, Restrictions, p.1]
22636 // A list item that appears in a reduction clause of a worksharing
22637 // construct must be shared in the parallel regions to which any of the
22638 // worksharing regions arising from the worksharing construct bind.
22639
22640 if (S.getLangOpts().OpenMP <= 52 &&
22642 !isOpenMPParallelDirective(CurrDir) &&
22643 !isOpenMPTeamsDirective(CurrDir)) {
22644 DVar = Stack->getImplicitDSA(D, true);
22645 if (DVar.CKind != OMPC_shared) {
22646 S.Diag(ELoc, diag::err_omp_required_access)
22647 << getOpenMPClauseNameForDiag(OMPC_reduction)
22648 << getOpenMPClauseNameForDiag(OMPC_shared);
22649 reportOriginalDsa(S, Stack, D, DVar);
22650 continue;
22651 }
22652 } else if (isOpenMPWorksharingDirective(CurrDir) &&
22653 !isOpenMPParallelDirective(CurrDir) &&
22654 !isOpenMPTeamsDirective(CurrDir)) {
22655 // OpenMP 6.0 [ 7.6.10 ]
22656 // Support Reduction over private variables with reduction clause.
22657 // A list item in a reduction clause can now be private in the enclosing
22658 // context. For orphaned constructs it is assumed to be shared unless
22659 // the original(private) modifier appears in the clause.
22660 DVar = Stack->getImplicitDSA(D, true);
22661 // Determine if the variable should be considered private
22662 IsPrivate = DVar.CKind != OMPC_shared;
22663 bool IsOrphaned = false;
22664 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
22665 IsOrphaned = ParentDir == OMPD_unknown;
22666 if ((IsOrphaned &&
22667 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
22668 IsPrivate = true;
22669 }
22670 } else {
22671 // Threadprivates cannot be shared between threads, so dignose if the base
22672 // is a threadprivate variable.
22673 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
22674 if (DVar.CKind == OMPC_threadprivate) {
22675 S.Diag(ELoc, diag::err_omp_wrong_dsa)
22676 << getOpenMPClauseNameForDiag(DVar.CKind)
22677 << getOpenMPClauseNameForDiag(OMPC_reduction);
22678 reportOriginalDsa(S, Stack, D, DVar);
22679 continue;
22680 }
22681 }
22682
22683 // Try to find 'declare reduction' corresponding construct before using
22684 // builtin/overloaded operators.
22685 CXXCastPath BasePath;
22686 ExprResult DeclareReductionRef = buildDeclareReductionRef(
22687 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
22688 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
22689 if (DeclareReductionRef.isInvalid())
22690 continue;
22691 if (S.CurContext->isDependentContext() &&
22692 (DeclareReductionRef.isUnset() ||
22693 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
22694 RD.push(RefExpr, DeclareReductionRef.get());
22695 // Handle non-dependent inscan reduction variables in dependent contexts.
22696 if (RD.RedModifier == OMPC_REDUCTION_inscan)
22697 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, nullptr,
22698 RD.RedModifier, ASE || OASE);
22699 continue;
22700 }
22701 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
22702 // Not allowed reduction identifier is found.
22703 if (S.LangOpts.OpenMP > 52)
22704 S.Diag(ReductionId.getBeginLoc(),
22705 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
22706 << Type << ReductionIdRange;
22707 else
22708 S.Diag(ReductionId.getBeginLoc(),
22709 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
22710 << Type << ReductionIdRange;
22711 continue;
22712 }
22713
22714 // OpenMP [2.14.3.6, reduction clause, Restrictions]
22715 // The type of a list item that appears in a reduction clause must be valid
22716 // for the reduction-identifier. For a max or min reduction in C, the type
22717 // of the list item must be an allowed arithmetic data type: char, int,
22718 // float, double, or _Bool, possibly modified with long, short, signed, or
22719 // unsigned. For a max or min reduction in C++, the type of the list item
22720 // must be an allowed arithmetic data type: char, wchar_t, int, float,
22721 // double, or bool, possibly modified with long, short, signed, or unsigned.
22722 if (DeclareReductionRef.isUnset()) {
22723 if ((BOK == BO_GT || BOK == BO_LT) &&
22724 !(Type->isScalarType() ||
22725 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
22726 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
22727 << getOpenMPClauseNameForDiag(ClauseKind)
22728 << S.getLangOpts().CPlusPlus;
22729 if (!ASE && !OASE) {
22730 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22732 S.Diag(D->getLocation(),
22733 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22734 << D;
22735 }
22736 continue;
22737 }
22738 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
22739 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
22740 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
22741 << getOpenMPClauseNameForDiag(ClauseKind);
22742 if (!ASE && !OASE) {
22743 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22745 S.Diag(D->getLocation(),
22746 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22747 << D;
22748 }
22749 continue;
22750 }
22751 }
22752
22753 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
22754 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
22755 D->hasAttrs() ? &D->getAttrs() : nullptr);
22756 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
22757 D->hasAttrs() ? &D->getAttrs() : nullptr);
22758 QualType PrivateTy = Type;
22759
22760 // Try if we can determine constant lengths for all array sections and avoid
22761 // the VLA.
22762 bool ConstantLengthOASE = false;
22763 if (OASE) {
22764 bool SingleElement;
22766 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
22767 Context, OASE, SingleElement, ArraySizes);
22768
22769 // If we don't have a single element, we must emit a constant array type.
22770 if (ConstantLengthOASE && !SingleElement) {
22771 for (llvm::APSInt &Size : ArraySizes)
22772 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
22774 /*IndexTypeQuals=*/0);
22775 }
22776 }
22777
22778 if ((OASE && !ConstantLengthOASE) ||
22779 (!OASE && !ASE &&
22781 if (!Context.getTargetInfo().isVLASupported()) {
22782 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
22783 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
22784 S.Diag(ELoc, diag::note_vla_unsupported);
22785 continue;
22786 } else {
22787 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
22788 S.targetDiag(ELoc, diag::note_vla_unsupported);
22789 }
22790 }
22791 // For arrays/array sections only:
22792 // Create pseudo array type for private copy. The size for this array will
22793 // be generated during codegen.
22794 // For array subscripts or single variables Private Ty is the same as Type
22795 // (type of the variable or single array element).
22796 PrivateTy = Context.getVariableArrayType(
22797 Type,
22798 new (Context)
22799 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
22800 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
22801 } else if (!ASE && !OASE &&
22802 Context.getAsArrayType(D->getType().getNonReferenceType())) {
22803 PrivateTy = D->getType().getNonReferenceType();
22804 }
22805 // Private copy.
22806 VarDecl *PrivateVD =
22807 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
22808 D->hasAttrs() ? &D->getAttrs() : nullptr,
22809 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
22810 // Add initializer for private variable.
22811 Expr *Init = nullptr;
22812 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
22813 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
22814 if (DeclareReductionRef.isUsable()) {
22815 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
22816 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
22817 if (DRD->getInitializer()) {
22818 Init = DRDRef;
22819 RHSVD->setInit(DRDRef);
22821 }
22822 } else {
22823 switch (BOK) {
22824 case BO_Add:
22825 case BO_Xor:
22826 case BO_Or:
22827 case BO_LOr:
22828 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
22830 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
22831 break;
22832 case BO_Mul:
22833 // '*' reduction op - initializer is '1'.
22834 // For C++ class types (e.g. std::complex) the OpenMP built-in
22835 // reduction identifiers are an extension: the standard only defines
22836 // identities for arithmetic (and, in Clang, _Complex) types. Without
22837 // an explicit initializer the private copy would be value-initialized,
22838 // which yields the *additive* identity (e.g. std::complex(0,0)) and is
22839 // wrong for multiplication. Initialize from the integer literal '1'
22840 // instead and let the converting constructor build the multiplicative
22841 // identity (e.g. std::complex(1) == (1,0)).
22842 if (Type->isScalarType() || Type->isAnyComplexType()) {
22843 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
22844 } else if (S.getLangOpts().CPlusPlus && Type->isRecordType()) {
22845 // Only use '1' when the type is actually copy-initializable from it.
22846 // Otherwise fall back to value-initialization (the previous behavior)
22847 // rather than rejecting the reduction, so a class that used to
22848 // compile keeps compiling. Such a class keeps its (possibly
22849 // incorrect) value-initialized identity, matching the pre-existing
22850 // behavior; BO_Add likewise relies on value-initialization for class
22851 // types.
22852 Expr *One = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
22853 InitializedEntity Entity =
22856 InitializationSequence Seq(S, Entity, Kind, One);
22857 if (Seq)
22858 Init = One;
22859 }
22860 break;
22861 case BO_LAnd:
22862 if (Type->isScalarType() || Type->isAnyComplexType()) {
22863 // '&&' reduction ops - initializer is '1'.
22864 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
22865 }
22866 break;
22867 case BO_And: {
22868 // '&' reduction op - initializer is '~0'.
22869 QualType OrigType = Type;
22870 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
22871 Type = ComplexTy->getElementType();
22872 if (Type->isRealFloatingType()) {
22873 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
22874 Context.getFloatTypeSemantics(Type));
22875 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
22876 Type, ELoc);
22877 } else if (Type->isScalarType()) {
22878 uint64_t Size = Context.getTypeSize(Type);
22879 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
22880 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
22881 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
22882 }
22883 if (Init && OrigType->isAnyComplexType()) {
22884 // Init = 0xFFFF + 0xFFFFi;
22885 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
22886 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
22887 }
22888 Type = OrigType;
22889 break;
22890 }
22891 case BO_LT:
22892 case BO_GT: {
22893 // 'min' reduction op - initializer is 'Largest representable number in
22894 // the reduction list item type'.
22895 // 'max' reduction op - initializer is 'Least representable number in
22896 // the reduction list item type'.
22897 if (Type->isIntegerType() || Type->isPointerType()) {
22898 bool IsSigned = Type->hasSignedIntegerRepresentation();
22899 uint64_t Size = Context.getTypeSize(Type);
22900 QualType IntTy =
22901 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
22902 llvm::APInt InitValue =
22903 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
22904 : llvm::APInt::getMinValue(Size)
22905 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
22906 : llvm::APInt::getMaxValue(Size);
22907 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
22908 if (Type->isPointerType()) {
22909 // Cast to pointer type.
22911 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
22912 if (CastExpr.isInvalid())
22913 continue;
22914 Init = CastExpr.get();
22915 }
22916 } else if (Type->isRealFloatingType()) {
22917 llvm::APFloat InitValue = llvm::APFloat::getLargest(
22918 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
22919 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
22920 Type, ELoc);
22921 }
22922 break;
22923 }
22924 case BO_PtrMemD:
22925 case BO_PtrMemI:
22926 case BO_MulAssign:
22927 case BO_Div:
22928 case BO_Rem:
22929 case BO_Sub:
22930 case BO_Shl:
22931 case BO_Shr:
22932 case BO_LE:
22933 case BO_GE:
22934 case BO_EQ:
22935 case BO_NE:
22936 case BO_Cmp:
22937 case BO_AndAssign:
22938 case BO_XorAssign:
22939 case BO_OrAssign:
22940 case BO_Assign:
22941 case BO_AddAssign:
22942 case BO_SubAssign:
22943 case BO_DivAssign:
22944 case BO_RemAssign:
22945 case BO_ShlAssign:
22946 case BO_ShrAssign:
22947 case BO_Comma:
22948 llvm_unreachable("Unexpected reduction operation");
22949 }
22950 }
22951 if (Init && DeclareReductionRef.isUnset()) {
22952 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
22953 // Store initializer for single element in private copy. Will be used
22954 // during codegen.
22955 PrivateVD->setInit(RHSVD->getInit());
22956 PrivateVD->setInitStyle(RHSVD->getInitStyle());
22957 } else if (!Init) {
22958 S.ActOnUninitializedDecl(RHSVD);
22959 // Store initializer for single element in private copy. Will be used
22960 // during codegen.
22961 PrivateVD->setInit(RHSVD->getInit());
22962 PrivateVD->setInitStyle(RHSVD->getInitStyle());
22963 }
22964 if (RHSVD->isInvalidDecl())
22965 continue;
22966 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
22967 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
22968 << Type << ReductionIdRange;
22969 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
22971 S.Diag(D->getLocation(),
22972 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
22973 << D;
22974 continue;
22975 }
22976 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
22977 ExprResult ReductionOp;
22978 if (DeclareReductionRef.isUsable()) {
22979 QualType RedTy = DeclareReductionRef.get()->getType();
22980 QualType PtrRedTy = Context.getPointerType(RedTy);
22981 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
22982 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
22983 if (!BasePath.empty()) {
22984 LHS = S.DefaultLvalueConversion(LHS.get());
22985 RHS = S.DefaultLvalueConversion(RHS.get());
22987 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
22988 LHS.get()->getValueKind(), FPOptionsOverride());
22990 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
22991 RHS.get()->getValueKind(), FPOptionsOverride());
22992 }
22994 QualType Params[] = {PtrRedTy, PtrRedTy};
22995 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
22996 auto *OVE = new (Context) OpaqueValueExpr(
22997 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
22998 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
22999 Expr *Args[] = {LHS.get(), RHS.get()};
23000 ReductionOp =
23001 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
23003 } else {
23005 if (Type->isRecordType() && CombBOK != BOK) {
23007 ReductionOp =
23008 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
23009 CombBOK, LHSDRE, RHSDRE);
23010 }
23011 if (!ReductionOp.isUsable()) {
23012 ReductionOp =
23013 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
23014 LHSDRE, RHSDRE);
23015 if (ReductionOp.isUsable()) {
23016 if (BOK != BO_LT && BOK != BO_GT) {
23017 ReductionOp =
23018 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
23019 BO_Assign, LHSDRE, ReductionOp.get());
23020 } else {
23021 auto *ConditionalOp = new (Context)
23022 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
23023 RHSDRE, Type, VK_LValue, OK_Ordinary);
23024 ReductionOp =
23025 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
23026 BO_Assign, LHSDRE, ConditionalOp);
23027 }
23028 }
23029 }
23030 if (ReductionOp.isUsable())
23031 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
23032 /*DiscardedValue=*/false);
23033 if (!ReductionOp.isUsable())
23034 continue;
23035 }
23036
23037 // Add copy operations for inscan reductions.
23038 // LHS = RHS;
23039 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
23040 if (ClauseKind == OMPC_reduction &&
23041 RD.RedModifier == OMPC_REDUCTION_inscan) {
23042 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
23043 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
23044 RHS.get());
23045 if (!CopyOpRes.isUsable())
23046 continue;
23047 CopyOpRes =
23048 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
23049 if (!CopyOpRes.isUsable())
23050 continue;
23051 // For simd directive and simd-based directives in simd mode no need to
23052 // construct temp array, need just a single temp element.
23053 if (Stack->getCurrentDirective() == OMPD_simd ||
23054 (S.getLangOpts().OpenMPSimd &&
23055 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
23056 VarDecl *TempArrayVD =
23057 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
23058 D->hasAttrs() ? &D->getAttrs() : nullptr);
23059 // Add a constructor to the temp decl.
23060 S.ActOnUninitializedDecl(TempArrayVD);
23061 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
23062 } else {
23063 // Build temp array for prefix sum.
23064 auto *Dim = new (S.Context)
23067 PrivateTy, Dim, ArraySizeModifier::Normal,
23068 /*IndexTypeQuals=*/0);
23069 VarDecl *TempArrayVD =
23070 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
23071 D->hasAttrs() ? &D->getAttrs() : nullptr);
23072 // Add a constructor to the temp decl.
23073 S.ActOnUninitializedDecl(TempArrayVD);
23074 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
23075 TempArrayElem =
23076 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
23077 auto *Idx = new (S.Context)
23079 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
23080 ELoc, Idx, ELoc);
23081 }
23082 }
23083
23084 // OpenMP [2.15.4.6, Restrictions, p.2]
23085 // A list item that appears in an in_reduction clause of a task construct
23086 // must appear in a task_reduction clause of a construct associated with a
23087 // taskgroup region that includes the participating task in its taskgroup
23088 // set. The construct associated with the innermost region that meets this
23089 // condition must specify the same reduction-identifier as the in_reduction
23090 // clause.
23091 if (ClauseKind == OMPC_in_reduction) {
23092 SourceRange ParentSR;
23093 BinaryOperatorKind ParentBOK;
23094 const Expr *ParentReductionOp = nullptr;
23095 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
23096 DSAStackTy::DSAVarData ParentBOKDSA =
23097 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
23098 ParentBOKTD);
23099 DSAStackTy::DSAVarData ParentReductionOpDSA =
23100 Stack->getTopMostTaskgroupReductionData(
23101 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
23102 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
23103 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
23104 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
23105 (DeclareReductionRef.isUsable() && IsParentBOK) ||
23106 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
23107 bool EmitError = true;
23108 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
23109 llvm::FoldingSetNodeID RedId, ParentRedId;
23110 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
23111 DeclareReductionRef.get()->Profile(RedId, Context,
23112 /*Canonical=*/true);
23113 EmitError = RedId != ParentRedId;
23114 }
23115 if (EmitError) {
23116 S.Diag(ReductionId.getBeginLoc(),
23117 diag::err_omp_reduction_identifier_mismatch)
23118 << ReductionIdRange << RefExpr->getSourceRange();
23119 S.Diag(ParentSR.getBegin(),
23120 diag::note_omp_previous_reduction_identifier)
23121 << ParentSR
23122 << (IsParentBOK ? ParentBOKDSA.RefExpr
23123 : ParentReductionOpDSA.RefExpr)
23124 ->getSourceRange();
23125 continue;
23126 }
23127 }
23128 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
23129 }
23130
23131 DeclRefExpr *Ref = nullptr;
23132 Expr *VarsExpr = RefExpr->IgnoreParens();
23133 bool IsBindingDecl = isa<BindingDecl>(D);
23134 if (!VD && !IsBindingDecl && !S.CurContext->isDependentContext()) {
23135 if (ASE || OASE) {
23136 TransformExprToCaptures RebuildToCapture(S, D);
23137 VarsExpr =
23138 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
23139 Ref = RebuildToCapture.getCapturedExpr();
23140 } else {
23141 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
23142 }
23143 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
23144 RD.ExprCaptures.emplace_back(Ref->getDecl());
23145 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
23146 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
23147 if (!RefRes.isUsable())
23148 continue;
23149 ExprResult PostUpdateRes =
23150 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
23151 RefRes.get());
23152 if (!PostUpdateRes.isUsable())
23153 continue;
23154 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
23155 Stack->getCurrentDirective() == OMPD_taskgroup) {
23156 S.Diag(RefExpr->getExprLoc(),
23157 diag::err_omp_reduction_non_addressable_expression)
23158 << RefExpr->getSourceRange();
23159 continue;
23160 }
23161 RD.ExprPostUpdates.emplace_back(
23162 S.IgnoredValueConversions(PostUpdateRes.get()).get());
23163 }
23164 }
23165 }
23166 // All reduction items are still marked as reduction (to do not increase
23167 // code base size).
23168 unsigned Modifier = RD.RedModifier;
23169 // Consider task_reductions as reductions with task modifier. Required for
23170 // correct analysis of in_reduction clauses.
23171 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
23172 Modifier = OMPC_REDUCTION_task;
23173 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
23174 ASE || OASE);
23175 if (Modifier == OMPC_REDUCTION_task &&
23176 (CurrDir == OMPD_taskgroup ||
23177 ((isOpenMPParallelDirective(CurrDir) ||
23178 isOpenMPWorksharingDirective(CurrDir)) &&
23179 !isOpenMPSimdDirective(CurrDir)))) {
23180 if (DeclareReductionRef.isUsable())
23181 Stack->addTaskgroupReductionData(D, ReductionIdRange,
23182 DeclareReductionRef.get());
23183 else
23184 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
23185 }
23186 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
23187 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
23188 TempArrayElem.get(), IsPrivate);
23189 }
23190 return RD.Vars.empty();
23191}
23192
23194 ArrayRef<Expr *> VarList,
23196 SourceLocation StartLoc, SourceLocation LParenLoc,
23197 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
23198 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
23199 ArrayRef<Expr *> UnresolvedReductions) {
23201 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
23202 OpenMPOriginalSharingModifier OriginalSharingModifier =
23203 static_cast<OpenMPOriginalSharingModifier>(
23204 Modifiers.OriginalSharingModifier);
23205 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
23206 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
23207 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
23208 /*Last=*/OMPC_REDUCTION_unknown)
23209 << getOpenMPClauseNameForDiag(OMPC_reduction);
23210 return nullptr;
23211 }
23212 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
23213 // A reduction clause with the inscan reduction-modifier may only appear on a
23214 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
23215 // construct, a parallel worksharing-loop construct or a parallel
23216 // worksharing-loop SIMD construct.
23217 if (Modifier == OMPC_REDUCTION_inscan &&
23218 (DSAStack->getCurrentDirective() != OMPD_for &&
23219 DSAStack->getCurrentDirective() != OMPD_for_simd &&
23220 DSAStack->getCurrentDirective() != OMPD_simd &&
23221 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
23222 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
23223 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
23224 return nullptr;
23225 }
23226 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
23227 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
23228 StartLoc, LParenLoc, ColonLoc, EndLoc,
23229 ReductionIdScopeSpec, ReductionId,
23230 UnresolvedReductions, RD))
23231 return nullptr;
23232
23233 return OMPReductionClause::Create(
23234 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
23235 Modifier, RD.Vars,
23236 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
23237 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
23238 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
23239 buildPreInits(getASTContext(), RD.ExprCaptures),
23240 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
23241 OriginalSharingModifier);
23242}
23243
23245 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
23246 SourceLocation ColonLoc, SourceLocation EndLoc,
23247 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
23248 ArrayRef<Expr *> UnresolvedReductions) {
23249 ReductionData RD(VarList.size());
23250 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
23251 VarList, StartLoc, LParenLoc, ColonLoc,
23252 EndLoc, ReductionIdScopeSpec, ReductionId,
23253 UnresolvedReductions, RD))
23254 return nullptr;
23255
23256 return OMPTaskReductionClause::Create(
23257 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
23258 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
23259 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
23260 buildPreInits(getASTContext(), RD.ExprCaptures),
23261 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
23262}
23263
23265 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
23266 SourceLocation ColonLoc, SourceLocation EndLoc,
23267 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
23268 ArrayRef<Expr *> UnresolvedReductions) {
23269 ReductionData RD(VarList.size());
23270 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
23271 StartLoc, LParenLoc, ColonLoc, EndLoc,
23272 ReductionIdScopeSpec, ReductionId,
23273 UnresolvedReductions, RD))
23274 return nullptr;
23275
23276 return OMPInReductionClause::Create(
23277 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
23278 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
23279 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
23280 buildPreInits(getASTContext(), RD.ExprCaptures),
23281 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
23282}
23283
23285 SourceLocation LinLoc) {
23286 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
23287 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
23288 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
23289 << getLangOpts().CPlusPlus;
23290 return true;
23291 }
23292 return false;
23293}
23294
23296 OpenMPLinearClauseKind LinKind,
23297 QualType Type, bool IsDeclareSimd) {
23298 const auto *VD = dyn_cast_or_null<VarDecl>(D);
23299 // A variable must not have an incomplete type or a reference type.
23300 if (SemaRef.RequireCompleteType(ELoc, Type,
23301 diag::err_omp_linear_incomplete_type))
23302 return true;
23303 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
23304 !Type->isReferenceType()) {
23305 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
23306 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
23307 return true;
23308 }
23309 Type = Type.getNonReferenceType();
23310
23311 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
23312 // A variable that is privatized must not have a const-qualified type
23313 // unless it is of class type with a mutable member. This restriction does
23314 // not apply to the firstprivate clause, nor to the linear clause on
23315 // declarative directives (like declare simd).
23316 if (!IsDeclareSimd &&
23317 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
23318 return true;
23319
23320 // A list item must be of integral or pointer type.
23321 Type = Type.getUnqualifiedType().getCanonicalType();
23322 const auto *Ty = Type.getTypePtrOrNull();
23323 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
23324 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
23325 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
23326 if (D) {
23327 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
23329 Diag(D->getLocation(),
23330 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
23331 << D;
23332 }
23333 return true;
23334 }
23335 return false;
23336}
23337
23339 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
23340 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
23341 SourceLocation LinLoc, SourceLocation ColonLoc,
23342 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
23346 SmallVector<Decl *, 4> ExprCaptures;
23347 SmallVector<Expr *, 4> ExprPostUpdates;
23348 // OpenMP 5.2 [Section 5.4.6, linear clause]
23349 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
23350 // 'ref'
23351 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
23352 getLangOpts().OpenMP >= 52)
23353 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
23354 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
23355 LinKind = OMPC_LINEAR_val;
23356 for (Expr *RefExpr : VarList) {
23357 assert(RefExpr && "NULL expr in OpenMP linear clause.");
23358 SourceLocation ELoc;
23359 SourceRange ERange;
23360 Expr *SimpleRefExpr = RefExpr;
23361 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23362 if (Res.second) {
23363 // It will be analyzed later.
23364 Vars.push_back(RefExpr);
23365 Privates.push_back(nullptr);
23366 Inits.push_back(nullptr);
23367 }
23368 ValueDecl *D = Res.first;
23369 if (!D)
23370 continue;
23371
23372 // Linear on bindings only works for simple simd, not parallel constructs.
23373 if (isa<BindingDecl>(D)) {
23374 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23375 if (isOpenMPParallelDirective(DKind)) {
23376 Diag(ELoc, diag::err_omp_unsupported_on_binding) << 2;
23377 continue;
23378 }
23379 }
23380
23381 QualType Type = D->getType();
23382 auto *VD = dyn_cast<VarDecl>(D);
23383
23384 // OpenMP [2.14.3.7, linear clause]
23385 // A list-item cannot appear in more than one linear clause.
23386 // A list-item that appears in a linear clause cannot appear in any
23387 // other data-sharing attribute clause.
23388 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
23389 if (DVar.RefExpr) {
23390 Diag(ELoc, diag::err_omp_wrong_dsa)
23391 << getOpenMPClauseNameForDiag(DVar.CKind)
23392 << getOpenMPClauseNameForDiag(OMPC_linear);
23394 continue;
23395 }
23396
23397 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
23398 continue;
23399 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
23400
23401 // Build private copy of original var.
23402 VarDecl *Private =
23403 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
23404 D->hasAttrs() ? &D->getAttrs() : nullptr,
23405 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
23406 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
23407 // Build var to save initial value.
23408 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
23409 DeclRefExpr *Ref = nullptr;
23410 bool IsBindingDecl = isa<BindingDecl>(D);
23411 if (!VD && !IsBindingDecl && !SemaRef.CurContext->isDependentContext()) {
23412 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
23413 if (!isOpenMPCapturedDecl(D)) {
23414 ExprCaptures.push_back(Ref->getDecl());
23415 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
23416 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
23417 if (!RefRes.isUsable())
23418 continue;
23419 ExprResult PostUpdateRes =
23420 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
23421 SimpleRefExpr, RefRes.get());
23422 if (!PostUpdateRes.isUsable())
23423 continue;
23424 ExprPostUpdates.push_back(
23425 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
23426 }
23427 }
23428 }
23429 // Read the initial value through the list item itself for every modifier;
23430 // a 'uval' item is a reference whose referenced value is linear, exactly as
23431 // for 'val', and need not have an initializer (e.g. a reference parameter).
23432 Expr *InitExpr = Ref ? Ref : SimpleRefExpr;
23433 SemaRef.AddInitializerToDecl(
23434 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
23435 /*DirectInit=*/false);
23436 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
23437
23438 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
23439 Vars.push_back(
23440 (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
23441 ? RefExpr->IgnoreParens()
23442 : Ref);
23443 Privates.push_back(PrivateRef);
23444 Inits.push_back(InitRef);
23445 }
23446
23447 if (Vars.empty())
23448 return nullptr;
23449
23450 Expr *StepExpr = Step;
23451 Expr *CalcStepExpr = nullptr;
23452 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
23453 !Step->isInstantiationDependent() &&
23455 SourceLocation StepLoc = Step->getBeginLoc();
23457 if (Val.isInvalid())
23458 return nullptr;
23459 StepExpr = Val.get();
23460
23461 // Build var to save the step value.
23462 VarDecl *SaveVar =
23463 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
23464 ExprResult SaveRef =
23465 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
23466 ExprResult CalcStep = SemaRef.BuildBinOp(
23467 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
23468 CalcStep =
23469 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
23470
23471 // Warn about zero linear step (it would be probably better specified as
23472 // making corresponding variables 'const').
23473 if (std::optional<llvm::APSInt> Result =
23475 if (!Result->isNegative() && !Result->isStrictlyPositive())
23476 Diag(StepLoc, diag::warn_omp_linear_step_zero)
23477 << Vars[0] << (Vars.size() > 1);
23478 } else if (CalcStep.isUsable()) {
23479 // Calculate the step beforehand instead of doing this on each iteration.
23480 // (This is not used if the number of iterations may be kfold-ed).
23481 CalcStepExpr = CalcStep.get();
23482 }
23483 }
23484
23485 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
23486 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
23487 Vars, Privates, Inits, StepExpr, CalcStepExpr,
23488 buildPreInits(getASTContext(), ExprCaptures),
23489 buildPostUpdate(SemaRef, ExprPostUpdates));
23490}
23491
23492static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
23493 Expr *NumIterations, Sema &SemaRef,
23494 Scope *S, DSAStackTy *Stack) {
23495 // Walk the vars and build update/final expressions for the CodeGen.
23498 SmallVector<Expr *, 8> UsedExprs;
23499 Expr *Step = Clause.getStep();
23500 Expr *CalcStep = Clause.getCalcStep();
23501 // OpenMP [2.14.3.7, linear clause]
23502 // If linear-step is not specified it is assumed to be 1.
23503 if (!Step)
23504 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
23505 else if (CalcStep)
23506 Step = cast<BinaryOperator>(CalcStep)->getLHS();
23507 bool HasErrors = false;
23508 auto CurInit = Clause.inits().begin();
23509 auto CurPrivate = Clause.privates().begin();
23510 for (Expr *RefExpr : Clause.varlist()) {
23511 SourceLocation ELoc;
23512 SourceRange ERange;
23513 Expr *SimpleRefExpr = RefExpr;
23514 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23515 ValueDecl *D = Res.first;
23516 if (Res.second || !D) {
23517 Updates.push_back(nullptr);
23518 Finals.push_back(nullptr);
23519 HasErrors = true;
23520 continue;
23521 }
23522 auto &&Info = Stack->isLoopControlVariable(D);
23523 // OpenMP [2.15.11, distribute simd Construct]
23524 // A list item may not appear in a linear clause, unless it is the loop
23525 // iteration variable.
23526 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
23527 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
23528 SemaRef.Diag(ELoc,
23529 diag::err_omp_linear_distribute_var_non_loop_iteration);
23530 Updates.push_back(nullptr);
23531 Finals.push_back(nullptr);
23532 HasErrors = true;
23533 continue;
23534 }
23535 Expr *InitExpr = *CurInit;
23536
23537 // Build privatized reference to the current linear var. The final value is
23538 // written back through the variable itself, also for 'uval' references.
23539 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
23540 Expr *CapturedRef;
23541 if (isa<BindingDecl>(DE->getDecl())) {
23542 CapturedRef = SimpleRefExpr;
23543 } else {
23544 CapturedRef =
23545 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
23546 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
23547 /*RefersToCapture=*/true);
23548 }
23549
23550 // Build update: Var = InitExpr + IV * Step
23552 if (!Info.first)
23554 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
23555 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
23556 else
23557 Update = *CurPrivate;
23558 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
23559 /*DiscardedValue=*/false);
23560
23561 // Build final: Var = PrivCopy;
23562 ExprResult Final;
23563 if (!Info.first)
23564 Final = SemaRef.BuildBinOp(
23565 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
23566 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
23567 else
23568 Final = *CurPrivate;
23569 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
23570 /*DiscardedValue=*/false);
23571
23572 if (!Update.isUsable() || !Final.isUsable()) {
23573 Updates.push_back(nullptr);
23574 Finals.push_back(nullptr);
23575 UsedExprs.push_back(nullptr);
23576 HasErrors = true;
23577 } else {
23578 Updates.push_back(Update.get());
23579 Finals.push_back(Final.get());
23580 if (!Info.first)
23581 UsedExprs.push_back(SimpleRefExpr);
23582 }
23583 ++CurInit;
23584 ++CurPrivate;
23585 }
23586 if (Expr *S = Clause.getStep())
23587 UsedExprs.push_back(S);
23588 // Fill the remaining part with the nullptr.
23589 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
23590 Clause.setUpdates(Updates);
23591 Clause.setFinals(Finals);
23592 Clause.setUsedExprs(UsedExprs);
23593 return HasErrors;
23594}
23595
23597 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
23598 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
23600 for (Expr *RefExpr : VarList) {
23601 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
23602 SourceLocation ELoc;
23603 SourceRange ERange;
23604 Expr *SimpleRefExpr = RefExpr;
23605 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23606 if (Res.second) {
23607 // It will be analyzed later.
23608 Vars.push_back(RefExpr);
23609 }
23610 ValueDecl *D = Res.first;
23611 if (!D)
23612 continue;
23613
23614 QualType QType = D->getType();
23615 auto *VD = dyn_cast<VarDecl>(D);
23616
23617 // OpenMP [2.8.1, simd construct, Restrictions]
23618 // The type of list items appearing in the aligned clause must be
23619 // array, pointer, reference to array, or reference to pointer.
23621 const Type *Ty = QType.getTypePtrOrNull();
23622 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
23623 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
23624 << QType << getLangOpts().CPlusPlus << ERange;
23625 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
23627 Diag(D->getLocation(),
23628 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
23629 << D;
23630 continue;
23631 }
23632
23633 // OpenMP [2.8.1, simd construct, Restrictions]
23634 // A list-item cannot appear in more than one aligned clause.
23635 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
23636 Diag(ELoc, diag::err_omp_used_in_clause_twice)
23637 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
23638 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
23639 << getOpenMPClauseNameForDiag(OMPC_aligned);
23640 continue;
23641 }
23642
23643 DeclRefExpr *Ref = nullptr;
23644 if (!VD && isOpenMPCapturedDecl(D))
23645 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
23646 Vars.push_back(SemaRef
23647 .DefaultFunctionArrayConversion(
23648 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
23649 .get());
23650 }
23651
23652 // OpenMP [2.8.1, simd construct, Description]
23653 // The parameter of the aligned clause, alignment, must be a constant
23654 // positive integer expression.
23655 // If no optional parameter is specified, implementation-defined default
23656 // alignments for SIMD instructions on the target platforms are assumed.
23657 if (Alignment != nullptr) {
23658 ExprResult AlignResult =
23659 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
23660 if (AlignResult.isInvalid())
23661 return nullptr;
23662 Alignment = AlignResult.get();
23663 }
23664 if (Vars.empty())
23665 return nullptr;
23666
23667 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
23668 ColonLoc, EndLoc, Vars, Alignment);
23669}
23670
23672 SourceLocation StartLoc,
23673 SourceLocation LParenLoc,
23674 SourceLocation EndLoc) {
23676 SmallVector<Expr *, 8> SrcExprs;
23677 SmallVector<Expr *, 8> DstExprs;
23678 SmallVector<Expr *, 8> AssignmentOps;
23679 for (Expr *RefExpr : VarList) {
23680 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
23681 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
23682 // It will be analyzed later.
23683 Vars.push_back(RefExpr);
23684 SrcExprs.push_back(nullptr);
23685 DstExprs.push_back(nullptr);
23686 AssignmentOps.push_back(nullptr);
23687 continue;
23688 }
23689
23690 SourceLocation ELoc = RefExpr->getExprLoc();
23691 // OpenMP [2.1, C/C++]
23692 // A list item is a variable name.
23693 // OpenMP [2.14.4.1, Restrictions, p.1]
23694 // A list item that appears in a copyin clause must be threadprivate.
23695 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
23696 if (!DE || !isa<VarDecl>(DE->getDecl())) {
23697 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
23698 << 0 << RefExpr->getSourceRange();
23699 continue;
23700 }
23701
23702 Decl *D = DE->getDecl();
23703 auto *VD = cast<VarDecl>(D);
23704
23705 QualType Type = VD->getType();
23707 // It will be analyzed later.
23708 Vars.push_back(DE);
23709 SrcExprs.push_back(nullptr);
23710 DstExprs.push_back(nullptr);
23711 AssignmentOps.push_back(nullptr);
23712 continue;
23713 }
23714
23715 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
23716 // A list item that appears in a copyin clause must be threadprivate.
23717 if (!DSAStack->isThreadPrivate(VD)) {
23718 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
23719 Diag(ELoc, diag::err_omp_required_access)
23720 << getOpenMPClauseNameForDiag(OMPC_copyin)
23721 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
23722 continue;
23723 }
23724
23725 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
23726 // A variable of class type (or array thereof) that appears in a
23727 // copyin clause requires an accessible, unambiguous copy assignment
23728 // operator for the class type.
23729 QualType ElemType =
23731 VarDecl *SrcVD =
23732 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
23733 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
23734 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
23735 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
23736 VarDecl *DstVD =
23737 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
23738 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
23739 DeclRefExpr *PseudoDstExpr =
23740 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
23741 // For arrays generate assignment operation for single element and replace
23742 // it by the original array element in CodeGen.
23743 ExprResult AssignmentOp =
23744 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
23745 PseudoDstExpr, PseudoSrcExpr);
23746 if (AssignmentOp.isInvalid())
23747 continue;
23748 AssignmentOp =
23749 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
23750 /*DiscardedValue=*/false);
23751 if (AssignmentOp.isInvalid())
23752 continue;
23753
23754 DSAStack->addDSA(VD, DE, OMPC_copyin);
23755 Vars.push_back(DE);
23756 SrcExprs.push_back(PseudoSrcExpr);
23757 DstExprs.push_back(PseudoDstExpr);
23758 AssignmentOps.push_back(AssignmentOp.get());
23759 }
23760
23761 if (Vars.empty())
23762 return nullptr;
23763
23764 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
23765 Vars, SrcExprs, DstExprs, AssignmentOps);
23766}
23767
23769 SourceLocation StartLoc,
23770 SourceLocation LParenLoc,
23771 SourceLocation EndLoc) {
23773 SmallVector<Expr *, 8> SrcExprs;
23774 SmallVector<Expr *, 8> DstExprs;
23775 SmallVector<Expr *, 8> AssignmentOps;
23776 for (Expr *RefExpr : VarList) {
23777 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
23778 SourceLocation ELoc;
23779 SourceRange ERange;
23780 Expr *SimpleRefExpr = RefExpr;
23781 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
23782 if (Res.second) {
23783 // It will be analyzed later.
23784 Vars.push_back(RefExpr);
23785 SrcExprs.push_back(nullptr);
23786 DstExprs.push_back(nullptr);
23787 AssignmentOps.push_back(nullptr);
23788 }
23789 ValueDecl *D = Res.first;
23790 if (!D)
23791 continue;
23792
23793 QualType Type = D->getType();
23794 auto *VD = dyn_cast<VarDecl>(D);
23795
23796 // OpenMP [2.14.4.2, Restrictions, p.2]
23797 // A list item that appears in a copyprivate clause may not appear in a
23798 // private or firstprivate clause on the single construct.
23799 if (!VD || !DSAStack->isThreadPrivate(VD)) {
23800 DSAStackTy::DSAVarData DVar =
23801 DSAStack->getTopDSA(D, /*FromParent=*/false);
23802 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
23803 DVar.RefExpr) {
23804 Diag(ELoc, diag::err_omp_wrong_dsa)
23805 << getOpenMPClauseNameForDiag(DVar.CKind)
23806 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
23808 continue;
23809 }
23810
23811 // OpenMP [2.11.4.2, Restrictions, p.1]
23812 // All list items that appear in a copyprivate clause must be either
23813 // threadprivate or private in the enclosing context.
23814 if (DVar.CKind == OMPC_unknown) {
23815 DVar = DSAStack->getImplicitDSA(D, false);
23816 // A data member is private only if an enclosing construct captured it.
23817 const bool IsShared = DVar.CKind == OMPC_shared;
23818 if (IsShared ||
23819 (isa<FieldDecl>(D) && !SemaRef.CurContext->isDependentContext() &&
23820 !isOpenMPCapturedDecl(D))) {
23821 Diag(ELoc, diag::err_omp_required_access)
23822 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
23823 << "threadprivate or private in the enclosing context";
23824 if (IsShared)
23826 continue;
23827 }
23828 }
23829 }
23830
23831 // Variably modified types are not supported.
23833 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
23834 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
23835 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
23836 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
23837 OMPVersion);
23838 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
23840 Diag(D->getLocation(),
23841 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
23842 << D;
23843 continue;
23844 }
23845
23846 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
23847 // A variable of class type (or array thereof) that appears in a
23848 // copyin clause requires an accessible, unambiguous copy assignment
23849 // operator for the class type.
23851 .getBaseElementType(Type.getNonReferenceType())
23853 VarDecl *SrcVD =
23854 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
23855 D->hasAttrs() ? &D->getAttrs() : nullptr);
23856 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
23857 VarDecl *DstVD =
23858 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
23859 D->hasAttrs() ? &D->getAttrs() : nullptr);
23860 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
23861 ExprResult AssignmentOp = SemaRef.BuildBinOp(
23862 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
23863 if (AssignmentOp.isInvalid())
23864 continue;
23865 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
23866 /*DiscardedValue=*/false);
23867 if (AssignmentOp.isInvalid())
23868 continue;
23869
23870 // No need to mark vars as copyprivate, they are already threadprivate or
23871 // implicitly private.
23872 const bool IsBindingDecl = isa<BindingDecl>(D);
23873 assert(VD || IsBindingDecl || SemaRef.CurContext->isDependentContext() ||
23875 Vars.push_back(
23876 (VD || IsBindingDecl || SemaRef.CurContext->isDependentContext())
23877 ? RefExpr->IgnoreParens()
23878 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
23879 SrcExprs.push_back(PseudoSrcExpr);
23880 DstExprs.push_back(PseudoDstExpr);
23881 AssignmentOps.push_back(AssignmentOp.get());
23882 }
23883
23884 if (Vars.empty())
23885 return nullptr;
23886
23887 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
23888 EndLoc, Vars, SrcExprs, DstExprs,
23889 AssignmentOps);
23890}
23891
23893 SourceLocation StartLoc,
23894 SourceLocation LParenLoc,
23895 SourceLocation EndLoc) {
23896 if (VarList.empty())
23897 return nullptr;
23898
23899 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
23900 VarList);
23901}
23902
23903/// Tries to find omp_depend_t. type.
23904static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
23905 bool Diagnose = true) {
23906 QualType OMPDependT = Stack->getOMPDependT();
23907 if (!OMPDependT.isNull())
23908 return true;
23909 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
23910 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
23911 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
23912 if (Diagnose)
23913 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
23914 return false;
23915 }
23916 Stack->setOMPDependT(PT.get());
23917 return true;
23918}
23919
23921 SourceLocation StartLoc,
23922 SourceLocation LParenLoc,
23923 SourceLocation EndLoc) {
23924 if (!Depobj)
23925 return nullptr;
23926
23927 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
23928
23929 // OpenMP 5.0, 2.17.10.1 depobj Construct
23930 // depobj is an lvalue expression of type omp_depend_t.
23931 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
23932 !Depobj->isInstantiationDependent() &&
23934 (OMPDependTFound && !getASTContext().typesAreCompatible(
23935 DSAStack->getOMPDependT(), Depobj->getType(),
23936 /*CompareUnqualified=*/true))) {
23937 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
23938 << 0 << Depobj->getType() << Depobj->getSourceRange();
23939 }
23940
23941 if (!Depobj->isLValue()) {
23942 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
23943 << 1 << Depobj->getSourceRange();
23944 }
23945
23946 return new (getASTContext())
23947 OMPDepobjClause(StartLoc, LParenLoc, EndLoc, Depobj);
23948}
23949
23950namespace {
23951// Utility struct that gathers the related info for doacross clause.
23952struct DoacrossDataInfoTy {
23953 // The list of expressions.
23955 // The OperatorOffset for doacross loop.
23956 DSAStackTy::OperatorOffsetTy OpsOffs;
23957 // The depended loop count.
23958 llvm::APSInt TotalDepCount;
23959};
23960} // namespace
23961static DoacrossDataInfoTy
23963 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
23964 SourceLocation EndLoc) {
23965
23967 DSAStackTy::OperatorOffsetTy OpsOffs;
23968 llvm::APSInt DepCounter(/*BitWidth=*/32);
23969 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
23970
23971 if (const Expr *OrderedCountExpr =
23972 Stack->getParentOrderedRegionParam().first) {
23973 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
23974 TotalDepCount.setIsUnsigned(/*Val=*/true);
23975 }
23976
23977 for (Expr *RefExpr : VarList) {
23978 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
23979 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
23980 // It will be analyzed later.
23981 Vars.push_back(RefExpr);
23982 continue;
23983 }
23984
23985 SourceLocation ELoc = RefExpr->getExprLoc();
23986 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
23987 if (!IsSource) {
23988 if (Stack->getParentOrderedRegionParam().first &&
23989 DepCounter >= TotalDepCount) {
23990 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
23991 continue;
23992 }
23993 ++DepCounter;
23994 // OpenMP [2.13.9, Summary]
23995 // depend(dependence-type : vec), where dependence-type is:
23996 // 'sink' and where vec is the iteration vector, which has the form:
23997 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
23998 // where n is the value specified by the ordered clause in the loop
23999 // directive, xi denotes the loop iteration variable of the i-th nested
24000 // loop associated with the loop directive, and di is a constant
24001 // non-negative integer.
24002 if (SemaRef.CurContext->isDependentContext()) {
24003 // It will be analyzed later.
24004 Vars.push_back(RefExpr);
24005 continue;
24006 }
24007 SimpleExpr = SimpleExpr->IgnoreImplicit();
24009 SourceLocation OOLoc;
24010 Expr *LHS = SimpleExpr;
24011 Expr *RHS = nullptr;
24012 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
24013 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
24014 OOLoc = BO->getOperatorLoc();
24015 LHS = BO->getLHS()->IgnoreParenImpCasts();
24016 RHS = BO->getRHS()->IgnoreParenImpCasts();
24017 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
24018 OOK = OCE->getOperator();
24019 OOLoc = OCE->getOperatorLoc();
24020 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
24021 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
24022 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
24023 OOK = MCE->getMethodDecl()
24024 ->getNameInfo()
24025 .getName()
24026 .getCXXOverloadedOperator();
24027 OOLoc = MCE->getCallee()->getExprLoc();
24028 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
24029 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
24030 }
24031 SourceLocation ELoc;
24032 SourceRange ERange;
24033 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
24034 if (Res.second) {
24035 // It will be analyzed later.
24036 Vars.push_back(RefExpr);
24037 }
24038 ValueDecl *D = Res.first;
24039 if (!D)
24040 continue;
24041
24042 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
24043 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
24044 continue;
24045 }
24046 if (RHS) {
24047 ExprResult RHSRes =
24049 RHS, OMPC_depend, /*StrictlyPositive=*/false);
24050 if (RHSRes.isInvalid())
24051 continue;
24052 }
24053 if (!SemaRef.CurContext->isDependentContext() &&
24054 Stack->getParentOrderedRegionParam().first &&
24055 DepCounter != Stack->isParentLoopControlVariable(D).first) {
24056 const ValueDecl *VD =
24057 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
24058 if (VD)
24059 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
24060 << 1 << VD;
24061 else
24062 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
24063 << 0;
24064 continue;
24065 }
24066 OpsOffs.emplace_back(RHS, OOK);
24067 }
24068 Vars.push_back(RefExpr->IgnoreParenImpCasts());
24069 }
24070 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
24071 TotalDepCount > VarList.size() &&
24072 Stack->getParentOrderedRegionParam().first &&
24073 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
24074 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
24075 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
24076 }
24077 return {Vars, OpsOffs, TotalDepCount};
24078}
24079
24081 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
24082 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
24083 SourceLocation EndLoc) {
24084 OpenMPDependClauseKind DepKind = Data.DepKind;
24085 SourceLocation DepLoc = Data.DepLoc;
24086 if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
24087 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
24088 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24089 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
24090 return nullptr;
24091 }
24092 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
24093 DepKind == OMPC_DEPEND_mutexinoutset) {
24094 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
24095 return nullptr;
24096 }
24097 if ((DSAStack->getCurrentDirective() != OMPD_ordered_standalone ||
24098 DSAStack->getCurrentDirective() == OMPD_depobj) &&
24099 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
24100 DepKind == OMPC_DEPEND_sink ||
24101 ((getLangOpts().OpenMP < 50 ||
24102 DSAStack->getCurrentDirective() == OMPD_depobj) &&
24103 DepKind == OMPC_DEPEND_depobj))) {
24104 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
24105 OMPC_DEPEND_outallmemory,
24106 OMPC_DEPEND_inoutallmemory};
24107 if (getLangOpts().OpenMP < 50 ||
24108 DSAStack->getCurrentDirective() == OMPD_depobj)
24109 Except.push_back(OMPC_DEPEND_depobj);
24110 if (getLangOpts().OpenMP < 51)
24111 Except.push_back(OMPC_DEPEND_inoutset);
24112 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
24113 ? "depend modifier(iterator) or "
24114 : "";
24115 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
24116 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
24117 /*Last=*/OMPC_DEPEND_unknown,
24118 Except)
24119 << getOpenMPClauseNameForDiag(OMPC_depend);
24120 return nullptr;
24121 }
24122 if (DepModifier &&
24123 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
24124 Diag(DepModifier->getExprLoc(),
24125 diag::err_omp_depend_sink_source_with_modifier);
24126 return nullptr;
24127 }
24128 if (DepModifier &&
24129 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
24130 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
24131
24133 DSAStackTy::OperatorOffsetTy OpsOffs;
24134 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
24135
24136 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
24137 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
24138 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
24139 Vars = VarOffset.Vars;
24140 OpsOffs = VarOffset.OpsOffs;
24141 TotalDepCount = VarOffset.TotalDepCount;
24142 } else {
24143 for (Expr *RefExpr : VarList) {
24144 assert(RefExpr && "NULL expr in OpenMP depend clause.");
24145 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
24146 // It will be analyzed later.
24147 Vars.push_back(RefExpr);
24148 continue;
24149 }
24150
24151 SourceLocation ELoc = RefExpr->getExprLoc();
24152 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
24153 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
24154 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
24155 if (OMPDependTFound)
24156 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
24157 DepKind == OMPC_DEPEND_depobj);
24158 if (DepKind == OMPC_DEPEND_depobj) {
24159 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
24160 // List items used in depend clauses with the depobj dependence type
24161 // must be expressions of the omp_depend_t type.
24162 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
24163 !RefExpr->isInstantiationDependent() &&
24164 !RefExpr->containsUnexpandedParameterPack() &&
24165 (OMPDependTFound &&
24166 !getASTContext().hasSameUnqualifiedType(
24167 DSAStack->getOMPDependT(), RefExpr->getType()))) {
24168 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
24169 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
24170 continue;
24171 }
24172 if (!RefExpr->isLValue()) {
24173 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
24174 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
24175 continue;
24176 }
24177 } else {
24178 // OpenMP 5.0 [2.17.11, Restrictions]
24179 // List items used in depend clauses cannot be zero-length array
24180 // sections.
24181 QualType ExprTy = RefExpr->getType().getNonReferenceType();
24182 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
24183 if (OASE) {
24184 QualType BaseType =
24186 if (BaseType.isNull())
24187 return nullptr;
24188 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
24189 ExprTy = ATy->getElementType();
24190 else
24191 ExprTy = BaseType->getPointeeType();
24192 if (BaseType.isNull() || ExprTy.isNull())
24193 return nullptr;
24194 ExprTy = ExprTy.getNonReferenceType();
24195 const Expr *Length = OASE->getLength();
24197 if (Length && !Length->isValueDependent() &&
24198 Length->EvaluateAsInt(Result, getASTContext()) &&
24199 Result.Val.getInt().isZero()) {
24200 Diag(ELoc,
24201 diag::err_omp_depend_zero_length_array_section_not_allowed)
24202 << SimpleExpr->getSourceRange();
24203 continue;
24204 }
24205 }
24206
24207 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
24208 // List items used in depend clauses with the in, out, inout,
24209 // inoutset, or mutexinoutset dependence types cannot be
24210 // expressions of the omp_depend_t type.
24211 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
24212 !RefExpr->isInstantiationDependent() &&
24213 !RefExpr->containsUnexpandedParameterPack() &&
24214 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
24215 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
24216 ExprTy.getTypePtr()))) {
24217 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24218 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
24219 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
24220 << RefExpr->getSourceRange();
24221 continue;
24222 }
24223
24224 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
24225 if (ASE && !ASE->getBase()->isTypeDependent() &&
24226 !ASE->getBase()
24227 ->getType()
24228 .getNonReferenceType()
24229 ->isPointerType() &&
24230 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
24231 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24232 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
24233 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
24234 << RefExpr->getSourceRange();
24235 continue;
24236 }
24237
24238 ExprResult Res;
24239 {
24241 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
24242 RefExpr->IgnoreParenImpCasts());
24243 }
24244 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
24246 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
24247 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
24248 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
24249 << RefExpr->getSourceRange();
24250 continue;
24251 }
24252 }
24253 }
24254 Vars.push_back(RefExpr->IgnoreParenImpCasts());
24255 }
24256 }
24257
24258 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
24259 DepKind != OMPC_DEPEND_outallmemory &&
24260 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
24261 return nullptr;
24262
24263 auto *C = OMPDependClause::Create(
24264 getASTContext(), StartLoc, LParenLoc, EndLoc,
24265 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
24266 TotalDepCount.getZExtValue());
24267 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
24268 DSAStack->isParentOrderedRegion())
24269 DSAStack->addDoacrossDependClause(C, OpsOffs);
24270 return C;
24271}
24272
24275 SourceLocation LParenLoc, SourceLocation ModifierLoc,
24276 SourceLocation EndLoc) {
24277 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
24278 "Unexpected device modifier in OpenMP < 50.");
24279
24280 bool ErrorFound = false;
24281 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
24282 std::string Values =
24283 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
24284 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24285 << Values << getOpenMPClauseNameForDiag(OMPC_device);
24286 ErrorFound = true;
24287 }
24288
24289 Expr *ValExpr = Device;
24290 Stmt *HelperValStmt = nullptr;
24291
24292 // OpenMP 5.2 [1.3, Execution Model]: a conforming device number is either
24293 // a non-negative integer that is less than or equal to omp_get_num_devices()
24294 // or equal to omp_initial_device or omp_invalid_device. The predefined
24295 // identifiers were introduced in OpenMP 5.2; earlier versions require a
24296 // non-negative integer.
24297 if (getLangOpts().OpenMP >= 52) {
24298 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
24299 !ValExpr->isInstantiationDependent()) {
24300 SourceLocation Loc = ValExpr->getExprLoc();
24302 if (Value.isInvalid()) {
24303 ErrorFound = true;
24304 } else {
24305 ValExpr = Value.get();
24306 if (std::optional<llvm::APSInt> Result =
24308 if (Result->isSigned() && Result->slt(-2)) {
24309 Diag(Loc, diag::err_omp_device_expression_invalid)
24310 << ValExpr->getSourceRange();
24311 ErrorFound = true;
24312 }
24313 }
24314 }
24315 }
24316 } else {
24317 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
24318 /*StrictlyPositive=*/false) ||
24319 ErrorFound;
24320 }
24321 if (ErrorFound)
24322 return nullptr;
24323
24324 // OpenMP 5.0 [2.12.5, Restrictions]
24325 // In case of ancestor device-modifier, a requires directive with
24326 // the reverse_offload clause must be specified.
24327 if (Modifier == OMPC_DEVICE_ancestor) {
24328 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
24329 SemaRef.targetDiag(
24330 StartLoc,
24331 diag::err_omp_device_ancestor_without_requires_reverse_offload);
24332 ErrorFound = true;
24333 }
24334 }
24335
24336 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24338 DKind, OMPC_device, getLangOpts().getOpenMPVersion());
24339 if (CaptureRegion != OMPD_unknown &&
24340 !SemaRef.CurContext->isDependentContext()) {
24341 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24342 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24343 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24344 HelperValStmt = buildPreInits(getASTContext(), Captures);
24345 }
24346
24347 return new (getASTContext())
24348 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
24349 LParenLoc, ModifierLoc, EndLoc);
24350}
24351
24353 DSAStackTy *Stack, QualType QTy,
24354 bool FullCheck = true) {
24355 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
24356 return false;
24357 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
24358 !QTy.isTriviallyCopyableType(SemaRef.Context))
24359 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
24360 return true;
24361}
24362
24363/// Return true if it can be proven that the provided array expression
24364/// (array section or array subscript) does NOT specify the whole size of the
24365/// array whose base type is \a BaseQTy.
24367 const Expr *E,
24368 QualType BaseQTy) {
24369 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
24370
24371 // If this is an array subscript, it refers to the whole size if the size of
24372 // the dimension is constant and equals 1. Also, an array section assumes the
24373 // format of an array subscript if no colon is used.
24374 if (isa<ArraySubscriptExpr>(E) ||
24375 (OASE && OASE->getColonLocFirst().isInvalid())) {
24376 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
24377 return ATy->getSExtSize() != 1;
24378 // Size can't be evaluated statically.
24379 return false;
24380 }
24381
24382 assert(OASE && "Expecting array section if not an array subscript.");
24383 const Expr *LowerBound = OASE->getLowerBound();
24384 const Expr *Length = OASE->getLength();
24385
24386 // If there is a lower bound that does not evaluates to zero, we are not
24387 // covering the whole dimension.
24388 if (LowerBound) {
24390 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
24391 return false; // Can't get the integer value as a constant.
24392
24393 llvm::APSInt ConstLowerBound = Result.Val.getInt();
24394 if (ConstLowerBound.getSExtValue())
24395 return true;
24396 }
24397
24398 // If we don't have a length we covering the whole dimension.
24399 if (!Length)
24400 return false;
24401
24402 // If the base is a pointer, we don't have a way to get the size of the
24403 // pointee.
24404 if (BaseQTy->isPointerType())
24405 return false;
24406
24407 // We can only check if the length is the same as the size of the dimension
24408 // if we have a constant array.
24409 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
24410 if (!CATy)
24411 return false;
24412
24414 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
24415 return false; // Can't get the integer value as a constant.
24416
24417 llvm::APSInt ConstLength = Result.Val.getInt();
24418 return CATy->getSExtSize() != ConstLength.getSExtValue();
24419}
24420
24421// Return true if it can be proven that the provided array expression (array
24422// section or array subscript) does NOT specify a single element of the array
24423// whose base type is \a BaseQTy.
24425 const Expr *E,
24426 QualType BaseQTy) {
24427 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
24428
24429 // An array subscript always refer to a single element. Also, an array section
24430 // assumes the format of an array subscript if no colon is used.
24431 if (isa<ArraySubscriptExpr>(E) ||
24432 (OASE && OASE->getColonLocFirst().isInvalid()))
24433 return false;
24434
24435 assert(OASE && "Expecting array section if not an array subscript.");
24436 const Expr *Length = OASE->getLength();
24437
24438 // If we don't have a length we have to check if the array has unitary size
24439 // for this dimension. Also, we should always expect a length if the base type
24440 // is pointer.
24441 if (!Length) {
24442 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
24443 return ATy->getSExtSize() != 1;
24444 // We cannot assume anything.
24445 return false;
24446 }
24447
24448 // Check if the length evaluates to 1.
24450 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
24451 return false; // Can't get the integer value as a constant.
24452
24453 llvm::APSInt ConstLength = Result.Val.getInt();
24454 return ConstLength.getSExtValue() != 1;
24455}
24456
24457// The base of elements of list in a map clause have to be either:
24458// - a reference to variable or field.
24459// - a member expression.
24460// - an array expression.
24461//
24462// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
24463// reference to 'r'.
24464//
24465// If we have:
24466//
24467// struct SS {
24468// Bla S;
24469// foo() {
24470// #pragma omp target map (S.Arr[:12]);
24471// }
24472// }
24473//
24474// We want to retrieve the member expression 'this->S';
24475
24476// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
24477// If a list item is an array section, it must specify contiguous storage.
24478//
24479// For this restriction it is sufficient that we make sure only references
24480// to variables or fields and array expressions, and that no array sections
24481// exist except in the rightmost expression (unless they cover the whole
24482// dimension of the array). E.g. these would be invalid:
24483//
24484// r.ArrS[3:5].Arr[6:7]
24485//
24486// r.ArrS[3:5].x
24487//
24488// but these would be valid:
24489// r.ArrS[3].Arr[6:7]
24490//
24491// r.ArrS[3].x
24492namespace {
24493class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
24494 Sema &SemaRef;
24495 OpenMPClauseKind CKind = OMPC_unknown;
24496 OpenMPDirectiveKind DKind = OMPD_unknown;
24498 bool IsNonContiguous = false;
24499 bool NoDiagnose = false;
24500 const Expr *RelevantExpr = nullptr;
24501 bool AllowUnitySizeArraySection = true;
24502 bool AllowWholeSizeArraySection = true;
24503 bool AllowAnotherPtr = true;
24504 SourceLocation ELoc;
24505 SourceRange ERange;
24506
24507 void emitErrorMsg() {
24508 // If nothing else worked, this is not a valid map clause expression.
24509 if (SemaRef.getLangOpts().OpenMP < 50) {
24510 SemaRef.Diag(ELoc,
24511 diag::err_omp_expected_named_var_member_or_array_expression)
24512 << ERange;
24513 } else {
24514 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
24515 << getOpenMPClauseNameForDiag(CKind) << ERange;
24516 }
24517 }
24518
24519public:
24520 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
24521 ValueDecl *D = DRE->getDecl();
24522 Expr *E = DRE;
24523
24524 // Handle BindingDecls by mapping them as member accesses.
24525 // When the user writes:
24526 // auto [a, b] = p;
24527 // #pragma omp target map(tofrom:a) map(to:b)
24528 // we transform it to:
24529 // #pragma omp target map(tofrom:p.x) map(to:p.y)
24530 // This avoids conflicts when different bindings have different map types.
24531 if (auto *BD = dyn_cast<BindingDecl>(D)) {
24533 Expr *BindingExpr = BD->getBinding();
24534
24535 // Check if the binding is a member expression (struct/class
24536 // decomposition).
24537 if (auto *ME = dyn_cast_or_null<MemberExpr>(BindingExpr)) {
24538
24539 // Use the DecompositionDecl as the base for the member expression.
24540 // The structured binding creates a copy (if initialized from a
24541 // variable) or holds the only storage (if initialized from a prvalue).
24542 // Using DD ensures map clauses reference the correct storage.
24543 Expr *BaseExpr =
24544 SemaRef
24545 .BuildDeclarationNameExpr(
24546 CXXScopeSpec(),
24547 DeclarationNameInfo(DD->getDeclName(), DRE->getLocation()),
24548 DD)
24549 .get();
24550
24551 // Create member expression: base.member.
24553 SemaRef.Context, BaseExpr, /*IsArrow=*/false, ME->getOperatorLoc(),
24554 ME->getQualifierLoc(), ME->getTemplateKeywordLoc(),
24555 ME->getMemberDecl(), ME->getFoundDecl(), ME->getMemberNameInfo(),
24556 /*TemplateArgs=*/nullptr, ME->getType(), ME->getValueKind(),
24557 ME->getObjectKind(), ME->isNonOdrUse());
24558
24559 // Now process this as a member expression, which will properly
24560 // handle the field-level mapping.
24561 return Visit(E);
24562 }
24563 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(BindingExpr)) {
24564 Expr *BaseExpr =
24565 SemaRef
24566 .BuildDeclarationNameExpr(
24567 CXXScopeSpec(),
24568 DeclarationNameInfo(DD->getDeclName(), DRE->getLocation()),
24569 DD)
24570 .get();
24571 E = new (SemaRef.Context) ArraySubscriptExpr(
24572 BaseExpr, ASE->getIdx(), ASE->getType(), ASE->getValueKind(),
24573 ASE->getObjectKind(), ASE->getRBracketLoc());
24574 return Visit(E);
24575 }
24576 // Tuple-like should already be rejected; do not map DD as a silent
24577 // fallback.
24578 SemaRef.Diag(DRE->getExprLoc(),
24579 diag::err_omp_unsupported_structured_binding_init)
24580 << 4;
24581 return false;
24582 }
24583 // Handle DecompositionDecl directly (implicit captures).
24584 else if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
24585 if (const VarDecl *OrigVar =
24586 getOriginalVarOrDiagnose(SemaRef, DD, DRE->getExprLoc())) {
24587 D = const_cast<VarDecl *>(OrigVar);
24588 DeclarationNameInfo NameInfo(D->getDeclName(), DRE->getLocation());
24589 E = DeclRefExpr::Create(SemaRef.Context, DRE->getQualifierLoc(),
24590 DRE->getTemplateKeywordLoc(), D,
24591 /*RefersToEnclosingVariableOrCapture=*/false,
24592 NameInfo, D->getType(), DRE->getValueKind(),
24593 DRE->getFoundDecl(),
24594 /*TemplateArgs=*/nullptr, DRE->isNonOdrUse());
24595 } else {
24596 return false;
24597 }
24598 } else if (!isa<VarDecl>(D)) {
24599 emitErrorMsg();
24600 return false;
24601 }
24602 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24603 RelevantExpr = E;
24604 // Record the component.
24605 Components.emplace_back(E, D, IsNonContiguous);
24606 return true;
24607 }
24608
24609 bool VisitMemberExpr(MemberExpr *ME) {
24610 Expr *E = ME;
24611 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
24612
24613 if (isa<CXXThisExpr>(BaseE)) {
24614 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24615 // We found a base expression: this->Val.
24616 RelevantExpr = ME;
24617 } else {
24618 E = BaseE;
24619 }
24620
24621 if (!isa<FieldDecl>(ME->getMemberDecl())) {
24622 if (!NoDiagnose) {
24623 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
24624 << ME->getSourceRange();
24625 return false;
24626 }
24627 if (RelevantExpr)
24628 return false;
24629 return Visit(E);
24630 }
24631
24632 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
24633
24634 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
24635 // A bit-field cannot appear in a map clause.
24636 //
24637 if (FD->isBitField()) {
24638 if (!NoDiagnose) {
24639 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
24640 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
24641 return false;
24642 }
24643 if (RelevantExpr)
24644 return false;
24645 return Visit(E);
24646 }
24647
24648 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
24649 // If the type of a list item is a reference to a type T then the type
24650 // will be considered to be T for all purposes of this clause.
24651 QualType CurType = BaseE->getType().getNonReferenceType();
24652
24653 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
24654 // A list item cannot be a variable that is a member of a structure with
24655 // a union type.
24656 //
24657 if (CurType->isUnionType()) {
24658 if (!NoDiagnose) {
24659 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
24660 << ME->getSourceRange();
24661 return false;
24662 }
24663 return RelevantExpr || Visit(E);
24664 }
24665
24666 // If we got a member expression, we should not expect any array section
24667 // before that:
24668 //
24669 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
24670 // If a list item is an element of a structure, only the rightmost symbol
24671 // of the variable reference can be an array section.
24672 //
24673 AllowUnitySizeArraySection = false;
24674 AllowWholeSizeArraySection = false;
24675
24676 // Record the component.
24677 Components.emplace_back(ME, FD, IsNonContiguous);
24678 return RelevantExpr || Visit(E);
24679 }
24680
24681 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
24682 Expr *E = AE->getBase()->IgnoreParenImpCasts();
24683
24684 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
24685 if (!NoDiagnose) {
24686 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
24687 << 0 << AE->getSourceRange();
24688 return false;
24689 }
24690 return RelevantExpr || Visit(E);
24691 }
24692
24693 // If we got an array subscript that express the whole dimension we
24694 // can have any array expressions before. If it only expressing part of
24695 // the dimension, we can only have unitary-size array expressions.
24697 AllowWholeSizeArraySection = false;
24698
24699 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
24700 Expr::EvalResult Result;
24701 if (!AE->getIdx()->isValueDependent() &&
24702 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
24703 !Result.Val.getInt().isZero()) {
24704 SemaRef.Diag(AE->getIdx()->getExprLoc(),
24705 diag::err_omp_invalid_map_this_expr);
24706 SemaRef.Diag(AE->getIdx()->getExprLoc(),
24707 diag::note_omp_invalid_subscript_on_this_ptr_map);
24708 }
24709 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24710 RelevantExpr = TE;
24711 }
24712
24713 // Record the component - we don't have any declaration associated.
24714 Components.emplace_back(AE, nullptr, IsNonContiguous);
24715
24716 return RelevantExpr || Visit(E);
24717 }
24718
24719 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
24720 // After OMP 5.0 Array section in reduction clause will be implicitly
24721 // mapped
24722 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
24723 "Array sections cannot be implicitly mapped.");
24724 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
24725 QualType CurType =
24727
24728 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
24729 // If the type of a list item is a reference to a type T then the type
24730 // will be considered to be T for all purposes of this clause.
24731 if (CurType->isReferenceType())
24732 CurType = CurType->getPointeeType();
24733
24734 bool IsPointer = CurType->isAnyPointerType();
24735
24736 if (!IsPointer && !CurType->isArrayType()) {
24737 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
24738 << 0 << OASE->getSourceRange();
24739 return false;
24740 }
24741
24742 bool NotWhole =
24743 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
24744 bool NotUnity =
24745 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
24746
24747 if (AllowWholeSizeArraySection) {
24748 // Any array section is currently allowed. Allowing a whole size array
24749 // section implies allowing a unity array section as well.
24750 //
24751 // If this array section refers to the whole dimension we can still
24752 // accept other array sections before this one, except if the base is a
24753 // pointer. Otherwise, only unitary sections are accepted.
24754 if (NotWhole || IsPointer)
24755 AllowWholeSizeArraySection = false;
24756 } else if (DKind == OMPD_target_update &&
24757 SemaRef.getLangOpts().OpenMP >= 50) {
24758 if (IsPointer && !AllowAnotherPtr)
24759 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
24760 << /*array of unknown bound */ 1;
24761 else
24762 IsNonContiguous = true;
24763 } else if (AllowUnitySizeArraySection && NotUnity) {
24764 // A unity or whole array section is not allowed and that is not
24765 // compatible with the properties of the current array section.
24766 if (NoDiagnose)
24767 return false;
24768 SemaRef.Diag(ELoc,
24769 diag::err_array_section_does_not_specify_contiguous_storage)
24770 << OASE->getSourceRange();
24771 return false;
24772 }
24773
24774 if (IsPointer)
24775 AllowAnotherPtr = false;
24776
24777 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
24778 Expr::EvalResult ResultR;
24779 Expr::EvalResult ResultL;
24780 if (!OASE->getLength()->isValueDependent() &&
24781 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
24782 !ResultR.Val.getInt().isOne()) {
24783 SemaRef.Diag(OASE->getLength()->getExprLoc(),
24784 diag::err_omp_invalid_map_this_expr);
24785 SemaRef.Diag(OASE->getLength()->getExprLoc(),
24786 diag::note_omp_invalid_length_on_this_ptr_mapping);
24787 }
24788 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
24789 OASE->getLowerBound()->EvaluateAsInt(ResultL,
24790 SemaRef.getASTContext()) &&
24791 !ResultL.Val.getInt().isZero()) {
24792 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
24793 diag::err_omp_invalid_map_this_expr);
24794 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
24795 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
24796 }
24797 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24798 RelevantExpr = TE;
24799 }
24800
24801 // Record the component - we don't have any declaration associated.
24802 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
24803 return RelevantExpr || Visit(E);
24804 }
24805 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
24806 Expr *Base = E->getBase();
24807
24808 // Record the component - we don't have any declaration associated.
24809 Components.emplace_back(E, nullptr, IsNonContiguous);
24810
24811 return Visit(Base->IgnoreParenImpCasts());
24812 }
24813
24814 bool VisitUnaryOperator(UnaryOperator *UO) {
24815 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
24816 UO->getOpcode() != UO_Deref) {
24817 emitErrorMsg();
24818 return false;
24819 }
24820 if (!RelevantExpr) {
24821 // Record the component if haven't found base decl.
24822 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
24823 }
24824 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
24825 }
24826 bool VisitBinaryOperator(BinaryOperator *BO) {
24827 // Since OpenMP 5.0 only pointer arithmetic (pointer +/- integer offset)
24828 // may lead to the base, which is in the pointer operand.
24829 Expr *PtrE = nullptr;
24830 if (SemaRef.getLangOpts().OpenMP >= 50 && BO->isAdditiveOp() &&
24831 BO->getType()->isPointerType()) {
24832 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
24833 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
24834 if (LE->getType()->isPointerType())
24835 PtrE = LE;
24836 else if (BO->getOpcode() == BO_Add && RE->getType()->isPointerType())
24837 PtrE = RE;
24838 }
24839 if (!PtrE) {
24840 emitErrorMsg();
24841 return false;
24842 }
24843 Components.emplace_back(BO, nullptr, /*IsNonContiguous=*/false);
24844 return RelevantExpr || Visit(PtrE);
24845 }
24846 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
24847 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24848 RelevantExpr = CTE;
24849 Components.emplace_back(CTE, nullptr, IsNonContiguous);
24850 return true;
24851 }
24852 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
24853 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
24854 Components.emplace_back(COCE, nullptr, IsNonContiguous);
24855 return true;
24856 }
24857 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
24858 Expr *Source = E->getSourceExpr();
24859 if (!Source) {
24860 emitErrorMsg();
24861 return false;
24862 }
24863 return Visit(Source);
24864 }
24865 bool VisitStmt(Stmt *) {
24866 emitErrorMsg();
24867 return false;
24868 }
24869 const Expr *getFoundBase() const { return RelevantExpr; }
24870 explicit MapBaseChecker(
24871 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
24873 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
24874 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
24875 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
24876};
24877} // namespace
24878
24879/// Return the expression of the base of the mappable expression or null if it
24880/// cannot be determined and do all the necessary checks to see if the
24881/// expression is valid as a standalone mappable expression. In the process,
24882/// record all the components of the expression.
24884 Sema &SemaRef, Expr *E,
24886 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
24887 SourceLocation ELoc = E->getExprLoc();
24888 SourceRange ERange = E->getSourceRange();
24889 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
24890 ERange);
24891 if (Checker.Visit(E->IgnoreParens())) {
24892 // Check if the highest dimension array section has length specified
24893 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
24894 (CKind == OMPC_to || CKind == OMPC_from)) {
24895 auto CI = CurComponents.rbegin();
24896 auto CE = CurComponents.rend();
24897 for (; CI != CE; ++CI) {
24898 const auto *OASE =
24899 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
24900 if (!OASE)
24901 continue;
24902 if (OASE && OASE->getLength())
24903 break;
24904 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
24905 << ERange;
24906 }
24907 }
24908 return Checker.getFoundBase();
24909 }
24910 return nullptr;
24911}
24912
24913// Return true if expression E associated with value VD has conflicts with other
24914// map information.
24916 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
24917 bool CurrentRegionOnly,
24919 OpenMPClauseKind CKind) {
24920 assert(VD && E);
24921 SourceLocation ELoc = E->getExprLoc();
24922 SourceRange ERange = E->getSourceRange();
24923
24924 // In order to easily check the conflicts we need to match each component of
24925 // the expression under test with the components of the expressions that are
24926 // already in the stack.
24927
24928 assert(!CurComponents.empty() && "Map clause expression with no components!");
24929 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
24930 "Map clause expression with unexpected base!");
24931
24932 // Variables to help detecting enclosing problems in data environment nests.
24933 bool IsEnclosedByDataEnvironmentExpr = false;
24934 const Expr *EnclosingExpr = nullptr;
24935
24936 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
24937 VD, CurrentRegionOnly,
24938 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
24939 ERange, CKind, &EnclosingExpr,
24941 StackComponents,
24942 OpenMPClauseKind Kind) {
24943 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
24944 return false;
24945 assert(!StackComponents.empty() &&
24946 "Map clause expression with no components!");
24947 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
24948 "Map clause expression with unexpected base!");
24949 (void)VD;
24950
24951 // The whole expression in the stack.
24952 const Expr *RE = StackComponents.front().getAssociatedExpression();
24953
24954 // Expressions must start from the same base. Here we detect at which
24955 // point both expressions diverge from each other and see if we can
24956 // detect if the memory referred to both expressions is contiguous and
24957 // do not overlap.
24958 auto CI = CurComponents.rbegin();
24959 auto CE = CurComponents.rend();
24960 auto SI = StackComponents.rbegin();
24961 auto SE = StackComponents.rend();
24962 for (; CI != CE && SI != SE; ++CI, ++SI) {
24963
24964 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
24965 // At most one list item can be an array item derived from a given
24966 // variable in map clauses of the same construct.
24967 if (CurrentRegionOnly &&
24968 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
24969 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
24970 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
24971 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
24972 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
24973 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
24974 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
24975 diag::err_omp_multiple_array_items_in_map_clause)
24976 << CI->getAssociatedExpression()->getSourceRange();
24977 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
24978 diag::note_used_here)
24979 << SI->getAssociatedExpression()->getSourceRange();
24980 return true;
24981 }
24982
24983 // Do both expressions have the same kind?
24984 if (CI->getAssociatedExpression()->getStmtClass() !=
24985 SI->getAssociatedExpression()->getStmtClass())
24986 break;
24987
24988 // Are we dealing with different variables/fields?
24989 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
24990 break;
24991 }
24992 // Check if the extra components of the expressions in the enclosing
24993 // data environment are redundant for the current base declaration.
24994 // If they are, the maps completely overlap, which is legal.
24995 for (; SI != SE; ++SI) {
24996 QualType Type;
24997 if (const auto *ASE =
24998 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
24999 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
25000 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
25001 SI->getAssociatedExpression())) {
25002 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
25004 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
25005 SI->getAssociatedExpression())) {
25006 Type = OASE->getBase()->getType()->getPointeeType();
25007 }
25008 if (Type.isNull() || Type->isAnyPointerType() ||
25010 SemaRef, SI->getAssociatedExpression(), Type))
25011 break;
25012 }
25013
25014 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
25015 // List items of map clauses in the same construct must not share
25016 // original storage.
25017 //
25018 // If the expressions are exactly the same or one is a subset of the
25019 // other, it means they are sharing storage.
25020 if (CI == CE && SI == SE) {
25021 if (CurrentRegionOnly) {
25022 if (CKind == OMPC_map) {
25023 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
25024 } else {
25025 assert(CKind == OMPC_to || CKind == OMPC_from);
25026 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
25027 << ERange;
25028 }
25029 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
25030 << RE->getSourceRange();
25031 return true;
25032 }
25033 // If we find the same expression in the enclosing data environment,
25034 // that is legal.
25035 IsEnclosedByDataEnvironmentExpr = true;
25036 return false;
25037 }
25038
25039 QualType DerivedType =
25040 std::prev(CI)->getAssociatedDeclaration()->getType();
25041 SourceLocation DerivedLoc =
25042 std::prev(CI)->getAssociatedExpression()->getExprLoc();
25043
25044 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
25045 // If the type of a list item is a reference to a type T then the type
25046 // will be considered to be T for all purposes of this clause.
25047 DerivedType = DerivedType.getNonReferenceType();
25048
25049 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
25050 // A variable for which the type is pointer and an array section
25051 // derived from that variable must not appear as list items of map
25052 // clauses of the same construct.
25053 //
25054 // Also, cover one of the cases in:
25055 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
25056 // If any part of the original storage of a list item has corresponding
25057 // storage in the device data environment, all of the original storage
25058 // must have corresponding storage in the device data environment.
25059 //
25060 if (DerivedType->isAnyPointerType()) {
25061 if (CI == CE || SI == SE) {
25062 SemaRef.Diag(
25063 DerivedLoc,
25064 diag::err_omp_pointer_mapped_along_with_derived_section)
25065 << DerivedLoc;
25066 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
25067 << RE->getSourceRange();
25068 return true;
25069 }
25070 if (CI->getAssociatedExpression()->getStmtClass() !=
25071 SI->getAssociatedExpression()->getStmtClass() ||
25072 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
25073 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
25074 assert(CI != CE && SI != SE);
25075 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
25076 << DerivedLoc;
25077 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
25078 << RE->getSourceRange();
25079 return true;
25080 }
25081 }
25082
25083 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
25084 // List items of map clauses in the same construct must not share
25085 // original storage.
25086 //
25087 // An expression is a subset of the other.
25088 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
25089 if (CKind == OMPC_map) {
25090 if (CI != CE || SI != SE) {
25091 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
25092 // a pointer.
25093 auto Begin =
25094 CI != CE ? CurComponents.begin() : StackComponents.begin();
25095 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
25096 auto It = Begin;
25097 while (It != End && !It->getAssociatedDeclaration())
25098 std::advance(It, 1);
25099 assert(It != End &&
25100 "Expected at least one component with the declaration.");
25101 if (It != Begin && It->getAssociatedDeclaration()
25102 ->getType()
25103 .getCanonicalType()
25104 ->isAnyPointerType()) {
25105 IsEnclosedByDataEnvironmentExpr = false;
25106 EnclosingExpr = nullptr;
25107 return false;
25108 }
25109 }
25110 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
25111 } else {
25112 assert(CKind == OMPC_to || CKind == OMPC_from);
25113 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
25114 << ERange;
25115 }
25116 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
25117 << RE->getSourceRange();
25118 return true;
25119 }
25120
25121 // The current expression uses the same base as other expression in the
25122 // data environment but does not contain it completely.
25123 if (!CurrentRegionOnly && SI != SE)
25124 EnclosingExpr = RE;
25125
25126 // The current expression is a subset of the expression in the data
25127 // environment.
25128 IsEnclosedByDataEnvironmentExpr |=
25129 (!CurrentRegionOnly && CI != CE && SI == SE);
25130
25131 return false;
25132 });
25133
25134 if (CurrentRegionOnly)
25135 return FoundError;
25136
25137 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
25138 // If any part of the original storage of a list item has corresponding
25139 // storage in the device data environment, all of the original storage must
25140 // have corresponding storage in the device data environment.
25141 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
25142 // If a list item is an element of a structure, and a different element of
25143 // the structure has a corresponding list item in the device data environment
25144 // prior to a task encountering the construct associated with the map clause,
25145 // then the list item must also have a corresponding list item in the device
25146 // data environment prior to the task encountering the construct.
25147 //
25148 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
25149 SemaRef.Diag(ELoc,
25150 diag::err_omp_original_storage_is_shared_and_does_not_contain)
25151 << ERange;
25152 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
25153 << EnclosingExpr->getSourceRange();
25154 return true;
25155 }
25156
25157 return FoundError;
25158}
25159
25160// Look up the user-defined mapper given the mapper name and mapped type, and
25161// build a reference to it. \a ItemLoc is the location of the mapped list item;
25162// it is used as the point of instantiation since \a MapperId has no location
25163// for implicit map clauses.
25165 CXXScopeSpec &MapperIdScopeSpec,
25166 const DeclarationNameInfo &MapperId,
25167 QualType Type,
25168 Expr *UnresolvedMapper,
25169 SourceLocation ItemLoc) {
25170 if (MapperIdScopeSpec.isInvalid())
25171 return ExprError();
25172 // Get the actual type for the array type.
25173 if (Type->isArrayType()) {
25174 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
25176 }
25177 // Find all user-defined mappers with the given MapperId.
25178 SmallVector<UnresolvedSet<8>, 4> Lookups;
25179 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
25180 Lookup.suppressDiagnostics();
25181 if (S) {
25182 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
25183 /*ObjectType=*/QualType())) {
25184 NamedDecl *D = Lookup.getRepresentativeDecl();
25185 while (S && !S->isDeclScope(D))
25186 S = S->getParent();
25187 if (S)
25188 S = S->getParent();
25189 Lookups.emplace_back();
25190 Lookups.back().append(Lookup.begin(), Lookup.end());
25191 Lookup.clear();
25192 }
25193 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
25194 // Extract the user-defined mappers with the given MapperId.
25195 Lookups.push_back(UnresolvedSet<8>());
25196 for (NamedDecl *D : ULE->decls()) {
25197 auto *DMD = cast<OMPDeclareMapperDecl>(D);
25198 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
25199 Lookups.back().addDecl(DMD);
25200 }
25201 }
25202 // Defer the lookup for dependent types. The results will be passed through
25203 // UnresolvedMapper on instantiation.
25204 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
25208 return !D->isInvalidDecl() &&
25209 (D->getType()->isDependentType() ||
25210 D->getType()->isInstantiationDependentType() ||
25211 D->getType()->containsUnexpandedParameterPack());
25212 })) {
25213 UnresolvedSet<8> URS;
25214 for (const UnresolvedSet<8> &Set : Lookups) {
25215 if (Set.empty())
25216 continue;
25217 URS.append(Set.begin(), Set.end());
25218 }
25220 SemaRef.Context, /*NamingClass=*/nullptr,
25221 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
25222 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
25223 /*KnownInstantiationDependent=*/false);
25224 }
25225 SourceLocation Loc = MapperId.getLoc();
25226 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
25227 // The type must be of struct, union or class type in C and C++
25229 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
25230 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
25231 return ExprError();
25232 }
25233 // Perform argument dependent lookup.
25234 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
25235 argumentDependentLookup(SemaRef, MapperId, ItemLoc, Type, Lookups);
25236 // Return the first user-defined mapper with the desired type.
25238 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
25239 if (!D->isInvalidDecl() &&
25240 SemaRef.Context.hasSameType(D->getType(), Type))
25241 return D;
25242 return nullptr;
25243 }))
25244 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
25245 // Find the first user-defined mapper with a type derived from the desired
25246 // type.
25248 Lookups, [&SemaRef, Type, ItemLoc](ValueDecl *D) -> ValueDecl * {
25249 if (!D->isInvalidDecl() &&
25250 SemaRef.IsDerivedFrom(ItemLoc, Type, D->getType()) &&
25251 !Type.isMoreQualifiedThan(D->getType(),
25252 SemaRef.getASTContext()))
25253 return D;
25254 return nullptr;
25255 })) {
25256 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
25257 /*DetectVirtual=*/false);
25258 if (SemaRef.IsDerivedFrom(ItemLoc, Type, VD->getType(), Paths)) {
25259 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
25260 VD->getType().getUnqualifiedType()))) {
25261 if (SemaRef.CheckBaseClassAccess(
25262 ItemLoc, VD->getType(), Type, Paths.front(),
25263 /*DiagID=*/0) != Sema::AR_inaccessible) {
25264 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
25265 }
25266 }
25267 }
25268 }
25269 // Report error if a mapper is specified, but cannot be found.
25270 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
25271 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
25272 << Type << MapperId.getName();
25273 return ExprError();
25274 }
25275 return ExprEmpty();
25276}
25277
25278namespace {
25279// Utility struct that gathers all the related lists associated with a mappable
25280// expression.
25281struct MappableVarListInfo {
25282 // The list of expressions.
25283 ArrayRef<Expr *> VarList;
25284 // The list of processed expressions.
25285 SmallVector<Expr *, 16> ProcessedVarList;
25286 // The mappble components for each expression.
25288 // The base declaration of the variable.
25289 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
25290 // The reference to the user-defined mapper associated with every expression.
25291 SmallVector<Expr *, 16> UDMapperList;
25292
25293 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
25294 // We have a list of components and base declarations for each entry in the
25295 // variable list.
25296 VarComponents.reserve(VarList.size());
25297 VarBaseDeclarations.reserve(VarList.size());
25298 }
25299};
25300} // namespace
25301
25303 DSAStackTy *Stack,
25305
25306 const RecordDecl *RD = BaseType->getAsRecordDecl();
25307 SourceRange Range = RD->getSourceRange();
25308 DeclarationNameInfo ImplicitName;
25309 // Dummy variable _s for Mapper.
25310 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
25311 DeclRefExpr *MapperVarRef =
25312 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
25313
25314 // Create implicit map clause for mapper.
25316 for (auto *FD : RD->fields()) {
25317 Expr *BE = S.BuildMemberExpr(
25318 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
25319 NestedNameSpecifierLoc(), Range.getBegin(), FD,
25321 /*HadMultipleCandidates=*/false,
25323 FD->getType(), VK_LValue, OK_Ordinary);
25324 SExprs.push_back(BE);
25325 }
25326 CXXScopeSpec MapperIdScopeSpec;
25327 DeclarationNameInfo MapperId;
25328 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
25329
25330 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
25331 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
25332 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
25333 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
25334 OMPVarListLocTy());
25335 Maps.push_back(MapClause);
25336 return MapperVarRef;
25337}
25338
25340 DSAStackTy *Stack) {
25341
25342 // Build impilicit map for mapper
25344 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
25345
25346 const RecordDecl *RD = BaseType->getAsRecordDecl();
25347 // AST context is RD's ParentASTContext().
25348 ASTContext &Ctx = RD->getParentASTContext();
25349 // DeclContext is RD's DeclContext.
25350 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
25351
25352 // Create implicit default mapper for "RD".
25353 DeclarationName MapperId;
25354 auto &DeclNames = Ctx.DeclarationNames;
25355 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
25356 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
25357 BaseType, MapperId, Maps, nullptr);
25358 Scope *Scope = S.getScopeForContext(DCT);
25359 if (Scope)
25360 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
25361 DCT->addDecl(DMD);
25362 DMD->setAccess(clang::AS_none);
25363 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
25364 VD->setDeclContext(DMD);
25365 VD->setLexicalDeclContext(DMD);
25366 DMD->addDecl(VD);
25367 DMD->setMapperVarRef(MapperVarRef);
25368 FieldDecl *FD = *RD->field_begin();
25369 // create mapper refence.
25371 DMD, false, SourceLocation(), BaseType, VK_LValue);
25372}
25373
25374// Look up the user-defined mapper given the mapper name and mapper type,
25375// return true if found one.
25376static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
25377 CXXScopeSpec &MapperIdScopeSpec,
25378 const DeclarationNameInfo &MapperId,
25379 QualType Type) {
25380 // Find all user-defined mappers with the given MapperId.
25381 SmallVector<UnresolvedSet<8>, 4> Lookups;
25382 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
25383 Lookup.suppressDiagnostics();
25384 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
25385 /*ObjectType=*/QualType())) {
25386 NamedDecl *D = Lookup.getRepresentativeDecl();
25387 while (S && !S->isDeclScope(D))
25388 S = S->getParent();
25389 if (S)
25390 S = S->getParent();
25391 Lookups.emplace_back();
25392 Lookups.back().append(Lookup.begin(), Lookup.end());
25393 Lookup.clear();
25394 }
25395 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
25399 return !D->isInvalidDecl() &&
25400 (D->getType()->isDependentType() ||
25401 D->getType()->isInstantiationDependentType() ||
25402 D->getType()->containsUnexpandedParameterPack());
25403 }))
25404 return false;
25405 // Perform argument dependent lookup.
25406 SourceLocation Loc = MapperId.getLoc();
25407 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
25408 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
25410 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
25411 if (!D->isInvalidDecl() &&
25412 SemaRef.Context.hasSameType(D->getType(), Type))
25413 return D;
25414 return nullptr;
25415 }))
25416 return true;
25417 // Find the first user-defined mapper with a type derived from the desired
25418 // type.
25420 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
25421 if (!D->isInvalidDecl() &&
25422 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
25423 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
25424 return D;
25425 return nullptr;
25426 });
25427 if (!VD)
25428 return false;
25429 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
25430 /*DetectVirtual=*/false);
25431 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
25432 bool IsAmbiguous = !Paths.isAmbiguous(
25434 if (IsAmbiguous)
25435 return false;
25436 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
25437 /*DiagID=*/0) != Sema::AR_inaccessible)
25438 return true;
25439 }
25440 return false;
25441}
25442
25443static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
25444 QualType CanonType, const Expr *E) {
25445
25446 // DFS over data members in structures/classes.
25448 {CanonType, nullptr});
25449 llvm::DenseMap<const Type *, bool> Visited;
25450 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
25451 while (!Types.empty()) {
25452 auto [BaseType, CurFD] = Types.pop_back_val();
25453 while (ParentChain.back().second == 0)
25454 ParentChain.pop_back();
25455 --ParentChain.back().second;
25456 if (BaseType.isNull())
25457 continue;
25458 // Only structs/classes are allowed to have mappers.
25459 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
25460 if (!RD)
25461 continue;
25462 auto It = Visited.find(BaseType.getTypePtr());
25463 if (It == Visited.end()) {
25464 // Try to find the associated user-defined mapper.
25465 CXXScopeSpec MapperIdScopeSpec;
25466 DeclarationNameInfo DefaultMapperId;
25468 &S.Context.Idents.get("default")));
25469 DefaultMapperId.setLoc(E->getExprLoc());
25470 bool HasUDMapper =
25471 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
25472 DefaultMapperId, BaseType);
25473 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
25474 }
25475 // Found default mapper.
25476 if (It->second)
25477 return true;
25478 // Check for the "default" mapper for data members.
25479 bool FirstIter = true;
25480 for (FieldDecl *FD : RD->fields()) {
25481 if (!FD)
25482 continue;
25483 QualType FieldTy = FD->getType();
25484 if (FieldTy.isNull() ||
25485 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
25486 continue;
25487 if (FirstIter) {
25488 FirstIter = false;
25489 ParentChain.emplace_back(CurFD, 1);
25490 } else {
25491 ++ParentChain.back().second;
25492 }
25493 Types.emplace_back(FieldTy, FD);
25494 }
25495 }
25496 return false;
25497}
25498
25499// Check the validity of the provided variable list for the provided clause kind
25500// \a CKind. In the check process the valid expressions, mappable expression
25501// components, variables, and user-defined mappers are extracted and used to
25502// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
25503// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
25504// and \a MapperId are expected to be valid if the clause kind is 'map'.
25506 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
25507 MappableVarListInfo &MVLI, SourceLocation StartLoc,
25508 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
25509 ArrayRef<Expr *> UnresolvedMappers,
25511 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
25512 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
25513 // We only expect mappable expressions in 'to', 'from', 'map', and
25514 // 'use_device_addr' clauses.
25515 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
25516 CKind == OMPC_use_device_addr) &&
25517 "Unexpected clause kind with mappable expressions!");
25518 llvm::omp::Version OMPVersion = SemaRef.getLangOpts().getOpenMPVersion();
25519
25520 // If the identifier of user-defined mapper is not specified, it is "default".
25521 // We do not change the actual name in this clause to distinguish whether a
25522 // mapper is specified explicitly, i.e., it is not explicitly specified when
25523 // MapperId.getName() is empty.
25524 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
25525 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
25526 MapperId.setName(DeclNames.getIdentifier(
25527 &SemaRef.getASTContext().Idents.get("default")));
25528 MapperId.setLoc(StartLoc);
25529 }
25530
25531 // Iterators to find the current unresolved mapper expression.
25532 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
25533 bool UpdateUMIt = false;
25534 Expr *UnresolvedMapper = nullptr;
25535
25536 bool HasHoldModifier =
25537 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
25538
25539 // Keep track of the mappable components and base declarations in this clause.
25540 // Each entry in the list is going to have a list of components associated. We
25541 // record each set of the components so that we can build the clause later on.
25542 // In the end we should have the same amount of declarations and component
25543 // lists.
25544
25545 for (Expr *RE : MVLI.VarList) {
25546 assert(RE && "Null expr in omp to/from/map clause");
25547 SourceLocation ELoc = RE->getExprLoc();
25548
25549 // Find the current unresolved mapper expression.
25550 if (UpdateUMIt && UMIt != UMEnd) {
25551 UMIt++;
25552 assert(
25553 UMIt != UMEnd &&
25554 "Expect the size of UnresolvedMappers to match with that of VarList");
25555 }
25556 UpdateUMIt = true;
25557 if (UMIt != UMEnd)
25558 UnresolvedMapper = *UMIt;
25559
25560 const Expr *VE = RE->IgnoreParenLValueCasts();
25561
25562 if (VE->isValueDependent() || VE->isTypeDependent() ||
25563 VE->isInstantiationDependent() ||
25564 VE->containsUnexpandedParameterPack()) {
25565 // Try to find the associated user-defined mapper.
25567 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25568 VE->getType().getCanonicalType(), UnresolvedMapper, ELoc);
25569 if (ER.isInvalid())
25570 continue;
25571 MVLI.UDMapperList.push_back(ER.get());
25572 // We can only analyze this information once the missing information is
25573 // resolved.
25574 MVLI.ProcessedVarList.push_back(RE);
25575 continue;
25576 }
25577
25579 if (!RE->isLValue()) {
25580 if (SemaRef.getLangOpts().OpenMP < 50) {
25581 SemaRef.Diag(
25582 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
25583 << RE->getSourceRange();
25584 } else {
25585 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
25586 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
25587 }
25588 continue;
25589 }
25590
25591 // Check for unsupported structured bindings early.
25592 if (!NoDiagnose) {
25593 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleExpr)) {
25594 const DecompositionDecl *DD = nullptr;
25595 const BindingDecl *BD = nullptr;
25596 if (const auto *B = dyn_cast<BindingDecl>(DRE->getDecl())) {
25597 BD = B;
25598 DD = cast<DecompositionDecl>(B->getDecomposedDecl());
25599 } else if (const auto *D =
25600 dyn_cast<DecompositionDecl>(DRE->getDecl())) {
25601 DD = D;
25602 }
25603 if (DD) {
25604 if (BD && BD->getHoldingVar()) {
25605 SemaRef.Diag(ELoc,
25606 diag::err_omp_unsupported_structured_binding_init)
25607 << 4;
25608 continue;
25609 }
25610 if (!getOriginalVarOrDiagnose(SemaRef, DD, ELoc))
25611 continue;
25612 }
25613 }
25614 }
25616 ValueDecl *CurDeclaration = nullptr;
25617
25618 // Obtain the array or member expression bases if required. Also, fill the
25619 // components array with all the components identified in the process.
25620 const Expr *BE =
25621 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
25622 DSAS->getCurrentDirective(), NoDiagnose);
25623 if (!BE)
25624 continue;
25625
25626 assert(!CurComponents.empty() &&
25627 "Invalid mappable expression information.");
25628
25629 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
25630 // Add store "this" pointer to class in DSAStackTy for future checking
25631 DSAS->addMappedClassesQualTypes(TE->getType());
25632 // Try to find the associated user-defined mapper.
25634 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25635 VE->getType().getCanonicalType(), UnresolvedMapper, ELoc);
25636 if (ER.isInvalid())
25637 continue;
25638 MVLI.UDMapperList.push_back(ER.get());
25639 // Skip restriction checking for variable or field declarations
25640 MVLI.ProcessedVarList.push_back(RE);
25641 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25642 MVLI.VarComponents.back().append(CurComponents.begin(),
25643 CurComponents.end());
25644 MVLI.VarBaseDeclarations.push_back(nullptr);
25645 continue;
25646 }
25647
25648 // For the following checks, we rely on the base declaration which is
25649 // expected to be associated with the last component. The declaration is
25650 // expected to be a variable or a field (if 'this' is being mapped).
25651 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
25652 assert(CurDeclaration && "Null decl on map clause.");
25653 assert(
25654 CurDeclaration->isCanonicalDecl() &&
25655 "Expecting components to have associated only canonical declarations.");
25656
25657 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
25658 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
25659
25660 assert((VD || FD) && "Only variables or fields are expected here!");
25661 (void)FD;
25662
25663 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
25664 // threadprivate variables cannot appear in a map clause.
25665 // OpenMP 4.5 [2.10.5, target update Construct]
25666 // threadprivate variables cannot appear in a from clause.
25667 if (VD && DSAS->isThreadPrivate(VD)) {
25668 if (NoDiagnose)
25669 continue;
25670 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
25671 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
25673 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
25674 continue;
25675 }
25676
25677 // OpenMP 6.0 [7.9.6, map Clause, Restrictions, p. 386]
25678 // A device-local variable must not appear as a list item in a map clause.
25679 if (VD && CKind == OMPC_map) {
25680 if (std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
25681 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
25682 if (*Res == OMPDeclareTargetDeclAttr::MT_Local) {
25683 if (NoDiagnose)
25684 continue;
25685 SemaRef.Diag(ELoc, diag::err_omp_device_local_in_clause)
25686 << VD << getOpenMPClauseNameForDiag(CKind);
25687 continue;
25688 }
25689 }
25690 }
25691
25692 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
25693 // A list item cannot appear in both a map clause and a data-sharing
25694 // attribute clause on the same construct.
25695
25696 // Check conflicts with other map clause expressions. We check the conflicts
25697 // with the current construct separately from the enclosing data
25698 // environment, because the restrictions are different. We only have to
25699 // check conflicts across regions for the map clauses.
25700 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
25701 /*CurrentRegionOnly=*/true, CurComponents, CKind))
25702 break;
25703 if (CKind == OMPC_map &&
25704 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
25705 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
25706 /*CurrentRegionOnly=*/false, CurComponents, CKind))
25707 break;
25708
25709 // OpenMP 4.5 [2.10.5, target update Construct]
25710 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
25711 // If the type of a list item is a reference to a type T then the type will
25712 // be considered to be T for all purposes of this clause.
25713 auto I = llvm::find_if(
25714 CurComponents,
25715 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
25716 return MC.getAssociatedDeclaration();
25717 });
25718 assert(I != CurComponents.end() && "Null decl on map clause.");
25719 (void)I;
25720 QualType Type;
25721 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
25722 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
25723 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
25724 if (ASE) {
25725 Type = ASE->getType().getNonReferenceType();
25726 } else if (OASE) {
25727 QualType BaseType =
25729 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
25730 Type = ATy->getElementType();
25731 else
25732 Type = BaseType->getPointeeType();
25733 Type = Type.getNonReferenceType();
25734 } else if (OAShE) {
25735 Type = OAShE->getBase()->getType()->getPointeeType();
25736 } else {
25737 Type = VE->getType();
25738 }
25739
25740 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
25741 // A list item in a to or from clause must have a mappable type.
25742 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
25743 // A list item must have a mappable type.
25744 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
25745 DSAS, Type, /*FullCheck=*/true))
25746 continue;
25747
25748 if (CKind == OMPC_map) {
25749 // target enter data
25750 // OpenMP [2.10.2, Restrictions, p. 99]
25751 // A map-type must be specified in all map clauses and must be either
25752 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
25753 // no map type is present.
25754 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
25755 if (DKind == OMPD_target_enter_data &&
25756 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
25757 SemaRef.getLangOpts().OpenMP >= 52)) {
25758 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
25759 << (IsMapTypeImplicit ? 1 : 0)
25760 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
25761 << getOpenMPDirectiveName(DKind, OMPVersion);
25762 continue;
25763 }
25764
25765 // target exit_data
25766 // OpenMP [2.10.3, Restrictions, p. 102]
25767 // A map-type must be specified in all map clauses and must be either
25768 // from, release, or delete. Starting with OpenMP 5.2 the default map
25769 // type is `from` if no map type is present.
25770 if (DKind == OMPD_target_exit_data &&
25771 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
25772 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
25773 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
25774 << (IsMapTypeImplicit ? 1 : 0)
25775 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
25776 << getOpenMPDirectiveName(DKind, OMPVersion);
25777 continue;
25778 }
25779
25780 // The 'ompx_hold' modifier is specifically intended to be used on a
25781 // 'target' or 'target data' directive to prevent data from being unmapped
25782 // during the associated statement. It is not permitted on a 'target
25783 // enter data' or 'target exit data' directive, which have no associated
25784 // statement.
25785 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
25786 HasHoldModifier) {
25787 SemaRef.Diag(StartLoc,
25788 diag::err_omp_invalid_map_type_modifier_for_directive)
25790 OMPC_MAP_MODIFIER_ompx_hold)
25791 << getOpenMPDirectiveName(DKind, OMPVersion);
25792 continue;
25793 }
25794
25795 // target, target data
25796 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
25797 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
25798 // A map-type in a map clause must be to, from, tofrom or alloc
25799 if ((DKind == OMPD_target_data ||
25801 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
25802 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
25803 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
25804 << (IsMapTypeImplicit ? 1 : 0)
25805 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
25806 << getOpenMPDirectiveName(DKind, OMPVersion);
25807 continue;
25808 }
25809
25810 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
25811 // A list item cannot appear in both a map clause and a data-sharing
25812 // attribute clause on the same construct
25813 //
25814 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
25815 // A list item cannot appear in both a map clause and a data-sharing
25816 // attribute clause on the same construct unless the construct is a
25817 // combined construct.
25818 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
25820 DKind == OMPD_target)) {
25821 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
25822 if (isOpenMPPrivate(DVar.CKind)) {
25823 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
25824 << getOpenMPClauseNameForDiag(DVar.CKind)
25825 << getOpenMPClauseNameForDiag(OMPC_map)
25826 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
25827 OMPVersion);
25828 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
25829 continue;
25830 }
25831 }
25832 }
25833
25834 // Try to find the associated user-defined mapper.
25836 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
25837 Type.getCanonicalType(), UnresolvedMapper, ELoc);
25838 if (ER.isInvalid())
25839 continue;
25840
25841 // If no user-defined mapper is found, we need to create an implicit one for
25842 // arrays/array-sections on structs that have members that have
25843 // user-defined mappers. This is needed to ensure that the mapper for the
25844 // member is invoked when mapping each element of the array/array-section.
25845 if (!ER.get()) {
25846 QualType BaseType;
25847
25849 BaseType = VE->getType().getCanonicalType();
25850 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
25851 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
25852 QualType BType =
25854 QualType ElemType;
25855 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
25856 ElemType = ATy->getElementType();
25857 else
25858 ElemType = BType->getPointeeType();
25859 BaseType = ElemType.getCanonicalType();
25860 }
25861 } else if (VE->getType()->isArrayType()) {
25862 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
25863 const QualType ElemType = AT->getElementType();
25864 BaseType = ElemType.getCanonicalType();
25865 }
25866
25867 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
25868 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
25869 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
25870 }
25871 }
25872 MVLI.UDMapperList.push_back(ER.get());
25873
25874 // Save the current expression.
25875 MVLI.ProcessedVarList.push_back(RE);
25876
25877 // Store the components in the stack so that they can be used to check
25878 // against other clauses later on.
25879 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
25880 /*WhereFoundClauseKind=*/OMPC_map);
25881
25882 // Save the components and declaration to create the clause. For purposes of
25883 // the clause creation, any component list that has base 'this' uses
25884 // null as base declaration.
25885 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25886 MVLI.VarComponents.back().append(CurComponents.begin(),
25887 CurComponents.end());
25888 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
25889 : CurDeclaration);
25890 }
25891}
25892
25894 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
25895 ArrayRef<SourceLocation> MapTypeModifiersLoc,
25896 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
25897 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
25898 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
25899 const OMPVarListLocTy &Locs, bool NoDiagnose,
25900 ArrayRef<Expr *> UnresolvedMappers) {
25901 OpenMPMapModifierKind Modifiers[] = {
25907
25908 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
25909 BuiltinType::OMPIterator))
25910 Diag(IteratorModifier->getExprLoc(),
25911 diag::err_omp_map_modifier_not_iterator);
25912
25913 // Process map-type-modifiers, flag errors for duplicate modifiers.
25914 unsigned Count = 0;
25915 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
25916 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
25917 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
25918 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
25919 continue;
25920 }
25921 assert(Count < NumberOfOMPMapClauseModifiers &&
25922 "Modifiers exceed the allowed number of map type modifiers");
25923 Modifiers[Count] = MapTypeModifiers[I];
25924 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
25925 ++Count;
25926 }
25927
25928 MappableVarListInfo MVLI(VarList);
25929 // Per OpenMP 6.0 p299 lines 3-4, a list item with the const specifier and
25930 // no mutable members is ignored for 'from' clauses. A const-qualified
25931 // variable cannot be modified on the device, so copying back to the host
25932 // is unnecessary and potentially unsafe. Strip the FROM component:
25933 // map(tofrom:) -> map(to:), map(from:) -> map(alloc:).
25934 for (auto *E : VarList) {
25935 if ((MapType == OMPC_MAP_from || MapType == OMPC_MAP_tofrom) &&
25937 MapType = (MapType == OMPC_MAP_tofrom) ? OMPC_MAP_to : OMPC_MAP_alloc;
25938 }
25940 MapperIdScopeSpec, MapperId, UnresolvedMappers,
25941 MapType, Modifiers, IsMapTypeImplicit,
25942 NoDiagnose);
25943
25944 // We need to produce a map clause even if we don't have variables so that
25945 // other diagnostics related with non-existing map clauses are accurate.
25946 return OMPMapClause::Create(
25947 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25948 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
25949 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
25950 MapperId, MapType, IsMapTypeImplicit, MapLoc);
25951}
25952
25955 assert(ParsedType.isUsable());
25956
25957 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
25958 if (ReductionType.isNull())
25959 return QualType();
25960
25961 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
25962 // A type name in a declare reduction directive cannot be a function type, an
25963 // array type, a reference type, or a type qualified with const, volatile or
25964 // restrict.
25965 if (ReductionType.hasQualifiers()) {
25966 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
25967 return QualType();
25968 }
25969
25970 if (ReductionType->isFunctionType()) {
25971 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
25972 return QualType();
25973 }
25974 if (ReductionType->isReferenceType()) {
25975 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
25976 return QualType();
25977 }
25978 if (ReductionType->isArrayType()) {
25979 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
25980 return QualType();
25981 }
25982 return ReductionType;
25983}
25984
25987 Scope *S, DeclContext *DC, DeclarationName Name,
25988 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
25989 AccessSpecifier AS, Decl *PrevDeclInScope) {
25991 Decls.reserve(ReductionTypes.size());
25992
25993 LookupResult Lookup(SemaRef, Name, SourceLocation(),
25995 SemaRef.forRedeclarationInCurContext());
25996 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
25997 // A reduction-identifier may not be re-declared in the current scope for the
25998 // same type or for a type that is compatible according to the base language
25999 // rules.
26000 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
26001 OMPDeclareReductionDecl *PrevDRD = nullptr;
26002 bool InCompoundScope = true;
26003 if (S != nullptr) {
26004 // Find previous declaration with the same name not referenced in other
26005 // declarations.
26006 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
26007 InCompoundScope =
26008 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
26009 SemaRef.LookupName(Lookup, S);
26010 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
26011 /*AllowInlineNamespace=*/false);
26012 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
26013 LookupResult::Filter Filter = Lookup.makeFilter();
26014 while (Filter.hasNext()) {
26015 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
26016 if (InCompoundScope) {
26017 UsedAsPrevious.try_emplace(PrevDecl, false);
26018 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
26019 UsedAsPrevious[D] = true;
26020 }
26021 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
26022 PrevDecl->getLocation();
26023 }
26024 Filter.done();
26025 if (InCompoundScope) {
26026 for (const auto &PrevData : UsedAsPrevious) {
26027 if (!PrevData.second) {
26028 PrevDRD = PrevData.first;
26029 break;
26030 }
26031 }
26032 }
26033 } else if (PrevDeclInScope != nullptr) {
26034 auto *PrevDRDInScope = PrevDRD =
26035 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
26036 do {
26037 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
26038 PrevDRDInScope->getLocation();
26039 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
26040 } while (PrevDRDInScope != nullptr);
26041 }
26042 for (const auto &TyData : ReductionTypes) {
26043 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
26044 bool Invalid = false;
26045 if (I != PreviousRedeclTypes.end()) {
26046 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
26047 << TyData.first;
26048 Diag(I->second, diag::note_previous_definition);
26049 Invalid = true;
26050 }
26051 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
26053 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
26054 DC->addDecl(DRD);
26055 DRD->setAccess(AS);
26056 Decls.push_back(DRD);
26057 if (Invalid)
26058 DRD->setInvalidDecl();
26059 else
26060 PrevDRD = DRD;
26061 }
26062
26063 return DeclGroupPtrTy::make(
26064 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
26065}
26066
26068 auto *DRD = cast<OMPDeclareReductionDecl>(D);
26069
26070 // Enter new function scope.
26071 SemaRef.PushFunctionScope();
26072 SemaRef.setFunctionHasBranchProtectedScope();
26073 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
26074
26075 if (S != nullptr)
26076 SemaRef.PushDeclContext(S, DRD);
26077 else
26078 SemaRef.CurContext = DRD;
26079
26080 SemaRef.PushExpressionEvaluationContext(
26082
26083 QualType ReductionType = DRD->getType();
26084 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
26085 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
26086 // uses semantics of argument handles by value, but it should be passed by
26087 // reference. C lang does not support references, so pass all parameters as
26088 // pointers.
26089 // Create 'T omp_in;' variable.
26090 VarDecl *OmpInParm =
26091 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
26092 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
26093 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
26094 // uses semantics of argument handles by value, but it should be passed by
26095 // reference. C lang does not support references, so pass all parameters as
26096 // pointers.
26097 // Create 'T omp_out;' variable.
26098 VarDecl *OmpOutParm =
26099 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
26100 if (S != nullptr) {
26101 SemaRef.PushOnScopeChains(OmpInParm, S);
26102 SemaRef.PushOnScopeChains(OmpOutParm, S);
26103 } else {
26104 DRD->addDecl(OmpInParm);
26105 DRD->addDecl(OmpOutParm);
26106 }
26107 Expr *InE =
26108 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
26109 Expr *OutE =
26110 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
26111 DRD->setCombinerData(InE, OutE);
26112}
26113
26115 Expr *Combiner) {
26116 auto *DRD = cast<OMPDeclareReductionDecl>(D);
26117 SemaRef.DiscardCleanupsInEvaluationContext();
26118 SemaRef.PopExpressionEvaluationContext();
26119
26120 SemaRef.PopDeclContext();
26121 SemaRef.PopFunctionScopeInfo();
26122
26123 if (Combiner != nullptr)
26124 DRD->setCombiner(Combiner);
26125 else
26126 DRD->setInvalidDecl();
26127}
26128
26130 Decl *D) {
26131 auto *DRD = cast<OMPDeclareReductionDecl>(D);
26132
26133 // Enter new function scope.
26134 SemaRef.PushFunctionScope();
26135 SemaRef.setFunctionHasBranchProtectedScope();
26136
26137 if (S != nullptr)
26138 SemaRef.PushDeclContext(S, DRD);
26139 else
26140 SemaRef.CurContext = DRD;
26141
26142 SemaRef.PushExpressionEvaluationContext(
26144
26145 QualType ReductionType = DRD->getType();
26146 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
26147 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
26148 // uses semantics of argument handles by value, but it should be passed by
26149 // reference. C lang does not support references, so pass all parameters as
26150 // pointers.
26151 // Create 'T omp_priv;' variable.
26152 VarDecl *OmpPrivParm =
26153 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
26154 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
26155 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
26156 // uses semantics of argument handles by value, but it should be passed by
26157 // reference. C lang does not support references, so pass all parameters as
26158 // pointers.
26159 // Create 'T omp_orig;' variable.
26160 VarDecl *OmpOrigParm =
26161 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
26162 if (S != nullptr) {
26163 SemaRef.PushOnScopeChains(OmpPrivParm, S);
26164 SemaRef.PushOnScopeChains(OmpOrigParm, S);
26165 } else {
26166 DRD->addDecl(OmpPrivParm);
26167 DRD->addDecl(OmpOrigParm);
26168 }
26169 Expr *OrigE =
26170 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
26171 Expr *PrivE =
26172 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
26173 DRD->setInitializerData(OrigE, PrivE);
26174 return OmpPrivParm;
26175}
26176
26178 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
26179 auto *DRD = cast<OMPDeclareReductionDecl>(D);
26180
26181 // Ensure OmpPrivParm is default-constructed before the user initializer runs
26182 // (required for class types with non-trivial default constructors).
26183 if (Initializer && !DRD->getDeclContext()->isDependentContext()) {
26184 QualType ReductionType = DRD->getType();
26185 if (CXXRecordDecl *RD = ReductionType->getAsCXXRecordDecl()) {
26186 if (!RD->hasTrivialDefaultConstructor())
26187 SemaRef.ActOnUninitializedDecl(OmpPrivParm);
26188 }
26189 }
26190
26191 SemaRef.DiscardCleanupsInEvaluationContext();
26192 SemaRef.PopExpressionEvaluationContext();
26193
26194 SemaRef.PopDeclContext();
26195 SemaRef.PopFunctionScopeInfo();
26196
26197 if (Initializer != nullptr) {
26198 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
26199 } else if (OmpPrivParm->hasInit()) {
26200 DRD->setInitializer(OmpPrivParm->getInit(),
26201 OmpPrivParm->isDirectInit()
26204 } else {
26205 DRD->setInvalidDecl();
26206 }
26207}
26208
26210 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
26211 for (Decl *D : DeclReductions.get()) {
26212 if (IsValid) {
26213 if (S)
26214 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
26215 /*AddToContext=*/false);
26216 } else {
26217 D->setInvalidDecl();
26218 }
26219 }
26220 return DeclReductions;
26221}
26222
26224 Declarator &D) {
26225 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
26226 QualType T = TInfo->getType();
26227 if (D.isInvalidType())
26228 return true;
26229
26230 if (getLangOpts().CPlusPlus) {
26231 // Check that there are no default arguments (C++ only).
26232 SemaRef.CheckExtraCXXDefaultArguments(D);
26233 }
26234
26235 return SemaRef.CreateParsedType(T, TInfo);
26236}
26237
26240 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
26241
26242 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
26243 assert(!MapperType.isNull() && "Expect valid mapper type");
26244
26245 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
26246 // The type must be of struct, union or class type in C and C++
26247 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
26248 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
26249 return QualType();
26250 }
26251 return MapperType;
26252}
26253
26255 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
26257 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
26258 LookupResult Lookup(SemaRef, Name, SourceLocation(),
26260 SemaRef.forRedeclarationInCurContext());
26261 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
26262 // A mapper-identifier may not be redeclared in the current scope for the
26263 // same type or for a type that is compatible according to the base language
26264 // rules.
26265 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
26266 OMPDeclareMapperDecl *PrevDMD = nullptr;
26267 bool InCompoundScope = true;
26268 if (S != nullptr) {
26269 // Find previous declaration with the same name not referenced in other
26270 // declarations.
26271 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
26272 InCompoundScope =
26273 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
26274 SemaRef.LookupName(Lookup, S);
26275 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
26276 /*AllowInlineNamespace=*/false);
26277 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
26278 LookupResult::Filter Filter = Lookup.makeFilter();
26279 while (Filter.hasNext()) {
26280 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
26281 if (InCompoundScope) {
26282 UsedAsPrevious.try_emplace(PrevDecl, false);
26283 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
26284 UsedAsPrevious[D] = true;
26285 }
26286 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
26287 PrevDecl->getLocation();
26288 }
26289 Filter.done();
26290 if (InCompoundScope) {
26291 for (const auto &PrevData : UsedAsPrevious) {
26292 if (!PrevData.second) {
26293 PrevDMD = PrevData.first;
26294 break;
26295 }
26296 }
26297 }
26298 } else if (PrevDeclInScope) {
26299 auto *PrevDMDInScope = PrevDMD =
26300 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
26301 do {
26302 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
26303 PrevDMDInScope->getLocation();
26304 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
26305 } while (PrevDMDInScope != nullptr);
26306 }
26307 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
26308 bool Invalid = false;
26309 if (I != PreviousRedeclTypes.end()) {
26310 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
26311 << MapperType << Name;
26312 Diag(I->second, diag::note_previous_definition);
26313 Invalid = true;
26314 }
26315 // Build expressions for implicit maps of data members with 'default'
26316 // mappers.
26317 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
26318 if (getLangOpts().OpenMP >= 50)
26320 ClausesWithImplicit);
26321 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
26322 MapperType, VN, ClausesWithImplicit,
26323 PrevDMD);
26324 if (S)
26325 SemaRef.PushOnScopeChains(DMD, S);
26326 else
26327 DC->addDecl(DMD);
26328 DMD->setAccess(AS);
26329 if (Invalid)
26330 DMD->setInvalidDecl();
26331
26332 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
26333 VD->setDeclContext(DMD);
26334 VD->setLexicalDeclContext(DMD);
26335 DMD->addDecl(VD);
26336 DMD->setMapperVarRef(MapperVarRef);
26337
26339}
26340
26342 Scope *S, QualType MapperType, SourceLocation StartLoc,
26343 DeclarationName VN) {
26344 TypeSourceInfo *TInfo =
26345 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
26346 auto *VD = VarDecl::Create(
26347 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
26348 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
26349 if (S)
26350 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
26351 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
26352 DSAStack->addDeclareMapperVarRef(E);
26353 return E;
26354}
26355
26357 bool IsGlobalVar =
26359 if (DSAStack->getDeclareMapperVarRef()) {
26360 if (IsGlobalVar)
26361 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
26362 DSAStack->addIteratorVarDecl(VD);
26363 } else {
26364 // Currently, only declare mapper handles global-scope iterator vars.
26365 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
26366 }
26367}
26368
26370 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
26371 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
26372 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
26373 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
26374 return true;
26376 return true;
26377 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
26378 return true;
26379 return false;
26380 }
26381 return true;
26382}
26383
26385 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
26386 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
26387}
26388
26390 int Modifier, Expr *ModifierExpr,
26391 SourceLocation ModifierLoc,
26392 ArrayRef<Expr *> VarList,
26393 SourceLocation VarListEndLoc) {
26394 assert(ModifierExpr && "Unexpected modifier expression.");
26395
26396 if (getLangOpts().OpenMP < 61) {
26397 Diag(ModifierLoc, diag::err_omp_modifier_requires_version)
26398 << getOpenMPSimpleClauseTypeName(ClauseKind, Modifier)
26399 << getOpenMPClauseName(ClauseKind) << "6.1";
26400 return ExprError();
26401 }
26402
26404 ModifierExpr, ClauseKind, /*StrictlyPositive=*/true,
26405 /*SuppressExprDiags=*/false);
26406 if (DimsRes.isInvalid())
26407 return ExprError();
26408
26409 ModifierExpr = DimsRes.get();
26410 if (ModifierExpr->isInstantiationDependent())
26411 return DimsRes;
26412
26413 uint64_t NumDims =
26414 ModifierExpr->EvaluateKnownConstInt(getASTContext()).getExtValue();
26415 if (NumDims == VarList.size())
26416 return DimsRes;
26417
26418 Diag(VarListEndLoc, diag::err_omp_unexpected_num_exprs)
26419 << getOpenMPClauseName(ClauseKind) << NumDims << VarList.size();
26420 return ExprError();
26421}
26422
26425 Expr *ModifierExpr, SourceLocation ModifierLoc,
26426 OpenMPNumTeamsClauseModifier ModifierExtra, Expr *,
26427 SourceLocation ModifierExtraLoc, SourceLocation StartLoc,
26428 SourceLocation LParenLoc, SourceLocation EndLoc) {
26429 if (VarList.empty())
26430 return nullptr;
26431
26432 for (Expr *ValExpr : VarList) {
26433 // OpenMP [teams Construct, Restrictions]
26434 // The num_teams expression must evaluate to a positive integer value.
26435 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
26436 /*StrictlyPositive=*/true))
26437 return nullptr;
26438 }
26439
26440 // OpenMP [teams Construct, Restrictions]
26441 // The lower-bound modifier cannot be specified if the dims modifier is
26442 // specified.
26443 if (Modifier != OMPC_NUMTEAMS_unknown &&
26444 ModifierExtra != OMPC_NUMTEAMS_unknown) {
26445 Diag(ModifierExtraLoc, diag::err_omp_incompatible_modifiers)
26446 << getOpenMPSimpleClauseTypeName(llvm::omp::OMPC_num_teams,
26447 ModifierExtra)
26448 << getOpenMPSimpleClauseTypeName(llvm::omp::OMPC_num_teams, Modifier)
26449 << getOpenMPClauseName(llvm::omp::OMPC_num_teams);
26450 ModifierExtra = OMPC_NUMTEAMS_unknown;
26451 ModifierExtraLoc = SourceLocation();
26452 }
26453
26454 if (Modifier == OMPC_NUMTEAMS_dims) {
26456 OMPC_num_teams, Modifier, ModifierExpr, ModifierLoc, VarList, EndLoc);
26457 if (Res.isInvalid())
26458 return nullptr;
26459 ModifierExpr = Res.get();
26460 } else if (Modifier == OMPC_NUMTEAMS_lower_bound) {
26461 assert(ModifierExpr && "Unexpected modifier expression.");
26462
26463 if (getLangOpts().OpenMP < 51) {
26464 Diag(ModifierLoc, diag::err_omp_modifier_requires_version)
26465 << getOpenMPSimpleClauseTypeName(llvm::omp::OMPC_num_teams, Modifier)
26466 << getOpenMPClauseName(llvm::omp::OMPC_num_teams) << "5.1";
26467 return nullptr;
26468 }
26469
26470 // OpenMP [teams Construct, Restrictions]
26471 // The lower-bound expression in num_teams must evaluate to a positive
26472 // integer value.
26473 if (!isNonNegativeIntegerValue(ModifierExpr, SemaRef, OMPC_num_teams,
26474 /*StrictlyPositive=*/true))
26475 return nullptr;
26476
26477 // OpenMP 5.2: Validate lower-bound is less than or equal to upper-bound.
26478 Expr *LowerBound = ModifierExpr;
26479 Expr *UpperBound = VarList[0];
26480
26481 // Check if both are compile-time constants for validation.
26482 if (!LowerBound->isValueDependent() && !UpperBound->isValueDependent() &&
26483 LowerBound->isIntegerConstantExpr(getASTContext()) &&
26484 UpperBound->isIntegerConstantExpr(getASTContext())) {
26485
26486 // Get the actual constant values.
26487 llvm::APSInt LowerVal =
26488 LowerBound->EvaluateKnownConstInt(getASTContext());
26489 llvm::APSInt UpperVal =
26490 UpperBound->EvaluateKnownConstInt(getASTContext());
26491
26492 if (LowerVal > UpperVal) {
26493 Diag(LowerBound->getExprLoc(),
26494 diag::err_omp_num_teams_lower_bound_larger)
26495 << LowerBound->getSourceRange() << UpperBound->getSourceRange();
26496 return nullptr;
26497 }
26498 }
26499 }
26500
26501 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26503 DKind, OMPC_num_teams, getLangOpts().getOpenMPVersion());
26504 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
26505 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
26506 LParenLoc, EndLoc, VarList, Modifier,
26507 ModifierExpr, ModifierLoc,
26508 /*PreInit=*/nullptr);
26509
26510 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26512 for (Expr *ValExpr : VarList) {
26513 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
26514 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
26515 Vars.push_back(ValExpr);
26516 }
26517
26518 if (ModifierExpr) {
26519 ModifierExpr = SemaRef.MakeFullExpr(ModifierExpr).get();
26520 ModifierExpr = tryBuildCapture(SemaRef, ModifierExpr, Captures).get();
26521 }
26522
26523 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
26524 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
26525 LParenLoc, EndLoc, Vars, Modifier,
26526 ModifierExpr, ModifierLoc, PreInit);
26527}
26528
26531 Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc,
26532 SourceLocation LParenLoc, SourceLocation EndLoc) {
26533 if (VarList.empty())
26534 return nullptr;
26535
26536 for (Expr *ValExpr : VarList) {
26537 // OpenMP [teams Constrcut, Restrictions]
26538 // The thread_limit expression must evaluate to a positive integer value.
26539 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
26540 /*StrictlyPositive=*/true))
26541 return nullptr;
26542 }
26543
26544 if (Modifier == OMPC_THREADLIMIT_dims) {
26545 ExprResult Res =
26546 ActOnOpenMPDimsModifier(OMPC_thread_limit, Modifier, ModifierExpr,
26547 ModifierLoc, VarList, EndLoc);
26548 if (Res.isInvalid())
26549 return nullptr;
26550 ModifierExpr = Res.get();
26551 }
26552
26553 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
26555 DKind, OMPC_thread_limit, getLangOpts().getOpenMPVersion());
26556 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
26557 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
26558 StartLoc, LParenLoc, EndLoc, VarList,
26559 Modifier, ModifierExpr, ModifierLoc,
26560 /*PreInit=*/nullptr);
26561
26562 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26564 for (Expr *ValExpr : VarList) {
26565 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
26566 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
26567 Vars.push_back(ValExpr);
26568 }
26569
26570 if (ModifierExpr) {
26571 ModifierExpr = SemaRef.MakeFullExpr(ModifierExpr).get();
26572 ModifierExpr = tryBuildCapture(SemaRef, ModifierExpr, Captures).get();
26573 }
26574
26575 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
26576 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
26577 LParenLoc, EndLoc, Vars, Modifier,
26578 ModifierExpr, ModifierLoc, PreInit);
26579}
26580
26582 SourceLocation StartLoc,
26583 SourceLocation LParenLoc,
26584 SourceLocation EndLoc) {
26585 Expr *ValExpr = Priority;
26586 Stmt *HelperValStmt = nullptr;
26587 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
26588
26589 // OpenMP [2.9.1, task Constrcut]
26590 // The priority-value is a non-negative numerical scalar expression.
26592 ValExpr, SemaRef, OMPC_priority,
26593 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
26594 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
26595 return nullptr;
26596
26597 return new (getASTContext()) OMPPriorityClause(
26598 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
26599}
26600
26602 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
26603 SourceLocation StartLoc, SourceLocation LParenLoc,
26604 SourceLocation ModifierLoc, SourceLocation EndLoc) {
26605 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
26606 "Unexpected grainsize modifier in OpenMP < 51.");
26607
26608 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
26609 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
26611 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
26612 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
26613 return nullptr;
26614 }
26615
26616 Expr *ValExpr = Grainsize;
26617 Stmt *HelperValStmt = nullptr;
26618 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
26619
26620 // OpenMP [2.9.2, taskloop Constrcut]
26621 // The parameter of the grainsize clause must be a positive integer
26622 // expression.
26623 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
26624 /*StrictlyPositive=*/true,
26625 /*BuildCapture=*/true,
26626 DSAStack->getCurrentDirective(),
26627 &CaptureRegion, &HelperValStmt))
26628 return nullptr;
26629
26630 return new (getASTContext())
26631 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
26632 StartLoc, LParenLoc, ModifierLoc, EndLoc);
26633}
26634
26636 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
26637 SourceLocation StartLoc, SourceLocation LParenLoc,
26638 SourceLocation ModifierLoc, SourceLocation EndLoc) {
26639 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
26640 "Unexpected num_tasks modifier in OpenMP < 51.");
26641
26642 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
26643 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
26645 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
26646 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
26647 return nullptr;
26648 }
26649
26650 Expr *ValExpr = NumTasks;
26651 Stmt *HelperValStmt = nullptr;
26652 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
26653
26654 // OpenMP [2.9.2, taskloop Constrcut]
26655 // The parameter of the num_tasks clause must be a positive integer
26656 // expression.
26658 ValExpr, SemaRef, OMPC_num_tasks,
26659 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
26660 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
26661 return nullptr;
26662
26663 return new (getASTContext())
26664 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
26665 StartLoc, LParenLoc, ModifierLoc, EndLoc);
26666}
26667
26669 SourceLocation StartLoc,
26670 SourceLocation LParenLoc,
26671 SourceLocation EndLoc) {
26672 // OpenMP [2.13.2, critical construct, Description]
26673 // ... where hint-expression is an integer constant expression that evaluates
26674 // to a valid lock hint.
26675 ExprResult HintExpr =
26676 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
26677 if (HintExpr.isInvalid())
26678 return nullptr;
26679 return new (getASTContext())
26680 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
26681}
26682
26683/// Tries to find omp_event_handle_t type.
26685 DSAStackTy *Stack) {
26686 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
26687 if (!OMPEventHandleT.isNull())
26688 return true;
26689 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
26690 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
26691 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
26692 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
26693 return false;
26694 }
26695 Stack->setOMPEventHandleT(PT.get());
26696 return true;
26697}
26698
26700 SourceLocation StartLoc,
26701 SourceLocation LParenLoc,
26702 SourceLocation EndLoc) {
26703 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
26704 !Evt->isInstantiationDependent() &&
26707 return nullptr;
26708 // OpenMP 5.0, 2.10.1 task Construct.
26709 // event-handle is a variable of the omp_event_handle_t type.
26710 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
26711 if (!Ref) {
26712 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
26713 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
26714 return nullptr;
26715 }
26716 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
26717 if (!VD) {
26718 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
26719 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
26720 return nullptr;
26721 }
26722 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
26723 VD->getType()) ||
26724 VD->getType().isConstant(getASTContext())) {
26725 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
26726 << "omp_event_handle_t" << 1 << VD->getType()
26727 << Evt->getSourceRange();
26728 return nullptr;
26729 }
26730 // OpenMP 5.0, 2.10.1 task Construct
26731 // [detach clause]... The event-handle will be considered as if it was
26732 // specified on a firstprivate clause.
26733 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
26734 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
26735 DVar.RefExpr) {
26736 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
26737 << getOpenMPClauseNameForDiag(DVar.CKind)
26738 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
26740 return nullptr;
26741 }
26742 }
26743
26744 return new (getASTContext())
26745 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
26746}
26747
26749 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
26750 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
26751 SourceLocation EndLoc) {
26752 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
26753 std::string Values;
26754 Values += "'";
26755 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
26756 Values += "'";
26757 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26758 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
26759 return nullptr;
26760 }
26761 Expr *ValExpr = ChunkSize;
26762 Stmt *HelperValStmt = nullptr;
26763 if (ChunkSize) {
26764 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
26765 !ChunkSize->isInstantiationDependent() &&
26766 !ChunkSize->containsUnexpandedParameterPack()) {
26767 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
26768 ExprResult Val =
26769 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
26770 if (Val.isInvalid())
26771 return nullptr;
26772
26773 ValExpr = Val.get();
26774
26775 // OpenMP [2.7.1, Restrictions]
26776 // chunk_size must be a loop invariant integer expression with a positive
26777 // value.
26778 if (std::optional<llvm::APSInt> Result =
26780 if (Result->isSigned() && !Result->isStrictlyPositive()) {
26781 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
26782 << "dist_schedule" << /*strictly positive*/ 1
26783 << ChunkSize->getSourceRange();
26784 return nullptr;
26785 }
26787 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
26788 getLangOpts().getOpenMPVersion()) != OMPD_unknown &&
26789 !SemaRef.CurContext->isDependentContext()) {
26790 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
26791 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
26792 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
26793 HelperValStmt = buildPreInits(getASTContext(), Captures);
26794 }
26795 }
26796 }
26797
26798 return new (getASTContext())
26799 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
26800 Kind, ValExpr, HelperValStmt);
26801}
26802
26805 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
26806 SourceLocation KindLoc, SourceLocation EndLoc) {
26807 if (getLangOpts().OpenMP < 50) {
26808 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
26809 Kind != OMPC_DEFAULTMAP_scalar) {
26810 std::string Value;
26811 SourceLocation Loc;
26812 Value += "'";
26813 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
26814 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
26815 OMPC_DEFAULTMAP_MODIFIER_tofrom);
26816 Loc = MLoc;
26817 } else {
26818 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
26819 OMPC_DEFAULTMAP_scalar);
26820 Loc = KindLoc;
26821 }
26822 Value += "'";
26823 Diag(Loc, diag::err_omp_unexpected_clause_value)
26824 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26825 return nullptr;
26826 }
26827 } else {
26828 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
26829 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
26830 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
26831 if (!isDefaultmapKind || !isDefaultmapModifier) {
26832 StringRef KindValue = getLangOpts().OpenMP < 52
26833 ? "'scalar', 'aggregate', 'pointer'"
26834 : "'scalar', 'aggregate', 'pointer', 'all'";
26835 if (getLangOpts().OpenMP == 50) {
26836 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
26837 "'firstprivate', 'none', 'default'";
26838 if (!isDefaultmapKind && isDefaultmapModifier) {
26839 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26840 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26841 } else if (isDefaultmapKind && !isDefaultmapModifier) {
26842 Diag(MLoc, diag::err_omp_unexpected_clause_value)
26843 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26844 } else {
26845 Diag(MLoc, diag::err_omp_unexpected_clause_value)
26846 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26847 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26848 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26849 }
26850 } else {
26851 StringRef ModifierValue =
26852 getLangOpts().OpenMP < 60
26853 ? "'alloc', 'from', 'to', 'tofrom', "
26854 "'firstprivate', 'none', 'default', 'present'"
26855 : "'storage', 'from', 'to', 'tofrom', "
26856 "'firstprivate', 'private', 'none', 'default', 'present'";
26857 if (!isDefaultmapKind && isDefaultmapModifier) {
26858 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26859 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26860 } else if (isDefaultmapKind && !isDefaultmapModifier) {
26861 Diag(MLoc, diag::err_omp_unexpected_clause_value)
26862 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26863 } else {
26864 Diag(MLoc, diag::err_omp_unexpected_clause_value)
26865 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26866 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
26867 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
26868 }
26869 }
26870 return nullptr;
26871 }
26872
26873 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
26874 // At most one defaultmap clause for each category can appear on the
26875 // directive.
26876 if (DSAStack->checkDefaultmapCategory(Kind)) {
26877 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
26878 return nullptr;
26879 }
26880 }
26881 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
26882 // Variable category is not specified - mark all categories.
26883 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
26884 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
26885 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
26886 } else {
26887 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
26888 }
26889
26890 return new (getASTContext())
26891 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
26892}
26893
26896 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
26897 if (!CurLexicalContext->isFileContext() &&
26898 !CurLexicalContext->isExternCContext() &&
26899 !CurLexicalContext->isExternCXXContext() &&
26900 !isa<CXXRecordDecl>(CurLexicalContext) &&
26901 !isa<ClassTemplateDecl>(CurLexicalContext) &&
26902 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
26903 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
26904 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
26905 return false;
26906 }
26907
26908 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
26909 if (getLangOpts().HIP)
26910 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
26911
26912 DeclareTargetNesting.push_back(DTCI);
26913 return true;
26914}
26915
26918 assert(!DeclareTargetNesting.empty() &&
26919 "check isInOpenMPDeclareTargetContext() first!");
26920 return DeclareTargetNesting.pop_back_val();
26921}
26922
26925 for (auto &It : DTCI.ExplicitlyMapped)
26926 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
26927}
26928
26930 if (DeclareTargetNesting.empty())
26931 return;
26932 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
26933 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
26934 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
26935 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
26936}
26937
26939 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
26941 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
26942 /*ObjectType=*/QualType(),
26943 /*AllowBuiltinCreation=*/true);
26944
26945 if (Lookup.isAmbiguous())
26946 return nullptr;
26947 Lookup.suppressDiagnostics();
26948
26949 if (!Lookup.isSingleResult()) {
26950 VarOrFuncDeclFilterCCC CCC(SemaRef);
26951 if (TypoCorrection Corrected =
26952 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
26954 SemaRef.diagnoseTypo(Corrected,
26955 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
26956 << Id.getName());
26957 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
26958 return nullptr;
26959 }
26960
26961 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
26962 return nullptr;
26963 }
26964
26965 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
26966 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
26968 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
26969 return nullptr;
26970 }
26971 return ND;
26972}
26973
26975 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
26977 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
26979 "Expected variable, function or function template.");
26980
26981 if (auto *VD = dyn_cast<VarDecl>(ND)) {
26982 // Only global variables can be marked as declare target.
26983 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
26984 !VD->isStaticDataMember()) {
26985 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
26986 << VD->getNameAsString();
26987 return;
26988 }
26989 }
26990 // Diagnose marking after use as it may lead to incorrect diagnosis and
26991 // codegen.
26992 if (getLangOpts().OpenMP >= 50 &&
26993 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
26994 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
26995
26996 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
26997 if (getLangOpts().HIP)
26998 Diag(Loc, diag::warn_hip_omp_target_directives);
26999
27000 // 'local' is incompatible with 'device_type(host)' because 'local'
27001 // variables exist only on the device.
27002 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
27003 DTCI.DT == OMPDeclareTargetDeclAttr::DT_Host) {
27004 Diag(Loc, diag::err_omp_declare_target_local_host_only);
27005 return;
27006 }
27007
27008 // Explicit declare target lists have precedence.
27009 const unsigned Level = -1;
27010
27011 auto *VD = cast<ValueDecl>(ND);
27012 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
27013 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
27014 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
27015 (*ActiveAttr)->getLevel() == Level) {
27016 Diag(Loc, diag::err_omp_device_type_mismatch)
27017 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
27018 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
27019 (*ActiveAttr)->getDevType());
27020 return;
27021 }
27022 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
27023 (*ActiveAttr)->getLevel() == Level) {
27024 Diag(Loc, diag::err_omp_declare_target_var_in_both_clauses)
27025 << ND
27026 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
27027 (*ActiveAttr)->getMapType())
27028 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(MT);
27029 return;
27030 }
27031
27032 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
27033 return;
27034
27035 Expr *IndirectE = nullptr;
27036 bool IsIndirect = false;
27037 if (DTCI.Indirect) {
27038 IndirectE = *DTCI.Indirect;
27039 if (!IndirectE)
27040 IsIndirect = true;
27041 }
27042 // FIXME: 'local' with 'device_type(nohost)' is not yet fully supported
27043 // in codegen. Treat as 'device_type(any)' for now. The variable will
27044 // exist on both host and device, but the host copy is unused.
27045 auto DT = DTCI.DT;
27046 if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
27047 DT == OMPDeclareTargetDeclAttr::DT_NoHost) {
27048 Diag(Loc, diag::warn_omp_declare_target_local_nohost);
27049 DT = OMPDeclareTargetDeclAttr::DT_Any;
27050 }
27051
27052 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
27053 getASTContext(), MT, DT, IndirectE, IsIndirect, Level,
27054 SourceRange(Loc, Loc));
27055 ND->addAttr(A);
27056 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
27057 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
27058 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
27059 if (auto *VD = dyn_cast<VarDecl>(ND);
27060 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
27061 VD->hasGlobalStorage())
27063}
27064
27066 Sema &SemaRef, Decl *D) {
27067 if (!D || !isa<VarDecl>(D))
27068 return;
27069 auto *VD = cast<VarDecl>(D);
27070 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
27071 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
27072 if (SemaRef.LangOpts.OpenMP >= 50 &&
27073 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
27074 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
27075 VD->hasGlobalStorage()) {
27076 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
27077 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
27078 *MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
27079 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
27080 // If a lambda declaration and definition appears between a
27081 // declare target directive and the matching end declare target
27082 // directive, all variables that are captured by the lambda
27083 // expression must also appear in a to clause.
27084 SemaRef.Diag(VD->getLocation(),
27085 diag::err_omp_lambda_capture_in_declare_target_not_to);
27086 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
27087 << VD << 0 << SR;
27088 return;
27089 }
27090 }
27091 if (MapTy)
27092 return;
27093 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
27094 SemaRef.Diag(SL, diag::note_used_here) << SR;
27095}
27096
27098 Sema &SemaRef, DSAStackTy *Stack,
27099 ValueDecl *VD) {
27100 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
27101 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
27102 /*FullCheck=*/false);
27103}
27104
27106 SourceLocation IdLoc) {
27107 if (!D || D->isInvalidDecl())
27108 return;
27109 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
27110 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
27111 if (auto *VD = dyn_cast<VarDecl>(D)) {
27112 // Only global variables can be marked as declare target.
27113 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
27114 !VD->isStaticDataMember())
27115 return;
27116 // 2.10.6: threadprivate variable cannot appear in a declare target
27117 // directive.
27118 if (DSAStack->isThreadPrivate(VD)) {
27119 Diag(SL, diag::err_omp_threadprivate_in_target);
27120 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
27121 return;
27122 }
27123 }
27124 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
27125 D = FTD->getTemplatedDecl();
27126 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
27127 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
27128 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
27129 if (IdLoc.isValid() && Res &&
27130 (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
27131 *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
27132 Diag(IdLoc, diag::err_omp_function_in_target_clause_list)
27133 << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(*Res);
27134 Diag(FD->getLocation(), diag::note_defined_here) << FD;
27135 return;
27136 }
27137 }
27138 if (auto *VD = dyn_cast<ValueDecl>(D)) {
27139 // Problem if any with var declared with incomplete type will be reported
27140 // as normal, so no need to check it here.
27141 if ((E || !VD->getType()->isIncompleteType()) &&
27143 return;
27144 if (!E && isInOpenMPDeclareTargetContext()) {
27145 // Checking declaration inside declare target region.
27146 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
27148 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
27149 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
27150 unsigned Level = DeclareTargetNesting.size();
27151 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
27152 return;
27153 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
27154 Expr *IndirectE = nullptr;
27155 bool IsIndirect = false;
27156 if (DTCI.Indirect) {
27157 IndirectE = *DTCI.Indirect;
27158 if (!IndirectE)
27159 IsIndirect = true;
27160 }
27161 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
27162 getASTContext(),
27163 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
27164 : OMPDeclareTargetDeclAttr::MT_To,
27165 DTCI.DT, IndirectE, IsIndirect, Level,
27166 SourceRange(DTCI.Loc, DTCI.Loc));
27167 D->addAttr(A);
27168 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
27169 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
27170 }
27171 return;
27172 }
27173 }
27174 if (!E)
27175 return;
27177}
27178
27179/// This class visits every VarDecl that the initializer references and adds
27180/// OMPDeclareTargetDeclAttr to each of them.
27181class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
27182 SmallVector<VarDecl *> DeclVector;
27183 Attr *A;
27184
27185public:
27186 /// A StmtVisitor class function that visits all DeclRefExpr and adds
27187 /// OMPDeclareTargetDeclAttr to them.
27189 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
27190 VD->addAttr(A);
27191 DeclVector.push_back(VD);
27192 }
27193 }
27194 /// A function that iterates across each of the Expr's children.
27195 void VisitExpr(Expr *Ex) {
27196 for (auto *Child : Ex->children()) {
27197 Visit(Child);
27198 }
27199 }
27200 /// A function that keeps a record of all the Decls that are variables, has
27201 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
27202 /// each Decl one at a time and use the inherited 'visit' functions to look
27203 /// for DeclRefExpr.
27205 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
27206 DeclVector.push_back(cast<VarDecl>(TD));
27207 llvm::SmallDenseSet<Decl *> Visited;
27208 while (!DeclVector.empty()) {
27209 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
27210 if (!Visited.insert(TargetVarDecl).second)
27211 continue;
27212
27213 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
27214 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
27215 if (Expr *Ex = TargetVarDecl->getInit())
27216 Visit(Ex);
27217 }
27218 }
27219 }
27220};
27221
27222/// Adding OMPDeclareTargetDeclAttr to variables with static storage
27223/// duration that are referenced in the initializer expression list of
27224/// variables with static storage duration in declare target directive.
27226 GlobalDeclRefChecker Checker;
27227 if (isa<VarDecl>(TargetDecl))
27228 Checker.declareTargetInitializer(TargetDecl);
27229}
27230
27232 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
27233 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
27234 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
27235 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
27236 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
27241
27242 // Process motion-modifiers, flag errors for duplicate modifiers.
27243 unsigned Count = 0;
27244 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
27245 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
27246 llvm::is_contained(Modifiers, MotionModifiers[I])) {
27247 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
27248 continue;
27249 }
27250 assert(Count < NumberOfOMPMotionModifiers &&
27251 "Modifiers exceed the allowed number of motion modifiers");
27252 Modifiers[Count] = MotionModifiers[I];
27253 ModifiersLoc[Count] = MotionModifiersLoc[I];
27254 ++Count;
27255 }
27256
27257 MappableVarListInfo MVLI(VarList);
27259 MapperIdScopeSpec, MapperId, UnresolvedMappers);
27260 if (MVLI.ProcessedVarList.empty())
27261 return nullptr;
27262 if (IteratorExpr)
27263 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
27264 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
27265 DSAStack->addIteratorVarDecl(VD);
27266 return OMPToClause::Create(
27267 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27268 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
27269 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
27270 MapperId);
27271}
27272
27274 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
27275 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
27276 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
27277 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
27278 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
27283
27284 // Process motion-modifiers, flag errors for duplicate modifiers.
27285 unsigned Count = 0;
27286 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
27287 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
27288 llvm::is_contained(Modifiers, MotionModifiers[I])) {
27289 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
27290 continue;
27291 }
27292 assert(Count < NumberOfOMPMotionModifiers &&
27293 "Modifiers exceed the allowed number of motion modifiers");
27294 Modifiers[Count] = MotionModifiers[I];
27295 ModifiersLoc[Count] = MotionModifiersLoc[I];
27296 ++Count;
27297 }
27298
27299 MappableVarListInfo MVLI(VarList);
27300 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
27301 MapperIdScopeSpec, MapperId, UnresolvedMappers);
27302 if (MVLI.ProcessedVarList.empty())
27303 return nullptr;
27304 if (IteratorExpr)
27305 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
27306 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
27307 DSAStack->addIteratorVarDecl(VD);
27308 return OMPFromClause::Create(
27309 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27310 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
27311 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
27312 MapperId);
27313}
27314
27316 ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
27317 OpenMPUseDevicePtrFallbackModifier FallbackModifier,
27318 SourceLocation FallbackModifierLoc) {
27319 MappableVarListInfo MVLI(VarList);
27320 SmallVector<Expr *, 8> PrivateCopies;
27322
27323 for (Expr *RefExpr : VarList) {
27324 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
27325 SourceLocation ELoc;
27326 SourceRange ERange;
27327 Expr *SimpleRefExpr = RefExpr;
27328 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
27329 if (Res.second) {
27330 // It will be analyzed later.
27331 MVLI.ProcessedVarList.push_back(RefExpr);
27332 PrivateCopies.push_back(nullptr);
27333 Inits.push_back(nullptr);
27334 }
27335 ValueDecl *D = Res.first;
27336 if (!D)
27337 continue;
27338
27339 QualType Type = D->getType();
27340 Type = Type.getNonReferenceType().getUnqualifiedType();
27341
27342 auto *VD = dyn_cast<VarDecl>(D);
27343
27344 // Item should be a pointer or reference to pointer.
27345 if (!Type->isPointerType()) {
27346 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
27347 << 0 << RefExpr->getSourceRange();
27348 continue;
27349 }
27350
27351 // Build the private variable and the expression that refers to it.
27352 auto VDPrivate =
27353 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
27354 D->hasAttrs() ? &D->getAttrs() : nullptr,
27355 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
27356 if (VDPrivate->isInvalidDecl())
27357 continue;
27358
27359 SemaRef.CurContext->addDecl(VDPrivate);
27360 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
27361 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
27362
27363 // Add temporary variable to initialize the private copy of the pointer.
27364 VarDecl *VDInit =
27365 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
27366 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
27367 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
27368 SemaRef.AddInitializerToDecl(
27369 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
27370 /*DirectInit=*/false);
27371
27372 // If required, build a capture to implement the privatization initialized
27373 // with the current list item value.
27374 DeclRefExpr *Ref = nullptr;
27375 if (!VD)
27376 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
27377 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
27378 PrivateCopies.push_back(VDPrivateRefExpr);
27379 Inits.push_back(VDInitRefExpr);
27380
27381 // We need to add a data sharing attribute for this variable to make sure it
27382 // is correctly captured. A variable that shows up in a use_device_ptr has
27383 // similar properties of a first private variable.
27384 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
27385
27386 // Create a mappable component for the list item. List items in this clause
27387 // only need a component.
27388 MVLI.VarBaseDeclarations.push_back(D);
27389 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
27390 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
27391 /*IsNonContiguous=*/false);
27392 }
27393
27394 if (MVLI.ProcessedVarList.empty())
27395 return nullptr;
27396
27398 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
27399 MVLI.VarBaseDeclarations, MVLI.VarComponents, FallbackModifier,
27400 FallbackModifierLoc);
27401}
27402
27403OMPClause *
27405 const OMPVarListLocTy &Locs) {
27406 MappableVarListInfo MVLI(VarList);
27407
27408 for (Expr *RefExpr : VarList) {
27409 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
27410 SourceLocation ELoc;
27411 SourceRange ERange;
27412 Expr *SimpleRefExpr = RefExpr;
27413 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
27414 /*AllowArraySection=*/true,
27415 /*AllowAssumedSizeArray=*/true);
27416 if (Res.second) {
27417 // It will be analyzed later.
27418 MVLI.ProcessedVarList.push_back(RefExpr);
27419 }
27420 ValueDecl *D = Res.first;
27421 if (!D)
27422 continue;
27423 auto *VD = dyn_cast<VarDecl>(D);
27424
27425 // If required, build a capture to implement the privatization initialized
27426 // with the current list item value.
27427 DeclRefExpr *Ref = nullptr;
27428 if (!VD)
27429 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
27430 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
27431
27432 // We need to add a data sharing attribute for this variable to make sure it
27433 // is correctly captured. A variable that shows up in a use_device_addr has
27434 // similar properties of a first private variable.
27435 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
27436
27437 // Use the map-like approach to fully populate VarComponents
27439
27441 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
27442 DSAStack->getCurrentDirective(),
27443 /*NoDiagnose=*/false);
27444
27445 if (!BE)
27446 continue;
27447
27448 assert(!CurComponents.empty() &&
27449 "use_device_addr clause expression with no components!");
27450
27451 // OpenMP use_device_addr: If a list item is an array section, the array
27452 // base must be a base language identifier. We caught the cases where
27453 // the array-section has a base-variable in getPrivateItem. e.g.
27454 // struct S {
27455 // int a[10];
27456 // }; S s1;
27457 // ... use_device_addr(s1.a[0]) // not ok, caught already
27458 //
27459 // But we still neeed to verify that the base-pointer is also a
27460 // base-language identifier, and catch cases like:
27461 // int *pa[10]; *p;
27462 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
27463 // ... use_device_addr(p[1]) // ok
27464 // ... use_device_addr(this->p[1]) // ok
27466 CurComponents, DSAStack->getCurrentDirective());
27467 const Expr *AttachPtrExpr = AttachPtrResult.first;
27468
27469 if (AttachPtrExpr) {
27470 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
27471 bool IsValidBase = false;
27472
27473 if (isa<DeclRefExpr>(BaseExpr))
27474 IsValidBase = true;
27475 else if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
27477 IsValidBase = true;
27478
27479 if (!IsValidBase) {
27480 SemaRef.Diag(ELoc,
27481 diag::err_omp_expected_base_pointer_var_name_member_expr)
27482 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
27483 << AttachPtrExpr->getSourceRange();
27484 continue;
27485 }
27486 }
27487
27488 // Get the declaration from the components
27489 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
27490 assert((isa<CXXThisExpr>(BE) || CurDeclaration) &&
27491 "Unexpected null decl for use_device_addr clause.");
27492
27493 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
27494 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
27495 MVLI.VarComponents.back().append(CurComponents.begin(),
27496 CurComponents.end());
27497 }
27498
27499 if (MVLI.ProcessedVarList.empty())
27500 return nullptr;
27501
27503 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27504 MVLI.VarComponents);
27505}
27506
27507OMPClause *
27509 const OMPVarListLocTy &Locs) {
27510 MappableVarListInfo MVLI(VarList);
27511 for (Expr *RefExpr : VarList) {
27512 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
27513 SourceLocation ELoc;
27514 SourceRange ERange;
27515 Expr *SimpleRefExpr = RefExpr;
27516 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
27517 if (Res.second) {
27518 // It will be analyzed later.
27519 MVLI.ProcessedVarList.push_back(RefExpr);
27520 }
27521 ValueDecl *D = Res.first;
27522 if (!D)
27523 continue;
27524
27525 QualType Type = D->getType();
27526 // item should be a pointer or array or reference to pointer or array
27527 if (!Type.getNonReferenceType()->isPointerType() &&
27528 !Type.getNonReferenceType()->isArrayType()) {
27529 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
27530 << 0 << RefExpr->getSourceRange();
27531 continue;
27532 }
27533
27534 // Check if the declaration in the clause does not show up in any data
27535 // sharing attribute.
27536 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
27537 if (isOpenMPPrivate(DVar.CKind)) {
27538 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
27539 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
27540 << getOpenMPClauseNameForDiag(DVar.CKind)
27541 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
27542 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
27543 OMPVersion);
27545 continue;
27546 }
27547
27548 const Expr *ConflictExpr;
27549 if (DSAStack->checkMappableExprComponentListsForDecl(
27550 D, /*CurrentRegionOnly=*/true,
27551 [&ConflictExpr](
27553 OpenMPClauseKind) -> bool {
27554 ConflictExpr = R.front().getAssociatedExpression();
27555 return true;
27556 })) {
27557 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
27558 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
27559 << ConflictExpr->getSourceRange();
27560 continue;
27561 }
27562
27563 // Store the components in the stack so that they can be used to check
27564 // against other clauses later on.
27566 SimpleRefExpr, D, /*IsNonContiguous=*/false);
27567 DSAStack->addMappableExpressionComponents(
27568 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
27569
27570 // Record the expression we've just processed.
27571 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
27572
27573 // Create a mappable component for the list item. List items in this clause
27574 // only need a component. We use a null declaration to signal fields in
27575 // 'this'.
27576 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
27577 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
27578 "Unexpected device pointer expression!");
27579 MVLI.VarBaseDeclarations.push_back(
27580 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
27581 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
27582 MVLI.VarComponents.back().push_back(MC);
27583 }
27584
27585 if (MVLI.ProcessedVarList.empty())
27586 return nullptr;
27587
27589 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27590 MVLI.VarComponents);
27591}
27592
27593OMPClause *
27595 const OMPVarListLocTy &Locs) {
27596 MappableVarListInfo MVLI(VarList);
27597 for (Expr *RefExpr : VarList) {
27598 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
27599 SourceLocation ELoc;
27600 SourceRange ERange;
27601 Expr *SimpleRefExpr = RefExpr;
27602 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
27603 /*AllowArraySection=*/true);
27604 if (Res.second) {
27605 // It will be analyzed later.
27606 MVLI.ProcessedVarList.push_back(RefExpr);
27607 }
27608 ValueDecl *D = Res.first;
27609 if (!D)
27610 continue;
27611
27612 // Check if the declaration in the clause does not show up in any data
27613 // sharing attribute.
27614 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
27615 if (isOpenMPPrivate(DVar.CKind)) {
27616 llvm::omp::Version OMPVersion = getLangOpts().getOpenMPVersion();
27617 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
27618 << getOpenMPClauseNameForDiag(DVar.CKind)
27619 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
27620 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
27621 OMPVersion);
27623 continue;
27624 }
27625
27626 const Expr *ConflictExpr;
27627 if (DSAStack->checkMappableExprComponentListsForDecl(
27628 D, /*CurrentRegionOnly=*/true,
27629 [&ConflictExpr](
27631 OpenMPClauseKind) -> bool {
27632 ConflictExpr = R.front().getAssociatedExpression();
27633 return true;
27634 })) {
27635 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
27636 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
27637 << ConflictExpr->getSourceRange();
27638 continue;
27639 }
27640
27641 // Store the components in the stack so that they can be used to check
27642 // against other clauses later on.
27643 Expr *Component = SimpleRefExpr;
27644 auto *VD = dyn_cast<VarDecl>(D);
27645 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
27646 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
27647 Component =
27648 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
27650 Component, D, /*IsNonContiguous=*/false);
27651 DSAStack->addMappableExpressionComponents(
27652 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
27653
27654 // Record the expression we've just processed.
27655 if (!VD && !SemaRef.CurContext->isDependentContext()) {
27656 DeclRefExpr *Ref =
27657 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
27658 assert(Ref && "has_device_addr capture failed");
27659 MVLI.ProcessedVarList.push_back(Ref);
27660 } else
27661 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
27662
27663 // Create a mappable component for the list item. List items in this clause
27664 // only need a component. We use a null declaration to signal fields in
27665 // 'this'.
27666 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
27667 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
27668 "Unexpected device pointer expression!");
27669 MVLI.VarBaseDeclarations.push_back(
27670 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
27671 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
27672 MVLI.VarComponents.back().push_back(MC);
27673 }
27674
27675 if (MVLI.ProcessedVarList.empty())
27676 return nullptr;
27677
27679 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
27680 MVLI.VarComponents);
27681}
27682
27684 Expr *Allocator, Expr *Alignment,
27685 OpenMPAllocateClauseModifier FirstAllocateModifier,
27686 SourceLocation FirstAllocateModifierLoc,
27687 OpenMPAllocateClauseModifier SecondAllocateModifier,
27688 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
27689 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
27690 SourceLocation EndLoc) {
27691 if (Allocator) {
27692 // Allocator expression is dependent - skip it for now and build the
27693 // allocator when instantiated.
27694 bool AllocDependent =
27695 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
27696 Allocator->isInstantiationDependent() ||
27697 Allocator->containsUnexpandedParameterPack());
27698 if (!AllocDependent) {
27699 // OpenMP [2.11.4 allocate Clause, Description]
27700 // allocator is an expression of omp_allocator_handle_t type.
27702 return nullptr;
27703
27704 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
27705 if (AllocatorRes.isInvalid())
27706 return nullptr;
27707 AllocatorRes = SemaRef.PerformImplicitConversion(
27708 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
27710 /*AllowExplicit=*/true);
27711 if (AllocatorRes.isInvalid())
27712 return nullptr;
27713 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
27714 }
27715 } else {
27716 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
27717 // allocate clauses that appear on a target construct or on constructs in a
27718 // target region must specify an allocator expression unless a requires
27719 // directive with the dynamic_allocators clause is present in the same
27720 // compilation unit.
27721 if (getLangOpts().OpenMPIsTargetDevice &&
27722 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
27723 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
27724 }
27725 if (Alignment) {
27726 bool AlignmentDependent = Alignment->isTypeDependent() ||
27727 Alignment->isValueDependent() ||
27728 Alignment->isInstantiationDependent() ||
27730 if (!AlignmentDependent) {
27731 ExprResult AlignResult =
27732 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
27733 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
27734 }
27735 }
27736 // Analyze and build list of variables.
27738 for (Expr *RefExpr : VarList) {
27739 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
27740 SourceLocation ELoc;
27741 SourceRange ERange;
27742 Expr *SimpleRefExpr = RefExpr;
27743 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
27744 if (Res.second) {
27745 // It will be analyzed later.
27746 Vars.push_back(RefExpr);
27747 }
27748 ValueDecl *D = Res.first;
27749 if (!D)
27750 continue;
27751
27752 auto *VD = dyn_cast<VarDecl>(D);
27753 DeclRefExpr *Ref = nullptr;
27754 if (!VD && !SemaRef.CurContext->isDependentContext())
27755 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
27756 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
27757 ? RefExpr->IgnoreParens()
27758 : Ref);
27759 }
27760
27761 if (Vars.empty())
27762 return nullptr;
27763
27764 if (Allocator)
27765 DSAStack->addInnerAllocatorExpr(Allocator);
27766
27768 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
27769 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
27770 SecondAllocateModifierLoc, EndLoc, Vars);
27771}
27772
27774 SourceLocation StartLoc,
27775 SourceLocation LParenLoc,
27776 SourceLocation EndLoc) {
27778 for (Expr *RefExpr : VarList) {
27779 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
27780 SourceLocation ELoc;
27781 SourceRange ERange;
27782 Expr *SimpleRefExpr = RefExpr;
27783 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
27784 if (Res.second)
27785 // It will be analyzed later.
27786 Vars.push_back(RefExpr);
27787 ValueDecl *D = Res.first;
27788 if (!D)
27789 continue;
27790
27791 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
27792 // A list-item cannot appear in more than one nontemporal clause.
27793 if (const Expr *PrevRef =
27794 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
27795 Diag(ELoc, diag::err_omp_used_in_clause_twice)
27796 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
27797 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
27798 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
27799 continue;
27800 }
27801
27802 Vars.push_back(RefExpr);
27803 }
27804
27805 if (Vars.empty())
27806 return nullptr;
27807
27808 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
27809 EndLoc, Vars);
27810}
27811
27813 Stmt *AStmt,
27814 SourceLocation StartLoc,
27815 SourceLocation EndLoc) {
27816 if (!AStmt)
27817 return StmtError();
27818
27819 SemaRef.setFunctionHasBranchProtectedScope();
27820
27821 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
27822 AStmt);
27823}
27824
27826 SourceLocation StartLoc,
27827 SourceLocation LParenLoc,
27828 SourceLocation EndLoc) {
27830 for (Expr *RefExpr : VarList) {
27831 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
27832 SourceLocation ELoc;
27833 SourceRange ERange;
27834 Expr *SimpleRefExpr = RefExpr;
27835 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
27836 /*AllowArraySection=*/true);
27837 if (Res.second)
27838 // It will be analyzed later.
27839 Vars.push_back(RefExpr);
27840 ValueDecl *D = Res.first;
27841 if (!D)
27842 continue;
27843
27844 const DSAStackTy::DSAVarData DVar =
27845 DSAStack->getTopDSA(D, /*FromParent=*/true);
27846 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
27847 // A list item that appears in the inclusive or exclusive clause must appear
27848 // in a reduction clause with the inscan modifier on the enclosing
27849 // worksharing-loop, worksharing-loop SIMD, or simd construct.
27850 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
27851 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
27852 << RefExpr->getSourceRange();
27853
27854 if (DSAStack->getParentDirective() != OMPD_unknown)
27855 DSAStack->markDeclAsUsedInScanDirective(D);
27856 Vars.push_back(RefExpr);
27857 }
27858
27859 if (Vars.empty())
27860 return nullptr;
27861
27862 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
27863 EndLoc, Vars);
27864}
27865
27867 SourceLocation StartLoc,
27868 SourceLocation LParenLoc,
27869 SourceLocation EndLoc) {
27871 for (Expr *RefExpr : VarList) {
27872 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
27873 SourceLocation ELoc;
27874 SourceRange ERange;
27875 Expr *SimpleRefExpr = RefExpr;
27876 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
27877 /*AllowArraySection=*/true);
27878 if (Res.second)
27879 // It will be analyzed later.
27880 Vars.push_back(RefExpr);
27881 ValueDecl *D = Res.first;
27882 if (!D)
27883 continue;
27884
27885 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
27886 DSAStackTy::DSAVarData DVar;
27887 if (ParentDirective != OMPD_unknown)
27888 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
27889 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
27890 // A list item that appears in the inclusive or exclusive clause must appear
27891 // in a reduction clause with the inscan modifier on the enclosing
27892 // worksharing-loop, worksharing-loop SIMD, or simd construct.
27893 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
27894 DVar.Modifier != OMPC_REDUCTION_inscan) {
27895 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
27896 << RefExpr->getSourceRange();
27897 } else {
27898 DSAStack->markDeclAsUsedInScanDirective(D);
27899 }
27900 Vars.push_back(RefExpr);
27901 }
27902
27903 if (Vars.empty())
27904 return nullptr;
27905
27906 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
27907 EndLoc, Vars);
27908}
27909
27910/// Tries to find omp_alloctrait_t type.
27911static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
27912 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
27913 if (!OMPAlloctraitT.isNull())
27914 return true;
27915 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
27916 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
27917 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
27918 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
27919 return false;
27920 }
27921 Stack->setOMPAlloctraitT(PT.get());
27922 return true;
27923}
27924
27926 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
27928 ASTContext &Context = getASTContext();
27929 // OpenMP [2.12.5, target Construct]
27930 // allocator is an identifier of omp_allocator_handle_t type.
27931 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
27932 return nullptr;
27933 // OpenMP [2.12.5, target Construct]
27934 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
27935 if (llvm::any_of(
27936 Data,
27937 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
27938 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
27939 return nullptr;
27940 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
27941 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
27942 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
27943 StringRef Allocator =
27944 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
27945 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
27946 PredefinedAllocators.insert(SemaRef.LookupSingleName(
27947 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
27948 }
27949
27951 for (const UsesAllocatorsData &D : Data) {
27952 Expr *AllocatorExpr = nullptr;
27953 // Check allocator expression.
27954 if (D.Allocator->isTypeDependent()) {
27955 AllocatorExpr = D.Allocator;
27956 } else {
27957 // Traits were specified - need to assign new allocator to the specified
27958 // allocator, so it must be an lvalue.
27959 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
27960 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
27961 bool IsPredefinedAllocator = false;
27962 if (DRE) {
27963 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
27964 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
27965 IsPredefinedAllocator =
27966 AllocatorTy !=
27967 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
27968 }
27969 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
27970 QualType AllocatorExprType = AllocatorExpr->getType();
27971 bool IsTypeCompatible = IsPredefinedAllocator;
27972 IsTypeCompatible = IsTypeCompatible ||
27973 Context.hasSameUnqualifiedType(AllocatorExprType,
27974 OMPAllocatorHandleT);
27975 IsTypeCompatible =
27976 IsTypeCompatible ||
27977 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
27978 bool IsNonConstantLValue =
27979 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
27980 if (!DRE || !IsTypeCompatible ||
27981 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
27982 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
27983 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
27984 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
27985 continue;
27986 }
27987 // OpenMP [2.12.5, target Construct]
27988 // Predefined allocators appearing in a uses_allocators clause cannot have
27989 // traits specified.
27990 if (IsPredefinedAllocator && D.AllocatorTraits) {
27992 diag::err_omp_predefined_allocator_with_traits)
27994 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
27995 << cast<NamedDecl>(DRE->getDecl())->getName()
27996 << D.Allocator->getSourceRange();
27997 continue;
27998 }
27999 // OpenMP [2.12.5, target Construct]
28000 // Non-predefined allocators appearing in a uses_allocators clause must
28001 // have traits specified.
28002 if (getLangOpts().OpenMP < 52) {
28003 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
28005 diag::err_omp_nonpredefined_allocator_without_traits);
28006 continue;
28007 }
28008 }
28009 // No allocator traits - just convert it to rvalue.
28010 if (!D.AllocatorTraits)
28011 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
28012 DSAStack->addUsesAllocatorsDecl(
28013 DRE->getDecl(),
28014 IsPredefinedAllocator
28015 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
28016 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
28017 }
28018 Expr *AllocatorTraitsExpr = nullptr;
28019 if (D.AllocatorTraits) {
28021 AllocatorTraitsExpr = D.AllocatorTraits;
28022 } else {
28023 // OpenMP [2.12.5, target Construct]
28024 // Arrays that contain allocator traits that appear in a uses_allocators
28025 // clause must be constant arrays, have constant values and be defined
28026 // in the same scope as the construct in which the clause appears.
28027 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
28028 // Check that traits expr is a constant array.
28029 QualType TraitTy;
28030 if (const ArrayType *Ty =
28031 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
28032 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
28033 TraitTy = ConstArrayTy->getElementType();
28034 if (TraitTy.isNull() ||
28035 !(Context.hasSameUnqualifiedType(TraitTy,
28036 DSAStack->getOMPAlloctraitT()) ||
28037 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
28038 /*CompareUnqualified=*/true))) {
28040 diag::err_omp_expected_array_alloctraits)
28041 << AllocatorTraitsExpr->getType();
28042 continue;
28043 }
28044 // Do not map by default allocator traits if it is a standalone
28045 // variable.
28046 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
28047 DSAStack->addUsesAllocatorsDecl(
28048 DRE->getDecl(),
28049 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
28050 }
28051 }
28052 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
28053 NewD.Allocator = AllocatorExpr;
28054 NewD.AllocatorTraits = AllocatorTraitsExpr;
28055 NewD.LParenLoc = D.LParenLoc;
28056 NewD.RParenLoc = D.RParenLoc;
28057 }
28058 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
28059 EndLoc, NewData);
28060}
28061
28063 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
28064 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
28066 for (Expr *RefExpr : Locators) {
28067 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
28068 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
28069 // It will be analyzed later.
28070 Vars.push_back(RefExpr);
28071 continue;
28072 }
28073
28074 SourceLocation ELoc = RefExpr->getExprLoc();
28075 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
28076
28077 if (!SimpleExpr->isLValue()) {
28078 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
28079 << 1 << 0 << RefExpr->getSourceRange();
28080 continue;
28081 }
28082
28083 ExprResult Res;
28084 {
28086 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
28087 }
28088 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
28090 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
28091 << 1 << 0 << RefExpr->getSourceRange();
28092 continue;
28093 }
28094 Vars.push_back(SimpleExpr);
28095 }
28096
28097 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
28098 ColonLoc, EndLoc, Modifier, Vars);
28099}
28100
28102 SourceLocation KindLoc,
28103 SourceLocation StartLoc,
28104 SourceLocation LParenLoc,
28105 SourceLocation EndLoc) {
28106 if (Kind == OMPC_BIND_unknown) {
28107 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
28108 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
28109 /*Last=*/unsigned(OMPC_BIND_unknown))
28110 << getOpenMPClauseNameForDiag(OMPC_bind);
28111 return nullptr;
28112 }
28113
28114 return new (getASTContext())
28115 OMPBindClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
28116}
28117
28119 SourceLocation StartLoc,
28120 SourceLocation LParenLoc,
28121 SourceLocation EndLoc) {
28122 Expr *ValExpr = Size;
28123 Stmt *HelperValStmt = nullptr;
28124
28125 // OpenMP [2.5, Restrictions]
28126 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
28127 // value.
28128 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
28129 /*StrictlyPositive=*/false))
28130 return nullptr;
28131
28132 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
28134 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().getOpenMPVersion());
28135 if (CaptureRegion != OMPD_unknown &&
28136 !SemaRef.CurContext->isDependentContext()) {
28137 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
28138 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
28139 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
28140 HelperValStmt = buildPreInits(getASTContext(), Captures);
28141 }
28142
28144 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
28145}
28146
28150 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
28151 SourceLocation M2Loc, SourceLocation EndLoc) {
28152
28153 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
28155 std::string Values = getListOfPossibleValues(
28156 OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
28157 Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
28158 : M2Loc,
28159 diag::err_omp_unexpected_clause_value)
28160 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
28161 return nullptr;
28162 }
28163
28164 Expr *ValExpr = Size;
28165 Stmt *HelperValStmt = nullptr;
28166
28167 // OpenMP [2.5, Restrictions]
28168 // The dyn_groupprivate expression must evaluate to a positive integer
28169 // value.
28170 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
28171 /*StrictlyPositive=*/false))
28172 return nullptr;
28173
28174 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
28176 DKind, OMPC_dyn_groupprivate, getLangOpts().getOpenMPVersion());
28177 if (CaptureRegion != OMPD_unknown &&
28178 !SemaRef.CurContext->isDependentContext()) {
28179 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
28180 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
28181 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
28182 HelperValStmt = buildPreInits(getASTContext(), Captures);
28183 }
28184
28186 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
28187 M1Loc, M2, M2Loc);
28188}
28189
28192 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
28193 SourceLocation LParenLoc, SourceLocation EndLoc) {
28194
28195 if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
28196 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
28197 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
28198 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
28199 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
28200 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
28201 return nullptr;
28202 }
28203
28205 DSAStackTy::OperatorOffsetTy OpsOffs;
28206 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
28207 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
28208 SemaRef,
28209 DepType == OMPC_DOACROSS_source ||
28210 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
28211 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
28212 VarList, DSAStack, EndLoc);
28213 Vars = VarOffset.Vars;
28214 OpsOffs = VarOffset.OpsOffs;
28215 TotalDepCount = VarOffset.TotalDepCount;
28216 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
28217 EndLoc, DepType, DepLoc, ColonLoc, Vars,
28218 TotalDepCount.getZExtValue());
28219 if (DSAStack->isParentOrderedRegion())
28220 DSAStack->addDoacrossDependClause(C, OpsOffs);
28221 return C;
28222}
28223
28225 SourceLocation StartLoc,
28226 SourceLocation LParenLoc,
28227 SourceLocation EndLoc) {
28228 return new (getASTContext())
28229 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
28230}
28231
28233 SourceLocation EndLoc) {
28234 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
28235}
28236
28238 SourceLocation LParenLoc,
28239 SourceLocation EndLoc) {
28240 if (E->HasSideEffects(getASTContext()))
28241 Diag(E->getBeginLoc(), diag::warn_assume_side_effects)
28242 << "holds" << E->getSourceRange();
28243 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
28244}
28245
28249 switch (CK) {
28250 case OMPC_absent:
28251 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
28252 case OMPC_contains:
28253 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
28254 default:
28255 llvm_unreachable("Unexpected OpenMP clause");
28256 }
28257}
28258
28260 SourceLocation Loc,
28261 SourceLocation RLoc) {
28262 switch (CK) {
28263 case OMPC_no_openmp:
28264 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
28265 case OMPC_no_openmp_routines:
28266 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
28267 case OMPC_no_parallelism:
28268 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
28269 case OMPC_no_openmp_constructs:
28270 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
28271 default:
28272 llvm_unreachable("Unexpected OpenMP clause");
28273 }
28274}
28275
28277 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
28278 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
28279 Expr *Stride, SourceLocation RBLoc) {
28280 ASTContext &Context = getASTContext();
28281 if (Base->hasPlaceholderType() &&
28282 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
28283 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
28284 if (Result.isInvalid())
28285 return ExprError();
28286 Base = Result.get();
28287 }
28288 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
28289 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
28290 if (Result.isInvalid())
28291 return ExprError();
28292 Result = SemaRef.DefaultLvalueConversion(Result.get());
28293 if (Result.isInvalid())
28294 return ExprError();
28295 LowerBound = Result.get();
28296 }
28297 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
28298 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
28299 if (Result.isInvalid())
28300 return ExprError();
28301 Result = SemaRef.DefaultLvalueConversion(Result.get());
28302 if (Result.isInvalid())
28303 return ExprError();
28304 Length = Result.get();
28305 }
28306 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
28307 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
28308 if (Result.isInvalid())
28309 return ExprError();
28310 Result = SemaRef.DefaultLvalueConversion(Result.get());
28311 if (Result.isInvalid())
28312 return ExprError();
28313 Stride = Result.get();
28314 }
28315
28316 // Build an unanalyzed expression if either operand is type-dependent.
28317 if (Base->isTypeDependent() ||
28318 (LowerBound &&
28319 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
28320 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
28321 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
28322 return new (Context) ArraySectionExpr(
28323 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
28324 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
28325 }
28326
28327 // Perform default conversions.
28329 QualType ResultTy;
28330 if (OriginalTy->isAnyPointerType()) {
28331 ResultTy = OriginalTy->getPointeeType();
28332 } else if (OriginalTy->isArrayType()) {
28333 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
28334 } else {
28335 return ExprError(
28336 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
28337 << Base->getSourceRange());
28338 }
28339 // C99 6.5.2.1p1
28340 if (LowerBound) {
28341 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
28342 LowerBound);
28343 if (Res.isInvalid())
28344 return ExprError(Diag(LowerBound->getExprLoc(),
28345 diag::err_omp_typecheck_section_not_integer)
28346 << 0 << LowerBound->getSourceRange());
28347 LowerBound = Res.get();
28348
28349 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
28350 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
28351 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
28352 << 0 << LowerBound->getSourceRange();
28353 }
28354 if (Length) {
28355 auto Res =
28356 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
28357 if (Res.isInvalid())
28358 return ExprError(Diag(Length->getExprLoc(),
28359 diag::err_omp_typecheck_section_not_integer)
28360 << 1 << Length->getSourceRange());
28361 Length = Res.get();
28362
28363 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
28364 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
28365 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
28366 << 1 << Length->getSourceRange();
28367 }
28368 if (Stride) {
28369 ExprResult Res =
28371 if (Res.isInvalid())
28372 return ExprError(Diag(Stride->getExprLoc(),
28373 diag::err_omp_typecheck_section_not_integer)
28374 << 1 << Stride->getSourceRange());
28375 Stride = Res.get();
28376
28377 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
28378 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
28379 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
28380 << 1 << Stride->getSourceRange();
28381 }
28382
28383 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
28384 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
28385 // type. Note that functions are not objects, and that (in C99 parlance)
28386 // incomplete types are not object types.
28387 if (ResultTy->isFunctionType()) {
28388 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
28389 << ResultTy << Base->getSourceRange();
28390 return ExprError();
28391 }
28392
28393 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
28394 diag::err_omp_section_incomplete_type, Base))
28395 return ExprError();
28396
28397 if (LowerBound && !OriginalTy->isAnyPointerType()) {
28399 if (LowerBound->EvaluateAsInt(Result, Context)) {
28400 // OpenMP 5.0, [2.1.5 Array Sections]
28401 // The array section must be a subset of the original array.
28402 llvm::APSInt LowerBoundValue = Result.Val.getInt();
28403 if (LowerBoundValue.isNegative()) {
28404 Diag(LowerBound->getExprLoc(),
28405 diag::err_omp_section_not_subset_of_array)
28406 << LowerBound->getSourceRange();
28407 return ExprError();
28408 }
28409 }
28410 }
28411
28412 if (Length) {
28414 if (Length->EvaluateAsInt(Result, Context)) {
28415 // OpenMP 5.0, [2.1.5 Array Sections]
28416 // The length must evaluate to non-negative integers.
28417 llvm::APSInt LengthValue = Result.Val.getInt();
28418 if (LengthValue.isNegative()) {
28419 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
28420 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
28421 << Length->getSourceRange();
28422 return ExprError();
28423 }
28424 }
28425 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
28426 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
28427 !OriginalTy->isVariableArrayType()))) {
28428 // OpenMP 5.0, [2.1.5 Array Sections]
28429 // When the size of the array dimension is not known, the length must be
28430 // specified explicitly.
28431 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
28432 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
28433 return ExprError();
28434 }
28435
28436 if (Stride) {
28438 if (Stride->EvaluateAsInt(Result, Context)) {
28439 // OpenMP 5.0, [2.1.5 Array Sections]
28440 // The stride must evaluate to a positive integer.
28441 llvm::APSInt StrideValue = Result.Val.getInt();
28442 if (!StrideValue.isStrictlyPositive()) {
28443 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
28444 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
28445 << Stride->getSourceRange();
28446 return ExprError();
28447 }
28448 }
28449 }
28450
28451 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
28452 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
28453 if (Result.isInvalid())
28454 return ExprError();
28455 Base = Result.get();
28456 }
28457 return new (Context) ArraySectionExpr(
28458 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
28459 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
28460}
28461
28463 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
28464 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
28465 ASTContext &Context = getASTContext();
28466 if (Base->hasPlaceholderType()) {
28467 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
28468 if (Result.isInvalid())
28469 return ExprError();
28470 Result = SemaRef.DefaultLvalueConversion(Result.get());
28471 if (Result.isInvalid())
28472 return ExprError();
28473 Base = Result.get();
28474 }
28475 QualType BaseTy = Base->getType();
28476 // Delay analysis of the types/expressions if instantiation/specialization is
28477 // required.
28478 if (!BaseTy->isPointerType() && Base->isTypeDependent())
28479 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
28480 LParenLoc, RParenLoc, Dims, Brackets);
28481 if (!BaseTy->isPointerType() ||
28482 (!Base->isTypeDependent() &&
28483 BaseTy->getPointeeType()->isIncompleteType()))
28484 return ExprError(Diag(Base->getExprLoc(),
28485 diag::err_omp_non_pointer_type_array_shaping_base)
28486 << Base->getSourceRange());
28487
28488 SmallVector<Expr *, 4> NewDims;
28489 bool ErrorFound = false;
28490 for (Expr *Dim : Dims) {
28491 if (Dim->hasPlaceholderType()) {
28492 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
28493 if (Result.isInvalid()) {
28494 ErrorFound = true;
28495 continue;
28496 }
28497 Result = SemaRef.DefaultLvalueConversion(Result.get());
28498 if (Result.isInvalid()) {
28499 ErrorFound = true;
28500 continue;
28501 }
28502 Dim = Result.get();
28503 }
28504 if (!Dim->isTypeDependent()) {
28507 if (Result.isInvalid()) {
28508 ErrorFound = true;
28509 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
28510 << Dim->getSourceRange();
28511 continue;
28512 }
28513 Dim = Result.get();
28514 Expr::EvalResult EvResult;
28515 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
28516 // OpenMP 5.0, [2.1.4 Array Shaping]
28517 // Each si is an integral type expression that must evaluate to a
28518 // positive integer.
28519 llvm::APSInt Value = EvResult.Val.getInt();
28520 if (!Value.isStrictlyPositive()) {
28521 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
28522 << toString(Value, /*Radix=*/10, /*Signed=*/true)
28523 << Dim->getSourceRange();
28524 ErrorFound = true;
28525 continue;
28526 }
28527 }
28528 }
28529 NewDims.push_back(Dim);
28530 }
28531 if (ErrorFound)
28532 return ExprError();
28533 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
28534 LParenLoc, RParenLoc, NewDims, Brackets);
28535}
28536
28538 SourceLocation IteratorKwLoc,
28539 SourceLocation LLoc,
28540 SourceLocation RLoc,
28542 ASTContext &Context = getASTContext();
28544 bool IsCorrect = true;
28545 for (const OMPIteratorData &D : Data) {
28546 TypeSourceInfo *TInfo = nullptr;
28547 SourceLocation StartLoc;
28548 QualType DeclTy;
28549 if (!D.Type.getAsOpaquePtr()) {
28550 // OpenMP 5.0, 2.1.6 Iterators
28551 // In an iterator-specifier, if the iterator-type is not specified then
28552 // the type of that iterator is of int type.
28553 DeclTy = Context.IntTy;
28554 StartLoc = D.DeclIdentLoc;
28555 } else {
28556 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
28557 StartLoc = TInfo->getTypeLoc().getBeginLoc();
28558 }
28559
28560 bool IsDeclTyDependent = DeclTy->isDependentType() ||
28563 if (!IsDeclTyDependent) {
28564 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
28565 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
28566 // The iterator-type must be an integral or pointer type.
28567 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
28568 << DeclTy;
28569 IsCorrect = false;
28570 continue;
28571 }
28572 if (DeclTy.isConstant(Context)) {
28573 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
28574 // The iterator-type must not be const qualified.
28575 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
28576 << DeclTy;
28577 IsCorrect = false;
28578 continue;
28579 }
28580 }
28581
28582 // Iterator declaration.
28583 assert(D.DeclIdent && "Identifier expected.");
28584 // Always try to create iterator declarator to avoid extra error messages
28585 // about unknown declarations use.
28586 auto *VD =
28587 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
28588 D.DeclIdent, DeclTy, TInfo, SC_None);
28589 VD->setImplicit();
28590 if (S) {
28591 // Check for conflicting previous declaration.
28592 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
28595 Previous.suppressDiagnostics();
28596 SemaRef.LookupName(Previous, S);
28597
28598 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
28599 /*ConsiderLinkage=*/false,
28600 /*AllowInlineNamespace=*/false);
28601 if (!Previous.empty()) {
28602 NamedDecl *Old = Previous.getRepresentativeDecl();
28603 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
28604 Diag(Old->getLocation(), diag::note_previous_definition);
28605 } else {
28606 SemaRef.PushOnScopeChains(VD, S);
28607 }
28608 } else {
28609 SemaRef.CurContext->addDecl(VD);
28610 }
28611
28612 /// Act on the iterator variable declaration.
28614
28615 Expr *Begin = D.Range.Begin;
28616 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
28617 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
28618 Begin, DeclTy, AssignmentAction::Converting);
28619 Begin = BeginRes.get();
28620 }
28621 Expr *End = D.Range.End;
28622 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
28623 ExprResult EndRes = SemaRef.PerformImplicitConversion(
28624 End, DeclTy, AssignmentAction::Converting);
28625 End = EndRes.get();
28626 }
28627 Expr *Step = D.Range.Step;
28628 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
28629 if (!Step->getType()->isIntegralType(Context)) {
28630 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
28631 << Step << Step->getSourceRange();
28632 IsCorrect = false;
28633 continue;
28634 }
28635 std::optional<llvm::APSInt> Result =
28636 Step->getIntegerConstantExpr(Context);
28637 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
28638 // If the step expression of a range-specification equals zero, the
28639 // behavior is unspecified.
28640 if (Result && Result->isZero()) {
28641 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
28642 << Step << Step->getSourceRange();
28643 IsCorrect = false;
28644 continue;
28645 }
28646 }
28647 if (!Begin || !End || !IsCorrect) {
28648 IsCorrect = false;
28649 continue;
28650 }
28651 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
28652 IDElem.IteratorDecl = VD;
28653 IDElem.AssignmentLoc = D.AssignLoc;
28654 IDElem.Range.Begin = Begin;
28655 IDElem.Range.End = End;
28656 IDElem.Range.Step = Step;
28657 IDElem.ColonLoc = D.ColonLoc;
28658 IDElem.SecondColonLoc = D.SecColonLoc;
28659 }
28660 if (!IsCorrect) {
28661 // Invalidate all created iterator declarations if error is found.
28662 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
28663 if (Decl *ID = D.IteratorDecl)
28664 ID->setInvalidDecl();
28665 }
28666 return ExprError();
28667 }
28669 if (!SemaRef.CurContext->isDependentContext()) {
28670 // Build number of ityeration for each iteration range.
28671 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
28672 // ((Begini-Stepi-1-Endi) / -Stepi);
28674 // (Endi - Begini)
28675 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
28676 D.Range.End, D.Range.Begin);
28677 if (!Res.isUsable()) {
28678 IsCorrect = false;
28679 continue;
28680 }
28681 ExprResult St, St1;
28682 if (D.Range.Step) {
28683 St = D.Range.Step;
28684 // (Endi - Begini) + Stepi
28685 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
28686 St.get());
28687 if (!Res.isUsable()) {
28688 IsCorrect = false;
28689 continue;
28690 }
28691 // (Endi - Begini) + Stepi - 1
28692 Res = SemaRef.CreateBuiltinBinOp(
28693 D.AssignmentLoc, BO_Sub, Res.get(),
28694 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
28695 if (!Res.isUsable()) {
28696 IsCorrect = false;
28697 continue;
28698 }
28699 // ((Endi - Begini) + Stepi - 1) / Stepi
28700 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
28701 St.get());
28702 if (!Res.isUsable()) {
28703 IsCorrect = false;
28704 continue;
28705 }
28706 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
28707 D.Range.Step);
28708 // (Begini - Endi)
28709 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
28710 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
28711 if (!Res1.isUsable()) {
28712 IsCorrect = false;
28713 continue;
28714 }
28715 // (Begini - Endi) - Stepi
28716 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
28717 St1.get());
28718 if (!Res1.isUsable()) {
28719 IsCorrect = false;
28720 continue;
28721 }
28722 // (Begini - Endi) - Stepi - 1
28723 Res1 = SemaRef.CreateBuiltinBinOp(
28724 D.AssignmentLoc, BO_Sub, Res1.get(),
28725 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
28726 if (!Res1.isUsable()) {
28727 IsCorrect = false;
28728 continue;
28729 }
28730 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
28731 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
28732 St1.get());
28733 if (!Res1.isUsable()) {
28734 IsCorrect = false;
28735 continue;
28736 }
28737 // Stepi > 0.
28738 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
28739 D.AssignmentLoc, BO_GT, D.Range.Step,
28740 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
28741 if (!CmpRes.isUsable()) {
28742 IsCorrect = false;
28743 continue;
28744 }
28745 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
28746 CmpRes.get(), Res.get(), Res1.get());
28747 if (!Res.isUsable()) {
28748 IsCorrect = false;
28749 continue;
28750 }
28751 }
28752 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
28753 if (!Res.isUsable()) {
28754 IsCorrect = false;
28755 continue;
28756 }
28757
28758 // Build counter update.
28759 // Build counter.
28760 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
28761 D.IteratorDecl->getBeginLoc(),
28762 D.IteratorDecl->getBeginLoc(), nullptr,
28763 Res.get()->getType(), nullptr, SC_None);
28764 CounterVD->setImplicit();
28765 ExprResult RefRes =
28766 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
28767 D.IteratorDecl->getBeginLoc());
28768 // Build counter update.
28769 // I = Begini + counter * Stepi;
28770 ExprResult UpdateRes;
28771 if (D.Range.Step) {
28772 UpdateRes = SemaRef.CreateBuiltinBinOp(
28773 D.AssignmentLoc, BO_Mul,
28774 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
28775 } else {
28776 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
28777 }
28778 if (!UpdateRes.isUsable()) {
28779 IsCorrect = false;
28780 continue;
28781 }
28782 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
28783 D.Range.Begin, UpdateRes.get());
28784 if (!UpdateRes.isUsable()) {
28785 IsCorrect = false;
28786 continue;
28787 }
28788 ExprResult VDRes =
28789 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
28790 cast<VarDecl>(D.IteratorDecl)->getType(),
28791 VK_LValue, D.IteratorDecl->getBeginLoc());
28792 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
28793 VDRes.get(), UpdateRes.get());
28794 if (!UpdateRes.isUsable()) {
28795 IsCorrect = false;
28796 continue;
28797 }
28798 UpdateRes =
28799 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
28800 if (!UpdateRes.isUsable()) {
28801 IsCorrect = false;
28802 continue;
28803 }
28804 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
28805 D.AssignmentLoc, UO_PreInc, RefRes.get());
28806 if (!CounterUpdateRes.isUsable()) {
28807 IsCorrect = false;
28808 continue;
28809 }
28810 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
28811 /*DiscardedValue=*/true);
28812 if (!CounterUpdateRes.isUsable()) {
28813 IsCorrect = false;
28814 continue;
28815 }
28816 OMPIteratorHelperData &HD = Helpers.emplace_back();
28817 HD.CounterVD = CounterVD;
28818 HD.Upper = Res.get();
28819 HD.Update = UpdateRes.get();
28820 HD.CounterUpdate = CounterUpdateRes.get();
28821 }
28822 } else {
28823 Helpers.assign(ID.size(), {});
28824 }
28825 if (!IsCorrect) {
28826 // Invalidate all created iterator declarations if error is found.
28827 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
28828 if (Decl *ID = D.IteratorDecl)
28829 ID->setInvalidDecl();
28830 }
28831 return ExprError();
28832 }
28833 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
28834 LLoc, RLoc, ID, Helpers);
28835}
28836
28837/// Check if \p AssumptionStr is a known assumption and warn if not.
28839 StringRef AssumptionStr) {
28840 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
28841 return;
28842
28843 unsigned BestEditDistance = 3;
28844 StringRef Suggestion;
28845 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
28846 unsigned EditDistance =
28847 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
28848 if (EditDistance < BestEditDistance) {
28849 Suggestion = KnownAssumptionIt.getKey();
28850 BestEditDistance = EditDistance;
28851 }
28852 }
28853
28854 if (!Suggestion.empty())
28855 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
28856 << AssumptionStr << Suggestion;
28857 else
28858 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
28859 << AssumptionStr;
28860}
28861
28863 // Handle the case where the attribute has a text message.
28864 StringRef Str;
28865 SourceLocation AttrStrLoc;
28866 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
28867 return;
28868
28869 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
28870
28871 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
28872}
28873
28875 : SemaBase(S), VarDataSharingAttributesStack(nullptr) {}
Defines the clang::ASTContext interface.
#define V(N, I)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
This file defines OpenMP nodes for declarative directives.
Expr::Classification Cl
FormatToken * Previous
The previous token in the unwrapped line.
FormatToken * Next
The next token in the unwrapped line.
static const Decl * getCanonicalDecl(const Decl *D)
Result
Implement __builtin_bit_cast and related operations.
#define X(type, name)
Definition Value.h:97
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.
bool resolveOMPAdjustArgsItem(const OMPAdjustArgsItem &Item, const FunctionDecl *FD, unsigned NumArgs, const ASTContext &Ctx, SmallVectorImpl< unsigned > &Positions)
Resolve one 'adjust_args' parameter-list item to the 1-based argument positions it identifies (OpenMP...
Defines some OpenMP-specific enums and functions.
llvm::DenseMap< Stmt *, Stmt * > MapTy
Definition ParentMap.cpp:21
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
@ ForVisibleRedeclaration
The lookup results will be used for redeclaration of a name, if an entity by that name already exists...
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
CastType
Definition SemaCast.cpp:51
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.
static bool checkOMPAdjustArgsBound(SemaOpenMP &S, const OMPAdjustArgsItem::Bound &Bound)
Check one bound of a parameter range 'lb:ub' (OpenMP 6.0 [5.2.1]).
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 hasConstQualifiedMappingType(QualType T)
static void updatePreInits(OMPLoopTransformationDirective *Transform, SmallVectorImpl< Stmt * > &PreInits)
Updates OriginalInits by checking Transform against loop transformation directives and appending thei...
static bool checkGenericLoopLastprivate(Sema &S, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind K, DSAStackTy *Stack)
static Stmt * buildLoopFinalization(ASTContext &Context, ArrayRef< OMPLoopBasedDirective::HelperExprs > LoopHelpers, ArrayRef< Stmt * > LoopStmts, ArrayRef< Stmt * > NestedFinals={})
Build loop variable finalization statement from HelperExprs.Finals.
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 bool isDeadAfterLoop(const Expr *Counter, const Stmt *LoopStmt)
Whether Counter is dead after LoopStmt: compiler generated (e.g.
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 bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static OMPClause * createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg, Stmt *HelperValStmt, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPAdjustArgsVal
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, llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopInductionVars)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
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 void appendStmtsBeforeNestedLoop(Stmt *LoopStmt, SmallVectorImpl< Stmt * > &BodyParts)
A non-innermost affected loop generated by a nested loop transformation (e.g.
static bool checkDecompositionCaptureConflict(Sema &SemaRef, OpenMPDirectiveKind DKind, llvm::SmallDenseMap< const DecompositionDecl *, std::pair< bool, SourceLocation >, 4 > &SeenDecompositions, const ValueDecl *D, SourceLocation ELoc, OpenMPClauseKind ClauseKind)
Check if bindings from the same structured binding have conflicting capture kinds (by-ref vs by-copy)...
static bool validateMultidimClauses(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, bool MayHaveBareClause=false)
Check the number of expressions specified in clauses that can contain multidimensional values,...
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 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 OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, llvm::omp::Version OMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
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 ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper, SourceLocation ItemLoc)
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static bool validateMultidimClauseExprs(SemaBase &SemaRef, OpenMPClauseKind ClauseKind, SourceLocation ClauseBeginLoc, ArrayRef< const Expr * > ClauseVarList, const Expr *DimsModifierExpr, const OMPXBareClause *BareClause=nullptr)
Check the number of expressions specified in a multidimensional clause and return whether an error wa...
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static std::pair< ValueDecl *, bool > getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc, SourceRange &ERange, bool AllowArraySection=false, bool AllowAssumedSizeArray=false, StringRef DiagType="")
static DeclRefExpr * buildImplicitMap(Sema &S, QualType BaseType, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Maps)
static bool checkClausesForDecompositionConflicts(Sema &SemaRef, OpenMPDirectiveKind DKind, ArrayRef< OMPClause * > Clauses, Stmt *Body=nullptr)
Helper to check all clauses in a directive for structured binding capture conflicts.
static bool checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
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 bool hasNoMutableFields(const CXXRecordDecl *RD)
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 bool checkOMPAdjustArgsRange(SemaOpenMP &S, const OMPAdjustArgsItem &Range)
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 Expr * buildInitListValue(Sema &SemaRef, Expr *E)
static Stmt * guardByLoopPreConds(ASTContext &Context, ArrayRef< OMPLoopBasedDirective::HelperExprs > Loops, Stmt *S)
Wrap S so it runs only if every loop in Loops has iterations.
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts, bool RelaxNestForPeeledTransformation=false)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static OMPAdjustArgsVal checkOMPAdjustArgsValue(SemaOpenMP &S, Expr *E, bool StrictlyPositive, llvm::APSInt &Result)
Check one 'adjust_args' integer expression for the constant property plus either the positive or the ...
static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static SourceLocation getOMPAdjustArgsItemLoc(const OMPAdjustArgsItem &Item, SourceLocation FallbackLoc)
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static bool checkPreferTypeArgs(SemaOpenMP &S, const OMPInteropInfo &Info)
Validate prefer_type fr() and attr() arguments in an OMPInteropInfo.
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void guardNestedLoopInit(ASTContext &Context, ArrayRef< OMPLoopBasedDirective::HelperExprs > LoopHelpers, unsigned I, SmallVectorImpl< Stmt * > &OriginalInit)
Run loop I's inits only if all enclosing loops have iterations.
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget, bool HasConstQualifier)
static bool checkOriginalVarMappedButOnlyBindingsUsed(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, Stmt *Body)
Check if original variable is explicitly mapped but only bindings are used.
#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 std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First, unsigned Last, ArrayRef< unsigned > Exclude={})
static DeclRefExpr * buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr, bool WithInit)
static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_alloctrait_t type.
static void appendFlattenedStmtList(SmallVectorImpl< Stmt * > &TargetList, Stmt *Item)
Append the Item or the content of a CompoundStmt to the list TargetList.
static bool isConstNotMutableType(Sema &SemaRef, QualType Type, bool AcceptIfMutable=true, bool *IsClassType=nullptr)
static void addLoopPreInits(ASTContext &Context, OMPLoopBasedDirective::HelperExprs &LoopHelper, Stmt *LoopStmt, ArrayRef< Stmt * > OriginalInit, SmallVectorImpl< Stmt * > &PreInits)
Add preinit statements that need to be propagated 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 QualType getIntTypeForBitwidthOrBitInt(ASTContext &C, unsigned Bits, bool Signed)
Like ASTContext::getIntTypeForBitwidth, but falls back to a _BitInt type when no standard integer typ...
static SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static T filterLookupForUDReductionAndMapper(SmallVectorImpl< U > &Lookups, const llvm::function_ref< T(ValueDecl *)> Gen)
This file declares semantic analysis for OpenMP constructs and clauses.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
This file defines OpenMP AST classes for executable directives and clauses.
static QualType getPointeeType(const MemRegion *R)
VerifyDiagnosticConsumer::Directive Directive
Look for variables declared in the body parts of a for-loop nest.
bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) override
bool VisitVarDecl(VarDecl *D) override
ForVarDeclFinder(llvm::SmallPtrSetImpl< const Decl * > &VD)
bool VisitForStmt(ForStmt *F) override
This class visits every VarDecl that the initializer references and adds OMPDeclareTargetDeclAttr to ...
void declareTargetInitializer(Decl *TD)
A function that keeps a record of all the Decls that are variables, has OMPDeclareTargetDeclAttr,...
void VisitDeclRefExpr(DeclRefExpr *Node)
A StmtVisitor class function that visits all DeclRefExpr and adds OMPDeclareTargetDeclAttr to them.
void VisitExpr(Expr *Ex)
A function that iterates across each of the Expr's children.
bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override
NestedLoopCounterVisitor()=default
bool VisitForStmt(ForStmt *FS) override
bool TraverseStmt(Stmt *S) override
bool TraverseDecl(Decl *D) override
unsigned getNestedLoopCount() const
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 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 OMPAssumeDirective * Create(const ASTContext &Ctx, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AStmt)
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...
static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
static OMPCancellationPointDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Creates directive.
Class that represents a component of a mappable expression. E.g. for an expression S....
SmallVector< MappableComponent, 8 > MappableExprComponentList
static std::pair< const Expr *, std::optional< size_t > > findAttachPtrExpr(MappableExprComponentListRef Components, OpenMPDirectiveKind CurDirKind)
Find the attach pointer expression from a list of mappable expression components.
ArrayRef< MappableComponent > MappableExprComponentListRef
SmallVector< MappableExprComponentList, 8 > MappableExprComponentLists
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.
static OMPCriticalDirective * Create(const ASTContext &C, const DeclarationNameInfo &Name, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
DeclarationNameInfo getDirectiveName() const
Return name of the 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.
This represents implicit clause 'depobj' for the 'pragma omp depobj' directive. This clause does not ...
static OMPDepobjDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
This represents 'destroy' clause in the 'pragma omp depobj' directive or the 'pragma omp interop' dir...
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 'dyn_groupprivate' clause in 'pragma omp target ...' and 'pragma omp teams ....
static OMPErrorDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
static OMPExclusiveClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'filter' clause in the 'pragma omp ...' directive.
static OMPFlattenDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp flatten'.
This represents implicit clause 'flush' for the 'pragma omp flush' directive. This clause does not ex...
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.
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.
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.
static OMPFromClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorExpr, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
static OMPFuseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumGeneratedTopLevelLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for pragma omp fuse'.
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.
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, Stmt *Finals)
Create a new AST node representation for 'pragma omp interchange'.
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.
Common class of data shared between OMPCanonicalLoopNestTransformationDirective and OMPCanonicalLoopS...
Stmt * getDirective() const
Returns the specific directive related to this loop transformation.
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.
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.
static OMPMetaDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< Stmt * > Variants, ArrayRef< Expr * > Conditions, ArrayRef< OMPTraitInfo * > TraitInfos, bool HasImplicitOtherwise)
This represents 'nocontext' clause in the 'pragma omp ...' directive.
This represents 'nogroup' clause in the 'pragma omp ...' directive.
This represents clause 'nontemporal' in the 'pragma omp ...' directives.
static OMPNontemporalClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
This represents 'novariants' clause in the 'pragma omp ...' directive.
This represents '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, OpenMPNumTeamsClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, Stmt *PreInit)
Creates clause with a list of variables VL.
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.
static OMPOrderedBlockAssocDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPOrderedStandaloneDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
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.
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.
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.
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.
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.
This represents 'priority' clause in the 'pragma omp ...' directive.
static OMPReverseDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, unsigned NumLoops, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp reverse'.
This represents 'simd' clause in the 'pragma omp ...' directive.
static OMPScanDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive with a list of Clauses.
static OMPScopeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive.
static OMPSectionDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel)
Creates directive.
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.
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.
static OMPSingleDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPSplitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp split'.
static OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp stripe'.
static OMPTargetDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetEnterDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetExitDataDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetParallelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetParallelGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTargetTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor)
Creates directive with a list of Clauses.
static OMPTargetUpdateDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTaskDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, bool HasCancel)
Creates directive with a list of Clauses.
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 OMPTaskgroupDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, Expr *ReductionRef)
Creates directive.
static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses)
Creates directive.
static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Creates directive.
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, OpenMPThreadLimitClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, Stmt *PreInit)
Creates clause with a list of variables VL.
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, Stmt *Finals)
Create a new AST node representation for 'pragma omp tile'.
static OMPToClause * Create(const ASTContext &C, const OMPVarListLocTy &Locs, ArrayRef< Expr * > Vars, ArrayRef< ValueDecl * > Declarations, MappableExprComponentListsRef ComponentLists, ArrayRef< Expr * > UDMapperRefs, Expr *IteratorModifier, ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, NestedNameSpecifierLoc UDMQualifierLoc, DeclarationNameInfo MapperId)
Creates clause with a list of variables Vars.
bool isExtensionActive(llvm::omp::TraitProperty TP)
Check the extension trait TP is active.
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
bool anyScoreOrCondition(llvm::function_ref< bool(Expr *&, bool)> Cond)
static OMPUnrollDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, unsigned NumGeneratedTopLevelLoops, Stmt *TransformedStmt, Stmt *PreInits, Stmt *Finals)
Create a new AST node representation for 'pragma omp unroll'.
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, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Creates clause with a list of variables Vars.
This represents clause 'uses_allocators' in the 'pragma omp target'-based directives.
static OMPUsesAllocatorsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< OMPUsesAllocatorsClause::Data > Data)
Creates clause with a list of allocators Data.
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.
APSInt & getInt()
Definition APValue.h:573
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified=false, bool AllowCXX=false, bool IsConditionalOperator=false)
DeclarationNameTable DeclarationNames
Definition ASTContext.h:856
QualType getUnsignedPointerDiffType() const
Return the unique unsigned counterpart of "ptrdiff_t" integer type.
ASTMutationListener * getASTMutationListener() const
Retrieve a pointer to the AST mutation listener associated with this AST context, if any.
CanQualType VoidPtrTy
void Deallocate(void *Ptr) const
Definition ASTContext.h:932
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
IdentifierTable & Idents
Definition ASTContext.h:852
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 BoolTy
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,...
CharUnits getAlignOfGlobalVarInChars(QualType T, const VarDecl *VD) const
Return the alignment in characters that should be given to a global variable with type T.
QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return a non-unique reference to the type for a variable array of the specified element type.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CanQualType VoidTy
static bool hasSameType(QualType T1, QualType T2)
Determine whether the given types T1 and T2 are equivalent.
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:971
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
An abstract interface that should be implemented by listeners that want to be notified when an AST en...
bool isUnset() const
Definition Ownership.h:168
PtrTy get() const
Definition Ownership.h:171
bool isInvalid() const
Definition Ownership.h:167
bool isUsable() const
Definition Ownership.h:169
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition Expr.h:7305
Expr * getBase()
Get base of the array section.
Definition Expr.h:7383
Expr * getLength()
Get length of array section.
Definition Expr.h:7393
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5442
Expr * getLowerBound()
Get lower bound of array section.
Definition Expr.h:7387
SourceLocation getColonLocFirst() const
Definition Expr.h:7414
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3820
QualType getElementType() const
Definition TypeBase.h:3832
Attr - This represents one attribute.
Definition Attr.h:47
Represents an attribute applied to a statement.
Definition Stmt.h:2214
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition Stmt.cpp:441
SourceLocation getBeginLoc() const
Definition Stmt.h:2253
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4107
Expr * getLHS() const
Definition Expr.h:4157
static bool isRelationalOp(Opcode Opc)
Definition Expr.h:4201
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2217
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition Expr.h:4254
SourceLocation getOperatorLoc() const
Definition Expr.h:4149
SourceLocation getExprLoc() const
Definition Expr.h:4148
static Opcode reverseComparisonOp(Opcode Opc)
Definition Expr.h:4226
Expr * getRHS() const
Definition Expr.h:4159
static bool isAdditiveOp(Opcode Opc)
Definition Expr.h:4193
Opcode getOpcode() const
Definition Expr.h:4152
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2179
BinaryOperatorKind Opcode
Definition Expr.h:4112
A binding in a decomposition declaration.
Definition DeclCXX.h:4223
VarDecl * getHoldingVar() const
Get the variable (if any) that holds the value of evaluating the binding.
Definition DeclCXX.cpp:3718
Expr * getBinding() const
Get the expression to which this declaration is bound.
Definition DeclCXX.h:4249
DecompositionDecl * getDecomposedDecl() const
Get the decomposition declaration that this binding represents a decomposition of.
Definition DeclCXX.h:4256
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
CXXBasePath & front()
bool isAmbiguous(CanQualType BaseType) const
Determine whether the path from the most-derived type to the given base type is ambiguous (i....
Represents a C++ constructor within a class.
Definition DeclCXX.h:2645
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2985
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:136
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:1243
bool hasDefinition() const
Definition DeclCXX.h:562
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:77
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition DeclSpec.h:189
SourceLocation getBeginLoc() const
Definition DeclSpec.h:87
bool isSet() const
Deprecated.
Definition DeclSpec.h:202
NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const
Retrieve a nested-name-specifier with location information, copied into the given AST context.
Definition DeclSpec.cpp:123
bool isInvalid() const
An error occurred during parsing of the scope specifier.
Definition DeclSpec.h:187
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:3012
SourceLocation getBeginLoc() const
Definition Expr.h:3346
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:1549
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3195
Expr * getCallee()
Definition Expr.h:3159
arg_range arguments()
Definition Expr.h:3264
A wrapper class around a pointer that always points to its canonical declaration.
Represents the body of a CapturedStmt, and serves as its DeclContext.
Definition Decl.h:5098
unsigned getNumParams() const
Definition Decl.h:5136
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5802
Stmt * getBody() const override
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Definition Decl.cpp:5798
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:5138
This captures a statement into a function.
Definition Stmt.h:3950
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition Stmt.cpp:1493
SourceRange getSourceRange() const LLVM_READONLY
Definition Stmt.h:4153
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition Stmt.h:4054
bool capturesVariable(const VarDecl *Var) const
True if this variable has been captured.
Definition Stmt.cpp:1517
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:4145
capture_range captures()
Definition Stmt.h:4088
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3745
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3362
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1751
SourceLocation getBeginLoc() const
Definition Stmt.h:1865
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:399
ConditionalOperator - The ?
Definition Expr.h:4460
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1467
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2108
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition DeclBase.h:2261
bool isFileContext() const
Definition DeclBase.h:2199
DeclContextLookupResult lookup_result
Definition DeclBase.h:2609
ASTContext & getParentASTContext() const
Definition DeclBase.h:2137
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
bool isNamespace() const
Definition DeclBase.h:2221
bool isTranslationUnit() const
Definition DeclBase.h:2204
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2405
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool Encloses(const DeclContext *DC) const
Determine whether this declaration context semantically encloses the declaration context DC.
void addHiddenDecl(Decl *D)
Add the declaration D to this context without modifying any lookup tables.
static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls)
Definition DeclGroup.h:64
Decl * getSingleDecl()
Definition DeclGroup.h:79
bool isSingleDecl() const
Definition DeclGroup.h:76
bool isNull() const
Definition DeclGroup.h:75
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1315
NamedDecl * getFoundDecl()
Get the NamedDecl through which this reference occurred.
Definition Expr.h:1426
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
Definition Expr.h:1442
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:498
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
Definition Expr.h:1408
ValueDecl * getDecl()
Definition Expr.h:1383
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1513
SourceLocation getEndLoc() const LLVM_READONLY
Definition Expr.cpp:561
SourceLocation getBeginLoc() const
Definition Expr.h:1394
SourceLocation getLocation() const
Definition Expr.h:1391
ConstexprSpecKind getConstexprSpecifier() const
Definition DeclSpec.h:905
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1642
SourceLocation getEndLoc() const
Definition Stmt.h:1665
const DeclGroupRef getDeclGroup() const
Definition Stmt.h:1660
const Decl * getSingleDecl() const
Definition Stmt.h:1657
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:1668
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:582
bool hasAttrs() const
Definition DeclBase.h:527
void addAttr(Attr *A)
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:602
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:178
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition DeclBase.cpp:594
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition DeclBase.cpp:604
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition DeclBase.h:1002
bool isInvalidDecl() const
Definition DeclBase.h:597
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:568
void setAccess(AccessSpecifier AS)
Definition DeclBase.h:511
SourceLocation getLocation() const
Definition DeclBase.h:448
void setImplicit(bool I=true)
Definition DeclBase.h:603
void setReferenced(bool R=true)
Definition DeclBase.h:632
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition DeclBase.h:1067
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition DeclBase.cpp:579
DeclContext * getDeclContext()
Definition DeclBase.h:457
AccessSpecifier getAccess() const
Definition DeclBase.h:516
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:440
AttrVec & getAttrs()
Definition DeclBase.h:533
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition DeclBase.cpp:385
bool hasAttr() const
Definition DeclBase.h:586
void setLexicalDeclContext(DeclContext *DC)
Definition DeclBase.cpp:389
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:996
Kind getKind() const
Definition DeclBase.h:451
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:436
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:1996
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition DeclSpec.h:2146
SourceLocation getIdentifierLoc() const
Definition DeclSpec.h:2436
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition DeclSpec.h:2439
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclSpec.h:2182
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition DeclSpec.h:2841
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition DeclSpec.h:2161
bool isInvalidType() const
Definition DeclSpec.h:2822
const IdentifierInfo * getIdentifier() const
Definition DeclSpec.h:2430
A decomposition declaration.
Definition DeclCXX.h:4287
OriginalVarResult getOriginalVar() const
If this decomposition was initialized from a variable (e.g., auto [a,b] = p), returns the variable.
Definition DeclCXX.cpp:3778
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
RAII object that enters a new expression evaluation context.
This represents one expression.
Definition Expr.h:114
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isIntegerConstantExpr(const ASTContext &Ctx) const
bool isGLValue() const
Definition Expr.h:289
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition Expr.h:703
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3134
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:179
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:449
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:196
llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const
EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
Definition Expr.h:243
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition Expr.cpp:3146
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3129
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3117
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition Expr.h:248
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3125
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:286
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:456
bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects=true) const
HasSideEffects - This routine returns true for all those expressions which have any effect other than...
Definition Expr.cpp:3728
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:225
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, bool AllowRelaxedEval=false) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3109
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:146
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Definition Decl.h:3311
bool isMutable() const
Determines whether this field is mutable (C++ only).
Definition Decl.h:3411
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3414
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4915
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition Decl.h:3558
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition Diagnostic.h:103
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition Expr.cpp:1086
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2899
Stmt * getBody()
Definition Stmt.h:2943
Represents a function declaration or definition.
Definition Decl.h:2071
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2944
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2917
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2609
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
bool isConsteval() const
Definition Decl.h:2621
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3886
FunctionDecl * getPreviousDecl()
Return the previous declaration of this declaration or NULL if this is the first declaration.
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5548
One of these records is kept for each identifier that is lexed.
void setMangledOpenMPVariantName(bool I)
Set whether this is the mangled name of an OpenMP variant.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
IfStmt - This represents an if/then/else.
Definition Stmt.h:2270
Stmt * getThen()
Definition Stmt.h:2359
static IfStmt * Create(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, SourceLocation RPL, Stmt *Then, SourceLocation EL=SourceLocation(), Stmt *Else=nullptr)
Create an IfStmt.
Definition Stmt.cpp:1044
Expr * getCond()
Definition Stmt.h:2347
Stmt * getElse()
Definition Stmt.h:2368
SourceLocation getBeginLoc() const
Definition Stmt.h:2482
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition Expr.h:1776
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2109
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition Overload.h:626
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.
Describes an entity that is being initialized.
static InitializedEntity InitializeTemporary(QualType Type)
Create the initialization entity for a temporary.
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:985
Describes the capture of a variable or of this, or of a C++1y init-capture.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
llvm::omp::Version getOpenMPVersion() const
Return the OpenMP version.
A class for iterating through a result set and possibly filtering out results.
Definition Lookup.h:677
Represents the results of name lookup.
Definition Lookup.h:147
LLVM_ATTRIBUTE_REINITIALIZES void clear()
Clears out any current state.
Definition Lookup.h:607
DeclClass * getAsSingle() const
Definition Lookup.h:558
bool empty() const
Return true if no decls were found.
Definition Lookup.h:362
Filter makeFilter()
Create a filter for this result set.
Definition Lookup.h:751
NamedDecl * getFoundDecl() const
Fetch the unique decl found by this lookup.
Definition Lookup.h:569
bool isAmbiguous() const
Definition Lookup.h:324
bool isSingleResult() const
Determines if this names a single result which is not an unresolved value using decl.
Definition Lookup.h:331
NamedDecl * getRepresentativeDecl() const
Fetches a representative decl. Useful for lazy diagnostics.
Definition Lookup.h:576
void suppressDiagnostics()
Suppress the diagnostics that would normally fire because of this lookup.
Definition Lookup.h:636
iterator end() const
Definition Lookup.h:359
static bool isVisible(Sema &SemaRef, NamedDecl *D)
Determine whether the given declaration is visible to the program.
iterator begin() const
Definition Lookup.h:358
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition Expr.h:3516
static MemberExpr * Create(const ASTContext &C, Expr *Base, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *MemberDecl, DeclAccessPair FoundDecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK, ExprObjectKind OK, NonOdrUseReason NOUR)
Definition Expr.cpp:1786
Expr * getBase() const
Definition Expr.h:3510
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:3494
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3628
This represents a decl that may have a name.
Definition Decl.h:276
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:297
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:303
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:342
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:319
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:1849
void setDeclName(DeclarationName N)
Set the name of this declaration.
Definition Decl.h:345
A C++ nested-name-specifier augmented with source location information.
Describes the source-level contents of one OpenMP 'adjust_args' clause.
static OMPAdjustArgsDescriptor * Create(const ASTContext &C, OpenMPAdjustArgsOpKind AdjustOp, OpenMPNeedDevicePtrModifier NeedDevicePtrModifier, ArrayRef< OMPAdjustArgsItem > Items)
This represents the 'align' clause in the 'pragma omp allocate' directive.
static OMPAllocateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, Expr *Allocator, Expr *Alignment, SourceLocation ColonLoc, OpenMPAllocateClauseModifier Modifier1, SourceLocation Modifier1Loc, OpenMPAllocateClauseModifier Modifier2, SourceLocation Modifier2Loc, SourceLocation EndLoc, ArrayRef< Expr * > VL)
Creates clause with a list of variables VL.
static bool classof(const OMPClause *T)
static OMPAllocateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL, ArrayRef< OMPClause * > CL)
This represents 'allocator' clause in the 'pragma omp ...' directive.
Expr * getBase()
Fetches base expression of array shaping expression.
Definition ExprOpenMP.h:90
static OMPArrayShapingExpr * Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > BracketRanges)
Definition Expr.cpp:5550
Pseudo declaration for capturing expressions.
Definition DeclOpenMP.h:445
static OMPCapturedExprDecl * Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, SourceLocation StartLoc)
static OMPClauseWithPostUpdate * get(OMPClause *C)
Class that handles pre-initialization statement for some clauses, like 'schedule',...
static OMPClauseWithPreInit * get(OMPClause *C)
This is a basic class for representing single OpenMP clause.
SourceLocation getBeginLoc() const
Returns the starting location of the clause.
SourceLocation getEndLoc() const
Returns the ending location of the clause.
OpenMPClauseKind getClauseKind() const
Returns kind of OpenMP clause (private, shared, reduction, etc.).
This represents 'collapse' clause in the 'pragma omp ...' directive.
static OMPCountsClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Counts, std::optional< unsigned > FillIdx, SourceLocation FillLoc)
Build a 'counts' AST node.
This represents 'pragma omp declare mapper ...' directive.
Definition DeclOpenMP.h:349
static OMPDeclareMapperDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, DeclarationName VarName, ArrayRef< OMPClause * > Clauses, OMPDeclareMapperDecl *PrevDeclInScope)
Creates declare mapper node.
This represents 'pragma omp declare reduction ...' directive.
Definition DeclOpenMP.h:239
static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope)
Create declare reduction node.
This represents 'default' clause in the 'pragma omp ...' directive.
This represents the 'depth' clause on the 'pragma omp flatten' (and 'pragma omp fuse') loop-transform...
This represents 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
This represents 'pragma omp groupprivate ...' directive.
Definition DeclOpenMP.h:173
static OMPGroupPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'if' clause in the 'pragma omp ...' directive.
static OMPIteratorExpr * Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef< IteratorDefinition > Data, ArrayRef< OMPIteratorHelperData > Helpers)
Definition Expr.cpp:5677
This class represents the 'looprange' clause in the 'pragma omp fuse' directive.
static OMPNumThreadsClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, OpenMPNumThreadsClauseModifier PrescriptivenessModifier, OpenMPNumThreadsClauseModifier DimsModifier, SourceLocation PrescriptivenessModifierLoc, SourceLocation DimsModifierLoc, Expr *DimsModifierExpr, Stmt *PreInit)
Creates clause with a list of variables/expressions.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This class represents the 'permutation' clause in the 'pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents 'pragma omp requires...' directive.
Definition DeclOpenMP.h:479
clauselist_range clauselists()
Definition DeclOpenMP.h:504
static OMPRequiresDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< OMPClause * > CL)
Create requires node.
This represents 'safelen' clause in the 'pragma omp ...' directive.
Expr * getSafelen() const
Return safe iteration space distance.
This represents 'simdlen' clause in the 'pragma omp ...' directive.
Expr * getSimdlen() const
Return safe iteration space distance.
static OMPSizesClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Sizes)
Build a 'sizes' AST node.
This represents 'pragma omp threadprivate ...' directive.
Definition DeclOpenMP.h:110
static OMPThreadPrivateDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, ArrayRef< Expr * > VL)
This represents 'threadset' clause in the 'pragma omp task ...' directive.
void * getAsOpaquePtr() const
Definition Ownership.h:91
PtrTy get() const
Definition Ownership.h:81
static OpaquePtr make(DeclGroupRef P)
Definition Ownership.h:61
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition Expr.h:1223
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1273
void setIsUnique(bool V)
Definition Expr.h:1275
Represents a parameter to a function.
Definition Decl.h:1832
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:2963
ParsedAttr - Represents a syntactic attribute.
Definition ParsedAttr.h:119
IdentifierTable & getIdentifierTable()
static PseudoObjectExpr * Create(const ASTContext &Context, Expr *syntactic, ArrayRef< Expr * > semantic, unsigned resultIndex)
Definition Expr.cpp:5238
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:3092
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8667
QualType withRestrict() const
Definition TypeBase.h:1191
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3825
QualType withConst() const
Definition TypeBase.h:1175
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1172
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8578
bool isConstant(const ASTContext &Ctx) const
Definition TypeBase.h:1098
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8763
QualType getCanonicalType() const
Definition TypeBase.h:8630
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8672
bool isMoreQualifiedThan(QualType Other, const ASTContext &Ctx) const
Determine whether this type is more qualified than the other given type, requiring exact equality for...
Definition TypeBase.h:8732
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8582
Represents a struct/union/class.
Definition Decl.h:4476
field_range fields() const
Definition Decl.h:4679
field_iterator field_begin() const
Definition Decl.cpp:5370
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3678
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:384
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition Scope.h:308
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition Scope.h:544
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:280
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition Scope.h:537
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition Scope.h:148
A generic diagnostic builder for errors which may or may not be deferred.
Definition SemaBase.h:111
SemaBase(Sema &S)
Definition SemaBase.cpp:7
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
const LangOptions & getLangOpts() const
Definition SemaBase.cpp:11
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
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 * ActOnOpenMPThreadsetClause(OpenMPThreadsetKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'threadset' 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...
StmtResult ActOnOpenMPParallelMasterDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel master' after parsing of the associated statement.
StmtResult ActOnOpenMPDispatchDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp dispatch' after parsing of the.
OMPClause * ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'read' clause.
OMPClause * ActOnOpenMPFilterClause(Expr *ThreadID, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'filter' clause.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
ExprResult ActOnOpenMPCall(ExprResult Call, Scope *Scope, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig)
Given the potential call expression Call, determine if there is a specialization via the OpenMP decla...
void setOpenMPDeviceNum(int Num)
Setter and getter functions for device_num.
OMPClause * ActOnOpenMPFullClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-form 'full' clauses.
StmtResult ActOnOpenMPSplitDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp split' after parsing of its associated statement.
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.
StmtResult ActOnOpenMPFlattenDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp flatten' after parsing of its clauses and the associated statement.
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.
ExprResult ActOnOpenMPDimsModifier(OpenMPClauseKind Kind, int Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, ArrayRef< Expr * > VarList, SourceLocation VarListEndLoc)
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a 'pragma omp end declare target' was enc...
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...
ArrayRef< const OMPRequiresDecl * > getRequiresDecls() const
The 'requires' directives seen so far in this translation unit.
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of 'pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPCountsClause(ArrayRef< Expr * > CountExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, std::optional< unsigned > FillIdx, SourceLocation FillLoc, unsigned FillCount)
Called on well-formed 'counts' clause after parsing its arguments.
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.
OMPClause * ActOnOpenMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
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'.
OMPGroupPrivateDecl * CheckOMPGroupPrivateDecl(SourceLocation Loc, ArrayRef< Expr * > VarList)
Builds a new OpenMPGroupPrivateDecl and checks its correctness.
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 * ActOnOpenMPLoopRangeClause(Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc)
Called on well-form 'looprange' clause after parsing its arguments.
OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'permutation' clause after parsing its arguments.
OMPClause * ActOnOpenMPNontemporalClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'nontemporal' clause.
OMPClause * ActOnOpenMPBindClause(OpenMPBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'bind' clause.
OMPClause * ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'threads' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
StmtResult ActOnOpenMPFuseDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp fuse' after parsing of its clauses and the associated statement.
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 * 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,...
OMPClause * ActOnOpenMPUseDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, OpenMPUseDevicePtrFallbackModifier FallbackModifier, SourceLocation FallbackModifierLoc)
Called on well-formed 'use_device_ptr' clause.
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.
friend class Sema
Definition SemaOpenMP.h:55
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the 'pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed 'pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed 'pragma omp allocate'.
OMPClause * ActOnOpenMPUpdateDependObjectsClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update_depend_objects' clause.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition SemaOpenMP.h:113
OMPAdjustArgsDescriptor * ActOnOpenMPAdjustArgsClause(OpenMPAdjustArgsOpKind AdjustOp, OpenMPNeedDevicePtrModifier NeedDevicePtrModifier, ArrayRef< OMPAdjustArgsItem > Items, SourceLocation Loc)
Called on well-formed 'adjust_args' clause of a '#pragma omp declare variant' directive.
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)
void addRequiresDecl(OMPRequiresDecl *D)
Registers a 'requires' directive deserialized from an AST file.
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)
DeclGroupPtrTy ActOnOpenMPGroupPrivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp groupprivate'.
bool isOpenMPDeclareMapperVarDeclAllowed(const VarDecl *VD) const
OMPClause * ActOnOpenMPInclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'inclusive' clause.
SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as host cod...
SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD)
Creates a SemaDiagnosticBuilder that emits the diagnostic if the current context is "used as device c...
StmtResult ActOnOpenMPSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp sections' after parsing of the associated statement.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
OMPClause * ActOnOpenMPTaskReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'task_reduction' clause.
OMPClause * ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc, Expr *Condition)
Called on well-formed 'nowait' clause.
StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp critical' after parsing of the associated statement.
StmtResult ActOnOpenMPMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp masked' after parsing of the.
StmtResult ActOnOpenMPStripeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Decl *D)
Act on D, a function definition inside of an omp [begin/end] assumes.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPOrderClause(OpenMPOrderClauseModifier Modifier, OpenMPOrderClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'order' clause.
llvm::SmallDenseMap< const ValueDecl *, const Expr *, 4 > VarsWithInheritedDSAType
Definition SemaOpenMP.h:446
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(ArrayRef< Expr * > VarList, OpenMPNumThreadsClauseModifier SimpleModifier, SourceLocation SimpleModifierLoc, OpenMPNumThreadsClauseModifier ComplexModifier, Expr *ComplexModifierExpr, SourceLocation ComplexModifierLoc, 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 statem...
bool isOpenMPGlobalCapturedDecl(ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified global variable must be captured by outer capture regions.
OMPClause * ActOnOpenMPInReductionClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'in_reduction' clause.
StmtResult ActOnOpenMPGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPFlushClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'flush' pseudo clause.
OMPRequiresDecl * CheckOMPRequiresDecl(SourceLocation Loc, ArrayRef< OMPClause * > Clauses)
Check restrictions on Requires directive.
void ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(Decl *D, SmallVectorImpl< FunctionDecl * > &Bases)
Register D as specialization of all base functions in Bases in the current omp begin/end declare vari...
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
Definition SemaOpenMP.h:253
void setOpenMPDeviceNumID(StringRef ID)
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
OMPClause * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, OpenMPThreadLimitClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
int getOpenMPDeviceNum() const
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
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:57
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 * ActOnOpenMPTransparentClause(Expr *Transparent, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'transparent' clause.
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.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, OpenMPNumTeamsClauseModifier Modifier, Expr *ModifierExpr, SourceLocation ModifierLoc, OpenMPNumTeamsClauseModifier ModifierExtra, Expr *ModifierExtraExpr, SourceLocation ModifierExtraLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
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.
StmtResult ActOnOpenMPMetaDirective(SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPTraitInfo * > TraitInfos, ArrayRef< Stmt * > Variants)
Called for metadirectives with user conditions that require runtime selection.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
Definition SemaOpenMP.h:58
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< OMPAdjustArgsDescriptor * > AdjustArgs, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition SemaOpenMP.h:387
OMPClause * ActOnOpenMPFromClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, Expr *IteratorModifier, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'from' clause.
StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancellation point'.
OMPClause * ActOnOpenMPDynGroupprivateClause(OpenMPDynGroupprivateClauseModifier M1, OpenMPDynGroupprivateClauseFallbackModifier M2, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation EndLoc)
Called on a well-formed 'dyn_groupprivate' clause.
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.
OMPClause * ActOnOpenMPToClause(ArrayRef< OpenMPMotionModifierKind > MotionModifiers, ArrayRef< SourceLocation > MotionModifiersLoc, Expr *IteratorModifier, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'to' clause.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPLinearClause(ArrayRef< Expr * > VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc)
Called on well-formed 'linear' clause.
OMPClause * ActOnOpenMPDefaultmapClause(OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc)
Called on well-formed 'defaultmap' clause.
StmtResult ActOnOpenMPMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskwait'.
StmtResult ActOnOpenMPForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp for simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPReductionClause(ArrayRef< Expr * > VarList, OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions={})
Called on well-formed 'reduction' clause.
OMPClause * ActOnOpenMPRelaxedClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'relaxed' clause.
OMPClause * ActOnOpenMPAlignedClause(ArrayRef< Expr * > VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'aligned' clause.
StmtResult ActOnOpenMPInteropDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp interop'.
OMPClause * ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depobj' pseudo clause.
OMPClause * ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'seq_cst' clause.
void checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D, SourceLocation IdLoc=SourceLocation())
Check declaration inside target region.
OMPClause * ActOnOpenMPNovariantsClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'novariants' clause.
OMPClause * ActOnOpenMPCopyprivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyprivate' clause.
OMPClause * ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'collapse' clause.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op)
StmtResult ActOnOpenMPTargetSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPDefaultClause(llvm::omp::DefaultKind M, SourceLocation MLoc, OpenMPDefaultClauseVariableCategory VCKind, SourceLocation VCKindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'default' clause.
OMPClause * ActOnOpenMPAlignClause(Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'align' clause.
OMPClause * ActOnOpenMPAtomicDefaultMemOrderClause(OpenMPAtomicDefaultMemOrderClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'atomic_default_mem_order' clause.
StmtResult ActOnOpenMPTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPWeakClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'weak' clause.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
StmtResult ActOnOpenMPTileDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp tile' after parsing of its clauses and the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel' after parsing of the associated statement.
StmtResult ActOnOpenMPSingleDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp single' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop simd' after parsing of the associated statement.
const ValueDecl * getOpenMPDeclareMapperVarName() const
StmtResult ActOnOpenMPParallelMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel master taskloop' after parsing of the associated statemen...
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed 'pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
OMPClause * ActOnOpenMPExclusiveClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'exclusive' clause.
OMPClause * ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'write' clause.
StmtResult ActOnOpenMPTargetParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel loop' after parsing of the associated statement.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed 'pragma omp [begin] assume[s]'.
StmtResult ActOnOpenMPTargetParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target parallel for simd' after parsing of the associated statemen...
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
OMPClause * ActOnOpenMPReverseOffloadClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'reverse_offload' clause.
StmtResult ActOnOpenMPTaskDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp task' after parsing of the associated statement.
OMPClause * ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc)
Called on well-formed 'if' clause.
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'.
OMPClause * ActOnOpenMPDepthClause(Expr *DepthExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depth' clause.
void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level)
Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) for FD based on DSA for the...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
StmtResult ActOnOpenMPCancelDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion)
Called on well-formed '#pragma omp cancel'.
StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskyield'.
StmtResult ActOnOpenMPTeamsDistributeSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute simd' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called for 'pragma omp declare mapper'.
A RAII object to enter scope of a compound statement.
Definition Sema.h:1340
Expr * get() const
Definition Sema.h:7923
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12724
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:7874
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:862
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1164
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',...
ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)
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:9501
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:9542
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:9544
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:9546
ExprResult CreateBuiltinBinOp(SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
CreateBuiltinBinOp - Creates a new built-in binary operation with operator Opc at location TokLoc.
SemaOpenMP & OpenMP()
Definition Sema.h:1558
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4927
@ AR_inaccessible
Definition Sema.h:1716
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition Sema.cpp:2493
FPOptionsOverride CurFPFeatureOverrides()
Definition Sema.h:2106
NamedDecl * LookupSingleName(Scope *S, DeclarationName Name, SourceLocation Loc, LookupNameKind NameKind, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Look up a name, looking for a single declaration.
ASTContext & Context
Definition Sema.h:1331
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp:81
void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext=true)
Add this decl to the scope shadowed decl chains.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition SemaExpr.cpp:769
ASTContext & getASTContext() const
Definition Sema.h:934
ExprResult BuildUnaryOp(Scope *S, SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *Input, bool IsAfterAmp=false)
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.
void PopExpressionEvaluationContext()
llvm::SmallSetVector< CXXRecordDecl *, 16 > AssociatedClassSet
Definition Sema.h:9494
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1235
DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)
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...
const LangOptions & getLangOpts() const
Definition Sema.h:927
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:1330
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.
ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type, SourceLocation LParenLoc, MultiExprArg Exprs, SourceLocation RParenLoc, bool ListInitialization)
const LangOptions & LangOpts
Definition Sema.h:1329
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition Sema.cpp:2739
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
Definition Sema.h:9493
DeclContext * getCurLexicalContext() const
Definition Sema.h:1168
ExprResult BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op)
void ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope, CapturedRegionKind Kind, unsigned NumParams)
ExprResult DefaultLvalueConversion(Expr *E)
Definition SemaExpr.cpp:649
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition Sema.h:15804
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition Sema.cpp:2694
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1471
bool IsDerivedFrom(SourceLocation Loc, CXXRecordDecl *Derived, CXXRecordDecl *Base, CXXBasePaths &Paths)
Determine whether the type Derived is a C++ class that is derived from the type Base.
StmtResult ActOnCapturedRegionEnd(Stmt *S)
ExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, Expr *E)
ExprResult ActOnConditionalOp(SourceLocation QuestionLoc, SourceLocation ColonLoc, Expr *CondExpr, Expr *LHSExpr, Expr *RHSExpr)
ActOnConditionalOp - Parse a ?
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:15759
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2679
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:11454
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=AllowFoldKind::No)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
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:276
ExprResult CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc, Expr *Idx, SourceLocation RLoc)
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
Definition Sema.h:6887
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6856
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition SemaStmt.cpp:76
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition Sema.h:1290
bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)
Perform qualified name lookup into a given context.
void DiscardCleanupsInEvaluationContext()
ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, BinaryOperatorKind Opc, Expr *LHSExpr, Expr *RHSExpr, bool ForFoldExpression=false)
ExprResult ActOnIntegerConstant(SourceLocation Loc, int64_t Val)
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)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, const FunctionDecl *FD=nullptr)
Definition Sema.cpp:2280
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition Sema.cpp:3137
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)
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
Definition SemaStmt.cpp:457
FullExprArg MakeFullExpr(Expr *Arg)
Definition Sema.h:7937
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8817
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
Definition Expr.h:4664
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Expr.h:4685
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:85
SourceLocation getEndLoc() const LLVM_READONLY
Definition Stmt.cpp:367
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
child_range children()
Definition Stmt.cpp:304
StmtClass getStmtClass() const
Definition Stmt.h:1504
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
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:210
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4988
bool isTLSSupported() const
Whether the target supports thread-local storage.
A semantic tree transformation that allows one to transform one abstract syntax tree into another.
Represents a declaration of a type.
Definition Decl.h:3664
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8549
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:267
QualType getType() const
Return the type wrapped by this type source info.
Definition TypeBase.h:8560
The base class of the type hierarchy.
Definition TypeBase.h:1879
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition TypeBase.h:9391
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isConstantArrayType() const
Definition TypeBase.h:8918
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool hasIntegerRepresentation() const
Determine whether this type has an integer representation of some sort, e.g., it is an integer type o...
Definition Type.cpp:2245
bool isArrayType() const
Definition TypeBase.h:8914
bool isArithmeticType() const
Definition Type.cpp:2550
bool isPointerType() const
Definition TypeBase.h:8815
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9248
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9498
bool isReferenceType() const
Definition TypeBase.h:8839
bool isEnumeralType() const
Definition TypeBase.h:8946
bool isScalarType() const
Definition TypeBase.h:9310
bool isVariableArrayType() const
Definition TypeBase.h:8926
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2282
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2504
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition Type.cpp:2355
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:9194
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2871
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:9169
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2863
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2631
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8950
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2469
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2436
bool isFunctionProtoType() const
Definition TypeBase.h:2665
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition TypeBase.h:9354
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2881
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9484
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2655
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition TypeBase.h:9448
bool isFunctionType() const
Definition TypeBase.h:8811
bool hasFloatingRepresentation() const
Determine whether this type has a floating-point representation of some sort, e.g....
Definition Type.cpp:2525
bool isStructureOrClassType() const
Definition Type.cpp:839
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2533
bool isFloatingType() const
Definition Type.cpp:2517
bool isAnyPointerType() const
Definition TypeBase.h:8823
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9431
bool isRecordType() const
Definition TypeBase.h:8942
bool isUnionType() const
Definition Type.cpp:851
bool isFunctionNoProtoType() const
Definition TypeBase.h:2664
Represents the declaration of a typedef-name via the 'typedef' type specifier.
Definition Decl.h:3818
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3713
Simple class containing the result of Sema::CorrectTypo.
NamedDecl * getCorrectionDecl() const
Gets the pointer to the declaration of the typo correction.
Expr * getSubExpr() const
Definition Expr.h:2354
Opcode getOpcode() const
Definition Expr.h:2349
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:464
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
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:714
void setType(QualType newType)
Definition Decl.h:726
QualType getType() const
Definition Decl.h:725
VarDecl * getPotentiallyDecomposedVarDecl()
Definition DeclCXX.cpp:3695
const Expr * getExprStmt() const
Definition Stmt.cpp:420
Represents a variable declaration or definition.
Definition Decl.h:934
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2132
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition Decl.h:1292
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1606
TLSKind getTLSKind() const
Definition Decl.cpp:2149
bool hasInit() const
Definition Decl.cpp:2400
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1489
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition Decl.h:1503
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2256
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2171
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2238
@ CInit
C-style initialization with assignment.
Definition Decl.h:939
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:942
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1308
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1249
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1216
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition Decl.h:1367
const Expr * getInit() const
Definition Decl.h:1393
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1192
@ TLS_None
Not a TLS variable.
Definition Decl.h:954
void setInit(Expr *I)
Definition Decl.cpp:2470
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1320
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1276
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition Decl.h:1508
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition Decl.h:1252
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1176
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:2521
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition Decl.h:1287
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1383
Retains information about a captured region.
Definition ScopeInfo.h:817
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:233
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
Defines the clang::TargetInfo interface.
Definition SPIR.cpp:47
VE builtins.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool LE(InterpState &S, CodePtr OpPC)
Definition Interp.h:1512
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
Top level wrappers for InstallAPI frontend operations.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
Privates[]
This class represents the 'transparent' clause in the 'pragma omp task' directive.
bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a teams directive in the outermost n...
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter)
Checks if the parameter to the fail clause in "#pragma atomic compare fail" is restricted only to mem...
@ CPlusPlus
MutableArrayRef< TemplateParameterList * > MultiTemplateParamsArg
Definition Ownership.h:263
bool isOpenMPTargetDataManagementDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target data offload directive.
OpenMPDefaultClauseVariableCategory
OpenMP variable-category for 'default' clause.
@ OMPC_DEFAULT_VC_unknown
Stmt Stmt llvm::function_ref< void(OMPLoopTransformationDirective *)> bool RelaxNestForPeeledTransformation
Definition StmtOpenMP.h:935
bool isOpenMPLoopTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive.
OpenMPDefaultmapClauseModifier
OpenMP modifiers for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_MODIFIER_last
@ OMPC_DEFAULTMAP_MODIFIER_unknown
OpenMPOrderClauseModifier
OpenMP modifiers for 'order' clause.
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_last
OpenMPNeedDevicePtrModifier
OpenMP 6.1 need_device modifier.
@ OMPC_NEED_DEVICE_PTR_unknown
OpenMPAdjustArgsOpKind
OpenMP adjust-op kinds for 'adjust_args' clause.
@ Comparison
A comparison.
Definition Sema.h:660
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition Specifiers.h:153
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:155
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
@ OMPC_AT_unknown
Expr * AssertSuccess(ExprResult R)
Definition Ownership.h:275
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
@ LCK_ByRef
Capturing by reference.
Definition Lambda.h:37
@ LCK_This
Capturing the *this object by reference.
Definition Lambda.h:34
OpenMPReductionClauseModifier
OpenMP modifiers for 'reduction' clause.
@ OMPC_REDUCTION_unknown
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Seq
'seq' clause, allowed on 'loop' and 'routine' directives.
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition OpenMPKinds.h:39
@ OMPC_SCHEDULE_MODIFIER_last
Definition OpenMPKinds.h:44
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition OpenMPKinds.h:40
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition Specifiers.h:127
@ AS_public
Definition Specifiers.h:128
@ AS_none
Definition Specifiers.h:131
SmallVector< Attr *, 4 > AttrVec
AttrVec - A vector of Attr, which is how they are stored on the AST.
ActionResult< Decl * > DeclResult
Definition Ownership.h:255
const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ CR_Default
@ CR_OpenMP
OpenMPNumTeamsClauseModifier
@ OMPC_NUMTEAMS_unknown
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:260
@ SC_Register
Definition Specifiers.h:261
@ SC_None
Definition Specifiers.h:254
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition Decl.h:5542
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
@ Dependent
Parse the block as a dependent block, which may be used in some template instantiations but not other...
Definition Parser.h:142
bool isOpenMPTaskingDirective(OpenMPDirectiveKind Kind)
Checks if the specified directive kind is one of tasking directives - task, taskloop,...
static constexpr unsigned NumberOfOMPMapClauseModifiers
Number of allowed map-type-modifiers.
Definition OpenMPKinds.h:88
ExprResult ExprEmpty()
Definition Ownership.h:272
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
OpenMPDynGroupprivateClauseFallbackModifier
@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown
MutableArrayRef< Expr * > MultiExprArg
Definition Ownership.h:259
StmtResult StmtError()
Definition Ownership.h:266
@ SD_Static
Static storage duration.
Definition Specifiers.h:345
@ Parameter
The parameter type of a method or function.
Definition TypeBase.h:909
@ Result
The result type of a method or function.
Definition TypeBase.h:906
ActionResult< ParsedType > TypeResult
Definition Ownership.h:251
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.
@ OMPC_BIND_unknown
const FunctionProtoType * T
OpenMPLastprivateModifier
OpenMP 'lastprivate' clause modifier.
@ OMPC_LASTPRIVATE_unknown
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
Definition OpenMPKinds.h:55
@ OMPC_DEPEND_unknown
Definition OpenMPKinds.h:59
bool isOpenMPCanonicalLoopSequenceTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPGrainsizeClauseModifier
@ OMPC_GRAINSIZE_unknown
bool isOpenMPCanonicalLoopNestTransformationDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a loop transformation directive that applies to a canonical loop...
OpenMPNumTasksClauseModifier
@ OMPC_NUMTASKS_unknown
OpenMPUseDevicePtrFallbackModifier
OpenMP 6.1 use_device_ptr fallback modifier.
@ OMPC_USE_DEVICE_PTR_FALLBACK_unknown
ExprResult ExprError()
Definition Ownership.h:265
bool isOpenMPOrderConcurrentNestableDirective(OpenMPDirectiveKind DKind, const LangOptions &LangOpts)
Checks if the specified directive is an order concurrent nestable directive that can be nested within...
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive can capture variables.
OpenMPSeverityClauseKind
OpenMP attributes for 'severity' clause.
@ OMPC_SEVERITY_unknown
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.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
Definition OpenMPKinds.h:92
@ OMPC_MOTION_MODIFIER_unknown
Definition OpenMPKinds.h:96
OpenMPDefaultmapClauseKind
OpenMP attributes for 'defaultmap' clause.
@ OMPC_DEFAULTMAP_unknown
OpenMPAllocateClauseModifier
OpenMP modifiers for 'allocate' clause.
@ OMPC_ALLOCATE_unknown
bool isOpenMPThreadPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of threadprivate clauses like 'threadprivate',...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Definition OpenMPKinds.h:63
@ OMPC_LINEAR_unknown
Definition OpenMPKinds.h:67
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is considered as "executable".
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
Definition OpenMPKinds.h:25
OpenMPDynGroupprivateClauseModifier
@ OMPC_DYN_GROUPPRIVATE_unknown
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
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:136
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:139
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:143
OpenMPThreadLimitClauseModifier
@ OMPC_THREADLIMIT_unknown
bool isOpenMPSimdizableDirective(OpenMPDirectiveKind DKind, OpenMPBindClauseKind BindKind, const LangOptions &LangOpts)
Checks if the specified directive is a simdizable directive, i.e.
SmallVector< CXXBaseSpecifier *, 4 > CXXCastPath
A simple array of base specifiers.
Definition ASTContext.h:147
void getOpenMPCaptureRegions(llvm::SmallVectorImpl< OpenMPDirectiveKind > &CaptureRegions, OpenMPDirectiveKind DKind)
Return the captured regions of an OpenMP directive.
OpenMPNumThreadsClauseModifier
@ OMPC_NUMTHREADS_unknown
OpenMPAtomicDefaultMemOrderClauseKind
OpenMP attributes for 'atomic_default_mem_order' clause.
@ OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown
DynamicRecursiveASTVisitorBase< false > DynamicRecursiveASTVisitor
U cast(CodeGen::Address addr)
Definition Address.h:327
OpenMPDeviceClauseModifier
OpenMP modifiers for 'device' clause.
Definition OpenMPKinds.h:48
@ OMPC_DEVICE_unknown
Definition OpenMPKinds.h:51
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Definition Ownership.h:230
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Definition OpenMPKinds.h:79
@ OMPC_MAP_MODIFIER_unknown
Definition OpenMPKinds.h:80
@ None
No keyword precedes the qualified type name.
Definition TypeBase.h:6167
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
Definition OpenMPKinds.h:28
bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified composite/combined directive constitutes a distribute directive in the outerm...
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
OpenMPOrderClauseKind
OpenMP attributes for 'order' clause.
@ OMPC_ORDER_unknown
@ Implicit
An implicit conversion.
Definition Sema.h:433
OpenMPScheduleClauseKind
OpenMP attributes for 'schedule' clause.
Definition OpenMPKinds.h:31
@ OMPC_SCHEDULE_unknown
Definition OpenMPKinds.h:35
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
ActionResult< Stmt * > StmtResult
Definition Ownership.h:250
OpenMPThreadsetKind
OpenMP modifiers for 'threadset' clause.
@ OMPC_THREADSET_unknown
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
Definition OpenMPKinds.h:71
@ OMPC_MAP_unknown
Definition OpenMPKinds.h:75
@ NOUR_Unevaluated
This name appears in an unevaluated operand.
Definition Specifiers.h:181
unsigned long uint64_t
int const char * function
Definition c++config.h:31
#define false
Definition stdbool.h:26
#define true
Definition stdbool.h:25
unsigned operator()(argument_type DK)
OpenMPDirectiveKind argument_type
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Clang specific specialization of the OMPContext to lookup target features.
const Expr * RHS
The original right-hand side.
Definition ExprCXX.h:318
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition ExprCXX.h:314
const Expr * LHS
The original left-hand side.
Definition ExprCXX.h:316
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:667
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:669
Extra information about a function prototype.
Definition TypeBase.h:5633
One bound of a parameter range.
Expr * E
The bound expression, or the logical offset for a NumArgs bound.
One item in an OpenMP 'adjust_args' parameter list.
Expr * E
A named parameter or positional expression for a Single item.
llvm::SmallVector< OMPInteropPref, 4 > Prefs
One entry of a prefer_type list.
llvm::SmallVector< Expr *, 2 > Attrs
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
This structure contains most locations needed for by an OMPVarListClause.
SourceLocation StartLoc
Starting location of the clause (the clause keyword).
SourceLocation LParenLoc
Location of '('.
SourceLocation EndLoc
Ending location of the clause.
std::optional< Expr * > Indirect
The directive with indirect clause.
Definition SemaOpenMP.h:332
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition SemaOpenMP.h:329
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition SemaOpenMP.h:326
SourceLocation Loc
The directive location.
Definition SemaOpenMP.h:335
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition SemaOpenMP.h:323
Data structure for iterator expression.
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.