clang 23.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"
21#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
26#include "clang/AST/StmtCXX.h"
35#include "clang/Sema/Lookup.h"
37#include "clang/Sema/Scope.h"
39#include "clang/Sema/Sema.h"
40#include "llvm/ADT/IndexedMap.h"
41#include "llvm/ADT/PointerEmbeddedInt.h"
42#include "llvm/ADT/STLExtras.h"
43#include "llvm/ADT/Sequence.h"
44#include "llvm/ADT/SetVector.h"
45#include "llvm/ADT/SmallSet.h"
46#include "llvm/ADT/StringExtras.h"
47#include "llvm/Frontend/OpenMP/OMPAssume.h"
48#include "llvm/Frontend/OpenMP/OMPConstants.h"
49#include "llvm/IR/Assumptions.h"
50#include <optional>
51
52using namespace clang;
53using namespace llvm::omp;
54
55//===----------------------------------------------------------------------===//
56// Stack of data-sharing attributes for variables
57//===----------------------------------------------------------------------===//
58
60 Sema &SemaRef, Expr *E,
62 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose);
63
65
66namespace {
67/// Default data sharing attributes, which can be applied to directive.
68enum DefaultDataSharingAttributes {
69 DSA_unspecified = 0, /// Data sharing attribute not specified.
70 DSA_none = 1 << 0, /// Default data sharing attribute 'none'.
71 DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
72 DSA_private = 1 << 2, /// Default data sharing attribute 'private'.
73 DSA_firstprivate = 1 << 3, /// Default data sharing attribute 'firstprivate'.
74};
75
76/// Variable Category attributes to restrict the modifier of the
77/// default clause (DefaultDataSharingAttributes)
78/// Not mentioning any Variable category attribute indicates
79/// the modifier (DefaultDataSharingAttributes) is for all variables.
80enum DefaultDataSharingVCAttributes {
81 DSA_VC_all = 0, /// for all variables.
82 DSA_VC_aggregate, /// for aggregate variables.
83 DSA_VC_pointer, /// for pointer variables.
84 DSA_VC_scalar, /// for scalar variables.
85};
86
87/// Stack for tracking declarations used in OpenMP directives and
88/// clauses and their data-sharing attributes.
89class DSAStackTy {
90public:
91 struct DSAVarData {
92 OpenMPDirectiveKind DKind = OMPD_unknown;
93 OpenMPClauseKind CKind = OMPC_unknown;
94 unsigned Modifier = 0;
95 const Expr *RefExpr = nullptr;
96 DeclRefExpr *PrivateCopy = nullptr;
97 SourceLocation ImplicitDSALoc;
98 bool AppliedToPointee = false;
99 DSAVarData() = default;
100 DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
101 const Expr *RefExpr, DeclRefExpr *PrivateCopy,
102 SourceLocation ImplicitDSALoc, unsigned Modifier,
103 bool AppliedToPointee)
104 : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
105 PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc),
106 AppliedToPointee(AppliedToPointee) {}
107 };
108 using OperatorOffsetTy =
109 llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
110 using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
111 /// Kind of the declaration used in the uses_allocators clauses.
112 enum class UsesAllocatorsDeclKind {
113 /// Predefined allocator
114 PredefinedAllocator,
115 /// User-defined allocator
116 UserDefinedAllocator,
117 /// The declaration that represent allocator trait
118 AllocatorTrait,
119 };
120
121private:
122 struct DSAInfo {
123 OpenMPClauseKind Attributes = OMPC_unknown;
124 unsigned Modifier = 0;
125 /// Pointer to a reference expression and a flag which shows that the
126 /// variable is marked as lastprivate(true) or not (false).
127 llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
128 DeclRefExpr *PrivateCopy = nullptr;
129 /// true if the attribute is applied to the pointee, not the variable
130 /// itself.
131 bool AppliedToPointee = false;
132 };
133 using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
134 using UsedRefMapTy = llvm::SmallDenseMap<const ValueDecl *, const Expr *, 8>;
135 using LCDeclInfo = std::pair<unsigned, VarDecl *>;
136 using LoopControlVariablesMapTy =
137 llvm::SmallDenseMap<const ValueDecl *, LCDeclInfo, 8>;
138 /// Struct that associates a component with the clause kind where they are
139 /// found.
140 struct MappedExprComponentTy {
142 OpenMPClauseKind Kind = OMPC_unknown;
143 };
144 using MappedExprComponentsTy =
145 llvm::DenseMap<const ValueDecl *, MappedExprComponentTy>;
146 using CriticalsWithHintsTy =
147 llvm::StringMap<std::pair<const OMPCriticalDirective *, llvm::APSInt>>;
148 struct ReductionData {
149 using BOKPtrType = llvm::PointerEmbeddedInt<BinaryOperatorKind, 16>;
150 SourceRange ReductionRange;
151 llvm::PointerUnion<const Expr *, BOKPtrType> ReductionOp;
152 ReductionData() = default;
153 void set(BinaryOperatorKind BO, SourceRange RR) {
154 ReductionRange = RR;
155 ReductionOp = BO;
156 }
157 void set(const Expr *RefExpr, SourceRange RR) {
158 ReductionRange = RR;
159 ReductionOp = RefExpr;
160 }
161 };
162 using DeclReductionMapTy =
163 llvm::SmallDenseMap<const ValueDecl *, ReductionData, 4>;
164 struct DefaultmapInfo {
165 OpenMPDefaultmapClauseModifier ImplicitBehavior =
167 SourceLocation SLoc;
168 DefaultmapInfo() = default;
169 DefaultmapInfo(OpenMPDefaultmapClauseModifier M, SourceLocation Loc)
170 : ImplicitBehavior(M), SLoc(Loc) {}
171 };
172
173 struct SharingMapTy {
174 DeclSAMapTy SharingMap;
175 DeclReductionMapTy ReductionMap;
176 UsedRefMapTy AlignedMap;
177 UsedRefMapTy NontemporalMap;
178 MappedExprComponentsTy MappedExprComponents;
179 LoopControlVariablesMapTy LCVMap;
180 DefaultDataSharingAttributes DefaultAttr = DSA_unspecified;
181 SourceLocation DefaultAttrLoc;
182 DefaultDataSharingVCAttributes DefaultVCAttr = DSA_VC_all;
183 SourceLocation DefaultAttrVCLoc;
184 DefaultmapInfo DefaultmapMap[OMPC_DEFAULTMAP_unknown + 1];
185 OpenMPDirectiveKind Directive = OMPD_unknown;
186 DeclarationNameInfo DirectiveName;
187 Scope *CurScope = nullptr;
188 DeclContext *Context = nullptr;
189 SourceLocation ConstructLoc;
190 /// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
191 /// get the data (loop counters etc.) about enclosing loop-based construct.
192 /// This data is required during codegen.
193 DoacrossClauseMapTy DoacrossDepends;
194 /// First argument (Expr *) contains optional argument of the
195 /// 'ordered' clause, the second one is true if the regions has 'ordered'
196 /// clause, false otherwise.
197 std::optional<std::pair<const Expr *, OMPOrderedClause *>> OrderedRegion;
198 bool RegionHasOrderConcurrent = false;
199 unsigned AssociatedLoops = 1;
200 bool HasMutipleLoops = false;
201 const Decl *PossiblyLoopCounter = nullptr;
202 bool NowaitRegion = false;
203 bool UntiedRegion = false;
204 bool CancelRegion = false;
205 bool LoopStart = false;
206 bool BodyComplete = false;
207 SourceLocation PrevScanLocation;
208 SourceLocation PrevOrderedLocation;
209 SourceLocation InnerTeamsRegionLoc;
210 /// Reference to the taskgroup task_reduction reference expression.
211 Expr *TaskgroupReductionRef = nullptr;
212 llvm::DenseSet<QualType> MappedClassesQualTypes;
213 SmallVector<Expr *, 4> InnerUsedAllocators;
214 llvm::DenseSet<CanonicalDeclPtr<Decl>> ImplicitTaskFirstprivates;
215 /// List of globals marked as declare target link in this target region
216 /// (isOpenMPTargetExecutionDirective(Directive) == true).
217 llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
218 /// List of decls used in inclusive/exclusive clauses of the scan directive.
219 llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
220 llvm::DenseMap<CanonicalDeclPtr<const Decl>, UsesAllocatorsDeclKind>
221 UsesAllocatorsDecls;
222 /// Data is required on creating capture fields for implicit
223 /// default first|private clause.
224 struct ImplicitDefaultFDInfoTy {
225 /// Field decl.
226 const FieldDecl *FD = nullptr;
227 /// Nesting stack level
228 size_t StackLevel = 0;
229 /// Capture variable decl.
230 VarDecl *VD = nullptr;
231 ImplicitDefaultFDInfoTy(const FieldDecl *FD, size_t StackLevel,
232 VarDecl *VD)
233 : FD(FD), StackLevel(StackLevel), VD(VD) {}
234 };
235 /// List of captured fields
236 llvm::SmallVector<ImplicitDefaultFDInfoTy, 8>
237 ImplicitDefaultFirstprivateFDs;
238 Expr *DeclareMapperVar = nullptr;
239 SmallVector<VarDecl *, 16> IteratorVarDecls;
240 SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
241 Scope *CurScope, SourceLocation Loc)
242 : Directive(DKind), DirectiveName(Name), CurScope(CurScope),
243 ConstructLoc(Loc) {}
244 SharingMapTy() = default;
245 };
246
247 using StackTy = SmallVector<SharingMapTy, 4>;
248
249 /// Stack of used declaration and their data-sharing attributes.
250 DeclSAMapTy Threadprivates;
251 DeclSAMapTy Groupprivates;
252 const FunctionScopeInfo *CurrentNonCapturingFunctionScope = nullptr;
253 SmallVector<std::pair<StackTy, const FunctionScopeInfo *>, 4> Stack;
254 /// true, if check for DSA must be from parent directive, false, if
255 /// from current directive.
256 OpenMPClauseKind ClauseKindMode = OMPC_unknown;
257 Sema &SemaRef;
258 bool ForceCapturing = false;
259 /// true if all the variables in the target executable directives must be
260 /// captured by reference.
261 bool ForceCaptureByReferenceInTargetExecutable = false;
262 CriticalsWithHintsTy Criticals;
263 unsigned IgnoredStackElements = 0;
264
265 /// Iterators over the stack iterate in order from innermost to outermost
266 /// directive.
267 using const_iterator = StackTy::const_reverse_iterator;
268 const_iterator begin() const {
269 return Stack.empty() ? const_iterator()
270 : Stack.back().first.rbegin() + IgnoredStackElements;
271 }
272 const_iterator end() const {
273 return Stack.empty() ? const_iterator() : Stack.back().first.rend();
274 }
275 using iterator = StackTy::reverse_iterator;
276 iterator begin() {
277 return Stack.empty() ? iterator()
278 : Stack.back().first.rbegin() + IgnoredStackElements;
279 }
280 iterator end() {
281 return Stack.empty() ? iterator() : Stack.back().first.rend();
282 }
283
284 // Convenience operations to get at the elements of the stack.
285
286 bool isStackEmpty() const {
287 return Stack.empty() ||
288 Stack.back().second != CurrentNonCapturingFunctionScope ||
289 Stack.back().first.size() <= IgnoredStackElements;
290 }
291 size_t getStackSize() const {
292 return isStackEmpty() ? 0
293 : Stack.back().first.size() - IgnoredStackElements;
294 }
295
296 SharingMapTy *getTopOfStackOrNull() {
297 size_t Size = getStackSize();
298 if (Size == 0)
299 return nullptr;
300 return &Stack.back().first[Size - 1];
301 }
302 const SharingMapTy *getTopOfStackOrNull() const {
303 return const_cast<DSAStackTy &>(*this).getTopOfStackOrNull();
304 }
305 SharingMapTy &getTopOfStack() {
306 assert(!isStackEmpty() && "no current directive");
307 return *getTopOfStackOrNull();
308 }
309 const SharingMapTy &getTopOfStack() const {
310 return const_cast<DSAStackTy &>(*this).getTopOfStack();
311 }
312
313 SharingMapTy *getSecondOnStackOrNull() {
314 size_t Size = getStackSize();
315 if (Size <= 1)
316 return nullptr;
317 return &Stack.back().first[Size - 2];
318 }
319 const SharingMapTy *getSecondOnStackOrNull() const {
320 return const_cast<DSAStackTy &>(*this).getSecondOnStackOrNull();
321 }
322
323 /// Get the stack element at a certain level (previously returned by
324 /// \c getNestingLevel).
325 ///
326 /// Note that nesting levels count from outermost to innermost, and this is
327 /// the reverse of our iteration order where new inner levels are pushed at
328 /// the front of the stack.
329 SharingMapTy &getStackElemAtLevel(unsigned Level) {
330 assert(Level < getStackSize() && "no such stack element");
331 return Stack.back().first[Level];
332 }
333 const SharingMapTy &getStackElemAtLevel(unsigned Level) const {
334 return const_cast<DSAStackTy &>(*this).getStackElemAtLevel(Level);
335 }
336
337 DSAVarData getDSA(const_iterator &Iter, ValueDecl *D) const;
338
339 /// Checks if the variable is a local for OpenMP region.
340 bool isOpenMPLocal(VarDecl *D, const_iterator Iter) const;
341
342 /// Vector of previously declared requires directives
343 SmallVector<const OMPRequiresDecl *, 2> RequiresDecls;
344 /// omp_allocator_handle_t type.
345 QualType OMPAllocatorHandleT;
346 /// omp_depend_t type.
347 QualType OMPDependT;
348 /// omp_event_handle_t type.
349 QualType OMPEventHandleT;
350 /// omp_alloctrait_t type.
351 QualType OMPAlloctraitT;
352 /// Expression for the predefined allocators.
353 Expr *OMPPredefinedAllocators[OMPAllocateDeclAttr::OMPUserDefinedMemAlloc] = {
354 nullptr};
355 /// Vector of previously encountered target directives
356 SmallVector<SourceLocation, 2> TargetLocations;
357 SourceLocation AtomicLocation;
358 /// Vector of declare variant construct traits.
359 SmallVector<llvm::omp::TraitProperty, 8> ConstructTraits;
360
361public:
362 explicit DSAStackTy(Sema &S) : SemaRef(S) {}
363
364 /// Sets omp_allocator_handle_t type.
365 void setOMPAllocatorHandleT(QualType Ty) { OMPAllocatorHandleT = Ty; }
366 /// Gets omp_allocator_handle_t type.
367 QualType getOMPAllocatorHandleT() const { return OMPAllocatorHandleT; }
368 /// Sets omp_alloctrait_t type.
369 void setOMPAlloctraitT(QualType Ty) { OMPAlloctraitT = Ty; }
370 /// Gets omp_alloctrait_t type.
371 QualType getOMPAlloctraitT() const { return OMPAlloctraitT; }
372 /// Sets the given default allocator.
373 void setAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
374 Expr *Allocator) {
375 OMPPredefinedAllocators[AllocatorKind] = Allocator;
376 }
377 /// Returns the specified default allocator.
378 Expr *getAllocator(OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind) const {
379 return OMPPredefinedAllocators[AllocatorKind];
380 }
381 /// Sets omp_depend_t type.
382 void setOMPDependT(QualType Ty) { OMPDependT = Ty; }
383 /// Gets omp_depend_t type.
384 QualType getOMPDependT() const { return OMPDependT; }
385
386 /// Sets omp_event_handle_t type.
387 void setOMPEventHandleT(QualType Ty) { OMPEventHandleT = Ty; }
388 /// Gets omp_event_handle_t type.
389 QualType getOMPEventHandleT() const { return OMPEventHandleT; }
390
391 bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
392 OpenMPClauseKind getClauseParsingMode() const {
393 assert(isClauseParsingMode() && "Must be in clause parsing mode.");
394 return ClauseKindMode;
395 }
396 void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
397
398 bool isBodyComplete() const {
399 const SharingMapTy *Top = getTopOfStackOrNull();
400 return Top && Top->BodyComplete;
401 }
402 void setBodyComplete() { getTopOfStack().BodyComplete = true; }
403
404 bool isForceVarCapturing() const { return ForceCapturing; }
405 void setForceVarCapturing(bool V) { ForceCapturing = V; }
406
407 void setForceCaptureByReferenceInTargetExecutable(bool V) {
408 ForceCaptureByReferenceInTargetExecutable = V;
409 }
410 bool isForceCaptureByReferenceInTargetExecutable() const {
411 return ForceCaptureByReferenceInTargetExecutable;
412 }
413
414 void push(OpenMPDirectiveKind DKind, const DeclarationNameInfo &DirName,
415 Scope *CurScope, SourceLocation Loc) {
416 assert(!IgnoredStackElements &&
417 "cannot change stack while ignoring elements");
418 if (Stack.empty() ||
419 Stack.back().second != CurrentNonCapturingFunctionScope)
420 Stack.emplace_back(StackTy(), CurrentNonCapturingFunctionScope);
421 Stack.back().first.emplace_back(DKind, DirName, CurScope, Loc);
422 Stack.back().first.back().DefaultAttrLoc = Loc;
423 }
424
425 void pop() {
426 assert(!IgnoredStackElements &&
427 "cannot change stack while ignoring elements");
428 assert(!Stack.back().first.empty() &&
429 "Data-sharing attributes stack is empty!");
430 Stack.back().first.pop_back();
431 }
432
433 /// RAII object to temporarily leave the scope of a directive when we want to
434 /// logically operate in its parent.
435 class ParentDirectiveScope {
436 DSAStackTy &Self;
437 bool Active;
438
439 public:
440 ParentDirectiveScope(DSAStackTy &Self, bool Activate)
441 : Self(Self), Active(false) {
442 if (Activate)
443 enable();
444 }
445 ~ParentDirectiveScope() { disable(); }
446 void disable() {
447 if (Active) {
448 --Self.IgnoredStackElements;
449 Active = false;
450 }
451 }
452 void enable() {
453 if (!Active) {
454 ++Self.IgnoredStackElements;
455 Active = true;
456 }
457 }
458 };
459
460 /// Marks that we're started loop parsing.
461 void loopInit() {
462 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
463 "Expected loop-based directive.");
464 getTopOfStack().LoopStart = true;
465 }
466 /// Start capturing of the variables in the loop context.
467 void loopStart() {
468 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
469 "Expected loop-based directive.");
470 getTopOfStack().LoopStart = false;
471 }
472 /// true, if variables are captured, false otherwise.
473 bool isLoopStarted() const {
474 assert(isOpenMPLoopDirective(getCurrentDirective()) &&
475 "Expected loop-based directive.");
476 return !getTopOfStack().LoopStart;
477 }
478 /// Marks (or clears) declaration as possibly loop counter.
479 void resetPossibleLoopCounter(const Decl *D = nullptr) {
480 getTopOfStack().PossiblyLoopCounter = D ? D->getCanonicalDecl() : D;
481 }
482 /// Gets the possible loop counter decl.
483 const Decl *getPossiblyLoopCounter() const {
484 return getTopOfStack().PossiblyLoopCounter;
485 }
486 /// Start new OpenMP region stack in new non-capturing function.
487 void pushFunction() {
488 assert(!IgnoredStackElements &&
489 "cannot change stack while ignoring elements");
490 const FunctionScopeInfo *CurFnScope = SemaRef.getCurFunction();
491 assert(!isa<CapturingScopeInfo>(CurFnScope));
492 CurrentNonCapturingFunctionScope = CurFnScope;
493 }
494 /// Pop region stack for non-capturing function.
495 void popFunction(const FunctionScopeInfo *OldFSI) {
496 assert(!IgnoredStackElements &&
497 "cannot change stack while ignoring elements");
498 if (!Stack.empty() && Stack.back().second == OldFSI) {
499 assert(Stack.back().first.empty());
500 Stack.pop_back();
501 }
502 CurrentNonCapturingFunctionScope = nullptr;
503 for (const FunctionScopeInfo *FSI : llvm::reverse(SemaRef.FunctionScopes)) {
504 if (!isa<CapturingScopeInfo>(FSI)) {
505 CurrentNonCapturingFunctionScope = FSI;
506 break;
507 }
508 }
509 }
510
511 void addCriticalWithHint(const OMPCriticalDirective *D, llvm::APSInt Hint) {
512 Criticals.try_emplace(D->getDirectiveName().getAsString(), D, Hint);
513 }
514 std::pair<const OMPCriticalDirective *, llvm::APSInt>
515 getCriticalWithHint(const DeclarationNameInfo &Name) const {
516 auto I = Criticals.find(Name.getAsString());
517 if (I != Criticals.end())
518 return I->second;
519 return std::make_pair(nullptr, llvm::APSInt());
520 }
521 /// If 'aligned' declaration for given variable \a D was not seen yet,
522 /// add it and return NULL; otherwise return previous occurrence's expression
523 /// for diagnostics.
524 const Expr *addUniqueAligned(const ValueDecl *D, const Expr *NewDE);
525 /// If 'nontemporal' declaration for given variable \a D was not seen yet,
526 /// add it and return NULL; otherwise return previous occurrence's expression
527 /// for diagnostics.
528 const Expr *addUniqueNontemporal(const ValueDecl *D, const Expr *NewDE);
529
530 /// Register specified variable as loop control variable.
531 void addLoopControlVariable(const ValueDecl *D, VarDecl *Capture);
532 /// Check if the specified variable is a loop control variable for
533 /// current region.
534 /// \return The index of the loop control variable in the list of associated
535 /// for-loops (from outer to inner).
536 const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const;
537 /// Check if the specified variable is a loop control variable for
538 /// parent region.
539 /// \return The index of the loop control variable in the list of associated
540 /// for-loops (from outer to inner).
541 const LCDeclInfo isParentLoopControlVariable(const ValueDecl *D) const;
542 /// Check if the specified variable is a loop control variable for
543 /// current region.
544 /// \return The index of the loop control variable in the list of associated
545 /// for-loops (from outer to inner).
546 const LCDeclInfo isLoopControlVariable(const ValueDecl *D,
547 unsigned Level) const;
548 /// Get the loop control variable for the I-th loop (or nullptr) in
549 /// parent directive.
550 const ValueDecl *getParentLoopControlVariable(unsigned I) const;
551
552 /// Marks the specified decl \p D as used in scan directive.
553 void markDeclAsUsedInScanDirective(ValueDecl *D) {
554 if (SharingMapTy *Stack = getSecondOnStackOrNull())
555 Stack->UsedInScanDirective.insert(D);
556 }
557
558 /// Checks if the specified declaration was used in the inner scan directive.
559 bool isUsedInScanDirective(ValueDecl *D) const {
560 if (const SharingMapTy *Stack = getTopOfStackOrNull())
561 return Stack->UsedInScanDirective.contains(D);
562 return false;
563 }
564
565 /// Adds explicit data sharing attribute to the specified declaration.
566 void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
567 DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0,
568 bool AppliedToPointee = false);
569
570 /// Adds additional information for the reduction items with the reduction id
571 /// represented as an operator.
572 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
574 /// Adds additional information for the reduction items with the reduction id
575 /// represented as reduction identifier.
576 void addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
577 const Expr *ReductionRef);
578 /// Returns the location and reduction operation from the innermost parent
579 /// region for the given \p D.
580 const DSAVarData
581 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
583 Expr *&TaskgroupDescriptor) const;
584 /// Returns the location and reduction operation from the innermost parent
585 /// region for the given \p D.
586 const DSAVarData
587 getTopMostTaskgroupReductionData(const ValueDecl *D, SourceRange &SR,
588 const Expr *&ReductionRef,
589 Expr *&TaskgroupDescriptor) const;
590 /// Return reduction reference expression for the current taskgroup or
591 /// parallel/worksharing directives with task reductions.
592 Expr *getTaskgroupReductionRef() const {
593 assert((getTopOfStack().Directive == OMPD_taskgroup ||
594 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
595 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
596 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
597 "taskgroup reference expression requested for non taskgroup or "
598 "parallel/worksharing directive.");
599 return getTopOfStack().TaskgroupReductionRef;
600 }
601 /// Checks if the given \p VD declaration is actually a taskgroup reduction
602 /// descriptor variable at the \p Level of OpenMP regions.
603 bool isTaskgroupReductionRef(const ValueDecl *VD, unsigned Level) const {
604 return getStackElemAtLevel(Level).TaskgroupReductionRef &&
605 cast<DeclRefExpr>(getStackElemAtLevel(Level).TaskgroupReductionRef)
606 ->getDecl() == VD;
607 }
608
609 /// Returns data sharing attributes from top of the stack for the
610 /// specified declaration.
611 const DSAVarData getTopDSA(ValueDecl *D, bool FromParent);
612 /// Returns data-sharing attributes for the specified declaration.
613 const DSAVarData getImplicitDSA(ValueDecl *D, bool FromParent) const;
614 /// Returns data-sharing attributes for the specified declaration.
615 const DSAVarData getImplicitDSA(ValueDecl *D, unsigned Level) const;
616 /// Checks if the specified variables has data-sharing attributes which
617 /// match specified \a CPred predicate in any directive which matches \a DPred
618 /// predicate.
619 const DSAVarData
620 hasDSA(ValueDecl *D,
621 const llvm::function_ref<bool(OpenMPClauseKind, bool,
622 DefaultDataSharingAttributes)>
623 CPred,
624 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
625 bool FromParent) const;
626 /// Checks if the specified variables has data-sharing attributes which
627 /// match specified \a CPred predicate in any innermost directive which
628 /// matches \a DPred predicate.
629 const DSAVarData
630 hasInnermostDSA(ValueDecl *D,
631 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
632 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
633 bool FromParent) const;
634 /// Checks if the specified variables has explicit data-sharing
635 /// attributes which match specified \a CPred predicate at the specified
636 /// OpenMP region.
637 bool
638 hasExplicitDSA(const ValueDecl *D,
639 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
640 unsigned Level, bool NotLastprivate = false) const;
641
642 /// Returns true if the directive at level \Level matches in the
643 /// specified \a DPred predicate.
644 bool hasExplicitDirective(
645 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
646 unsigned Level) const;
647
648 /// Finds a directive which matches specified \a DPred predicate.
649 bool hasDirective(
650 const llvm::function_ref<bool(
651 OpenMPDirectiveKind, const DeclarationNameInfo &, SourceLocation)>
652 DPred,
653 bool FromParent) const;
654
655 /// Returns currently analyzed directive.
656 OpenMPDirectiveKind getCurrentDirective() const {
657 const SharingMapTy *Top = getTopOfStackOrNull();
658 return Top ? Top->Directive : OMPD_unknown;
659 }
660 /// Returns directive kind at specified level.
661 OpenMPDirectiveKind getDirective(unsigned Level) const {
662 assert(!isStackEmpty() && "No directive at specified level.");
663 return getStackElemAtLevel(Level).Directive;
664 }
665 /// Returns the capture region at the specified level.
666 OpenMPDirectiveKind getCaptureRegion(unsigned Level,
667 unsigned OpenMPCaptureLevel) const {
668 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
669 getOpenMPCaptureRegions(CaptureRegions, getDirective(Level));
670 return CaptureRegions[OpenMPCaptureLevel];
671 }
672 /// Returns parent directive.
673 OpenMPDirectiveKind getParentDirective() const {
674 const SharingMapTy *Parent = getSecondOnStackOrNull();
675 return Parent ? Parent->Directive : OMPD_unknown;
676 }
677
678 /// Add requires decl to internal vector
679 void addRequiresDecl(OMPRequiresDecl *RD) { RequiresDecls.push_back(RD); }
680
681 /// Checks if the defined 'requires' directive has specified type of clause.
682 template <typename ClauseType> bool hasRequiresDeclWithClause() const {
683 return llvm::any_of(RequiresDecls, [](const OMPRequiresDecl *D) {
684 return llvm::any_of(D->clauselists(), [](const OMPClause *C) {
685 return isa<ClauseType>(C);
686 });
687 });
688 }
689
690 /// Checks for a duplicate clause amongst previously declared requires
691 /// directives
692 bool hasDuplicateRequiresClause(ArrayRef<OMPClause *> ClauseList) const {
693 bool IsDuplicate = false;
694 for (OMPClause *CNew : ClauseList) {
695 for (const OMPRequiresDecl *D : RequiresDecls) {
696 for (const OMPClause *CPrev : D->clauselists()) {
697 if (CNew->getClauseKind() == CPrev->getClauseKind()) {
698 SemaRef.Diag(CNew->getBeginLoc(),
699 diag::err_omp_requires_clause_redeclaration)
700 << getOpenMPClauseNameForDiag(CNew->getClauseKind());
701 SemaRef.Diag(CPrev->getBeginLoc(),
702 diag::note_omp_requires_previous_clause)
703 << getOpenMPClauseNameForDiag(CPrev->getClauseKind());
704 IsDuplicate = true;
705 }
706 }
707 }
708 }
709 return IsDuplicate;
710 }
711
712 /// Add location of previously encountered target to internal vector
713 void addTargetDirLocation(SourceLocation LocStart) {
714 TargetLocations.push_back(LocStart);
715 }
716
717 /// Add location for the first encountered atomic directive.
718 void addAtomicDirectiveLoc(SourceLocation Loc) {
719 if (AtomicLocation.isInvalid())
720 AtomicLocation = Loc;
721 }
722
723 /// Returns the location of the first encountered atomic directive in the
724 /// module.
725 SourceLocation getAtomicDirectiveLoc() const { return AtomicLocation; }
726
727 // Return previously encountered target region locations.
728 ArrayRef<SourceLocation> getEncounteredTargetLocs() const {
729 return TargetLocations;
730 }
731
732 /// Set default data sharing attribute to none.
733 void setDefaultDSANone(SourceLocation Loc) {
734 getTopOfStack().DefaultAttr = DSA_none;
735 getTopOfStack().DefaultAttrLoc = Loc;
736 }
737 /// Set default data sharing attribute to shared.
738 void setDefaultDSAShared(SourceLocation Loc) {
739 getTopOfStack().DefaultAttr = DSA_shared;
740 getTopOfStack().DefaultAttrLoc = Loc;
741 }
742 /// Set default data sharing attribute to private.
743 void setDefaultDSAPrivate(SourceLocation Loc) {
744 getTopOfStack().DefaultAttr = DSA_private;
745 getTopOfStack().DefaultAttrLoc = Loc;
746 }
747 /// Set default data sharing attribute to firstprivate.
748 void setDefaultDSAFirstPrivate(SourceLocation Loc) {
749 getTopOfStack().DefaultAttr = DSA_firstprivate;
750 getTopOfStack().DefaultAttrLoc = Loc;
751 }
752 /// Set default data sharing variable category attribute to aggregate.
753 void setDefaultDSAVCAggregate(SourceLocation VCLoc) {
754 getTopOfStack().DefaultVCAttr = DSA_VC_aggregate;
755 getTopOfStack().DefaultAttrVCLoc = VCLoc;
756 }
757 /// Set default data sharing variable category attribute to all.
758 void setDefaultDSAVCAll(SourceLocation VCLoc) {
759 getTopOfStack().DefaultVCAttr = DSA_VC_all;
760 getTopOfStack().DefaultAttrVCLoc = VCLoc;
761 }
762 /// Set default data sharing variable category attribute to pointer.
763 void setDefaultDSAVCPointer(SourceLocation VCLoc) {
764 getTopOfStack().DefaultVCAttr = DSA_VC_pointer;
765 getTopOfStack().DefaultAttrVCLoc = VCLoc;
766 }
767 /// Set default data sharing variable category attribute to scalar.
768 void setDefaultDSAVCScalar(SourceLocation VCLoc) {
769 getTopOfStack().DefaultVCAttr = DSA_VC_scalar;
770 getTopOfStack().DefaultAttrVCLoc = VCLoc;
771 }
772 /// Set default data mapping attribute to Modifier:Kind
773 void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
774 OpenMPDefaultmapClauseKind Kind, SourceLocation Loc) {
775 DefaultmapInfo &DMI = getTopOfStack().DefaultmapMap[Kind];
776 DMI.ImplicitBehavior = M;
777 DMI.SLoc = Loc;
778 }
779 /// Check whether the implicit-behavior has been set in defaultmap
780 bool checkDefaultmapCategory(OpenMPDefaultmapClauseKind VariableCategory) {
781 if (VariableCategory == OMPC_DEFAULTMAP_unknown)
782 return getTopOfStack()
783 .DefaultmapMap[OMPC_DEFAULTMAP_aggregate]
784 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
785 getTopOfStack()
786 .DefaultmapMap[OMPC_DEFAULTMAP_scalar]
787 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown ||
788 getTopOfStack()
789 .DefaultmapMap[OMPC_DEFAULTMAP_pointer]
790 .ImplicitBehavior != OMPC_DEFAULTMAP_MODIFIER_unknown;
791 return getTopOfStack().DefaultmapMap[VariableCategory].ImplicitBehavior !=
793 }
794
795 ArrayRef<llvm::omp::TraitProperty> getConstructTraits() {
796 return ConstructTraits;
797 }
798 void handleConstructTrait(ArrayRef<llvm::omp::TraitProperty> Traits,
799 bool ScopeEntry) {
800 if (ScopeEntry)
801 ConstructTraits.append(Traits.begin(), Traits.end());
802 else
803 for (llvm::omp::TraitProperty Trait : llvm::reverse(Traits)) {
804 llvm::omp::TraitProperty Top = ConstructTraits.pop_back_val();
805 assert(Top == Trait && "Something left a trait on the stack!");
806 (void)Trait;
807 (void)Top;
808 }
809 }
810
811 DefaultDataSharingAttributes getDefaultDSA(unsigned Level) const {
812 return getStackSize() <= Level ? DSA_unspecified
813 : getStackElemAtLevel(Level).DefaultAttr;
814 }
815 DefaultDataSharingAttributes getDefaultDSA() const {
816 return isStackEmpty() ? DSA_unspecified : getTopOfStack().DefaultAttr;
817 }
818 SourceLocation getDefaultDSALocation() const {
819 return isStackEmpty() ? SourceLocation() : getTopOfStack().DefaultAttrLoc;
820 }
822 getDefaultmapModifier(OpenMPDefaultmapClauseKind Kind) const {
823 return isStackEmpty()
825 : getTopOfStack().DefaultmapMap[Kind].ImplicitBehavior;
826 }
828 getDefaultmapModifierAtLevel(unsigned Level,
829 OpenMPDefaultmapClauseKind Kind) const {
830 return getStackElemAtLevel(Level).DefaultmapMap[Kind].ImplicitBehavior;
831 }
832 bool isDefaultmapCapturedByRef(unsigned Level,
833 OpenMPDefaultmapClauseKind Kind) const {
835 getDefaultmapModifierAtLevel(Level, Kind);
836 if (Kind == OMPC_DEFAULTMAP_scalar || Kind == OMPC_DEFAULTMAP_pointer) {
837 return (M == OMPC_DEFAULTMAP_MODIFIER_alloc) ||
838 (M == OMPC_DEFAULTMAP_MODIFIER_to) ||
839 (M == OMPC_DEFAULTMAP_MODIFIER_from) ||
840 (M == OMPC_DEFAULTMAP_MODIFIER_tofrom) ||
841 (M == OMPC_DEFAULTMAP_MODIFIER_present) ||
842 (M == OMPC_DEFAULTMAP_MODIFIER_storage);
843 }
844 return true;
845 }
846 static bool mustBeFirstprivateBase(OpenMPDefaultmapClauseModifier M,
848 switch (Kind) {
849 case OMPC_DEFAULTMAP_scalar:
850 case OMPC_DEFAULTMAP_pointer:
851 return (M == OMPC_DEFAULTMAP_MODIFIER_unknown) ||
852 (M == OMPC_DEFAULTMAP_MODIFIER_firstprivate) ||
853 (M == OMPC_DEFAULTMAP_MODIFIER_default);
854 case OMPC_DEFAULTMAP_aggregate:
855 return M == OMPC_DEFAULTMAP_MODIFIER_firstprivate;
856 default:
857 break;
858 }
859 llvm_unreachable("Unexpected OpenMPDefaultmapClauseKind enum");
860 }
861 bool mustBeFirstprivateAtLevel(unsigned Level,
862 OpenMPDefaultmapClauseKind Kind) const {
864 getDefaultmapModifierAtLevel(Level, Kind);
865 return mustBeFirstprivateBase(M, Kind);
866 }
867 bool mustBeFirstprivate(OpenMPDefaultmapClauseKind Kind) const {
868 OpenMPDefaultmapClauseModifier M = getDefaultmapModifier(Kind);
869 return mustBeFirstprivateBase(M, Kind);
870 }
871
872 /// Checks if the specified variable is a threadprivate.
873 bool isThreadPrivate(VarDecl *D) {
874 const DSAVarData DVar = getTopDSA(D, false);
875 return isOpenMPThreadPrivate(DVar.CKind);
876 }
877
878 /// Marks current region as ordered (it has an 'ordered' clause).
879 void setOrderedRegion(bool IsOrdered, const Expr *Param,
880 OMPOrderedClause *Clause) {
881 if (IsOrdered)
882 getTopOfStack().OrderedRegion.emplace(Param, Clause);
883 else
884 getTopOfStack().OrderedRegion.reset();
885 }
886 /// Returns true, if region is ordered (has associated 'ordered' clause),
887 /// false - otherwise.
888 bool isOrderedRegion() const {
889 if (const SharingMapTy *Top = getTopOfStackOrNull())
890 return Top->OrderedRegion.has_value();
891 return false;
892 }
893 /// Returns optional parameter for the ordered region.
894 std::pair<const Expr *, OMPOrderedClause *> getOrderedRegionParam() const {
895 if (const SharingMapTy *Top = getTopOfStackOrNull())
896 if (Top->OrderedRegion)
897 return *Top->OrderedRegion;
898 return std::make_pair(nullptr, nullptr);
899 }
900 /// Returns true, if parent region is ordered (has associated
901 /// 'ordered' clause), false - otherwise.
902 bool isParentOrderedRegion() const {
903 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
904 return Parent->OrderedRegion.has_value();
905 return false;
906 }
907 /// Returns optional parameter for the ordered region.
908 std::pair<const Expr *, OMPOrderedClause *>
909 getParentOrderedRegionParam() const {
910 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
911 if (Parent->OrderedRegion)
912 return *Parent->OrderedRegion;
913 return std::make_pair(nullptr, nullptr);
914 }
915 /// Marks current region as having an 'order' clause.
916 void setRegionHasOrderConcurrent(bool HasOrderConcurrent) {
917 getTopOfStack().RegionHasOrderConcurrent = HasOrderConcurrent;
918 }
919 /// Returns true, if parent region is order (has associated
920 /// 'order' clause), false - otherwise.
921 bool isParentOrderConcurrent() const {
922 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
923 return Parent->RegionHasOrderConcurrent;
924 return false;
925 }
926 /// Marks current region as nowait (it has a 'nowait' clause).
927 void setNowaitRegion(bool IsNowait = true) {
928 getTopOfStack().NowaitRegion = IsNowait;
929 }
930 /// Returns true, if parent region is nowait (has associated
931 /// 'nowait' clause), false - otherwise.
932 bool isParentNowaitRegion() const {
933 if (const SharingMapTy *Parent = getSecondOnStackOrNull())
934 return Parent->NowaitRegion;
935 return false;
936 }
937 /// Marks current region as untied (it has a 'untied' clause).
938 void setUntiedRegion(bool IsUntied = true) {
939 getTopOfStack().UntiedRegion = IsUntied;
940 }
941 /// Return true if current region is untied.
942 bool isUntiedRegion() const {
943 const SharingMapTy *Top = getTopOfStackOrNull();
944 return Top ? Top->UntiedRegion : false;
945 }
946 /// Marks parent region as cancel region.
947 void setParentCancelRegion(bool Cancel = true) {
948 if (SharingMapTy *Parent = getSecondOnStackOrNull())
949 Parent->CancelRegion |= Cancel;
950 }
951 /// Return true if current region has inner cancel construct.
952 bool isCancelRegion() const {
953 const SharingMapTy *Top = getTopOfStackOrNull();
954 return Top ? Top->CancelRegion : false;
955 }
956
957 /// Mark that parent region already has scan directive.
958 void setParentHasScanDirective(SourceLocation Loc) {
959 if (SharingMapTy *Parent = getSecondOnStackOrNull())
960 Parent->PrevScanLocation = Loc;
961 }
962 /// Return true if current region has inner cancel construct.
963 bool doesParentHasScanDirective() const {
964 const SharingMapTy *Top = getSecondOnStackOrNull();
965 return Top ? Top->PrevScanLocation.isValid() : false;
966 }
967 /// Return true if current region has inner cancel construct.
968 SourceLocation getParentScanDirectiveLoc() const {
969 const SharingMapTy *Top = getSecondOnStackOrNull();
970 return Top ? Top->PrevScanLocation : SourceLocation();
971 }
972 /// Mark that parent region already has ordered directive.
973 void setParentHasOrderedDirective(SourceLocation Loc) {
974 if (SharingMapTy *Parent = getSecondOnStackOrNull())
975 Parent->PrevOrderedLocation = Loc;
976 }
977 /// Return true if current region has inner ordered construct.
978 bool doesParentHasOrderedDirective() const {
979 const SharingMapTy *Top = getSecondOnStackOrNull();
980 return Top ? Top->PrevOrderedLocation.isValid() : false;
981 }
982 /// Returns the location of the previously specified ordered directive.
983 SourceLocation getParentOrderedDirectiveLoc() const {
984 const SharingMapTy *Top = getSecondOnStackOrNull();
985 return Top ? Top->PrevOrderedLocation : SourceLocation();
986 }
987
988 /// Set collapse value for the region.
989 void setAssociatedLoops(unsigned Val) {
990 getTopOfStack().AssociatedLoops = Val;
991 if (Val > 1)
992 getTopOfStack().HasMutipleLoops = true;
993 }
994 /// Return collapse value for region.
995 unsigned getAssociatedLoops() const {
996 const SharingMapTy *Top = getTopOfStackOrNull();
997 return Top ? Top->AssociatedLoops : 0;
998 }
999 /// Returns true if the construct is associated with multiple loops.
1000 bool hasMutipleLoops() const {
1001 const SharingMapTy *Top = getTopOfStackOrNull();
1002 return Top ? Top->HasMutipleLoops : false;
1003 }
1004
1005 /// Marks current target region as one with closely nested teams
1006 /// region.
1007 void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
1008 if (SharingMapTy *Parent = getSecondOnStackOrNull())
1009 Parent->InnerTeamsRegionLoc = TeamsRegionLoc;
1010 }
1011 /// Returns true, if current region has closely nested teams region.
1012 bool hasInnerTeamsRegion() const {
1013 return getInnerTeamsRegionLoc().isValid();
1014 }
1015 /// Returns location of the nested teams region (if any).
1016 SourceLocation getInnerTeamsRegionLoc() const {
1017 const SharingMapTy *Top = getTopOfStackOrNull();
1018 return Top ? Top->InnerTeamsRegionLoc : SourceLocation();
1019 }
1020
1021 Scope *getCurScope() const {
1022 const SharingMapTy *Top = getTopOfStackOrNull();
1023 return Top ? Top->CurScope : nullptr;
1024 }
1025 void setContext(DeclContext *DC) { getTopOfStack().Context = DC; }
1026 SourceLocation getConstructLoc() const {
1027 const SharingMapTy *Top = getTopOfStackOrNull();
1028 return Top ? Top->ConstructLoc : SourceLocation();
1029 }
1030
1031 /// Do the check specified in \a Check to all component lists and return true
1032 /// if any issue is found.
1033 bool checkMappableExprComponentListsForDecl(
1034 const ValueDecl *VD, bool CurrentRegionOnly,
1035 const llvm::function_ref<
1038 Check) const {
1039 if (isStackEmpty())
1040 return false;
1041 auto SI = begin();
1042 auto SE = end();
1043
1044 if (SI == SE)
1045 return false;
1046
1047 if (CurrentRegionOnly)
1048 SE = std::next(SI);
1049 else
1050 std::advance(SI, 1);
1051
1052 for (; SI != SE; ++SI) {
1053 auto MI = SI->MappedExprComponents.find(VD);
1054 if (MI != SI->MappedExprComponents.end())
1056 MI->second.Components)
1057 if (Check(L, MI->second.Kind))
1058 return true;
1059 }
1060 return false;
1061 }
1062
1063 /// Do the check specified in \a Check to all component lists at a given level
1064 /// and return true if any issue is found.
1065 bool checkMappableExprComponentListsForDeclAtLevel(
1066 const ValueDecl *VD, unsigned Level,
1067 const llvm::function_ref<
1070 Check) const {
1071 if (getStackSize() <= Level)
1072 return false;
1073
1074 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
1075 auto MI = StackElem.MappedExprComponents.find(VD);
1076 if (MI != StackElem.MappedExprComponents.end())
1078 MI->second.Components)
1079 if (Check(L, MI->second.Kind))
1080 return true;
1081 return false;
1082 }
1083
1084 /// Create a new mappable expression component list associated with a given
1085 /// declaration and initialize it with the provided list of components.
1086 void addMappableExpressionComponents(
1087 const ValueDecl *VD,
1089 OpenMPClauseKind WhereFoundClauseKind) {
1090 MappedExprComponentTy &MEC = getTopOfStack().MappedExprComponents[VD];
1091 // Create new entry and append the new components there.
1092 MEC.Components.resize(MEC.Components.size() + 1);
1093 MEC.Components.back().append(Components.begin(), Components.end());
1094 MEC.Kind = WhereFoundClauseKind;
1095 }
1096
1097 unsigned getNestingLevel() const {
1098 assert(!isStackEmpty());
1099 return getStackSize() - 1;
1100 }
1101 void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
1102 SharingMapTy *Parent = getSecondOnStackOrNull();
1103 assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
1104 Parent->DoacrossDepends.try_emplace(C, OpsOffs);
1105 }
1106 llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
1107 getDoacrossDependClauses() const {
1108 const SharingMapTy &StackElem = getTopOfStack();
1109 if (isOpenMPWorksharingDirective(StackElem.Directive)) {
1110 const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
1111 return llvm::make_range(Ref.begin(), Ref.end());
1112 }
1113 return llvm::make_range(StackElem.DoacrossDepends.end(),
1114 StackElem.DoacrossDepends.end());
1115 }
1116
1117 // Store types of classes which have been explicitly mapped
1118 void addMappedClassesQualTypes(QualType QT) {
1119 SharingMapTy &StackElem = getTopOfStack();
1120 StackElem.MappedClassesQualTypes.insert(QT);
1121 }
1122
1123 // Return set of mapped classes types
1124 bool isClassPreviouslyMapped(QualType QT) const {
1125 const SharingMapTy &StackElem = getTopOfStack();
1126 return StackElem.MappedClassesQualTypes.contains(QT);
1127 }
1128
1129 /// Adds global declare target to the parent target region.
1130 void addToParentTargetRegionLinkGlobals(DeclRefExpr *E) {
1131 assert(*OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
1132 E->getDecl()) == OMPDeclareTargetDeclAttr::MT_Link &&
1133 "Expected declare target link global.");
1134 for (auto &Elem : *this) {
1135 if (isOpenMPTargetExecutionDirective(Elem.Directive)) {
1136 Elem.DeclareTargetLinkVarDecls.push_back(E);
1137 return;
1138 }
1139 }
1140 }
1141
1142 /// Returns the list of globals with declare target link if current directive
1143 /// is target.
1144 ArrayRef<DeclRefExpr *> getLinkGlobals() const {
1145 assert(isOpenMPTargetExecutionDirective(getCurrentDirective()) &&
1146 "Expected target executable directive.");
1147 return getTopOfStack().DeclareTargetLinkVarDecls;
1148 }
1149
1150 /// Adds list of allocators expressions.
1151 void addInnerAllocatorExpr(Expr *E) {
1152 getTopOfStack().InnerUsedAllocators.push_back(E);
1153 }
1154 /// Return list of used allocators.
1155 ArrayRef<Expr *> getInnerAllocators() const {
1156 return getTopOfStack().InnerUsedAllocators;
1157 }
1158 /// Marks the declaration as implicitly firstprivate nin the task-based
1159 /// regions.
1160 void addImplicitTaskFirstprivate(unsigned Level, Decl *D) {
1161 getStackElemAtLevel(Level).ImplicitTaskFirstprivates.insert(D);
1162 }
1163 /// Checks if the decl is implicitly firstprivate in the task-based region.
1164 bool isImplicitTaskFirstprivate(Decl *D) const {
1165 return getTopOfStack().ImplicitTaskFirstprivates.contains(D);
1166 }
1167
1168 /// Marks decl as used in uses_allocators clause as the allocator.
1169 void addUsesAllocatorsDecl(const Decl *D, UsesAllocatorsDeclKind Kind) {
1170 getTopOfStack().UsesAllocatorsDecls.try_emplace(D, Kind);
1171 }
1172 /// Checks if specified decl is used in uses allocator clause as the
1173 /// allocator.
1174 std::optional<UsesAllocatorsDeclKind>
1175 isUsesAllocatorsDecl(unsigned Level, const Decl *D) const {
1176 const SharingMapTy &StackElem = getTopOfStack();
1177 auto I = StackElem.UsesAllocatorsDecls.find(D);
1178 if (I == StackElem.UsesAllocatorsDecls.end())
1179 return std::nullopt;
1180 return I->getSecond();
1181 }
1182 std::optional<UsesAllocatorsDeclKind>
1183 isUsesAllocatorsDecl(const Decl *D) const {
1184 const SharingMapTy &StackElem = getTopOfStack();
1185 auto I = StackElem.UsesAllocatorsDecls.find(D);
1186 if (I == StackElem.UsesAllocatorsDecls.end())
1187 return std::nullopt;
1188 return I->getSecond();
1189 }
1190
1191 void addDeclareMapperVarRef(Expr *Ref) {
1192 SharingMapTy &StackElem = getTopOfStack();
1193 StackElem.DeclareMapperVar = Ref;
1194 }
1195 const Expr *getDeclareMapperVarRef() const {
1196 const SharingMapTy *Top = getTopOfStackOrNull();
1197 return Top ? Top->DeclareMapperVar : nullptr;
1198 }
1199
1200 /// Add a new iterator variable.
1201 void addIteratorVarDecl(VarDecl *VD) {
1202 SharingMapTy &StackElem = getTopOfStack();
1203 StackElem.IteratorVarDecls.push_back(VD->getCanonicalDecl());
1204 }
1205 /// Check if variable declaration is an iterator VarDecl.
1206 bool isIteratorVarDecl(const VarDecl *VD) const {
1207 const SharingMapTy *Top = getTopOfStackOrNull();
1208 if (!Top)
1209 return false;
1210
1211 return llvm::is_contained(Top->IteratorVarDecls, VD->getCanonicalDecl());
1212 }
1213 /// get captured field from ImplicitDefaultFirstprivateFDs
1214 VarDecl *getImplicitFDCapExprDecl(const FieldDecl *FD) const {
1215 const_iterator I = begin();
1216 const_iterator EndI = end();
1217 size_t StackLevel = getStackSize();
1218 for (; I != EndI; ++I) {
1219 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1220 break;
1221 StackLevel--;
1222 }
1223 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1224 if (I == EndI)
1225 return nullptr;
1226 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1227 if (IFD.FD == FD && IFD.StackLevel == StackLevel)
1228 return IFD.VD;
1229 return nullptr;
1230 }
1231 /// Check if capture decl is field captured in ImplicitDefaultFirstprivateFDs
1232 bool isImplicitDefaultFirstprivateFD(VarDecl *VD) const {
1233 const_iterator I = begin();
1234 const_iterator EndI = end();
1235 for (; I != EndI; ++I)
1236 if (I->DefaultAttr == DSA_firstprivate || I->DefaultAttr == DSA_private)
1237 break;
1238 if (I == EndI)
1239 return false;
1240 for (const auto &IFD : I->ImplicitDefaultFirstprivateFDs)
1241 if (IFD.VD == VD)
1242 return true;
1243 return false;
1244 }
1245 /// Store capture FD info in ImplicitDefaultFirstprivateFDs
1246 void addImplicitDefaultFirstprivateFD(const FieldDecl *FD, VarDecl *VD) {
1247 iterator I = begin();
1248 const_iterator EndI = end();
1249 size_t StackLevel = getStackSize();
1250 for (; I != EndI; ++I) {
1251 if (I->DefaultAttr == DSA_private || I->DefaultAttr == DSA_firstprivate) {
1252 I->ImplicitDefaultFirstprivateFDs.emplace_back(FD, StackLevel, VD);
1253 break;
1254 }
1255 StackLevel--;
1256 }
1257 assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
1258 }
1259};
1260
1261bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1262 return isOpenMPParallelDirective(DKind) || isOpenMPTeamsDirective(DKind);
1263}
1264
1265bool isImplicitOrExplicitTaskingRegion(OpenMPDirectiveKind DKind) {
1266 return isImplicitTaskingRegion(DKind) || isOpenMPTaskingDirective(DKind) ||
1267 DKind == OMPD_unknown;
1268}
1269
1270} // namespace
1271
1272static const Expr *getExprAsWritten(const Expr *E) {
1273 if (const auto *FE = dyn_cast<FullExpr>(E))
1274 E = FE->getSubExpr();
1275
1276 if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(E))
1277 E = MTE->getSubExpr();
1278
1279 while (const auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E))
1280 E = Binder->getSubExpr();
1281
1282 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E))
1283 E = ICE->getSubExprAsWritten();
1284 return E->IgnoreParens();
1285}
1286
1288 return const_cast<Expr *>(getExprAsWritten(const_cast<const Expr *>(E)));
1289}
1290
1291static const ValueDecl *getCanonicalDecl(const ValueDecl *D) {
1292 if (const auto *CED = dyn_cast<OMPCapturedExprDecl>(D))
1293 if (const auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
1294 D = ME->getMemberDecl();
1295
1297 return D;
1298}
1299
1301 return const_cast<ValueDecl *>(
1302 getCanonicalDecl(const_cast<const ValueDecl *>(D)));
1303}
1304
1306 if (C == OMPC_threadprivate)
1307 return getOpenMPClauseName(C).str() + " or thread local";
1308 return getOpenMPClauseName(C).str();
1309}
1310
1311DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1312 ValueDecl *D) const {
1313 D = getCanonicalDecl(D);
1314 auto *VD = dyn_cast<VarDecl>(D);
1315 const auto *FD = dyn_cast<FieldDecl>(D);
1316 DSAVarData DVar;
1317 if (Iter == end()) {
1318 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1319 // in a region but not in construct]
1320 // File-scope or namespace-scope variables referenced in called routines
1321 // in the region are shared unless they appear in a threadprivate
1322 // directive.
1323 if (VD && !VD->isFunctionOrMethodVarDecl() && !isa<ParmVarDecl>(VD))
1324 DVar.CKind = OMPC_shared;
1325
1326 // OpenMP [2.9.1.2, Data-sharing Attribute Rules for Variables Referenced
1327 // in a region but not in construct]
1328 // Variables with static storage duration that are declared in called
1329 // routines in the region are shared.
1330 if (VD && VD->hasGlobalStorage())
1331 DVar.CKind = OMPC_shared;
1332
1333 // Non-static data members are shared by default.
1334 if (FD)
1335 DVar.CKind = OMPC_shared;
1336
1337 return DVar;
1338 }
1339
1340 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1341 // in a Construct, C/C++, predetermined, p.1]
1342 // Variables with automatic storage duration that are declared in a scope
1343 // inside the construct are private.
1344 if (VD && isOpenMPLocal(VD, Iter) && VD->isLocalVarDecl() &&
1345 (VD->getStorageClass() == SC_Auto || VD->getStorageClass() == SC_None)) {
1346 DVar.CKind = OMPC_private;
1347 return DVar;
1348 }
1349
1350 DVar.DKind = Iter->Directive;
1351 // Explicitly specified attributes and local variables with predetermined
1352 // attributes.
1353 if (Iter->SharingMap.count(D)) {
1354 const DSAInfo &Data = Iter->SharingMap.lookup(D);
1355 DVar.RefExpr = Data.RefExpr.getPointer();
1356 DVar.PrivateCopy = Data.PrivateCopy;
1357 DVar.CKind = Data.Attributes;
1358 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1359 DVar.Modifier = Data.Modifier;
1360 DVar.AppliedToPointee = Data.AppliedToPointee;
1361 return DVar;
1362 }
1363
1364 DefaultDataSharingAttributes IterDA = Iter->DefaultAttr;
1365 switch (Iter->DefaultVCAttr) {
1366 case DSA_VC_aggregate:
1367 if (!D->getType()->isAggregateType())
1368 IterDA = DSA_none;
1369 break;
1370 case DSA_VC_pointer:
1371 if (!D->getType()->isPointerType())
1372 IterDA = DSA_none;
1373 break;
1374 case DSA_VC_scalar:
1375 if (!D->getType()->isScalarType())
1376 IterDA = DSA_none;
1377 break;
1378 case DSA_VC_all:
1379 break;
1380 }
1381
1382 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1383 // in a Construct, C/C++, implicitly determined, p.1]
1384 // In a parallel or task construct, the data-sharing attributes of these
1385 // variables are determined by the default clause, if present.
1386 switch (IterDA) {
1387 case DSA_shared:
1388 DVar.CKind = OMPC_shared;
1389 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1390 return DVar;
1391 case DSA_none:
1392 return DVar;
1393 case DSA_firstprivate:
1394 if (VD && VD->getStorageDuration() == SD_Static &&
1395 VD->getDeclContext()->isFileContext()) {
1396 DVar.CKind = OMPC_unknown;
1397 } else {
1398 DVar.CKind = OMPC_firstprivate;
1399 }
1400 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1401 return DVar;
1402 case DSA_private:
1403 // each variable with static storage duration that is declared
1404 // in a namespace or global scope and referenced in the construct,
1405 // and that does not have a predetermined data-sharing attribute
1406 if (VD && VD->getStorageDuration() == SD_Static &&
1407 VD->getDeclContext()->isFileContext()) {
1408 DVar.CKind = OMPC_unknown;
1409 } else {
1410 DVar.CKind = OMPC_private;
1411 }
1412 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1413 return DVar;
1414 case DSA_unspecified:
1415 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1416 // in a Construct, implicitly determined, p.2]
1417 // In a parallel construct, if no default clause is present, these
1418 // variables are shared.
1419 DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1420 if ((isOpenMPParallelDirective(DVar.DKind) &&
1421 !isOpenMPTaskLoopDirective(DVar.DKind)) ||
1422 isOpenMPTeamsDirective(DVar.DKind)) {
1423 DVar.CKind = OMPC_shared;
1424 return DVar;
1425 }
1426
1427 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1428 // in a Construct, implicitly determined, p.4]
1429 // In a task construct, if no default clause is present, a variable that in
1430 // the enclosing context is determined to be shared by all implicit tasks
1431 // bound to the current team is shared.
1432 if (isOpenMPTaskingDirective(DVar.DKind)) {
1433 DSAVarData DVarTemp;
1434 const_iterator I = Iter, E = end();
1435 do {
1436 ++I;
1437 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
1438 // Referenced in a Construct, implicitly determined, p.6]
1439 // In a task construct, if no default clause is present, a variable
1440 // whose data-sharing attribute is not determined by the rules above is
1441 // firstprivate.
1442 DVarTemp = getDSA(I, D);
1443 if (DVarTemp.CKind != OMPC_shared) {
1444 DVar.RefExpr = nullptr;
1445 DVar.CKind = OMPC_firstprivate;
1446 return DVar;
1447 }
1448 } while (I != E && !isImplicitTaskingRegion(I->Directive));
1449 DVar.CKind =
1450 (DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
1451 return DVar;
1452 }
1453 }
1454 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1455 // in a Construct, implicitly determined, p.3]
1456 // For constructs other than task, if no default clause is present, these
1457 // variables inherit their data-sharing attributes from the enclosing
1458 // context.
1459 return getDSA(++Iter, D);
1460}
1461
1462const Expr *DSAStackTy::addUniqueAligned(const ValueDecl *D,
1463 const Expr *NewDE) {
1464 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1465 D = getCanonicalDecl(D);
1466 SharingMapTy &StackElem = getTopOfStack();
1467 auto [It, Inserted] = StackElem.AlignedMap.try_emplace(D, NewDE);
1468 if (Inserted) {
1469 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1470 return nullptr;
1471 }
1472 assert(It->second && "Unexpected nullptr expr in the aligned map");
1473 return It->second;
1474}
1475
1476const Expr *DSAStackTy::addUniqueNontemporal(const ValueDecl *D,
1477 const Expr *NewDE) {
1478 assert(!isStackEmpty() && "Data sharing attributes stack is empty");
1479 D = getCanonicalDecl(D);
1480 SharingMapTy &StackElem = getTopOfStack();
1481 auto [It, Inserted] = StackElem.NontemporalMap.try_emplace(D, NewDE);
1482 if (Inserted) {
1483 assert(NewDE && "Unexpected nullptr expr to be added into aligned map");
1484 return nullptr;
1485 }
1486 assert(It->second && "Unexpected nullptr expr in the aligned map");
1487 return It->second;
1488}
1489
1490void DSAStackTy::addLoopControlVariable(const ValueDecl *D, VarDecl *Capture) {
1491 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1492 D = getCanonicalDecl(D);
1493 SharingMapTy &StackElem = getTopOfStack();
1494 StackElem.LCVMap.try_emplace(
1495 D, LCDeclInfo(StackElem.LCVMap.size() + 1, Capture));
1496}
1497
1498const DSAStackTy::LCDeclInfo
1499DSAStackTy::isLoopControlVariable(const ValueDecl *D) const {
1500 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1501 D = getCanonicalDecl(D);
1502 const SharingMapTy &StackElem = getTopOfStack();
1503 auto It = StackElem.LCVMap.find(D);
1504 if (It != StackElem.LCVMap.end())
1505 return It->second;
1506 return {0, nullptr};
1507}
1508
1509const DSAStackTy::LCDeclInfo
1510DSAStackTy::isLoopControlVariable(const ValueDecl *D, unsigned Level) const {
1511 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1512 D = getCanonicalDecl(D);
1513 for (unsigned I = Level + 1; I > 0; --I) {
1514 const SharingMapTy &StackElem = getStackElemAtLevel(I - 1);
1515 auto It = StackElem.LCVMap.find(D);
1516 if (It != StackElem.LCVMap.end())
1517 return It->second;
1518 }
1519 return {0, nullptr};
1520}
1521
1522const DSAStackTy::LCDeclInfo
1523DSAStackTy::isParentLoopControlVariable(const ValueDecl *D) const {
1524 const SharingMapTy *Parent = getSecondOnStackOrNull();
1525 assert(Parent && "Data-sharing attributes stack is empty");
1526 D = getCanonicalDecl(D);
1527 auto It = Parent->LCVMap.find(D);
1528 if (It != Parent->LCVMap.end())
1529 return It->second;
1530 return {0, nullptr};
1531}
1532
1533const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1534 const SharingMapTy *Parent = getSecondOnStackOrNull();
1535 assert(Parent && "Data-sharing attributes stack is empty");
1536 if (Parent->LCVMap.size() < I)
1537 return nullptr;
1538 for (const auto &Pair : Parent->LCVMap)
1539 if (Pair.second.first == I)
1540 return Pair.first;
1541 return nullptr;
1542}
1543
1544void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1545 DeclRefExpr *PrivateCopy, unsigned Modifier,
1546 bool AppliedToPointee) {
1547 D = getCanonicalDecl(D);
1548 if (A == OMPC_threadprivate) {
1549 DSAInfo &Data = Threadprivates[D];
1550 Data.Attributes = A;
1551 Data.RefExpr.setPointer(E);
1552 Data.PrivateCopy = nullptr;
1553 Data.Modifier = Modifier;
1554 } else if (A == OMPC_groupprivate) {
1555 DSAInfo &Data = Groupprivates[D];
1556 Data.Attributes = A;
1557 Data.RefExpr.setPointer(E);
1558 Data.PrivateCopy = nullptr;
1559 Data.Modifier = Modifier;
1560 } else {
1561 DSAInfo &Data = getTopOfStack().SharingMap[D];
1562 assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1563 (A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1564 (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1565 (isLoopControlVariable(D).first && A == OMPC_private));
1566 Data.Modifier = Modifier;
1567 if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1568 Data.RefExpr.setInt(/*IntVal=*/true);
1569 return;
1570 }
1571 const bool IsLastprivate =
1572 A == OMPC_lastprivate || Data.Attributes == OMPC_lastprivate;
1573 Data.Attributes = A;
1574 Data.RefExpr.setPointerAndInt(E, IsLastprivate);
1575 Data.PrivateCopy = PrivateCopy;
1576 Data.AppliedToPointee = AppliedToPointee;
1577 if (PrivateCopy) {
1578 DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1579 Data.Modifier = Modifier;
1580 Data.Attributes = A;
1581 Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1582 Data.PrivateCopy = nullptr;
1583 Data.AppliedToPointee = AppliedToPointee;
1584 }
1585 }
1586}
1587
1588/// Build a variable declaration for OpenMP loop iteration variable.
1590 StringRef Name, const AttrVec *Attrs = nullptr,
1591 DeclRefExpr *OrigRef = nullptr) {
1592 DeclContext *DC = SemaRef.CurContext;
1593 IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
1594 TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
1595 auto *Decl =
1596 VarDecl::Create(SemaRef.Context, DC, Loc, Loc, II, Type, TInfo, SC_None);
1597 if (Attrs) {
1598 for (specific_attr_iterator<AlignedAttr> I(Attrs->begin()), E(Attrs->end());
1599 I != E; ++I)
1600 Decl->addAttr(*I);
1601 }
1602 Decl->setImplicit();
1603 if (OrigRef) {
1604 Decl->addAttr(
1605 OMPReferencedVarAttr::CreateImplicit(SemaRef.Context, OrigRef));
1606 }
1607 return Decl;
1608}
1609
1611 SourceLocation Loc,
1612 bool RefersToCapture = false) {
1613 D->setReferenced();
1614 D->markUsed(S.Context);
1616 SourceLocation(), D, RefersToCapture, Loc, Ty,
1617 VK_LValue);
1618}
1619
1620void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1621 BinaryOperatorKind BOK) {
1622 D = getCanonicalDecl(D);
1623 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1624 assert(
1625 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1626 "Additional reduction info may be specified only for reduction items.");
1627 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1628 assert(ReductionData.ReductionRange.isInvalid() &&
1629 (getTopOfStack().Directive == OMPD_taskgroup ||
1630 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1631 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1632 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1633 "Additional reduction info may be specified only once for reduction "
1634 "items.");
1635 ReductionData.set(BOK, SR);
1636 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1637 if (!TaskgroupReductionRef) {
1638 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1639 SemaRef.Context.VoidPtrTy, ".task_red.");
1640 TaskgroupReductionRef =
1641 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1642 }
1643}
1644
1645void DSAStackTy::addTaskgroupReductionData(const ValueDecl *D, SourceRange SR,
1646 const Expr *ReductionRef) {
1647 D = getCanonicalDecl(D);
1648 assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
1649 assert(
1650 getTopOfStack().SharingMap[D].Attributes == OMPC_reduction &&
1651 "Additional reduction info may be specified only for reduction items.");
1652 ReductionData &ReductionData = getTopOfStack().ReductionMap[D];
1653 assert(ReductionData.ReductionRange.isInvalid() &&
1654 (getTopOfStack().Directive == OMPD_taskgroup ||
1655 ((isOpenMPParallelDirective(getTopOfStack().Directive) ||
1656 isOpenMPWorksharingDirective(getTopOfStack().Directive)) &&
1657 !isOpenMPSimdDirective(getTopOfStack().Directive))) &&
1658 "Additional reduction info may be specified only once for reduction "
1659 "items.");
1660 ReductionData.set(ReductionRef, SR);
1661 Expr *&TaskgroupReductionRef = getTopOfStack().TaskgroupReductionRef;
1662 if (!TaskgroupReductionRef) {
1663 VarDecl *VD = buildVarDecl(SemaRef, SR.getBegin(),
1664 SemaRef.Context.VoidPtrTy, ".task_red.");
1665 TaskgroupReductionRef =
1666 buildDeclRefExpr(SemaRef, VD, SemaRef.Context.VoidPtrTy, SR.getBegin());
1667 }
1668}
1669
1670const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1671 const ValueDecl *D, SourceRange &SR, BinaryOperatorKind &BOK,
1672 Expr *&TaskgroupDescriptor) const {
1673 D = getCanonicalDecl(D);
1674 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1675 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1676 const DSAInfo &Data = I->SharingMap.lookup(D);
1677 if (Data.Attributes != OMPC_reduction ||
1678 Data.Modifier != OMPC_REDUCTION_task)
1679 continue;
1680 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1681 if (!ReductionData.ReductionOp ||
1682 isa<const Expr *>(ReductionData.ReductionOp))
1683 return DSAVarData();
1684 SR = ReductionData.ReductionRange;
1685 BOK = cast<ReductionData::BOKPtrType>(ReductionData.ReductionOp);
1686 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1687 "expression for the descriptor is not "
1688 "set.");
1689 TaskgroupDescriptor = I->TaskgroupReductionRef;
1690 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1691 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1692 /*AppliedToPointee=*/false);
1693 }
1694 return DSAVarData();
1695}
1696
1697const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1698 const ValueDecl *D, SourceRange &SR, const Expr *&ReductionRef,
1699 Expr *&TaskgroupDescriptor) const {
1700 D = getCanonicalDecl(D);
1701 assert(!isStackEmpty() && "Data-sharing attributes stack is empty.");
1702 for (const_iterator I = begin() + 1, E = end(); I != E; ++I) {
1703 const DSAInfo &Data = I->SharingMap.lookup(D);
1704 if (Data.Attributes != OMPC_reduction ||
1705 Data.Modifier != OMPC_REDUCTION_task)
1706 continue;
1707 const ReductionData &ReductionData = I->ReductionMap.lookup(D);
1708 if (!ReductionData.ReductionOp ||
1709 !isa<const Expr *>(ReductionData.ReductionOp))
1710 return DSAVarData();
1711 SR = ReductionData.ReductionRange;
1712 ReductionRef = cast<const Expr *>(ReductionData.ReductionOp);
1713 assert(I->TaskgroupReductionRef && "taskgroup reduction reference "
1714 "expression for the descriptor is not "
1715 "set.");
1716 TaskgroupDescriptor = I->TaskgroupReductionRef;
1717 return DSAVarData(I->Directive, OMPC_reduction, Data.RefExpr.getPointer(),
1718 Data.PrivateCopy, I->DefaultAttrLoc, OMPC_REDUCTION_task,
1719 /*AppliedToPointee=*/false);
1720 }
1721 return DSAVarData();
1722}
1723
1724bool DSAStackTy::isOpenMPLocal(VarDecl *D, const_iterator I) const {
1725 D = D->getCanonicalDecl();
1726 for (const_iterator E = end(); I != E; ++I) {
1727 if (isImplicitOrExplicitTaskingRegion(I->Directive) ||
1728 isOpenMPTargetExecutionDirective(I->Directive)) {
1729 if (I->CurScope) {
1730 Scope *TopScope = I->CurScope->getParent();
1731 Scope *CurScope = getCurScope();
1732 while (CurScope && CurScope != TopScope && !CurScope->isDeclScope(D))
1733 CurScope = CurScope->getParent();
1734 return CurScope != TopScope;
1735 }
1736 for (DeclContext *DC = D->getDeclContext(); DC; DC = DC->getParent())
1737 if (I->Context == DC)
1738 return true;
1739 return false;
1740 }
1741 }
1742 return false;
1743}
1744
1746 bool AcceptIfMutable = true,
1747 bool *IsClassType = nullptr) {
1748 ASTContext &Context = SemaRef.getASTContext();
1749 Type = Type.getNonReferenceType().getCanonicalType();
1750 bool IsConstant = Type.isConstant(Context);
1751 Type = Context.getBaseElementType(Type);
1752 const CXXRecordDecl *RD = AcceptIfMutable && SemaRef.getLangOpts().CPlusPlus
1754 : nullptr;
1755 if (const auto *CTSD = dyn_cast_or_null<ClassTemplateSpecializationDecl>(RD))
1756 if (const ClassTemplateDecl *CTD = CTSD->getSpecializedTemplate())
1757 RD = CTD->getTemplatedDecl();
1758 if (IsClassType)
1759 *IsClassType = RD;
1760 return IsConstant && !(SemaRef.getLangOpts().CPlusPlus && RD &&
1761 RD->hasDefinition() && RD->hasMutableFields());
1762}
1763
1764static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D,
1766 SourceLocation ELoc,
1767 bool AcceptIfMutable = true,
1768 bool ListItemNotVar = false) {
1769 ASTContext &Context = SemaRef.getASTContext();
1770 bool IsClassType;
1771 if (isConstNotMutableType(SemaRef, Type, AcceptIfMutable, &IsClassType)) {
1772 unsigned Diag = ListItemNotVar ? diag::err_omp_const_list_item
1773 : IsClassType ? diag::err_omp_const_not_mutable_variable
1774 : diag::err_omp_const_variable;
1775 SemaRef.Diag(ELoc, Diag) << getOpenMPClauseNameForDiag(CKind);
1776 if (!ListItemNotVar && D) {
1777 const VarDecl *VD = dyn_cast<VarDecl>(D);
1778 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
1780 SemaRef.Diag(D->getLocation(),
1781 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
1782 << D;
1783 }
1784 return true;
1785 }
1786 return false;
1787}
1788
1789const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1790 bool FromParent) {
1791 D = getCanonicalDecl(D);
1792 DSAVarData DVar;
1793
1794 auto *VD = dyn_cast<VarDecl>(D);
1795 auto TI = Threadprivates.find(D);
1796 if (TI != Threadprivates.end()) {
1797 DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1798 DVar.CKind = OMPC_threadprivate;
1799 DVar.Modifier = TI->getSecond().Modifier;
1800 return DVar;
1801 }
1802 if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
1803 DVar.RefExpr = buildDeclRefExpr(
1804 SemaRef, VD, D->getType().getNonReferenceType(),
1805 VD->getAttr<OMPThreadPrivateDeclAttr>()->getLocation());
1806 DVar.CKind = OMPC_threadprivate;
1807 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1808 return DVar;
1809 }
1810 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1811 // in a Construct, C/C++, predetermined, p.1]
1812 // Variables appearing in threadprivate directives are threadprivate.
1813 if ((VD && VD->getTLSKind() != VarDecl::TLS_None &&
1814 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
1815 SemaRef.getLangOpts().OpenMPUseTLS &&
1816 SemaRef.getASTContext().getTargetInfo().isTLSSupported())) ||
1817 (VD && VD->getStorageClass() == SC_Register &&
1818 VD->hasAttr<AsmLabelAttr>() && !VD->isLocalVarDecl())) {
1819 DVar.RefExpr = buildDeclRefExpr(
1820 SemaRef, VD, D->getType().getNonReferenceType(), D->getLocation());
1821 DVar.CKind = OMPC_threadprivate;
1822 addDSA(D, DVar.RefExpr, OMPC_threadprivate);
1823 return DVar;
1824 }
1825 if (SemaRef.getLangOpts().OpenMPCUDAMode && VD &&
1826 VD->isLocalVarDeclOrParm() && !isStackEmpty() &&
1827 !isLoopControlVariable(D).first) {
1828 const_iterator IterTarget =
1829 std::find_if(begin(), end(), [](const SharingMapTy &Data) {
1830 return isOpenMPTargetExecutionDirective(Data.Directive);
1831 });
1832 if (IterTarget != end()) {
1833 const_iterator ParentIterTarget = IterTarget + 1;
1834 for (const_iterator Iter = begin(); Iter != ParentIterTarget; ++Iter) {
1835 if (isOpenMPLocal(VD, Iter)) {
1836 DVar.RefExpr =
1837 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1838 D->getLocation());
1839 DVar.CKind = OMPC_threadprivate;
1840 return DVar;
1841 }
1842 }
1843 if (!isClauseParsingMode() || IterTarget != begin()) {
1844 auto DSAIter = IterTarget->SharingMap.find(D);
1845 if (DSAIter != IterTarget->SharingMap.end() &&
1846 isOpenMPPrivate(DSAIter->getSecond().Attributes)) {
1847 DVar.RefExpr = DSAIter->getSecond().RefExpr.getPointer();
1848 DVar.CKind = OMPC_threadprivate;
1849 return DVar;
1850 }
1851 const_iterator End = end();
1852 if (!SemaRef.OpenMP().isOpenMPCapturedByRef(
1853 D, std::distance(ParentIterTarget, End),
1854 /*OpenMPCaptureLevel=*/0)) {
1855 DVar.RefExpr =
1856 buildDeclRefExpr(SemaRef, VD, D->getType().getNonReferenceType(),
1857 IterTarget->ConstructLoc);
1858 DVar.CKind = OMPC_threadprivate;
1859 return DVar;
1860 }
1861 }
1862 }
1863 }
1864
1865 if (isStackEmpty())
1866 // Not in OpenMP execution region and top scope was already checked.
1867 return DVar;
1868
1869 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1870 // in a Construct, C/C++, predetermined, p.4]
1871 // Static data members are shared.
1872 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1873 // in a Construct, C/C++, predetermined, p.7]
1874 // Variables with static storage duration that are declared in a scope
1875 // inside the construct are shared.
1876 if (VD && VD->isStaticDataMember()) {
1877 // Check for explicitly specified attributes.
1878 const_iterator I = begin();
1879 const_iterator EndI = end();
1880 if (FromParent && I != EndI)
1881 ++I;
1882 if (I != EndI) {
1883 auto It = I->SharingMap.find(D);
1884 if (It != I->SharingMap.end()) {
1885 const DSAInfo &Data = It->getSecond();
1886 DVar.RefExpr = Data.RefExpr.getPointer();
1887 DVar.PrivateCopy = Data.PrivateCopy;
1888 DVar.CKind = Data.Attributes;
1889 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1890 DVar.DKind = I->Directive;
1891 DVar.Modifier = Data.Modifier;
1892 DVar.AppliedToPointee = Data.AppliedToPointee;
1893 return DVar;
1894 }
1895 }
1896
1897 DVar.CKind = OMPC_shared;
1898 return DVar;
1899 }
1900
1901 auto &&MatchesAlways = [](OpenMPDirectiveKind) { return true; };
1902 // The predetermined shared attribute for const-qualified types having no
1903 // mutable members was removed after OpenMP 3.1.
1904 if (SemaRef.LangOpts.OpenMP <= 31) {
1905 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
1906 // in a Construct, C/C++, predetermined, p.6]
1907 // Variables with const qualified type having no mutable member are
1908 // shared.
1909 if (isConstNotMutableType(SemaRef, D->getType())) {
1910 // Variables with const-qualified type having no mutable member may be
1911 // listed in a firstprivate clause, even if they are static data members.
1912 DSAVarData DVarTemp = hasInnermostDSA(
1913 D,
1914 [](OpenMPClauseKind C, bool) {
1915 return C == OMPC_firstprivate || C == OMPC_shared;
1916 },
1917 MatchesAlways, FromParent);
1918 if (DVarTemp.CKind != OMPC_unknown && DVarTemp.RefExpr)
1919 return DVarTemp;
1920
1921 DVar.CKind = OMPC_shared;
1922 return DVar;
1923 }
1924 }
1925
1926 // Explicitly specified attributes and local variables with predetermined
1927 // attributes.
1928 const_iterator I = begin();
1929 const_iterator EndI = end();
1930 if (FromParent && I != EndI)
1931 ++I;
1932 if (I == EndI)
1933 return DVar;
1934 auto It = I->SharingMap.find(D);
1935 if (It != I->SharingMap.end()) {
1936 const DSAInfo &Data = It->getSecond();
1937 DVar.RefExpr = Data.RefExpr.getPointer();
1938 DVar.PrivateCopy = Data.PrivateCopy;
1939 DVar.CKind = Data.Attributes;
1940 DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1941 DVar.DKind = I->Directive;
1942 DVar.Modifier = Data.Modifier;
1943 DVar.AppliedToPointee = Data.AppliedToPointee;
1944 }
1945
1946 return DVar;
1947}
1948
1949const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1950 bool FromParent) const {
1951 if (isStackEmpty()) {
1952 const_iterator I;
1953 return getDSA(I, D);
1954 }
1955 D = getCanonicalDecl(D);
1956 const_iterator StartI = begin();
1957 const_iterator EndI = end();
1958 if (FromParent && StartI != EndI)
1959 ++StartI;
1960 return getDSA(StartI, D);
1961}
1962
1963const DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
1964 unsigned Level) const {
1965 if (getStackSize() <= Level)
1966 return DSAVarData();
1967 D = getCanonicalDecl(D);
1968 const_iterator StartI = std::next(begin(), getStackSize() - 1 - Level);
1969 return getDSA(StartI, D);
1970}
1971
1972const DSAStackTy::DSAVarData
1973DSAStackTy::hasDSA(ValueDecl *D,
1974 const llvm::function_ref<bool(OpenMPClauseKind, bool,
1975 DefaultDataSharingAttributes)>
1976 CPred,
1977 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
1978 bool FromParent) const {
1979 if (isStackEmpty())
1980 return {};
1981 D = getCanonicalDecl(D);
1982 const_iterator I = begin();
1983 const_iterator EndI = end();
1984 if (FromParent && I != EndI)
1985 ++I;
1986 for (; I != EndI; ++I) {
1987 if (!DPred(I->Directive) &&
1988 !isImplicitOrExplicitTaskingRegion(I->Directive))
1989 continue;
1990 const_iterator NewI = I;
1991 DSAVarData DVar = getDSA(NewI, D);
1992 if (I == NewI && CPred(DVar.CKind, DVar.AppliedToPointee, I->DefaultAttr))
1993 return DVar;
1994 }
1995 return {};
1996}
1997
1998const DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
1999 ValueDecl *D, const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2000 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2001 bool FromParent) const {
2002 if (isStackEmpty())
2003 return {};
2004 D = getCanonicalDecl(D);
2005 const_iterator StartI = begin();
2006 const_iterator EndI = end();
2007 if (FromParent && StartI != EndI)
2008 ++StartI;
2009 if (StartI == EndI || !DPred(StartI->Directive))
2010 return {};
2011 const_iterator NewI = StartI;
2012 DSAVarData DVar = getDSA(NewI, D);
2013 return (NewI == StartI && CPred(DVar.CKind, DVar.AppliedToPointee))
2014 ? DVar
2015 : DSAVarData();
2016}
2017
2018bool DSAStackTy::hasExplicitDSA(
2019 const ValueDecl *D,
2020 const llvm::function_ref<bool(OpenMPClauseKind, bool)> CPred,
2021 unsigned Level, bool NotLastprivate) const {
2022 if (getStackSize() <= Level)
2023 return false;
2024 D = getCanonicalDecl(D);
2025 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2026 auto I = StackElem.SharingMap.find(D);
2027 if (I != StackElem.SharingMap.end() && I->getSecond().RefExpr.getPointer() &&
2028 CPred(I->getSecond().Attributes, I->getSecond().AppliedToPointee) &&
2029 (!NotLastprivate || !I->getSecond().RefExpr.getInt()))
2030 return true;
2031 // Check predetermined rules for the loop control variables.
2032 auto LI = StackElem.LCVMap.find(D);
2033 if (LI != StackElem.LCVMap.end())
2034 return CPred(OMPC_private, /*AppliedToPointee=*/false);
2035 return false;
2036}
2037
2038bool DSAStackTy::hasExplicitDirective(
2039 const llvm::function_ref<bool(OpenMPDirectiveKind)> DPred,
2040 unsigned Level) const {
2041 if (getStackSize() <= Level)
2042 return false;
2043 const SharingMapTy &StackElem = getStackElemAtLevel(Level);
2044 return DPred(StackElem.Directive);
2045}
2046
2047bool DSAStackTy::hasDirective(
2048 const llvm::function_ref<bool(OpenMPDirectiveKind,
2049 const DeclarationNameInfo &, SourceLocation)>
2050 DPred,
2051 bool FromParent) const {
2052 // We look only in the enclosing region.
2053 size_t Skip = FromParent ? 2 : 1;
2054 for (const_iterator I = begin() + std::min(Skip, getStackSize()), E = end();
2055 I != E; ++I) {
2056 if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
2057 return true;
2058 }
2059 return false;
2060}
2061
2062void SemaOpenMP::InitDataSharingAttributesStack() {
2063 VarDataSharingAttributesStack = new DSAStackTy(SemaRef);
2064}
2065
2066#define DSAStack static_cast<DSAStackTy *>(VarDataSharingAttributesStack)
2067
2068void SemaOpenMP::pushOpenMPFunctionRegion() { DSAStack->pushFunction(); }
2069
2070void SemaOpenMP::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) {
2071 DSAStack->popFunction(OldFSI);
2072}
2073
2075 assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsTargetDevice &&
2076 "Expected OpenMP device compilation.");
2078}
2079
2080namespace {
2081/// Status of the function emission on the host/device.
2082enum class FunctionEmissionStatus {
2083 Emitted,
2084 Discarded,
2085 Unknown,
2086};
2087} // anonymous namespace
2088
2089SemaBase::SemaDiagnosticBuilder
2091 const FunctionDecl *FD) {
2092 assert(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice &&
2093 "Expected OpenMP device compilation.");
2094
2095 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2096 if (FD) {
2097 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2098 switch (FES) {
2100 Kind = SemaDiagnosticBuilder::K_Immediate;
2101 break;
2103 // TODO: We should always delay diagnostics here in case a target
2104 // region is in a function we do not emit. However, as the
2105 // current diagnostics are associated with the function containing
2106 // the target region and we do not emit that one, we would miss out
2107 // on diagnostics for the target region itself. We need to anchor
2108 // the diagnostics with the new generated function *or* ensure we
2109 // emit diagnostics associated with the surrounding function.
2111 ? SemaDiagnosticBuilder::K_Deferred
2112 : SemaDiagnosticBuilder::K_Immediate;
2113 break;
2116 Kind = SemaDiagnosticBuilder::K_Nop;
2117 break;
2119 llvm_unreachable("CUDADiscarded unexpected in OpenMP device compilation");
2120 break;
2121 }
2122 }
2123
2124 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2125}
2126
2129 const FunctionDecl *FD) {
2130 assert(getLangOpts().OpenMP && !getLangOpts().OpenMPIsTargetDevice &&
2131 "Expected OpenMP host compilation.");
2132
2133 SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop;
2134 if (FD) {
2135 Sema::FunctionEmissionStatus FES = SemaRef.getEmissionStatus(FD);
2136 switch (FES) {
2138 Kind = SemaDiagnosticBuilder::K_Immediate;
2139 break;
2141 Kind = SemaDiagnosticBuilder::K_Deferred;
2142 break;
2146 Kind = SemaDiagnosticBuilder::K_Nop;
2147 break;
2148 }
2149 }
2150
2151 return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, SemaRef);
2152}
2153
2156 if (LO.OpenMP <= 45) {
2158 return OMPC_DEFAULTMAP_scalar;
2159 return OMPC_DEFAULTMAP_aggregate;
2160 }
2162 return OMPC_DEFAULTMAP_pointer;
2164 return OMPC_DEFAULTMAP_scalar;
2165 return OMPC_DEFAULTMAP_aggregate;
2166}
2167
2168bool SemaOpenMP::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
2169 unsigned OpenMPCaptureLevel) const {
2170 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2171
2172 ASTContext &Ctx = getASTContext();
2173 bool IsByRef = true;
2174
2175 // Find the directive that is associated with the provided scope.
2177 QualType Ty = D->getType();
2178
2179 bool IsVariableUsedInMapClause = false;
2180 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level)) {
2181 // This table summarizes how a given variable should be passed to the device
2182 // given its type and the clauses where it appears. This table is based on
2183 // the description in OpenMP 4.5 [2.10.4, target Construct] and
2184 // OpenMP 4.5 [2.15.5, Data-mapping Attribute Rules and Clauses].
2185 //
2186 // =========================================================================
2187 // | type | defaultmap | pvt | first | is_device_ptr | map | res. |
2188 // | |(tofrom:scalar)| | pvt | |has_dv_adr| |
2189 // =========================================================================
2190 // | scl | | | | - | | bycopy|
2191 // | scl | | - | x | - | - | bycopy|
2192 // | scl | | x | - | - | - | null |
2193 // | scl | x | | | - | | byref |
2194 // | scl | x | - | x | - | - | bycopy|
2195 // | scl | x | x | - | - | - | null |
2196 // | scl | | - | - | - | x | byref |
2197 // | scl | x | - | - | - | x | byref |
2198 //
2199 // | agg | n.a. | | | - | | byref |
2200 // | agg | n.a. | - | x | - | - | byref |
2201 // | agg | n.a. | x | - | - | - | null |
2202 // | agg | n.a. | - | - | - | x | byref |
2203 // | agg | n.a. | - | - | - | x[] | byref |
2204 //
2205 // | ptr | n.a. | | | - | | bycopy|
2206 // | ptr | n.a. | - | x | - | - | bycopy|
2207 // | ptr | n.a. | x | - | - | - | null |
2208 // | ptr | n.a. | - | - | - | x | byref |
2209 // | ptr | n.a. | - | - | - | x, x[] | bycopy|
2210 // | ptr | n.a. | - | - | - | x[] | bycopy|
2211 // | ptr | n.a. | - | - | x | | bycopy|
2212 // | ptr | n.a. | - | - | x | x | bycopy|
2213 // | ptr | n.a. | - | - | x | x[] | bycopy|
2214 // =========================================================================
2215 // Legend:
2216 // scl - scalar
2217 // ptr - pointer
2218 // agg - aggregate
2219 // x - applies
2220 // - - invalid in this combination
2221 // [] - mapped with an array section
2222 // byref - should be mapped by reference
2223 // byval - should be mapped by value
2224 // null - initialize a local variable to null on the device
2225 //
2226 // Observations:
2227 // - All scalar declarations that show up in a map clause have to be passed
2228 // by reference, because they may have been mapped in the enclosing data
2229 // environment.
2230 // - If the scalar value does not fit the size of uintptr, it has to be
2231 // passed by reference, regardless the result in the table above.
2232 // - For pointers mapped by value that have either an implicit map or an
2233 // array section, the runtime library may pass the NULL value to the
2234 // device instead of the value passed to it by the compiler.
2235 // - If both a pointer and a dereference of it are mapped, then the pointer
2236 // should be passed by reference.
2237
2238 if (Ty->isReferenceType())
2239 Ty = Ty->castAs<ReferenceType>()->getPointeeType();
2240
2241 // Locate map clauses and see if the variable being captured is mapped by
2242 // itself, or referred to, in any of those clauses. Here we only care about
2243 // variables, not fields, because fields are part of aggregates.
2244 bool IsVariableAssociatedWithSection = false;
2245 bool IsVariableItselfMapped = false;
2246
2247 DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2248 D, Level,
2249 [&IsVariableUsedInMapClause, &IsVariableAssociatedWithSection,
2250 &IsVariableItselfMapped,
2252 MapExprComponents,
2253 OpenMPClauseKind WhereFoundClauseKind) {
2254 // Both map and has_device_addr clauses information influences how a
2255 // variable is captured. E.g. is_device_ptr does not require changing
2256 // the default behavior.
2257 if (WhereFoundClauseKind != OMPC_map &&
2258 WhereFoundClauseKind != OMPC_has_device_addr)
2259 return false;
2260
2261 auto EI = MapExprComponents.rbegin();
2262 auto EE = MapExprComponents.rend();
2263
2264 assert(EI != EE && "Invalid map expression!");
2265
2266 if (isa<DeclRefExpr>(EI->getAssociatedExpression()) &&
2267 EI->getAssociatedDeclaration() == D) {
2268 IsVariableUsedInMapClause = true;
2269
2270 // If the component list has only one element, it's for mapping the
2271 // variable itself, like map(p). This takes precedence in
2272 // determining how it's captured, so we don't need to look further
2273 // for any other maps that use the variable (like map(p[0]) etc.)
2274 if (MapExprComponents.size() == 1) {
2275 IsVariableItselfMapped = true;
2276 return true;
2277 }
2278 }
2279
2280 ++EI;
2281 if (EI == EE)
2282 return false;
2283 auto Last = std::prev(EE);
2284 const auto *UO =
2285 dyn_cast<UnaryOperator>(Last->getAssociatedExpression());
2286 if ((UO && UO->getOpcode() == UO_Deref) ||
2287 isa<ArraySubscriptExpr>(Last->getAssociatedExpression()) ||
2288 isa<ArraySectionExpr>(Last->getAssociatedExpression()) ||
2289 isa<MemberExpr>(EI->getAssociatedExpression()) ||
2290 isa<OMPArrayShapingExpr>(Last->getAssociatedExpression())) {
2291 IsVariableAssociatedWithSection = true;
2292 // We've found a case like map(p[0]) or map(p->a) or map(*p),
2293 // so we are done with this particular map, but we need to keep
2294 // looking in case we find a map(p).
2295 return false;
2296 }
2297
2298 // Keep looking for more map info.
2299 return false;
2300 });
2301
2302 if (IsVariableUsedInMapClause) {
2303 // If variable is identified in a map clause it is always captured by
2304 // reference except if it is a pointer that is dereferenced somehow, but
2305 // not itself mapped.
2306 //
2307 // OpenMP 6.0, 7.1.1: Data sharing attribute rules, variables referenced
2308 // in a construct::
2309 // If a list item in a has_device_addr clause or in a map clause on the
2310 // target construct has a base pointer, and the base pointer is a scalar
2311 // variable *that is not a list item in a map clause on the construct*,
2312 // the base pointer is firstprivate.
2313 //
2314 // OpenMP 4.5, 2.15.1.1: Data-sharing Attribute Rules for Variables
2315 // Referenced in a Construct:
2316 // If an array section is a list item in a map clause on the target
2317 // construct and the array section is derived from a variable for which
2318 // the type is pointer then that variable is firstprivate.
2319 IsByRef = IsVariableItselfMapped ||
2320 !(Ty->isPointerType() && IsVariableAssociatedWithSection);
2321 } else {
2322 // By default, all the data that has a scalar type is mapped by copy
2323 // (except for reduction variables).
2324 // Defaultmap scalar is mutual exclusive to defaultmap pointer
2325 IsByRef = (DSAStack->isForceCaptureByReferenceInTargetExecutable() &&
2326 !Ty->isAnyPointerType()) ||
2327 !Ty->isScalarType() ||
2328 DSAStack->isDefaultmapCapturedByRef(
2330 DSAStack->hasExplicitDSA(
2331 D,
2332 [](OpenMPClauseKind K, bool AppliedToPointee) {
2333 return K == OMPC_reduction && !AppliedToPointee;
2334 },
2335 Level);
2336 }
2337 }
2338
2339 if (IsByRef && Ty.getNonReferenceType()->isScalarType()) {
2340 IsByRef =
2341 ((IsVariableUsedInMapClause &&
2342 DSAStack->getCaptureRegion(Level, OpenMPCaptureLevel) ==
2343 OMPD_target) ||
2344 !(DSAStack->hasExplicitDSA(
2345 D,
2346 [](OpenMPClauseKind K, bool AppliedToPointee) -> bool {
2347 return K == OMPC_firstprivate ||
2348 (K == OMPC_reduction && AppliedToPointee);
2349 },
2350 Level, /*NotLastprivate=*/true) ||
2351 DSAStack->isUsesAllocatorsDecl(Level, D))) &&
2352 // If the variable is artificial and must be captured by value - try to
2353 // capture by value.
2354 !(isa<OMPCapturedExprDecl>(D) && !D->hasAttr<OMPCaptureNoInitAttr>() &&
2355 !cast<OMPCapturedExprDecl>(D)->getInit()->isGLValue()) &&
2356 // If the variable is implicitly firstprivate and scalar - capture by
2357 // copy
2358 !((DSAStack->getDefaultDSA() == DSA_firstprivate ||
2359 DSAStack->getDefaultDSA() == DSA_private) &&
2360 !DSAStack->hasExplicitDSA(
2361 D, [](OpenMPClauseKind K, bool) { return K != OMPC_unknown; },
2362 Level) &&
2363 !DSAStack->isLoopControlVariable(D, Level).first);
2364 }
2365
2366 // When passing data by copy, we need to make sure it fits the uintptr size
2367 // and alignment, because the runtime library only deals with uintptr types.
2368 // If it does not fit the uintptr size, we need to pass the data by reference
2369 // instead.
2370 if (!IsByRef && (Ctx.getTypeSizeInChars(Ty) >
2372 Ctx.getAlignOfGlobalVarInChars(Ty, dyn_cast<VarDecl>(D)) >
2373 Ctx.getTypeAlignInChars(Ctx.getUIntPtrType()))) {
2374 IsByRef = true;
2375 }
2376
2377 return IsByRef;
2378}
2379
2380unsigned SemaOpenMP::getOpenMPNestingLevel() const {
2381 assert(getLangOpts().OpenMP);
2382 return DSAStack->getNestingLevel();
2383}
2384
2386 return isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) &&
2387 DSAStack->isUntiedRegion();
2388}
2389
2391 return (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) &&
2392 !DSAStack->isClauseParsingMode()) ||
2393 DSAStack->hasDirective(
2395 SourceLocation) -> bool {
2397 },
2398 false);
2399}
2400
2402 // Only rebuild for Field.
2403 if (!isa<FieldDecl>(D))
2404 return false;
2405 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2406 D,
2407 [](OpenMPClauseKind C, bool AppliedToPointee,
2408 DefaultDataSharingAttributes DefaultAttr) {
2409 return isOpenMPPrivate(C) && !AppliedToPointee &&
2410 (DefaultAttr == DSA_firstprivate || DefaultAttr == DSA_private);
2411 },
2412 [](OpenMPDirectiveKind) { return true; },
2413 DSAStack->isClauseParsingMode());
2414 if (DVarPrivate.CKind != OMPC_unknown)
2415 return true;
2416 return false;
2417}
2418
2420 Expr *CaptureExpr, bool WithInit,
2421 DeclContext *CurContext,
2422 bool AsExpression);
2423
2425 unsigned StopAt) {
2426 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2427 D = getCanonicalDecl(D);
2428
2429 auto *VD = dyn_cast<VarDecl>(D);
2430 // Do not capture constexpr variables.
2431 if (VD && VD->isConstexpr())
2432 return nullptr;
2433
2434 // If we want to determine whether the variable should be captured from the
2435 // perspective of the current capturing scope, and we've already left all the
2436 // capturing scopes of the top directive on the stack, check from the
2437 // perspective of its parent directive (if any) instead.
2438 DSAStackTy::ParentDirectiveScope InParentDirectiveRAII(
2439 *DSAStack, CheckScopeInfo && DSAStack->isBodyComplete());
2440
2441 // If we are attempting to capture a global variable in a directive with
2442 // 'target' we return true so that this global is also mapped to the device.
2443 //
2444 if (VD && !VD->hasLocalStorage() &&
2445 (SemaRef.getCurCapturedRegion() || SemaRef.getCurBlock() ||
2446 SemaRef.getCurLambda())) {
2448 DSAStackTy::DSAVarData DVarTop =
2449 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2450 if (DVarTop.CKind != OMPC_unknown && DVarTop.RefExpr)
2451 return VD;
2452 // If the declaration is enclosed in a 'declare target' directive,
2453 // then it should not be captured.
2454 //
2455 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2456 return nullptr;
2457 CapturedRegionScopeInfo *CSI = nullptr;
2458 for (FunctionScopeInfo *FSI : llvm::drop_begin(
2459 llvm::reverse(SemaRef.FunctionScopes),
2460 CheckScopeInfo ? (SemaRef.FunctionScopes.size() - (StopAt + 1))
2461 : 0)) {
2462 if (!isa<CapturingScopeInfo>(FSI))
2463 return nullptr;
2464 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2465 if (RSI->CapRegionKind == CR_OpenMP) {
2466 CSI = RSI;
2467 break;
2468 }
2469 }
2470 assert(CSI && "Failed to find CapturedRegionScopeInfo");
2473 DSAStack->getDirective(CSI->OpenMPLevel));
2474 if (Regions[CSI->OpenMPCaptureLevel] != OMPD_task)
2475 return VD;
2476 }
2478 // Try to mark variable as declare target if it is used in capturing
2479 // regions.
2480 if (getLangOpts().OpenMP <= 45 &&
2481 !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
2483 return nullptr;
2484 }
2485 }
2486
2487 if (CheckScopeInfo) {
2488 bool OpenMPFound = false;
2489 for (unsigned I = StopAt + 1; I > 0; --I) {
2490 FunctionScopeInfo *FSI = SemaRef.FunctionScopes[I - 1];
2491 if (!isa<CapturingScopeInfo>(FSI))
2492 return nullptr;
2493 if (auto *RSI = dyn_cast<CapturedRegionScopeInfo>(FSI))
2494 if (RSI->CapRegionKind == CR_OpenMP) {
2495 OpenMPFound = true;
2496 break;
2497 }
2498 }
2499 if (!OpenMPFound)
2500 return nullptr;
2501 }
2502
2503 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2504 (!DSAStack->isClauseParsingMode() ||
2505 DSAStack->getParentDirective() != OMPD_unknown)) {
2506 auto &&Info = DSAStack->isLoopControlVariable(D);
2507 if (Info.first ||
2508 (VD && VD->hasLocalStorage() &&
2509 isImplicitOrExplicitTaskingRegion(DSAStack->getCurrentDirective())) ||
2510 (VD && DSAStack->isForceVarCapturing()))
2511 return VD ? VD : Info.second;
2512 DSAStackTy::DSAVarData DVarTop =
2513 DSAStack->getTopDSA(D, DSAStack->isClauseParsingMode());
2514 if (DVarTop.CKind != OMPC_unknown && isOpenMPPrivate(DVarTop.CKind) &&
2515 (!VD || VD->hasLocalStorage() ||
2516 !(DVarTop.AppliedToPointee && DVarTop.CKind != OMPC_reduction)))
2517 return VD ? VD : cast<VarDecl>(DVarTop.PrivateCopy->getDecl());
2518 // Threadprivate variables must not be captured.
2519 if (isOpenMPThreadPrivate(DVarTop.CKind))
2520 return nullptr;
2521 // The variable is not private or it is the variable in the directive with
2522 // default(none) clause and not used in any clause.
2523 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2524 D,
2525 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
2526 return isOpenMPPrivate(C) && !AppliedToPointee;
2527 },
2528 [](OpenMPDirectiveKind) { return true; },
2529 DSAStack->isClauseParsingMode());
2530 // Global shared must not be captured.
2531 if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
2532 ((DSAStack->getDefaultDSA() != DSA_none &&
2533 DSAStack->getDefaultDSA() != DSA_private &&
2534 DSAStack->getDefaultDSA() != DSA_firstprivate) ||
2535 DVarTop.CKind == OMPC_shared))
2536 return nullptr;
2537 auto *FD = dyn_cast<FieldDecl>(D);
2538 if (DVarPrivate.CKind != OMPC_unknown && !VD && FD &&
2539 !DVarPrivate.PrivateCopy) {
2540 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2541 D,
2542 [](OpenMPClauseKind C, bool AppliedToPointee,
2543 DefaultDataSharingAttributes DefaultAttr) {
2544 return isOpenMPPrivate(C) && !AppliedToPointee &&
2545 (DefaultAttr == DSA_firstprivate ||
2546 DefaultAttr == DSA_private);
2547 },
2548 [](OpenMPDirectiveKind) { return true; },
2549 DSAStack->isClauseParsingMode());
2550 if (DVarPrivate.CKind == OMPC_unknown)
2551 return nullptr;
2552
2553 VarDecl *VD = DSAStack->getImplicitFDCapExprDecl(FD);
2554 if (VD)
2555 return VD;
2556 if (SemaRef.getCurrentThisType().isNull())
2557 return nullptr;
2558 Expr *ThisExpr = SemaRef.BuildCXXThisExpr(SourceLocation(),
2559 SemaRef.getCurrentThisType(),
2560 /*IsImplicit=*/true);
2561 const CXXScopeSpec CS = CXXScopeSpec();
2562 Expr *ME = SemaRef.BuildMemberExpr(
2563 ThisExpr, /*IsArrow=*/true, SourceLocation(),
2566 /*HadMultipleCandidates=*/false, DeclarationNameInfo(), FD->getType(),
2569 SemaRef, FD->getIdentifier(), ME, DVarPrivate.CKind != OMPC_private,
2570 SemaRef.CurContext->getParent(), /*AsExpression=*/false);
2571 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
2573 VD = cast<VarDecl>(VDPrivateRefExpr->getDecl());
2574 DSAStack->addImplicitDefaultFirstprivateFD(FD, VD);
2575 return VD;
2576 }
2577 if (DVarPrivate.CKind != OMPC_unknown ||
2578 (VD && (DSAStack->getDefaultDSA() == DSA_none ||
2579 DSAStack->getDefaultDSA() == DSA_private ||
2580 DSAStack->getDefaultDSA() == DSA_firstprivate)))
2581 return VD ? VD : cast<VarDecl>(DVarPrivate.PrivateCopy->getDecl());
2582 }
2583 return nullptr;
2584}
2585
2586void SemaOpenMP::adjustOpenMPTargetScopeIndex(unsigned &FunctionScopesIndex,
2587 unsigned Level) const {
2588 FunctionScopesIndex -= getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2589}
2590
2592 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2593 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()))
2594 DSAStack->loopInit();
2595}
2596
2598 assert(getLangOpts().OpenMP && "OpenMP must be enabled.");
2599 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
2600 DSAStack->resetPossibleLoopCounter();
2601 DSAStack->loopStart();
2602 }
2603}
2604
2606 unsigned CapLevel) const {
2607 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2608 if (DSAStack->getCurrentDirective() != OMPD_unknown &&
2609 (!DSAStack->isClauseParsingMode() ||
2610 DSAStack->getParentDirective() != OMPD_unknown)) {
2611 DSAStackTy::DSAVarData DVarPrivate = DSAStack->hasDSA(
2612 D,
2613 [](OpenMPClauseKind C, bool AppliedToPointee,
2614 DefaultDataSharingAttributes DefaultAttr) {
2615 return isOpenMPPrivate(C) && !AppliedToPointee &&
2616 DefaultAttr == DSA_private;
2617 },
2618 [](OpenMPDirectiveKind) { return true; },
2619 DSAStack->isClauseParsingMode());
2620 if (DVarPrivate.CKind == OMPC_private && isa<OMPCapturedExprDecl>(D) &&
2621 DSAStack->isImplicitDefaultFirstprivateFD(cast<VarDecl>(D)) &&
2622 !DSAStack->isLoopControlVariable(D).first)
2623 return OMPC_private;
2624 }
2625 if (DSAStack->hasExplicitDirective(isOpenMPTaskingDirective, Level)) {
2626 bool IsTriviallyCopyable =
2628 getASTContext()) &&
2629 !D->getType()
2633 OpenMPDirectiveKind DKind = DSAStack->getDirective(Level);
2635 getOpenMPCaptureRegions(CaptureRegions, DKind);
2636 if (isOpenMPTaskingDirective(CaptureRegions[CapLevel]) &&
2637 (IsTriviallyCopyable ||
2638 !isOpenMPTaskLoopDirective(CaptureRegions[CapLevel]))) {
2639 if (DSAStack->hasExplicitDSA(
2640 D,
2641 [](OpenMPClauseKind K, bool) { return K == OMPC_firstprivate; },
2642 Level, /*NotLastprivate=*/true))
2643 return OMPC_firstprivate;
2644 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2645 if (DVar.CKind != OMPC_shared &&
2646 !DSAStack->isLoopControlVariable(D, Level).first && !DVar.RefExpr) {
2647 DSAStack->addImplicitTaskFirstprivate(Level, D);
2648 return OMPC_firstprivate;
2649 }
2650 }
2651 }
2652 if (isOpenMPLoopDirective(DSAStack->getCurrentDirective()) &&
2653 !isOpenMPLoopTransformationDirective(DSAStack->getCurrentDirective())) {
2654 if (DSAStack->getAssociatedLoops() > 0 && !DSAStack->isLoopStarted()) {
2655 DSAStack->resetPossibleLoopCounter(D);
2656 DSAStack->loopStart();
2657 return OMPC_private;
2658 }
2659 if ((DSAStack->getPossiblyLoopCounter() == D->getCanonicalDecl() ||
2660 DSAStack->isLoopControlVariable(D).first) &&
2661 !DSAStack->hasExplicitDSA(
2662 D, [](OpenMPClauseKind K, bool) { return K != OMPC_private; },
2663 Level) &&
2664 !isOpenMPSimdDirective(DSAStack->getCurrentDirective()))
2665 return OMPC_private;
2666 }
2667 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2668 if (DSAStack->isThreadPrivate(const_cast<VarDecl *>(VD)) &&
2669 DSAStack->isForceVarCapturing() &&
2670 !DSAStack->hasExplicitDSA(
2671 D, [](OpenMPClauseKind K, bool) { return K == OMPC_copyin; },
2672 Level))
2673 return OMPC_private;
2674 }
2675 // User-defined allocators are private since they must be defined in the
2676 // context of target region.
2677 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective, Level) &&
2678 DSAStack->isUsesAllocatorsDecl(Level, D).value_or(
2679 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
2680 DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator)
2681 return OMPC_private;
2682 return (DSAStack->hasExplicitDSA(
2683 D, [](OpenMPClauseKind K, bool) { return K == OMPC_private; },
2684 Level) ||
2685 (DSAStack->isClauseParsingMode() &&
2686 DSAStack->getClauseParsingMode() == OMPC_private) ||
2687 // Consider taskgroup reduction descriptor variable a private
2688 // to avoid possible capture in the region.
2689 (DSAStack->hasExplicitDirective(
2690 [](OpenMPDirectiveKind K) {
2691 return K == OMPD_taskgroup ||
2692 ((isOpenMPParallelDirective(K) ||
2693 isOpenMPWorksharingDirective(K)) &&
2694 !isOpenMPSimdDirective(K));
2695 },
2696 Level) &&
2697 DSAStack->isTaskgroupReductionRef(D, Level)))
2698 ? OMPC_private
2699 : OMPC_unknown;
2700}
2701
2703 unsigned Level) {
2704 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2705 D = getCanonicalDecl(D);
2706 OpenMPClauseKind OMPC = OMPC_unknown;
2707 for (unsigned I = DSAStack->getNestingLevel() + 1; I > Level; --I) {
2708 const unsigned NewLevel = I - 1;
2709 if (DSAStack->hasExplicitDSA(
2710 D,
2711 [&OMPC](const OpenMPClauseKind K, bool AppliedToPointee) {
2712 if (isOpenMPPrivate(K) && !AppliedToPointee) {
2713 OMPC = K;
2714 return true;
2715 }
2716 return false;
2717 },
2718 NewLevel))
2719 break;
2720 if (DSAStack->checkMappableExprComponentListsForDeclAtLevel(
2721 D, NewLevel,
2723 OpenMPClauseKind) { return true; })) {
2724 OMPC = OMPC_map;
2725 break;
2726 }
2727 if (DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2728 NewLevel)) {
2729 OMPC = OMPC_map;
2730 if (DSAStack->mustBeFirstprivateAtLevel(
2732 OMPC = OMPC_firstprivate;
2733 break;
2734 }
2735 }
2736 if (OMPC != OMPC_unknown)
2737 FD->addAttr(
2738 OMPCaptureKindAttr::CreateImplicit(getASTContext(), unsigned(OMPC)));
2739}
2740
2742 unsigned CaptureLevel) const {
2743 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2744 // Return true if the current level is no longer enclosed in a target region.
2745
2747 getOpenMPCaptureRegions(Regions, DSAStack->getDirective(Level));
2748 const auto *VD = dyn_cast<VarDecl>(D);
2749 return VD && !VD->hasLocalStorage() &&
2750 DSAStack->hasExplicitDirective(isOpenMPTargetExecutionDirective,
2751 Level) &&
2752 Regions[CaptureLevel] != OMPD_task;
2753}
2754
2756 unsigned CaptureLevel) const {
2757 assert(getLangOpts().OpenMP && "OpenMP is not allowed");
2758 // Return true if the current level is no longer enclosed in a target region.
2759
2760 if (const auto *VD = dyn_cast<VarDecl>(D)) {
2761 if (!VD->hasLocalStorage()) {
2763 return true;
2764 DSAStackTy::DSAVarData TopDVar =
2765 DSAStack->getTopDSA(D, /*FromParent=*/false);
2766 unsigned NumLevels =
2767 getOpenMPCaptureLevels(DSAStack->getDirective(Level));
2768 if (Level == 0)
2769 // non-file scope static variable with default(firstprivate)
2770 // should be global captured.
2771 return (NumLevels == CaptureLevel + 1 &&
2772 (TopDVar.CKind != OMPC_shared ||
2773 DSAStack->getDefaultDSA() == DSA_firstprivate));
2774 do {
2775 --Level;
2776 DSAStackTy::DSAVarData DVar = DSAStack->getImplicitDSA(D, Level);
2777 if (DVar.CKind != OMPC_shared)
2778 return true;
2779 } while (Level > 0);
2780 }
2781 }
2782 return true;
2783}
2784
2785void SemaOpenMP::DestroyDataSharingAttributesStack() { delete DSAStack; }
2786
2788 OMPTraitInfo &TI) {
2789 OMPDeclareVariantScopes.push_back(OMPDeclareVariantScope(TI));
2790}
2791
2794 "Not in OpenMP declare variant scope!");
2795
2796 OMPDeclareVariantScopes.pop_back();
2797}
2798
2800 const FunctionDecl *Callee,
2801 SourceLocation Loc) {
2802 assert(getLangOpts().OpenMP && "Expected OpenMP compilation mode.");
2803 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2804 OMPDeclareTargetDeclAttr::getDeviceType(Caller->getMostRecentDecl());
2805 // Ignore host functions during device analysis.
2806 if (getLangOpts().OpenMPIsTargetDevice &&
2807 (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host))
2808 return;
2809 // Ignore nohost functions during host analysis.
2810 if (!getLangOpts().OpenMPIsTargetDevice && DevTy &&
2811 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
2812 return;
2813 const FunctionDecl *FD = Callee->getMostRecentDecl();
2814 DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD);
2815 if (getLangOpts().OpenMPIsTargetDevice && DevTy &&
2816 *DevTy == OMPDeclareTargetDeclAttr::DT_Host) {
2817 // Diagnose host function called during device codegen.
2818 StringRef HostDevTy =
2819 getOpenMPSimpleClauseTypeName(OMPC_device_type, OMPC_DEVICE_TYPE_host);
2820 Diag(Loc, diag::err_omp_wrong_device_function_call) << HostDevTy << 0;
2821 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2822 diag::note_omp_marked_device_type_here)
2823 << HostDevTy;
2824 return;
2825 }
2826 if (!getLangOpts().OpenMPIsTargetDevice &&
2827 !getLangOpts().OpenMPOffloadMandatory && DevTy &&
2828 *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) {
2829 // In OpenMP 5.2 or later, if the function has a host variant then allow
2830 // that to be called instead
2831 auto &&HasHostAttr = [](const FunctionDecl *Callee) {
2832 for (OMPDeclareVariantAttr *A :
2833 Callee->specific_attrs<OMPDeclareVariantAttr>()) {
2834 auto *DeclRefVariant = cast<DeclRefExpr>(A->getVariantFuncRef());
2835 auto *VariantFD = cast<FunctionDecl>(DeclRefVariant->getDecl());
2836 std::optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
2837 OMPDeclareTargetDeclAttr::getDeviceType(
2838 VariantFD->getMostRecentDecl());
2839 if (!DevTy || *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
2840 return true;
2841 }
2842 return false;
2843 };
2844 if (getLangOpts().OpenMP >= 52 &&
2845 Callee->hasAttr<OMPDeclareVariantAttr>() && HasHostAttr(Callee))
2846 return;
2847 // Diagnose nohost function called during host codegen.
2848 StringRef NoHostDevTy = getOpenMPSimpleClauseTypeName(
2849 OMPC_device_type, OMPC_DEVICE_TYPE_nohost);
2850 Diag(Loc, diag::err_omp_wrong_device_function_call) << NoHostDevTy << 1;
2851 Diag(*OMPDeclareTargetDeclAttr::getLocation(FD),
2852 diag::note_omp_marked_device_type_here)
2853 << NoHostDevTy;
2854 }
2855}
2856
2858 const DeclarationNameInfo &DirName,
2859 Scope *CurScope, SourceLocation Loc) {
2860 DSAStack->push(DKind, DirName, CurScope, Loc);
2861 SemaRef.PushExpressionEvaluationContext(
2863}
2864
2866 DSAStack->setClauseParsingMode(K);
2867}
2868
2870 DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2871 SemaRef.CleanupVarDeclMarking();
2872}
2873
2874static std::pair<ValueDecl *, bool>
2875getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2876 SourceRange &ERange, bool AllowArraySection = false,
2877 bool AllowAssumedSizeArray = false, StringRef DiagType = "");
2878
2879/// Check consistency of the reduction clauses.
2880static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2881 ArrayRef<OMPClause *> Clauses) {
2882 bool InscanFound = false;
2883 SourceLocation InscanLoc;
2884 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2885 // A reduction clause without the inscan reduction-modifier may not appear on
2886 // a construct on which a reduction clause with the inscan reduction-modifier
2887 // appears.
2888 for (OMPClause *C : Clauses) {
2889 if (C->getClauseKind() != OMPC_reduction)
2890 continue;
2891 auto *RC = cast<OMPReductionClause>(C);
2892 if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2893 InscanFound = true;
2894 InscanLoc = RC->getModifierLoc();
2895 continue;
2896 }
2897 if (RC->getModifier() == OMPC_REDUCTION_task) {
2898 // OpenMP 5.0, 2.19.5.4 reduction Clause.
2899 // A reduction clause with the task reduction-modifier may only appear on
2900 // a parallel construct, a worksharing construct or a combined or
2901 // composite construct for which any of the aforementioned constructs is a
2902 // constituent construct and simd or loop are not constituent constructs.
2903 OpenMPDirectiveKind CurDir = Stack->getCurrentDirective();
2904 if (!(isOpenMPParallelDirective(CurDir) ||
2906 isOpenMPSimdDirective(CurDir))
2907 S.Diag(RC->getModifierLoc(),
2908 diag::err_omp_reduction_task_not_parallel_or_worksharing);
2909 continue;
2910 }
2911 }
2912 if (InscanFound) {
2913 for (OMPClause *C : Clauses) {
2914 if (C->getClauseKind() != OMPC_reduction)
2915 continue;
2916 auto *RC = cast<OMPReductionClause>(C);
2917 if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2918 S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2919 ? RC->getBeginLoc()
2920 : RC->getModifierLoc(),
2921 diag::err_omp_inscan_reduction_expected);
2922 S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2923 continue;
2924 }
2925 for (Expr *Ref : RC->varlist()) {
2926 assert(Ref && "NULL expr in OpenMP reduction clause.");
2927 SourceLocation ELoc;
2928 SourceRange ERange;
2929 Expr *SimpleRefExpr = Ref;
2930 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2931 /*AllowArraySection=*/true);
2932 ValueDecl *D = Res.first;
2933 if (!D)
2934 continue;
2935 if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2936 S.Diag(Ref->getExprLoc(),
2937 diag::err_omp_reduction_not_inclusive_exclusive)
2938 << Ref->getSourceRange();
2939 }
2940 }
2941 }
2942 }
2943}
2944
2945static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2946 ArrayRef<OMPClause *> Clauses);
2947static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2948 bool WithInit);
2949
2950static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
2951 const ValueDecl *D,
2952 const DSAStackTy::DSAVarData &DVar,
2953 bool IsLoopIterVar = false);
2954
2956 // OpenMP [2.14.3.5, Restrictions, C/C++, p.1]
2957 // A variable of class type (or array thereof) that appears in a lastprivate
2958 // clause requires an accessible, unambiguous default constructor for the
2959 // class type, unless the list item is also specified in a firstprivate
2960 // clause.
2961
2962 auto FinalizeLastprivate = [&](OMPLastprivateClause *Clause) {
2963 SmallVector<Expr *, 8> PrivateCopies;
2964 for (Expr *DE : Clause->varlist()) {
2965 if (DE->isValueDependent() || DE->isTypeDependent()) {
2966 PrivateCopies.push_back(nullptr);
2967 continue;
2968 }
2969 auto *DRE = cast<DeclRefExpr>(DE->IgnoreParens());
2970 auto *VD = cast<VarDecl>(DRE->getDecl());
2972 const DSAStackTy::DSAVarData DVar =
2973 DSAStack->getTopDSA(VD, /*FromParent=*/false);
2974 if (DVar.CKind != OMPC_lastprivate) {
2975 // The variable is also a firstprivate, so initialization sequence
2976 // for private copy is generated already.
2977 PrivateCopies.push_back(nullptr);
2978 continue;
2979 }
2980 // Generate helper private variable and initialize it with the
2981 // default value. The address of the original variable is replaced
2982 // by the address of the new private variable in CodeGen. This new
2983 // variable is not added to IdResolver, so the code in the OpenMP
2984 // region uses original variable for proper diagnostics.
2985 VarDecl *VDPrivate = buildVarDecl(
2986 SemaRef, DE->getExprLoc(), Type.getUnqualifiedType(), VD->getName(),
2987 VD->hasAttrs() ? &VD->getAttrs() : nullptr, DRE);
2988 SemaRef.ActOnUninitializedDecl(VDPrivate);
2989 if (VDPrivate->isInvalidDecl()) {
2990 PrivateCopies.push_back(nullptr);
2991 continue;
2992 }
2993 PrivateCopies.push_back(buildDeclRefExpr(
2994 SemaRef, VDPrivate, DE->getType(), DE->getExprLoc()));
2995 }
2996 Clause->setPrivateCopies(PrivateCopies);
2997 };
2998
2999 auto FinalizeNontemporal = [&](OMPNontemporalClause *Clause) {
3000 // Finalize nontemporal clause by handling private copies, if any.
3001 SmallVector<Expr *, 8> PrivateRefs;
3002 for (Expr *RefExpr : Clause->varlist()) {
3003 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
3004 SourceLocation ELoc;
3005 SourceRange ERange;
3006 Expr *SimpleRefExpr = RefExpr;
3007 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
3008 if (Res.second)
3009 // It will be analyzed later.
3010 PrivateRefs.push_back(RefExpr);
3011 ValueDecl *D = Res.first;
3012 if (!D)
3013 continue;
3014
3015 const DSAStackTy::DSAVarData DVar =
3016 DSAStack->getTopDSA(D, /*FromParent=*/false);
3017 PrivateRefs.push_back(DVar.PrivateCopy ? DVar.PrivateCopy
3018 : SimpleRefExpr);
3019 }
3020 Clause->setPrivateRefs(PrivateRefs);
3021 };
3022
3023 auto FinalizeAllocators = [&](OMPUsesAllocatorsClause *Clause) {
3024 for (unsigned I = 0, E = Clause->getNumberOfAllocators(); I < E; ++I) {
3025 OMPUsesAllocatorsClause::Data D = Clause->getAllocatorData(I);
3026 auto *DRE = dyn_cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts());
3027 if (!DRE)
3028 continue;
3029 ValueDecl *VD = DRE->getDecl();
3030 if (!VD || !isa<VarDecl>(VD))
3031 continue;
3032 DSAStackTy::DSAVarData DVar =
3033 DSAStack->getTopDSA(VD, /*FromParent=*/false);
3034 // OpenMP [2.12.5, target Construct]
3035 // Memory allocators that appear in a uses_allocators clause cannot
3036 // appear in other data-sharing attribute clauses or data-mapping
3037 // attribute clauses in the same construct.
3038 Expr *MapExpr = nullptr;
3039 if (DVar.RefExpr ||
3040 DSAStack->checkMappableExprComponentListsForDecl(
3041 VD, /*CurrentRegionOnly=*/true,
3042 [VD, &MapExpr](
3044 MapExprComponents,
3046 auto MI = MapExprComponents.rbegin();
3047 auto ME = MapExprComponents.rend();
3048 if (MI != ME &&
3049 MI->getAssociatedDeclaration()->getCanonicalDecl() ==
3050 VD->getCanonicalDecl()) {
3051 MapExpr = MI->getAssociatedExpression();
3052 return true;
3053 }
3054 return false;
3055 })) {
3056 Diag(D.Allocator->getExprLoc(), diag::err_omp_allocator_used_in_clauses)
3057 << D.Allocator->getSourceRange();
3058 if (DVar.RefExpr)
3060 else
3061 Diag(MapExpr->getExprLoc(), diag::note_used_here)
3062 << MapExpr->getSourceRange();
3063 }
3064 }
3065 };
3066
3067 if (const auto *D = dyn_cast_or_null<OMPExecutableDirective>(CurDirective)) {
3068 for (OMPClause *C : D->clauses()) {
3069 if (auto *Clause = dyn_cast<OMPLastprivateClause>(C)) {
3070 FinalizeLastprivate(Clause);
3071 } else if (auto *Clause = dyn_cast<OMPNontemporalClause>(C)) {
3072 FinalizeNontemporal(Clause);
3073 } else if (auto *Clause = dyn_cast<OMPUsesAllocatorsClause>(C)) {
3074 FinalizeAllocators(Clause);
3075 }
3076 }
3077 // Check allocate clauses.
3078 if (!SemaRef.CurContext->isDependentContext())
3079 checkAllocateClauses(SemaRef, DSAStack, D->clauses());
3080 checkReductionClauses(SemaRef, DSAStack, D->clauses());
3081 }
3082
3083 DSAStack->pop();
3086}
3087
3088static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
3089 Expr *NumIterations, Sema &SemaRef,
3090 Scope *S, DSAStackTy *Stack);
3091
3092static bool finishLinearClauses(Sema &SemaRef, ArrayRef<OMPClause *> Clauses,
3093 OMPLoopBasedDirective::HelperExprs &B,
3094 DSAStackTy *Stack) {
3095 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
3096 "loop exprs were not built");
3097
3098 if (SemaRef.CurContext->isDependentContext())
3099 return false;
3100
3101 // Finalize the clauses that need pre-built expressions for CodeGen.
3102 for (OMPClause *C : Clauses) {
3103 auto *LC = dyn_cast<OMPLinearClause>(C);
3104 if (!LC)
3105 continue;
3106 if (FinishOpenMPLinearClause(*LC, cast<DeclRefExpr>(B.IterationVarRef),
3107 B.NumIterations, SemaRef,
3108 SemaRef.getCurScope(), Stack))
3109 return true;
3110 }
3111
3112 return false;
3113}
3114
3115namespace {
3116
3117class VarDeclFilterCCC final : public CorrectionCandidateCallback {
3118private:
3119 Sema &SemaRef;
3120
3121public:
3122 explicit VarDeclFilterCCC(Sema &S) : SemaRef(S) {}
3123 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3124 NamedDecl *ND = Candidate.getCorrectionDecl();
3125 if (const auto *VD = dyn_cast_or_null<VarDecl>(ND)) {
3126 return VD->hasGlobalStorage() &&
3127 SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3128 SemaRef.getCurScope());
3129 }
3130 return false;
3131 }
3132
3133 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3134 return std::make_unique<VarDeclFilterCCC>(*this);
3135 }
3136};
3137
3138class VarOrFuncDeclFilterCCC final : public CorrectionCandidateCallback {
3139private:
3140 Sema &SemaRef;
3141
3142public:
3143 explicit VarOrFuncDeclFilterCCC(Sema &S) : SemaRef(S) {}
3144 bool ValidateCandidate(const TypoCorrection &Candidate) override {
3145 NamedDecl *ND = Candidate.getCorrectionDecl();
3146 if (ND && ((isa<VarDecl>(ND) && ND->getKind() == Decl::Var) ||
3147 isa<FunctionDecl>(ND))) {
3148 return SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(),
3149 SemaRef.getCurScope());
3150 }
3151 return false;
3152 }
3153
3154 std::unique_ptr<CorrectionCandidateCallback> clone() override {
3155 return std::make_unique<VarOrFuncDeclFilterCCC>(*this);
3156 }
3157};
3158
3159} // namespace
3160
3162 CXXScopeSpec &ScopeSpec,
3163 const DeclarationNameInfo &Id,
3164 OpenMPDirectiveKind Kind) {
3165 ASTContext &Context = getASTContext();
3166 unsigned OMPVersion = getLangOpts().OpenMP;
3168 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
3169 /*ObjectType=*/QualType(),
3170 /*AllowBuiltinCreation=*/true);
3171
3172 if (Lookup.isAmbiguous())
3173 return ExprError();
3174
3175 VarDecl *VD;
3176 if (!Lookup.isSingleResult()) {
3177 VarDeclFilterCCC CCC(SemaRef);
3178 if (TypoCorrection Corrected =
3179 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
3181 SemaRef.diagnoseTypo(
3182 Corrected,
3183 SemaRef.PDiag(Lookup.empty() ? diag::err_undeclared_var_use_suggest
3184 : diag::err_omp_expected_var_arg_suggest)
3185 << Id.getName());
3186 VD = Corrected.getCorrectionDeclAs<VarDecl>();
3187 } else {
3188 Diag(Id.getLoc(), Lookup.empty() ? diag::err_undeclared_var_use
3189 : diag::err_omp_expected_var_arg)
3190 << Id.getName();
3191 return ExprError();
3192 }
3193 } else if (!(VD = Lookup.getAsSingle<VarDecl>())) {
3194 Diag(Id.getLoc(), diag::err_omp_expected_var_arg) << Id.getName();
3195 Diag(Lookup.getFoundDecl()->getLocation(), diag::note_declared_at);
3196 return ExprError();
3197 }
3198 Lookup.suppressDiagnostics();
3199
3200 // OpenMP [2.9.2, Syntax, C/C++]
3201 // Variables must be file-scope, namespace-scope, or static block-scope.
3202 if ((Kind == OMPD_threadprivate || Kind == OMPD_groupprivate) &&
3203 !VD->hasGlobalStorage()) {
3204 Diag(Id.getLoc(), diag::err_omp_global_var_arg)
3205 << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
3206 bool IsDecl =
3208 Diag(VD->getLocation(),
3209 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3210 << VD;
3211 return ExprError();
3212 }
3213
3214 VarDecl *CanonicalVD = VD->getCanonicalDecl();
3215 NamedDecl *ND = CanonicalVD;
3216 // OpenMP [2.9.2, Restrictions, C/C++, p.2]
3217 // A threadprivate or groupprivate directive for file-scope variables must
3218 // appear outside any definition or declaration.
3219 if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
3220 !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
3221 Diag(Id.getLoc(), diag::err_omp_var_scope)
3222 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3223 bool IsDecl =
3225 Diag(VD->getLocation(),
3226 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3227 << VD;
3228 return ExprError();
3229 }
3230 // OpenMP [2.9.2, Restrictions, C/C++, p.3]
3231 // A threadprivate or groupprivate directive for static class member
3232 // variables must appear in the class definition, in the same scope in which
3233 // the member variables are declared.
3234 if (CanonicalVD->isStaticDataMember() &&
3235 !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
3236 Diag(Id.getLoc(), diag::err_omp_var_scope)
3237 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3238 bool IsDecl =
3240 Diag(VD->getLocation(),
3241 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3242 << VD;
3243 return ExprError();
3244 }
3245 // OpenMP [2.9.2, Restrictions, C/C++, p.4]
3246 // A threadprivate or groupprivate directive for namespace-scope variables
3247 // must appear outside any definition or declaration other than the
3248 // namespace definition itself.
3249 if (CanonicalVD->getDeclContext()->isNamespace() &&
3250 (!SemaRef.getCurLexicalContext()->isFileContext() ||
3251 !SemaRef.getCurLexicalContext()->Encloses(
3252 CanonicalVD->getDeclContext()))) {
3253 Diag(Id.getLoc(), diag::err_omp_var_scope)
3254 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3255 bool IsDecl =
3257 Diag(VD->getLocation(),
3258 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3259 << VD;
3260 return ExprError();
3261 }
3262 // OpenMP [2.9.2, Restrictions, C/C++, p.6]
3263 // A threadprivate or groupprivate directive for static block-scope
3264 // variables must appear in the scope of the variable and not in a nested
3265 // scope.
3266 if (CanonicalVD->isLocalVarDecl() && CurScope &&
3267 !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
3268 Diag(Id.getLoc(), diag::err_omp_var_scope)
3269 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3270 bool IsDecl =
3272 Diag(VD->getLocation(),
3273 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3274 << VD;
3275 return ExprError();
3276 }
3277
3278 // OpenMP [2.9.2, Restrictions, C/C++, p.2-6]
3279 // A threadprivate or groupprivate directive must lexically precede all
3280 // references to any of the variables in its list.
3281 if ((Kind == OMPD_threadprivate && VD->isUsed() &&
3282 !DSAStack->isThreadPrivate(VD)) ||
3283 (Kind == OMPD_groupprivate && VD->isUsed())) {
3284 Diag(Id.getLoc(), diag::err_omp_var_used)
3285 << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
3286 return ExprError();
3287 }
3288
3289 QualType ExprType = VD->getType().getNonReferenceType();
3291 SourceLocation(), VD,
3292 /*RefersToEnclosingVariableOrCapture=*/false,
3293 Id.getLoc(), ExprType, VK_LValue);
3294}
3295
3298 ArrayRef<Expr *> VarList) {
3299 if (OMPThreadPrivateDecl *D = CheckOMPThreadPrivateDecl(Loc, VarList)) {
3300 SemaRef.CurContext->addDecl(D);
3302 }
3303 return nullptr;
3304}
3305
3308 ArrayRef<Expr *> VarList) {
3309 if (!getLangOpts().OpenMP || getLangOpts().OpenMP < 60) {
3310 Diag(Loc, diag::err_omp_unexpected_directive)
3311 << getOpenMPDirectiveName(OMPD_groupprivate, getLangOpts().OpenMP);
3312 return nullptr;
3313 }
3314 if (OMPGroupPrivateDecl *D = CheckOMPGroupPrivateDecl(Loc, VarList)) {
3315 SemaRef.CurContext->addDecl(D);
3317 }
3318 return nullptr;
3319}
3320
3321namespace {
3322class LocalVarRefChecker final
3323 : public ConstStmtVisitor<LocalVarRefChecker, bool> {
3324 Sema &SemaRef;
3325
3326public:
3327 bool VisitDeclRefExpr(const DeclRefExpr *E) {
3328 if (const auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3329 if (VD->hasLocalStorage()) {
3330 SemaRef.Diag(E->getBeginLoc(),
3331 diag::err_omp_local_var_in_threadprivate_init)
3332 << E->getSourceRange();
3333 SemaRef.Diag(VD->getLocation(), diag::note_defined_here)
3334 << VD << VD->getSourceRange();
3335 return true;
3336 }
3337 }
3338 return false;
3339 }
3340 bool VisitStmt(const Stmt *S) {
3341 for (const Stmt *Child : S->children()) {
3342 if (Child && Visit(Child))
3343 return true;
3344 }
3345 return false;
3346 }
3347 explicit LocalVarRefChecker(Sema &SemaRef) : SemaRef(SemaRef) {}
3348};
3349} // namespace
3350
3351OMPThreadPrivateDecl *
3353 ArrayRef<Expr *> VarList) {
3354 ASTContext &Context = getASTContext();
3356 for (Expr *RefExpr : VarList) {
3357 auto *DE = cast<DeclRefExpr>(RefExpr);
3358 auto *VD = cast<VarDecl>(DE->getDecl());
3359 SourceLocation ILoc = DE->getExprLoc();
3360
3361 // Mark variable as used.
3362 VD->setReferenced();
3363 VD->markUsed(Context);
3364
3365 QualType QType = VD->getType();
3366 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3367 // It will be analyzed later.
3368 Vars.push_back(DE);
3369 continue;
3370 }
3371
3372 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3373 // A threadprivate variable must not have an incomplete type.
3374 if (SemaRef.RequireCompleteType(
3375 ILoc, VD->getType(), diag::err_omp_threadprivate_incomplete_type)) {
3376 continue;
3377 }
3378
3379 // OpenMP [2.9.2, Restrictions, C/C++, p.10]
3380 // A threadprivate variable must not have a reference type.
3381 if (VD->getType()->isReferenceType()) {
3382 unsigned OMPVersion = getLangOpts().OpenMP;
3383 Diag(ILoc, diag::err_omp_ref_type_arg)
3384 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
3385 << VD->getType();
3386 bool IsDecl =
3388 Diag(VD->getLocation(),
3389 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3390 << VD;
3391 continue;
3392 }
3393
3394 // Check if this is a TLS variable. If TLS is not being supported, produce
3395 // the corresponding diagnostic.
3396 if ((VD->getTLSKind() != VarDecl::TLS_None &&
3397 !(VD->hasAttr<OMPThreadPrivateDeclAttr>() &&
3398 getLangOpts().OpenMPUseTLS &&
3399 getASTContext().getTargetInfo().isTLSSupported())) ||
3400 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3401 !VD->isLocalVarDecl())) {
3402 Diag(ILoc, diag::err_omp_var_thread_local)
3403 << VD << ((VD->getTLSKind() != VarDecl::TLS_None) ? 0 : 1);
3404 bool IsDecl =
3406 Diag(VD->getLocation(),
3407 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3408 << VD;
3409 continue;
3410 }
3411
3412 // Check if initial value of threadprivate variable reference variable with
3413 // local storage (it is not supported by runtime).
3414 if (const Expr *Init = VD->getAnyInitializer()) {
3415 LocalVarRefChecker Checker(SemaRef);
3416 if (Checker.Visit(Init))
3417 continue;
3418 }
3419
3420 Vars.push_back(RefExpr);
3421 DSAStack->addDSA(VD, DE, OMPC_threadprivate);
3422 VD->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(
3423 Context, SourceRange(Loc, Loc)));
3424 if (ASTMutationListener *ML = Context.getASTMutationListener())
3425 ML->DeclarationMarkedOpenMPThreadPrivate(VD);
3426 }
3427 OMPThreadPrivateDecl *D = nullptr;
3428 if (!Vars.empty()) {
3429 D = OMPThreadPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3430 Loc, Vars);
3431 D->setAccess(AS_public);
3432 }
3433 return D;
3434}
3435
3438 ArrayRef<Expr *> VarList) {
3439 ASTContext &Context = getASTContext();
3441 for (Expr *RefExpr : VarList) {
3442 auto *DE = cast<DeclRefExpr>(RefExpr);
3443 auto *VD = cast<VarDecl>(DE->getDecl());
3444 SourceLocation ILoc = DE->getExprLoc();
3445
3446 // Mark variable as used.
3447 VD->setReferenced();
3448 VD->markUsed(Context);
3449
3450 QualType QType = VD->getType();
3451 if (QType->isDependentType() || QType->isInstantiationDependentType()) {
3452 // It will be analyzed later.
3453 Vars.push_back(DE);
3454 continue;
3455 }
3456
3457 // OpenMP groupprivate restrictions:
3458 // A groupprivate variable must not have an incomplete type.
3459 if (SemaRef.RequireCompleteType(
3460 ILoc, VD->getType(), diag::err_omp_groupprivate_incomplete_type)) {
3461 continue;
3462 }
3463
3464 // A groupprivate variable must not have a reference type.
3465 if (VD->getType()->isReferenceType()) {
3466 Diag(ILoc, diag::err_omp_ref_type_arg)
3467 << getOpenMPDirectiveName(OMPD_groupprivate) << VD->getType();
3468 bool IsDecl =
3470 Diag(VD->getLocation(),
3471 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3472 << VD;
3473 continue;
3474 }
3475
3476 // A variable that is declared with an initializer must not appear in a
3477 // groupprivate directive.
3478 if (VD->getAnyInitializer()) {
3479 Diag(ILoc, diag::err_omp_groupprivate_with_initializer)
3480 << VD->getDeclName();
3481 bool IsDecl =
3483 Diag(VD->getLocation(),
3484 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3485 << VD;
3486 continue;
3487 }
3488
3489 Vars.push_back(RefExpr);
3490 DSAStack->addDSA(VD, DE, OMPC_groupprivate);
3491 VD->addAttr(OMPGroupPrivateDeclAttr::CreateImplicit(Context,
3492 SourceRange(Loc, Loc)));
3493 if (ASTMutationListener *ML = Context.getASTMutationListener())
3494 ML->DeclarationMarkedOpenMPGroupPrivate(VD);
3495 }
3496 OMPGroupPrivateDecl *D = nullptr;
3497 if (!Vars.empty()) {
3498 D = OMPGroupPrivateDecl::Create(Context, SemaRef.getCurLexicalContext(),
3499 Loc, Vars);
3500 D->setAccess(AS_public);
3501 }
3502 return D;
3503}
3504
3505static OMPAllocateDeclAttr::AllocatorTypeTy
3506getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator) {
3507 if (!Allocator)
3508 return OMPAllocateDeclAttr::OMPNullMemAlloc;
3509 if (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3510 Allocator->isInstantiationDependent() ||
3512 return OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3513 auto AllocatorKindRes = OMPAllocateDeclAttr::OMPUserDefinedMemAlloc;
3514 llvm::FoldingSetNodeID AEId;
3515 const Expr *AE = Allocator->IgnoreParenImpCasts();
3516 AE->IgnoreImpCasts()->Profile(AEId, S.getASTContext(), /*Canonical=*/true);
3517 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
3518 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
3519 const Expr *DefAllocator = Stack->getAllocator(AllocatorKind);
3520 llvm::FoldingSetNodeID DAEId;
3521 DefAllocator->IgnoreImpCasts()->Profile(DAEId, S.getASTContext(),
3522 /*Canonical=*/true);
3523 if (AEId == DAEId) {
3524 AllocatorKindRes = AllocatorKind;
3525 break;
3526 }
3527 }
3528 return AllocatorKindRes;
3529}
3530
3532 Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD,
3533 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator) {
3534 if (!VD->hasAttr<OMPAllocateDeclAttr>())
3535 return false;
3536 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
3537 Expr *PrevAllocator = A->getAllocator();
3538 OMPAllocateDeclAttr::AllocatorTypeTy PrevAllocatorKind =
3539 getAllocatorKind(S, Stack, PrevAllocator);
3540 bool AllocatorsMatch = AllocatorKind == PrevAllocatorKind;
3541 if (AllocatorsMatch &&
3542 AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc &&
3543 Allocator && PrevAllocator) {
3544 const Expr *AE = Allocator->IgnoreParenImpCasts();
3545 const Expr *PAE = PrevAllocator->IgnoreParenImpCasts();
3546 llvm::FoldingSetNodeID AEId, PAEId;
3547 AE->Profile(AEId, S.Context, /*Canonical=*/true);
3548 PAE->Profile(PAEId, S.Context, /*Canonical=*/true);
3549 AllocatorsMatch = AEId == PAEId;
3550 }
3551 if (!AllocatorsMatch) {
3552 SmallString<256> AllocatorBuffer;
3553 llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer);
3554 if (Allocator)
3555 Allocator->printPretty(AllocatorStream, nullptr, S.getPrintingPolicy());
3556 SmallString<256> PrevAllocatorBuffer;
3557 llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer);
3558 if (PrevAllocator)
3559 PrevAllocator->printPretty(PrevAllocatorStream, nullptr,
3560 S.getPrintingPolicy());
3561
3562 SourceLocation AllocatorLoc =
3563 Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc();
3564 SourceRange AllocatorRange =
3565 Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange();
3566 SourceLocation PrevAllocatorLoc =
3567 PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation();
3568 SourceRange PrevAllocatorRange =
3569 PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange();
3570 S.Diag(AllocatorLoc, diag::warn_omp_used_different_allocator)
3571 << (Allocator ? 1 : 0) << AllocatorStream.str()
3572 << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str()
3573 << AllocatorRange;
3574 S.Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator)
3575 << PrevAllocatorRange;
3576 return true;
3577 }
3578 return false;
3579}
3580
3581static void
3583 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind,
3584 Expr *Allocator, Expr *Alignment, SourceRange SR) {
3585 if (VD->hasAttr<OMPAllocateDeclAttr>())
3586 return;
3587 if (Alignment &&
3588 (Alignment->isTypeDependent() || Alignment->isValueDependent() ||
3589 Alignment->isInstantiationDependent() ||
3590 Alignment->containsUnexpandedParameterPack()))
3591 // Apply later when we have a usable value.
3592 return;
3593 if (Allocator &&
3594 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
3595 Allocator->isInstantiationDependent() ||
3596 Allocator->containsUnexpandedParameterPack()))
3597 return;
3598 auto *A = OMPAllocateDeclAttr::CreateImplicit(S.Context, AllocatorKind,
3599 Allocator, Alignment, SR);
3600 VD->addAttr(A);
3602 ML->DeclarationMarkedOpenMPAllocate(VD, A);
3603}
3604
3607 DeclContext *Owner) {
3608 assert(Clauses.size() <= 2 && "Expected at most two clauses.");
3609 Expr *Alignment = nullptr;
3610 Expr *Allocator = nullptr;
3611 if (Clauses.empty()) {
3612 // OpenMP 5.0, 2.11.3 allocate Directive, Restrictions.
3613 // allocate directives that appear in a target region must specify an
3614 // allocator clause unless a requires directive with the dynamic_allocators
3615 // clause is present in the same compilation unit.
3616 if (getLangOpts().OpenMPIsTargetDevice &&
3617 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
3618 SemaRef.targetDiag(Loc, diag::err_expected_allocator_clause);
3619 } else {
3620 for (const OMPClause *C : Clauses)
3621 if (const auto *AC = dyn_cast<OMPAllocatorClause>(C))
3622 Allocator = AC->getAllocator();
3623 else if (const auto *AC = dyn_cast<OMPAlignClause>(C))
3624 Alignment = AC->getAlignment();
3625 else
3626 llvm_unreachable("Unexpected clause on allocate directive");
3627 }
3628 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
3629 getAllocatorKind(SemaRef, DSAStack, Allocator);
3631 for (Expr *RefExpr : VarList) {
3632 auto *DE = cast<DeclRefExpr>(RefExpr);
3633 auto *VD = cast<VarDecl>(DE->getDecl());
3634
3635 // Check if this is a TLS variable or global register.
3636 if (VD->getTLSKind() != VarDecl::TLS_None ||
3637 VD->hasAttr<OMPThreadPrivateDeclAttr>() ||
3638 (VD->getStorageClass() == SC_Register && VD->hasAttr<AsmLabelAttr>() &&
3639 !VD->isLocalVarDecl()))
3640 continue;
3641
3642 // If the used several times in the allocate directive, the same allocator
3643 // must be used.
3645 AllocatorKind, Allocator))
3646 continue;
3647
3648 // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++
3649 // If a list item has a static storage type, the allocator expression in the
3650 // allocator clause must be a constant expression that evaluates to one of
3651 // the predefined memory allocator values.
3652 if (Allocator && VD->hasGlobalStorage()) {
3653 if (AllocatorKind == OMPAllocateDeclAttr::OMPUserDefinedMemAlloc) {
3654 Diag(Allocator->getExprLoc(),
3655 diag::err_omp_expected_predefined_allocator)
3656 << Allocator->getSourceRange();
3657 bool IsDecl = VD->isThisDeclarationADefinition(getASTContext()) ==
3659 Diag(VD->getLocation(),
3660 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
3661 << VD;
3662 continue;
3663 }
3664 }
3665
3666 Vars.push_back(RefExpr);
3667 applyOMPAllocateAttribute(SemaRef, VD, AllocatorKind, Allocator, Alignment,
3668 DE->getSourceRange());
3669 }
3670 if (Vars.empty())
3671 return nullptr;
3672 if (!Owner)
3673 Owner = SemaRef.getCurLexicalContext();
3674 auto *D = OMPAllocateDecl::Create(getASTContext(), Owner, Loc, Vars, Clauses);
3675 D->setAccess(AS_public);
3676 Owner->addDecl(D);
3678}
3679
3682 ArrayRef<OMPClause *> ClauseList) {
3683 OMPRequiresDecl *D = nullptr;
3684 if (!SemaRef.CurContext->isFileContext()) {
3685 Diag(Loc, diag::err_omp_invalid_scope) << "requires";
3686 } else {
3687 D = CheckOMPRequiresDecl(Loc, ClauseList);
3688 if (D) {
3689 SemaRef.CurContext->addDecl(D);
3690 DSAStack->addRequiresDecl(D);
3691 }
3692 }
3694}
3695
3697 OpenMPDirectiveKind DKind,
3698 ArrayRef<std::string> Assumptions,
3699 bool SkippedClauses) {
3700 if (!SkippedClauses && Assumptions.empty()) {
3701 unsigned OMPVersion = getLangOpts().OpenMP;
3702 Diag(Loc, diag::err_omp_no_clause_for_directive)
3703 << llvm::omp::getAllAssumeClauseOptions()
3704 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
3705 }
3706
3707 auto *AA =
3708 OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), Loc);
3709 if (DKind == llvm::omp::Directive::OMPD_begin_assumes) {
3710 OMPAssumeScoped.push_back(AA);
3711 return;
3712 }
3713
3714 // Global assumes without assumption clauses are ignored.
3715 if (Assumptions.empty())
3716 return;
3717
3718 assert(DKind == llvm::omp::Directive::OMPD_assumes &&
3719 "Unexpected omp assumption directive!");
3720 OMPAssumeGlobal.push_back(AA);
3721
3722 // The OMPAssumeGlobal scope above will take care of new declarations but
3723 // we also want to apply the assumption to existing ones, e.g., to
3724 // declarations in included headers. To this end, we traverse all existing
3725 // declaration contexts and annotate function declarations here.
3726 SmallVector<DeclContext *, 8> DeclContexts;
3727 auto *Ctx = SemaRef.CurContext;
3728 while (Ctx->getLexicalParent())
3729 Ctx = Ctx->getLexicalParent();
3730 DeclContexts.push_back(Ctx);
3731 while (!DeclContexts.empty()) {
3732 DeclContext *DC = DeclContexts.pop_back_val();
3733 for (auto *SubDC : DC->decls()) {
3734 if (SubDC->isInvalidDecl())
3735 continue;
3736 if (auto *CTD = dyn_cast<ClassTemplateDecl>(SubDC)) {
3737 DeclContexts.push_back(CTD->getTemplatedDecl());
3738 llvm::append_range(DeclContexts, CTD->specializations());
3739 continue;
3740 }
3741 if (auto *DC = dyn_cast<DeclContext>(SubDC))
3742 DeclContexts.push_back(DC);
3743 if (auto *F = dyn_cast<FunctionDecl>(SubDC)) {
3744 F->addAttr(AA);
3745 continue;
3746 }
3747 }
3748 }
3749}
3750
3752 assert(isInOpenMPAssumeScope() && "Not in OpenMP assumes scope!");
3753 OMPAssumeScoped.pop_back();
3754}
3755
3757 Stmt *AStmt,
3758 SourceLocation StartLoc,
3759 SourceLocation EndLoc) {
3760 if (!AStmt)
3761 return StmtError();
3762
3763 return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
3764 AStmt);
3765}
3766
3769 ArrayRef<OMPClause *> ClauseList) {
3770 /// For target specific clauses, the requires directive cannot be
3771 /// specified after the handling of any of the target regions in the
3772 /// current compilation unit.
3773 ArrayRef<SourceLocation> TargetLocations =
3774 DSAStack->getEncounteredTargetLocs();
3775 SourceLocation AtomicLoc = DSAStack->getAtomicDirectiveLoc();
3776 if (!TargetLocations.empty() || !AtomicLoc.isInvalid()) {
3777 for (const OMPClause *CNew : ClauseList) {
3778 // Check if any of the requires clauses affect target regions.
3783 Diag(Loc, diag::err_omp_directive_before_requires)
3784 << "target" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3785 for (SourceLocation TargetLoc : TargetLocations) {
3786 Diag(TargetLoc, diag::note_omp_requires_encountered_directive)
3787 << "target";
3788 }
3789 } else if (!AtomicLoc.isInvalid() &&
3791 Diag(Loc, diag::err_omp_directive_before_requires)
3792 << "atomic" << getOpenMPClauseNameForDiag(CNew->getClauseKind());
3793 Diag(AtomicLoc, diag::note_omp_requires_encountered_directive)
3794 << "atomic";
3795 }
3796 }
3797 }
3798
3799 if (!DSAStack->hasDuplicateRequiresClause(ClauseList))
3801 getASTContext(), SemaRef.getCurLexicalContext(), Loc, ClauseList);
3802 return nullptr;
3803}
3804
3805static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack,
3806 const ValueDecl *D,
3807 const DSAStackTy::DSAVarData &DVar,
3808 bool IsLoopIterVar) {
3809 if (DVar.RefExpr) {
3810 SemaRef.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_explicit_dsa)
3811 << getOpenMPClauseNameForDiag(DVar.CKind);
3812 return;
3813 }
3814 enum {
3815 PDSA_StaticMemberShared,
3816 PDSA_StaticLocalVarShared,
3817 PDSA_LoopIterVarPrivate,
3818 PDSA_LoopIterVarLinear,
3819 PDSA_LoopIterVarLastprivate,
3820 PDSA_ConstVarShared,
3821 PDSA_GlobalVarShared,
3822 PDSA_TaskVarFirstprivate,
3823 PDSA_LocalVarPrivate,
3824 PDSA_Implicit
3825 } Reason = PDSA_Implicit;
3826 bool ReportHint = false;
3827 auto ReportLoc = D->getLocation();
3828 auto *VD = dyn_cast<VarDecl>(D);
3829 if (IsLoopIterVar) {
3830 if (DVar.CKind == OMPC_private)
3831 Reason = PDSA_LoopIterVarPrivate;
3832 else if (DVar.CKind == OMPC_lastprivate)
3833 Reason = PDSA_LoopIterVarLastprivate;
3834 else
3835 Reason = PDSA_LoopIterVarLinear;
3836 } else if (isOpenMPTaskingDirective(DVar.DKind) &&
3837 DVar.CKind == OMPC_firstprivate) {
3838 Reason = PDSA_TaskVarFirstprivate;
3839 ReportLoc = DVar.ImplicitDSALoc;
3840 } else if (VD && VD->isStaticLocal())
3841 Reason = PDSA_StaticLocalVarShared;
3842 else if (VD && VD->isStaticDataMember())
3843 Reason = PDSA_StaticMemberShared;
3844 else if (VD && VD->isFileVarDecl())
3845 Reason = PDSA_GlobalVarShared;
3846 else if (D->getType().isConstant(SemaRef.getASTContext()))
3847 Reason = PDSA_ConstVarShared;
3848 else if (VD && VD->isLocalVarDecl() && DVar.CKind == OMPC_private) {
3849 ReportHint = true;
3850 Reason = PDSA_LocalVarPrivate;
3851 }
3852 if (Reason != PDSA_Implicit) {
3853 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
3854 SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
3855 << Reason << ReportHint
3856 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
3857 } else if (DVar.ImplicitDSALoc.isValid()) {
3858 SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
3859 << getOpenMPClauseNameForDiag(DVar.CKind);
3860 }
3861}
3862
3865 bool IsAggregateOrDeclareTarget) {
3867 switch (M) {
3868 case OMPC_DEFAULTMAP_MODIFIER_alloc:
3869 case OMPC_DEFAULTMAP_MODIFIER_storage:
3870 Kind = OMPC_MAP_alloc;
3871 break;
3872 case OMPC_DEFAULTMAP_MODIFIER_to:
3873 Kind = OMPC_MAP_to;
3874 break;
3875 case OMPC_DEFAULTMAP_MODIFIER_from:
3876 Kind = OMPC_MAP_from;
3877 break;
3878 case OMPC_DEFAULTMAP_MODIFIER_tofrom:
3879 Kind = OMPC_MAP_tofrom;
3880 break;
3881 case OMPC_DEFAULTMAP_MODIFIER_present:
3882 // OpenMP 5.1 [2.21.7.3] defaultmap clause, Description]
3883 // If implicit-behavior is present, each variable referenced in the
3884 // construct in the category specified by variable-category is treated as if
3885 // it had been listed in a map clause with the map-type of alloc and
3886 // map-type-modifier of present.
3887 Kind = OMPC_MAP_alloc;
3888 break;
3889 case OMPC_DEFAULTMAP_MODIFIER_firstprivate:
3890 case OMPC_DEFAULTMAP_MODIFIER_private:
3892 llvm_unreachable("Unexpected defaultmap implicit behavior");
3893 case OMPC_DEFAULTMAP_MODIFIER_none:
3894 case OMPC_DEFAULTMAP_MODIFIER_default:
3896 // IsAggregateOrDeclareTarget could be true if:
3897 // 1. the implicit behavior for aggregate is tofrom
3898 // 2. it's a declare target link
3899 if (IsAggregateOrDeclareTarget) {
3900 Kind = OMPC_MAP_tofrom;
3901 break;
3902 }
3903 llvm_unreachable("Unexpected defaultmap implicit behavior");
3904 }
3905 assert(Kind != OMPC_MAP_unknown && "Expect map kind to be known");
3906 return Kind;
3907}
3908
3909namespace {
3910struct VariableImplicitInfo {
3911 static const unsigned MapKindNum = OMPC_MAP_unknown;
3912 static const unsigned DefaultmapKindNum = OMPC_DEFAULTMAP_unknown + 1;
3913
3914 llvm::SetVector<Expr *> Privates;
3915 llvm::SetVector<Expr *> Firstprivates;
3916 llvm::SetVector<Expr *> Mappings[DefaultmapKindNum][MapKindNum];
3917 llvm::SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
3918 MapModifiers[DefaultmapKindNum];
3919};
3920
3921class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
3922 DSAStackTy *Stack;
3923 Sema &SemaRef;
3924 OpenMPDirectiveKind DKind = OMPD_unknown;
3925 bool ErrorFound = false;
3926 bool TryCaptureCXXThisMembers = false;
3927 CapturedStmt *CS = nullptr;
3928
3929 VariableImplicitInfo ImpInfo;
3930 SemaOpenMP::VarsWithInheritedDSAType VarsWithInheritedDSA;
3931 llvm::SmallDenseSet<const ValueDecl *, 4> ImplicitDeclarations;
3932
3933 void VisitSubCaptures(OMPExecutableDirective *S) {
3934 // Check implicitly captured variables.
3935 if (!S->hasAssociatedStmt() || !S->getAssociatedStmt())
3936 return;
3937 if (S->getDirectiveKind() == OMPD_atomic ||
3938 S->getDirectiveKind() == OMPD_critical ||
3939 S->getDirectiveKind() == OMPD_section ||
3940 S->getDirectiveKind() == OMPD_master ||
3941 S->getDirectiveKind() == OMPD_masked ||
3942 S->getDirectiveKind() == OMPD_scope ||
3943 S->getDirectiveKind() == OMPD_assume ||
3944 isOpenMPLoopTransformationDirective(S->getDirectiveKind())) {
3945 Visit(S->getAssociatedStmt());
3946 return;
3947 }
3948 visitSubCaptures(S->getInnermostCapturedStmt());
3949 // Try to capture inner this->member references to generate correct mappings
3950 // and diagnostics.
3951 if (TryCaptureCXXThisMembers ||
3953 llvm::any_of(S->getInnermostCapturedStmt()->captures(),
3954 [](const CapturedStmt::Capture &C) {
3955 return C.capturesThis();
3956 }))) {
3957 bool SavedTryCaptureCXXThisMembers = TryCaptureCXXThisMembers;
3958 TryCaptureCXXThisMembers = true;
3959 Visit(S->getInnermostCapturedStmt()->getCapturedStmt());
3960 TryCaptureCXXThisMembers = SavedTryCaptureCXXThisMembers;
3961 }
3962 // In tasks firstprivates are not captured anymore, need to analyze them
3963 // explicitly.
3964 if (isOpenMPTaskingDirective(S->getDirectiveKind()) &&
3965 !isOpenMPTaskLoopDirective(S->getDirectiveKind())) {
3966 for (OMPClause *C : S->clauses())
3967 if (auto *FC = dyn_cast<OMPFirstprivateClause>(C)) {
3968 for (Expr *Ref : FC->varlist())
3969 Visit(Ref);
3970 }
3971 }
3972 }
3973
3974public:
3975 void VisitDeclRefExpr(DeclRefExpr *E) {
3976 if (TryCaptureCXXThisMembers || E->isTypeDependent() ||
3980 return;
3981 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
3982 // Check the datasharing rules for the expressions in the clauses.
3983 if (!CS || (isa<OMPCapturedExprDecl>(VD) && !CS->capturesVariable(VD) &&
3984 !Stack->getTopDSA(VD, /*FromParent=*/false).RefExpr &&
3985 !Stack->isImplicitDefaultFirstprivateFD(VD))) {
3986 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(VD))
3987 if (!CED->hasAttr<OMPCaptureNoInitAttr>()) {
3988 Visit(CED->getInit());
3989 return;
3990 }
3991 } else if (VD->isImplicit() || isa<OMPCapturedExprDecl>(VD))
3992 // Do not analyze internal variables and do not enclose them into
3993 // implicit clauses.
3994 if (!Stack->isImplicitDefaultFirstprivateFD(VD))
3995 return;
3996 VD = VD->getCanonicalDecl();
3997 // Skip internally declared variables.
3998 if (VD->hasLocalStorage() && CS && !CS->capturesVariable(VD) &&
3999 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4000 !Stack->isImplicitTaskFirstprivate(VD))
4001 return;
4002 // Skip allocators in uses_allocators clauses.
4003 if (Stack->isUsesAllocatorsDecl(VD))
4004 return;
4005
4006 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
4007 // Check if the variable has explicit DSA set and stop analysis if it so.
4008 if (DVar.RefExpr || !ImplicitDeclarations.insert(VD).second)
4009 return;
4010
4011 // Skip internally declared static variables.
4012 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
4013 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
4014 if (VD->hasGlobalStorage() && CS && !CS->capturesVariable(VD) &&
4015 (Stack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
4016 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) &&
4017 !Stack->isImplicitDefaultFirstprivateFD(VD) &&
4018 !Stack->isImplicitTaskFirstprivate(VD))
4019 return;
4020
4021 SourceLocation ELoc = E->getExprLoc();
4022 // The default(none) clause requires that each variable that is referenced
4023 // in the construct, and does not have a predetermined data-sharing
4024 // attribute, must have its data-sharing attribute explicitly determined
4025 // by being listed in a data-sharing attribute clause.
4026 if (DVar.CKind == OMPC_unknown &&
4027 (Stack->getDefaultDSA() == DSA_none ||
4028 Stack->getDefaultDSA() == DSA_private ||
4029 Stack->getDefaultDSA() == DSA_firstprivate) &&
4030 isImplicitOrExplicitTaskingRegion(DKind) &&
4031 VarsWithInheritedDSA.count(VD) == 0) {
4032 bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
4033 if (!InheritedDSA && (Stack->getDefaultDSA() == DSA_firstprivate ||
4034 Stack->getDefaultDSA() == DSA_private)) {
4035 DSAStackTy::DSAVarData DVar =
4036 Stack->getImplicitDSA(VD, /*FromParent=*/false);
4037 InheritedDSA = DVar.CKind == OMPC_unknown;
4038 }
4039 if (InheritedDSA)
4040 VarsWithInheritedDSA[VD] = E;
4041 if (Stack->getDefaultDSA() == DSA_none)
4042 return;
4043 }
4044
4045 // OpenMP 5.0 [2.19.7.2, defaultmap clause, Description]
4046 // If implicit-behavior is none, each variable referenced in the
4047 // construct that does not have a predetermined data-sharing attribute
4048 // and does not appear in a to or link clause on a declare target
4049 // directive must be listed in a data-mapping attribute clause, a
4050 // data-sharing attribute clause (including a data-sharing attribute
4051 // clause on a combined construct where target. is one of the
4052 // constituent constructs), or an is_device_ptr clause.
4053 OpenMPDefaultmapClauseKind ClauseKind =
4055 if (SemaRef.getLangOpts().OpenMP >= 50) {
4056 bool IsModifierNone = Stack->getDefaultmapModifier(ClauseKind) ==
4057 OMPC_DEFAULTMAP_MODIFIER_none;
4058 if (DVar.CKind == OMPC_unknown && IsModifierNone &&
4059 VarsWithInheritedDSA.count(VD) == 0 && !Res) {
4060 // Only check for data-mapping attribute and is_device_ptr here
4061 // since we have already make sure that the declaration does not
4062 // have a data-sharing attribute above
4063 if (!Stack->checkMappableExprComponentListsForDecl(
4064 VD, /*CurrentRegionOnly=*/true,
4066 MapExprComponents,
4068 auto MI = MapExprComponents.rbegin();
4069 auto ME = MapExprComponents.rend();
4070 return MI != ME && MI->getAssociatedDeclaration() == VD;
4071 })) {
4072 VarsWithInheritedDSA[VD] = E;
4073 return;
4074 }
4075 }
4076 }
4077 if (SemaRef.getLangOpts().OpenMP > 50) {
4078 bool IsModifierPresent = Stack->getDefaultmapModifier(ClauseKind) ==
4079 OMPC_DEFAULTMAP_MODIFIER_present;
4080 if (IsModifierPresent) {
4081 if (!llvm::is_contained(ImpInfo.MapModifiers[ClauseKind],
4082 OMPC_MAP_MODIFIER_present)) {
4083 ImpInfo.MapModifiers[ClauseKind].push_back(
4084 OMPC_MAP_MODIFIER_present);
4085 }
4086 }
4087 }
4088
4090 !Stack->isLoopControlVariable(VD).first) {
4091 if (!Stack->checkMappableExprComponentListsForDecl(
4092 VD, /*CurrentRegionOnly=*/true,
4094 StackComponents,
4096 if (SemaRef.LangOpts.OpenMP >= 50)
4097 return !StackComponents.empty();
4098 // Variable is used if it has been marked as an array, array
4099 // section, array shaping or the variable itself.
4100 return StackComponents.size() == 1 ||
4101 llvm::all_of(
4102 llvm::drop_begin(llvm::reverse(StackComponents)),
4103 [](const OMPClauseMappableExprCommon::
4104 MappableComponent &MC) {
4105 return MC.getAssociatedDeclaration() ==
4106 nullptr &&
4107 (isa<ArraySectionExpr>(
4108 MC.getAssociatedExpression()) ||
4109 isa<OMPArrayShapingExpr>(
4110 MC.getAssociatedExpression()) ||
4111 isa<ArraySubscriptExpr>(
4112 MC.getAssociatedExpression()));
4113 });
4114 })) {
4115 bool IsFirstprivate = false;
4116 // By default lambdas are captured as firstprivates.
4117 if (const auto *RD =
4119 IsFirstprivate = RD->isLambda();
4120 IsFirstprivate =
4121 IsFirstprivate || (Stack->mustBeFirstprivate(ClauseKind) && !Res);
4122 if (IsFirstprivate) {
4123 ImpInfo.Firstprivates.insert(E);
4124 } else {
4126 Stack->getDefaultmapModifier(ClauseKind);
4127 if (M == OMPC_DEFAULTMAP_MODIFIER_private) {
4128 ImpInfo.Privates.insert(E);
4129 } else {
4131 M, ClauseKind == OMPC_DEFAULTMAP_aggregate || Res);
4132 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4133 }
4134 }
4135 return;
4136 }
4137 }
4138
4139 // OpenMP [2.9.3.6, Restrictions, p.2]
4140 // A list item that appears in a reduction clause of the innermost
4141 // enclosing worksharing or parallel construct may not be accessed in an
4142 // explicit task.
4143 DVar = Stack->hasInnermostDSA(
4144 VD,
4145 [](OpenMPClauseKind C, bool AppliedToPointee) {
4146 return C == OMPC_reduction && !AppliedToPointee;
4147 },
4148 [](OpenMPDirectiveKind K) {
4149 return isOpenMPParallelDirective(K) ||
4151 },
4152 /*FromParent=*/true);
4153 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4154 ErrorFound = true;
4155 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4156 reportOriginalDsa(SemaRef, Stack, VD, DVar);
4157 return;
4158 }
4159
4160 // Define implicit data-sharing attributes for task.
4161 DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
4162 if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
4163 (((Stack->getDefaultDSA() == DSA_firstprivate &&
4164 DVar.CKind == OMPC_firstprivate) ||
4165 (Stack->getDefaultDSA() == DSA_private &&
4166 DVar.CKind == OMPC_private)) &&
4167 !DVar.RefExpr)) &&
4168 !Stack->isLoopControlVariable(VD).first) {
4169 if (Stack->getDefaultDSA() == DSA_private)
4170 ImpInfo.Privates.insert(E);
4171 else
4172 ImpInfo.Firstprivates.insert(E);
4173 return;
4174 }
4175
4176 // Store implicitly used globals with declare target link for parent
4177 // target.
4178 if (!isOpenMPTargetExecutionDirective(DKind) && Res &&
4179 *Res == OMPDeclareTargetDeclAttr::MT_Link) {
4180 Stack->addToParentTargetRegionLinkGlobals(E);
4181 return;
4182 }
4183 }
4184 }
4185 void VisitMemberExpr(MemberExpr *E) {
4186 if (E->isTypeDependent() || E->isValueDependent() ||
4188 return;
4189 auto *FD = dyn_cast<FieldDecl>(E->getMemberDecl());
4190 if (auto *TE = dyn_cast<CXXThisExpr>(E->getBase()->IgnoreParenCasts())) {
4191 if (!FD)
4192 return;
4193 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(FD, /*FromParent=*/false);
4194 // Check if the variable has explicit DSA set and stop analysis if it
4195 // so.
4196 if (DVar.RefExpr || !ImplicitDeclarations.insert(FD).second)
4197 return;
4198
4200 !Stack->isLoopControlVariable(FD).first &&
4201 !Stack->checkMappableExprComponentListsForDecl(
4202 FD, /*CurrentRegionOnly=*/true,
4204 StackComponents,
4206 return isa<CXXThisExpr>(
4207 cast<MemberExpr>(
4208 StackComponents.back().getAssociatedExpression())
4209 ->getBase()
4210 ->IgnoreParens());
4211 })) {
4212 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
4213 // A bit-field cannot appear in a map clause.
4214 //
4215 if (FD->isBitField())
4216 return;
4217
4218 // Check to see if the member expression is referencing a class that
4219 // has already been explicitly mapped
4220 if (Stack->isClassPreviouslyMapped(TE->getType()))
4221 return;
4222
4224 Stack->getDefaultmapModifier(OMPC_DEFAULTMAP_aggregate);
4225 OpenMPDefaultmapClauseKind ClauseKind =
4228 Modifier, /*IsAggregateOrDeclareTarget=*/true);
4229 ImpInfo.Mappings[ClauseKind][Kind].insert(E);
4230 return;
4231 }
4232
4233 SourceLocation ELoc = E->getExprLoc();
4234 // OpenMP [2.9.3.6, Restrictions, p.2]
4235 // A list item that appears in a reduction clause of the innermost
4236 // enclosing worksharing or parallel construct may not be accessed in
4237 // an explicit task.
4238 DVar = Stack->hasInnermostDSA(
4239 FD,
4240 [](OpenMPClauseKind C, bool AppliedToPointee) {
4241 return C == OMPC_reduction && !AppliedToPointee;
4242 },
4243 [](OpenMPDirectiveKind K) {
4244 return isOpenMPParallelDirective(K) ||
4246 },
4247 /*FromParent=*/true);
4248 if (isOpenMPTaskingDirective(DKind) && DVar.CKind == OMPC_reduction) {
4249 ErrorFound = true;
4250 SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task);
4251 reportOriginalDsa(SemaRef, Stack, FD, DVar);
4252 return;
4253 }
4254
4255 // Define implicit data-sharing attributes for task.
4256 DVar = Stack->getImplicitDSA(FD, /*FromParent=*/false);
4257 if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
4258 !Stack->isLoopControlVariable(FD).first) {
4259 // Check if there is a captured expression for the current field in the
4260 // region. Do not mark it as firstprivate unless there is no captured
4261 // expression.
4262 // TODO: try to make it firstprivate.
4263 if (DVar.CKind != OMPC_unknown)
4264 ImpInfo.Firstprivates.insert(E);
4265 }
4266 return;
4267 }
4270 if (!checkMapClauseExpressionBase(SemaRef, E, CurComponents, OMPC_map,
4271 DKind, /*NoDiagnose=*/true))
4272 return;
4273 const auto *VD = cast<ValueDecl>(
4274 CurComponents.back().getAssociatedDeclaration()->getCanonicalDecl());
4275 if (!Stack->checkMappableExprComponentListsForDecl(
4276 VD, /*CurrentRegionOnly=*/true,
4277 [&CurComponents](
4279 StackComponents,
4281 auto CCI = CurComponents.rbegin();
4282 auto CCE = CurComponents.rend();
4283 for (const auto &SC : llvm::reverse(StackComponents)) {
4284 // Do both expressions have the same kind?
4285 if (CCI->getAssociatedExpression()->getStmtClass() !=
4286 SC.getAssociatedExpression()->getStmtClass())
4287 if (!((isa<ArraySectionExpr>(
4288 SC.getAssociatedExpression()) ||
4289 isa<OMPArrayShapingExpr>(
4290 SC.getAssociatedExpression())) &&
4291 isa<ArraySubscriptExpr>(
4292 CCI->getAssociatedExpression())))
4293 return false;
4294
4295 const Decl *CCD = CCI->getAssociatedDeclaration();
4296 const Decl *SCD = SC.getAssociatedDeclaration();
4297 CCD = CCD ? CCD->getCanonicalDecl() : nullptr;
4298 SCD = SCD ? SCD->getCanonicalDecl() : nullptr;
4299 if (SCD != CCD)
4300 return false;
4301 std::advance(CCI, 1);
4302 if (CCI == CCE)
4303 break;
4304 }
4305 return true;
4306 })) {
4307 Visit(E->getBase());
4308 }
4309 } else if (!TryCaptureCXXThisMembers) {
4310 Visit(E->getBase());
4311 }
4312 }
4313 void VisitOMPExecutableDirective(OMPExecutableDirective *S) {
4314 for (OMPClause *C : S->clauses()) {
4315 // Skip analysis of arguments of private clauses for task|target
4316 // directives.
4317 if (isa_and_nonnull<OMPPrivateClause>(C))
4318 continue;
4319 // Skip analysis of arguments of implicitly defined firstprivate clause
4320 // for task|target directives.
4321 // Skip analysis of arguments of implicitly defined map clause for target
4322 // directives.
4324 C->isImplicit() && !isOpenMPTaskingDirective(DKind))) {
4325 for (Stmt *CC : C->children()) {
4326 if (CC)
4327 Visit(CC);
4328 }
4329 }
4330 }
4331 // Check implicitly captured variables.
4332 VisitSubCaptures(S);
4333 }
4334
4335 void VisitOMPCanonicalLoopNestTransformationDirective(
4336 OMPCanonicalLoopNestTransformationDirective *S) {
4337 // Loop transformation directives do not introduce data sharing
4338 VisitStmt(S);
4339 }
4340
4341 void VisitCallExpr(CallExpr *S) {
4342 for (Stmt *C : S->arguments()) {
4343 if (C) {
4344 // Check implicitly captured variables in the task-based directives to
4345 // check if they must be firstprivatized.
4346 Visit(C);
4347 }
4348 }
4349 if (Expr *Callee = S->getCallee()) {
4350 auto *CI = Callee->IgnoreParenImpCasts();
4351 if (auto *CE = dyn_cast<MemberExpr>(CI))
4352 Visit(CE->getBase());
4353 else if (auto *CE = dyn_cast<DeclRefExpr>(CI))
4354 Visit(CE);
4355 }
4356 }
4357 void VisitStmt(Stmt *S) {
4358 for (Stmt *C : S->children()) {
4359 if (C) {
4360 // Check implicitly captured variables in the task-based directives to
4361 // check if they must be firstprivatized.
4362 Visit(C);
4363 }
4364 }
4365 }
4366
4367 void visitSubCaptures(CapturedStmt *S) {
4368 for (const CapturedStmt::Capture &Cap : S->captures()) {
4369 if (!Cap.capturesVariable() && !Cap.capturesVariableByCopy())
4370 continue;
4371 VarDecl *VD = Cap.getCapturedVar();
4372 // Do not try to map the variable if it or its sub-component was mapped
4373 // already.
4375 Stack->checkMappableExprComponentListsForDecl(
4376 VD, /*CurrentRegionOnly=*/true,
4378 OpenMPClauseKind) { return true; }))
4379 continue;
4380 DeclRefExpr *DRE = buildDeclRefExpr(
4381 SemaRef, VD, VD->getType().getNonLValueExprType(SemaRef.Context),
4382 Cap.getLocation(), /*RefersToCapture=*/true);
4383 Visit(DRE);
4384 }
4385 }
4386 bool isErrorFound() const { return ErrorFound; }
4387 const VariableImplicitInfo &getImplicitInfo() const { return ImpInfo; }
4388 const SemaOpenMP::VarsWithInheritedDSAType &getVarsWithInheritedDSA() const {
4389 return VarsWithInheritedDSA;
4390 }
4391
4392 DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS)
4393 : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {
4394 DKind = S->getCurrentDirective();
4395 // Process declare target link variables for the target directives.
4397 for (DeclRefExpr *E : Stack->getLinkGlobals())
4398 Visit(E);
4399 }
4400 }
4401};
4402} // namespace
4403
4404static void handleDeclareVariantConstructTrait(DSAStackTy *Stack,
4405 OpenMPDirectiveKind DKind,
4406 bool ScopeEntry) {
4409 Traits.emplace_back(llvm::omp::TraitProperty::construct_target_target);
4410 if (isOpenMPTeamsDirective(DKind))
4411 Traits.emplace_back(llvm::omp::TraitProperty::construct_teams_teams);
4412 if (isOpenMPParallelDirective(DKind))
4413 Traits.emplace_back(llvm::omp::TraitProperty::construct_parallel_parallel);
4415 Traits.emplace_back(llvm::omp::TraitProperty::construct_for_for);
4416 if (isOpenMPSimdDirective(DKind))
4417 Traits.emplace_back(llvm::omp::TraitProperty::construct_simd_simd);
4418 Stack->handleConstructTrait(Traits, ScopeEntry);
4419}
4420
4421static SmallVector<SemaOpenMP::CapturedParamNameType>
4422getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing) {
4423 ASTContext &Context = SemaRef.getASTContext();
4424 QualType KmpInt32Ty =
4425 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4426 QualType KmpInt32PtrTy =
4427 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4429 std::make_pair(".global_tid.", KmpInt32PtrTy),
4430 std::make_pair(".bound_tid.", KmpInt32PtrTy),
4431 };
4432 if (LoopBoundSharing) {
4433 QualType KmpSizeTy = Context.getSizeType().withConst();
4434 Params.push_back(std::make_pair(".previous.lb.", KmpSizeTy));
4435 Params.push_back(std::make_pair(".previous.ub.", KmpSizeTy));
4436 }
4437
4438 // __context with shared vars
4439 Params.push_back(std::make_pair(StringRef(), QualType()));
4440 return Params;
4441}
4442
4443static SmallVector<SemaOpenMP::CapturedParamNameType>
4445 return getParallelRegionParams(SemaRef, /*LoopBoundSharing=*/false);
4446}
4447
4448static SmallVector<SemaOpenMP::CapturedParamNameType>
4450 ASTContext &Context = SemaRef.getASTContext();
4451 QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1).withConst();
4452 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4453 QualType KmpInt32PtrTy =
4454 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4455 QualType Args[] = {VoidPtrTy};
4457 EPI.Variadic = true;
4458 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4460 std::make_pair(".global_tid.", KmpInt32Ty),
4461 std::make_pair(".part_id.", KmpInt32PtrTy),
4462 std::make_pair(".privates.", VoidPtrTy),
4463 std::make_pair(
4464 ".copy_fn.",
4465 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4466 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4467 std::make_pair(StringRef(), QualType()) // __context with shared vars
4468 };
4469 return Params;
4470}
4471
4472static SmallVector<SemaOpenMP::CapturedParamNameType>
4474 ASTContext &Context = SemaRef.getASTContext();
4476 if (SemaRef.getLangOpts().OpenMPIsTargetDevice) {
4477 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4478 Params.push_back(std::make_pair(StringRef("dyn_ptr"), VoidPtrTy));
4479 }
4480 // __context with shared vars
4481 Params.push_back(std::make_pair(StringRef(), QualType()));
4482 return Params;
4483}
4484
4485static SmallVector<SemaOpenMP::CapturedParamNameType>
4488 std::make_pair(StringRef(), QualType()) // __context with shared vars
4489 };
4490 return Params;
4491}
4492
4493static SmallVector<SemaOpenMP::CapturedParamNameType>
4495 ASTContext &Context = SemaRef.getASTContext();
4496 QualType KmpInt32Ty =
4497 Context.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1).withConst();
4498 QualType KmpUInt64Ty =
4499 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0).withConst();
4500 QualType KmpInt64Ty =
4501 Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1).withConst();
4502 QualType VoidPtrTy = Context.VoidPtrTy.withConst().withRestrict();
4503 QualType KmpInt32PtrTy =
4504 Context.getPointerType(KmpInt32Ty).withConst().withRestrict();
4505 QualType Args[] = {VoidPtrTy};
4507 EPI.Variadic = true;
4508 QualType CopyFnType = Context.getFunctionType(Context.VoidTy, Args, EPI);
4510 std::make_pair(".global_tid.", KmpInt32Ty),
4511 std::make_pair(".part_id.", KmpInt32PtrTy),
4512 std::make_pair(".privates.", VoidPtrTy),
4513 std::make_pair(
4514 ".copy_fn.",
4515 Context.getPointerType(CopyFnType).withConst().withRestrict()),
4516 std::make_pair(".task_t.", Context.VoidPtrTy.withConst()),
4517 std::make_pair(".lb.", KmpUInt64Ty),
4518 std::make_pair(".ub.", KmpUInt64Ty),
4519 std::make_pair(".st.", KmpInt64Ty),
4520 std::make_pair(".liter.", KmpInt32Ty),
4521 std::make_pair(".reductions.", VoidPtrTy),
4522 std::make_pair(StringRef(), QualType()) // __context with shared vars
4523 };
4524 return Params;
4525}
4526
4528 Scope *CurScope, SourceLocation Loc) {
4530 getOpenMPCaptureRegions(Regions, DKind);
4531
4532 bool LoopBoundSharing = isOpenMPLoopBoundSharingDirective(DKind);
4533
4534 auto MarkAsInlined = [&](CapturedRegionScopeInfo *CSI) {
4535 CSI->TheCapturedDecl->addAttr(AlwaysInlineAttr::CreateImplicit(
4536 SemaRef.getASTContext(), {}, AlwaysInlineAttr::Keyword_forceinline));
4537 };
4538
4539 for (auto [Level, RKind] : llvm::enumerate(Regions)) {
4540 switch (RKind) {
4541 // All region kinds that can be returned from `getOpenMPCaptureRegions`
4542 // are listed here.
4543 case OMPD_parallel:
4545 Loc, CurScope, CR_OpenMP,
4546 getParallelRegionParams(SemaRef, LoopBoundSharing), Level);
4547 break;
4548 case OMPD_teams:
4549 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4550 getTeamsRegionParams(SemaRef), Level);
4551 break;
4552 case OMPD_task:
4553 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4554 getTaskRegionParams(SemaRef), Level);
4555 // Mark this captured region as inlined, because we don't use outlined
4556 // function directly.
4557 MarkAsInlined(SemaRef.getCurCapturedRegion());
4558 break;
4559 case OMPD_taskloop:
4560 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4561 getTaskloopRegionParams(SemaRef), Level);
4562 // Mark this captured region as inlined, because we don't use outlined
4563 // function directly.
4564 MarkAsInlined(SemaRef.getCurCapturedRegion());
4565 break;
4566 case OMPD_target:
4567 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4568 getTargetRegionParams(SemaRef), Level);
4569 break;
4570 case OMPD_unknown:
4571 SemaRef.ActOnCapturedRegionStart(Loc, CurScope, CR_OpenMP,
4572 getUnknownRegionParams(SemaRef));
4573 break;
4574 case OMPD_metadirective:
4575 case OMPD_nothing:
4576 default:
4577 llvm_unreachable("Unexpected capture region");
4578 }
4579 }
4580}
4581
4583 Scope *CurScope) {
4584 switch (DKind) {
4585 case OMPD_atomic:
4586 case OMPD_critical:
4587 case OMPD_masked:
4588 case OMPD_master:
4589 case OMPD_section:
4590 case OMPD_tile:
4591 case OMPD_stripe:
4592 case OMPD_unroll:
4593 case OMPD_reverse:
4594 case OMPD_interchange:
4595 case OMPD_fuse:
4596 case OMPD_assume:
4597 break;
4598 default:
4599 processCapturedRegions(SemaRef, DKind, CurScope,
4600 DSAStack->getConstructLoc());
4601 break;
4602 }
4603
4604 DSAStack->setContext(SemaRef.CurContext);
4605 handleDeclareVariantConstructTrait(DSAStack, DKind, /*ScopeEntry=*/true);
4606}
4607
4608int SemaOpenMP::getNumberOfConstructScopes(unsigned Level) const {
4609 return getOpenMPCaptureLevels(DSAStack->getDirective(Level));
4610}
4611
4614 getOpenMPCaptureRegions(CaptureRegions, DKind);
4615 return CaptureRegions.size();
4616}
4617
4619 Expr *CaptureExpr, bool WithInit,
4620 DeclContext *CurContext,
4621 bool AsExpression) {
4622 assert(CaptureExpr);
4623 ASTContext &C = S.getASTContext();
4624 Expr *Init = AsExpression ? CaptureExpr : CaptureExpr->IgnoreImpCasts();
4625 QualType Ty = Init->getType();
4626 if (CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue()) {
4627 if (S.getLangOpts().CPlusPlus) {
4628 Ty = C.getLValueReferenceType(Ty);
4629 } else {
4630 Ty = C.getPointerType(Ty);
4631 ExprResult Res =
4632 S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_AddrOf, Init);
4633 if (!Res.isUsable())
4634 return nullptr;
4635 Init = Res.get();
4636 }
4637 WithInit = true;
4638 }
4639 auto *CED = OMPCapturedExprDecl::Create(C, CurContext, Id, Ty,
4640 CaptureExpr->getBeginLoc());
4641 if (!WithInit)
4642 CED->addAttr(OMPCaptureNoInitAttr::CreateImplicit(C));
4643 CurContext->addHiddenDecl(CED);
4645 S.AddInitializerToDecl(CED, Init, /*DirectInit=*/false);
4646 return CED;
4647}
4648
4649static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
4650 bool WithInit) {
4652 if (VarDecl *VD = S.OpenMP().isOpenMPCapturedDecl(D))
4654 else
4655 CD = buildCaptureDecl(S, D->getIdentifier(), CaptureExpr, WithInit,
4656 S.CurContext,
4657 /*AsExpression=*/false);
4658 return buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4659 CaptureExpr->getExprLoc());
4660}
4661
4662static ExprResult buildCapture(Sema &S, Expr *CaptureExpr, DeclRefExpr *&Ref,
4663 StringRef Name) {
4664 CaptureExpr = S.DefaultLvalueConversion(CaptureExpr).get();
4665 if (!Ref) {
4667 S, &S.getASTContext().Idents.get(Name), CaptureExpr,
4668 /*WithInit=*/true, S.CurContext, /*AsExpression=*/true);
4669 Ref = buildDeclRefExpr(S, CD, CD->getType().getNonReferenceType(),
4670 CaptureExpr->getExprLoc());
4671 }
4672 ExprResult Res = Ref;
4673 if (!S.getLangOpts().CPlusPlus &&
4674 CaptureExpr->getObjectKind() == OK_Ordinary && CaptureExpr->isGLValue() &&
4675 Ref->getType()->isPointerType()) {
4676 Res = S.CreateBuiltinUnaryOp(CaptureExpr->getExprLoc(), UO_Deref, Ref);
4677 if (!Res.isUsable())
4678 return ExprError();
4679 }
4680 return S.DefaultLvalueConversion(Res.get());
4681}
4682
4683namespace {
4684// OpenMP directives parsed in this section are represented as a
4685// CapturedStatement with an associated statement. If a syntax error
4686// is detected during the parsing of the associated statement, the
4687// compiler must abort processing and close the CapturedStatement.
4688//
4689// Combined directives such as 'target parallel' have more than one
4690// nested CapturedStatements. This RAII ensures that we unwind out
4691// of all the nested CapturedStatements when an error is found.
4692class CaptureRegionUnwinderRAII {
4693private:
4694 Sema &S;
4695 bool &ErrorFound;
4696 OpenMPDirectiveKind DKind = OMPD_unknown;
4697
4698public:
4699 CaptureRegionUnwinderRAII(Sema &S, bool &ErrorFound,
4700 OpenMPDirectiveKind DKind)
4701 : S(S), ErrorFound(ErrorFound), DKind(DKind) {}
4702 ~CaptureRegionUnwinderRAII() {
4703 if (ErrorFound) {
4704 int ThisCaptureLevel = S.OpenMP().getOpenMPCaptureLevels(DKind);
4705 while (--ThisCaptureLevel >= 0)
4707 }
4708 }
4709};
4710} // namespace
4711
4713 // Capture variables captured by reference in lambdas for target-based
4714 // directives.
4715 if (!SemaRef.CurContext->isDependentContext() &&
4716 (isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective()) ||
4718 DSAStack->getCurrentDirective()))) {
4719 QualType Type = V->getType();
4720 if (const auto *RD = Type.getCanonicalType()
4721 .getNonReferenceType()
4722 ->getAsCXXRecordDecl()) {
4723 bool SavedForceCaptureByReferenceInTargetExecutable =
4724 DSAStack->isForceCaptureByReferenceInTargetExecutable();
4725 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4726 /*V=*/true);
4727 if (RD->isLambda()) {
4728 llvm::DenseMap<const ValueDecl *, FieldDecl *> Captures;
4729 FieldDecl *ThisCapture;
4730 RD->getCaptureFields(Captures, ThisCapture);
4731 for (const LambdaCapture &LC : RD->captures()) {
4732 if (LC.getCaptureKind() == LCK_ByRef) {
4733 VarDecl *VD = cast<VarDecl>(LC.getCapturedVar());
4734 DeclContext *VDC = VD->getDeclContext();
4735 if (!VDC->Encloses(SemaRef.CurContext))
4736 continue;
4737 SemaRef.MarkVariableReferenced(LC.getLocation(), VD);
4738 } else if (LC.getCaptureKind() == LCK_This) {
4739 QualType ThisTy = SemaRef.getCurrentThisType();
4740 if (!ThisTy.isNull() && getASTContext().typesAreCompatible(
4741 ThisTy, ThisCapture->getType()))
4742 SemaRef.CheckCXXThisCapture(LC.getLocation());
4743 }
4744 }
4745 }
4746 DSAStack->setForceCaptureByReferenceInTargetExecutable(
4747 SavedForceCaptureByReferenceInTargetExecutable);
4748 }
4749 }
4750}
4751
4753 const ArrayRef<OMPClause *> Clauses) {
4754 const OMPOrderedClause *Ordered = nullptr;
4755 const OMPOrderClause *Order = nullptr;
4756
4757 for (const OMPClause *Clause : Clauses) {
4758 if (Clause->getClauseKind() == OMPC_ordered)
4759 Ordered = cast<OMPOrderedClause>(Clause);
4760 else if (Clause->getClauseKind() == OMPC_order) {
4761 Order = cast<OMPOrderClause>(Clause);
4762 if (Order->getKind() != OMPC_ORDER_concurrent)
4763 Order = nullptr;
4764 }
4765 if (Ordered && Order)
4766 break;
4767 }
4768
4769 if (Ordered && Order) {
4770 S.Diag(Order->getKindKwLoc(),
4771 diag::err_omp_simple_clause_incompatible_with_ordered)
4772 << getOpenMPClauseNameForDiag(OMPC_order)
4773 << getOpenMPSimpleClauseTypeName(OMPC_order, OMPC_ORDER_concurrent)
4774 << SourceRange(Order->getBeginLoc(), Order->getEndLoc());
4775 S.Diag(Ordered->getBeginLoc(), diag::note_omp_ordered_param)
4776 << 0 << SourceRange(Ordered->getBeginLoc(), Ordered->getEndLoc());
4777 return true;
4778 }
4779 return false;
4780}
4781
4783 ArrayRef<OMPClause *> Clauses) {
4785 /*ScopeEntry=*/false);
4786 if (!isOpenMPCapturingDirective(DSAStack->getCurrentDirective()))
4787 return S;
4788
4789 bool ErrorFound = false;
4790 CaptureRegionUnwinderRAII CaptureRegionUnwinder(
4791 SemaRef, ErrorFound, DSAStack->getCurrentDirective());
4792 if (!S.isUsable()) {
4793 ErrorFound = true;
4794 return StmtError();
4795 }
4796
4798 getOpenMPCaptureRegions(CaptureRegions, DSAStack->getCurrentDirective());
4799 OMPOrderedClause *OC = nullptr;
4800 OMPScheduleClause *SC = nullptr;
4803 // This is required for proper codegen.
4804 for (OMPClause *Clause : Clauses) {
4805 if (!getLangOpts().OpenMPSimd &&
4806 (isOpenMPTaskingDirective(DSAStack->getCurrentDirective()) ||
4807 DSAStack->getCurrentDirective() == OMPD_target) &&
4808 Clause->getClauseKind() == OMPC_in_reduction) {
4809 // Capture taskgroup task_reduction descriptors inside the tasking regions
4810 // with the corresponding in_reduction items.
4811 auto *IRC = cast<OMPInReductionClause>(Clause);
4812 for (Expr *E : IRC->taskgroup_descriptors())
4813 if (E)
4814 SemaRef.MarkDeclarationsReferencedInExpr(E);
4815 }
4816 if (isOpenMPPrivate(Clause->getClauseKind()) ||
4817 Clause->getClauseKind() == OMPC_copyprivate ||
4818 (getLangOpts().OpenMPUseTLS &&
4819 getASTContext().getTargetInfo().isTLSSupported() &&
4820 Clause->getClauseKind() == OMPC_copyin)) {
4821 DSAStack->setForceVarCapturing(Clause->getClauseKind() == OMPC_copyin);
4822 // Mark all variables in private list clauses as used in inner region.
4823 for (Stmt *VarRef : Clause->children()) {
4824 if (auto *E = cast_or_null<Expr>(VarRef)) {
4825 SemaRef.MarkDeclarationsReferencedInExpr(E);
4826 }
4827 }
4828 DSAStack->setForceVarCapturing(/*V=*/false);
4829 } else if (CaptureRegions.size() > 1 ||
4830 CaptureRegions.back() != OMPD_unknown) {
4831 if (auto *C = OMPClauseWithPreInit::get(Clause))
4832 PICs.push_back(C);
4833 if (auto *C = OMPClauseWithPostUpdate::get(Clause)) {
4834 if (Expr *E = C->getPostUpdateExpr())
4835 SemaRef.MarkDeclarationsReferencedInExpr(E);
4836 }
4837 }
4838 if (Clause->getClauseKind() == OMPC_schedule)
4839 SC = cast<OMPScheduleClause>(Clause);
4840 else if (Clause->getClauseKind() == OMPC_ordered)
4841 OC = cast<OMPOrderedClause>(Clause);
4842 else if (Clause->getClauseKind() == OMPC_linear)
4843 LCs.push_back(cast<OMPLinearClause>(Clause));
4844 }
4845 // Capture allocator expressions if used.
4846 for (Expr *E : DSAStack->getInnerAllocators())
4847 SemaRef.MarkDeclarationsReferencedInExpr(E);
4848 // OpenMP, 2.7.1 Loop Construct, Restrictions
4849 // The nonmonotonic modifier cannot be specified if an ordered clause is
4850 // specified.
4851 if (SC &&
4852 (SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
4853 SC->getSecondScheduleModifier() ==
4854 OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
4855 OC) {
4856 Diag(SC->getFirstScheduleModifier() == OMPC_SCHEDULE_MODIFIER_nonmonotonic
4857 ? SC->getFirstScheduleModifierLoc()
4858 : SC->getSecondScheduleModifierLoc(),
4859 diag::err_omp_simple_clause_incompatible_with_ordered)
4860 << getOpenMPClauseNameForDiag(OMPC_schedule)
4861 << getOpenMPSimpleClauseTypeName(OMPC_schedule,
4862 OMPC_SCHEDULE_MODIFIER_nonmonotonic)
4863 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4864 ErrorFound = true;
4865 }
4866 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Restrictions.
4867 // If an order(concurrent) clause is present, an ordered clause may not appear
4868 // on the same directive.
4869 if (checkOrderedOrderSpecified(SemaRef, Clauses))
4870 ErrorFound = true;
4871 if (!LCs.empty() && OC && OC->getNumForLoops()) {
4872 for (const OMPLinearClause *C : LCs) {
4873 Diag(C->getBeginLoc(), diag::err_omp_linear_ordered)
4874 << SourceRange(OC->getBeginLoc(), OC->getEndLoc());
4875 }
4876 ErrorFound = true;
4877 }
4878 if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
4879 isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
4880 OC->getNumForLoops()) {
4881 unsigned OMPVersion = getLangOpts().OpenMP;
4882 Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
4883 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
4884 ErrorFound = true;
4885 }
4886 if (ErrorFound) {
4887 return StmtError();
4888 }
4889 StmtResult SR = S;
4890 unsigned CompletedRegions = 0;
4891 for (OpenMPDirectiveKind ThisCaptureRegion : llvm::reverse(CaptureRegions)) {
4892 // Mark all variables in private list clauses as used in inner region.
4893 // Required for proper codegen of combined directives.
4894 // TODO: add processing for other clauses.
4895 if (ThisCaptureRegion != OMPD_unknown) {
4896 for (const clang::OMPClauseWithPreInit *C : PICs) {
4897 OpenMPDirectiveKind CaptureRegion = C->getCaptureRegion();
4898 // Find the particular capture region for the clause if the
4899 // directive is a combined one with multiple capture regions.
4900 // If the directive is not a combined one, the capture region
4901 // associated with the clause is OMPD_unknown and is generated
4902 // only once.
4903 if (CaptureRegion == ThisCaptureRegion ||
4904 CaptureRegion == OMPD_unknown) {
4905 if (auto *DS = cast_or_null<DeclStmt>(C->getPreInitStmt())) {
4906 for (Decl *D : DS->decls())
4907 SemaRef.MarkVariableReferenced(D->getLocation(),
4908 cast<VarDecl>(D));
4909 }
4910 }
4911 }
4912 }
4913 if (ThisCaptureRegion == OMPD_target) {
4914 // Capture allocator traits in the target region. They are used implicitly
4915 // and, thus, are not captured by default.
4916 for (OMPClause *C : Clauses) {
4917 if (const auto *UAC = dyn_cast<OMPUsesAllocatorsClause>(C)) {
4918 for (unsigned I = 0, End = UAC->getNumberOfAllocators(); I < End;
4919 ++I) {
4920 OMPUsesAllocatorsClause::Data D = UAC->getAllocatorData(I);
4921 if (Expr *E = D.AllocatorTraits)
4922 SemaRef.MarkDeclarationsReferencedInExpr(E);
4923 }
4924 continue;
4925 }
4926 }
4927 }
4928 if (ThisCaptureRegion == OMPD_parallel) {
4929 // Capture temp arrays for inscan reductions and locals in aligned
4930 // clauses.
4931 for (OMPClause *C : Clauses) {
4932 if (auto *RC = dyn_cast<OMPReductionClause>(C)) {
4933 if (RC->getModifier() != OMPC_REDUCTION_inscan)
4934 continue;
4935 for (Expr *E : RC->copy_array_temps())
4936 if (E)
4937 SemaRef.MarkDeclarationsReferencedInExpr(E);
4938 }
4939 if (auto *AC = dyn_cast<OMPAlignedClause>(C)) {
4940 for (Expr *E : AC->varlist())
4941 SemaRef.MarkDeclarationsReferencedInExpr(E);
4942 }
4943 }
4944 }
4945 if (++CompletedRegions == CaptureRegions.size())
4946 DSAStack->setBodyComplete();
4947 SR = SemaRef.ActOnCapturedRegionEnd(SR.get());
4948 }
4949 return SR;
4950}
4951
4952static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion,
4953 OpenMPDirectiveKind CancelRegion,
4954 SourceLocation StartLoc) {
4955 // CancelRegion is only needed for cancel and cancellation_point.
4956 if (CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_cancellation_point)
4957 return false;
4958
4959 if (CancelRegion == OMPD_parallel || CancelRegion == OMPD_for ||
4960 CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
4961 return false;
4962
4963 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4964 SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
4965 << getOpenMPDirectiveName(CancelRegion, OMPVersion);
4966 return true;
4967}
4968
4969static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4970 OpenMPDirectiveKind CurrentRegion,
4971 const DeclarationNameInfo &CurrentName,
4972 OpenMPDirectiveKind CancelRegion,
4973 OpenMPBindClauseKind BindKind,
4974 SourceLocation StartLoc) {
4975 if (!Stack->getCurScope())
4976 return false;
4977
4978 OpenMPDirectiveKind ParentRegion = Stack->getParentDirective();
4979 OpenMPDirectiveKind OffendingRegion = ParentRegion;
4980 bool NestingProhibited = false;
4981 bool CloseNesting = true;
4982 bool OrphanSeen = false;
4983 enum {
4984 NoRecommend,
4985 ShouldBeInParallelRegion,
4986 ShouldBeInOrderedRegion,
4987 ShouldBeInTargetRegion,
4988 ShouldBeInTeamsRegion,
4989 ShouldBeInLoopSimdRegion,
4990 } Recommend = NoRecommend;
4991
4994 getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
4995 OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
4996 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
4997
4998 if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
5000 SemaRef.LangOpts)) {
5001 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
5002 << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5003 return true;
5004 }
5005 if (isOpenMPSimdDirective(ParentRegion) &&
5006 ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
5007 (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
5008 CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
5009 CurrentRegion != OMPD_scan))) {
5010 // OpenMP [2.16, Nesting of Regions]
5011 // OpenMP constructs may not be nested inside a simd region.
5012 // OpenMP [2.8.1,simd Construct, Restrictions]
5013 // An ordered construct with the simd clause is the only OpenMP
5014 // construct that can appear in the simd region.
5015 // Allowing a SIMD construct nested in another SIMD construct is an
5016 // extension. The OpenMP 4.5 spec does not allow it. Issue a warning
5017 // message.
5018 // OpenMP 5.0 [2.9.3.1, simd Construct, Restrictions]
5019 // The only OpenMP constructs that can be encountered during execution of
5020 // a simd region are the atomic construct, the loop construct, the simd
5021 // construct and the ordered construct with the simd clause.
5022 SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
5023 ? diag::err_omp_prohibited_region_simd
5024 : diag::warn_omp_nesting_simd)
5025 << (OMPVersion >= 50 ? 1 : 0);
5026 return CurrentRegion != OMPD_simd;
5027 }
5028 if (EnclosingConstruct == OMPD_atomic) {
5029 // OpenMP [2.16, Nesting of Regions]
5030 // OpenMP constructs may not be nested inside an atomic region.
5031 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_atomic);
5032 return true;
5033 }
5034 if (CurrentRegion == OMPD_section) {
5035 // OpenMP [2.7.2, sections Construct, Restrictions]
5036 // Orphaned section directives are prohibited. That is, the section
5037 // directives must appear within the sections construct and must not be
5038 // encountered elsewhere in the sections region.
5039 if (EnclosingConstruct != OMPD_sections) {
5040 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
5041 << (ParentRegion != OMPD_unknown)
5042 << getOpenMPDirectiveName(ParentRegion, OMPVersion);
5043 return true;
5044 }
5045 return false;
5046 }
5047 // Allow some constructs (except teams and cancellation constructs) to be
5048 // orphaned (they could be used in functions, called from OpenMP regions
5049 // with the required preconditions).
5050 if (ParentRegion == OMPD_unknown &&
5051 !isOpenMPNestingTeamsDirective(CurrentRegion) &&
5052 CurrentRegion != OMPD_cancellation_point &&
5053 CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
5054 return false;
5055 // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
5056 // for a detailed explanation
5057 if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
5058 (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
5059 (isOpenMPWorksharingDirective(ParentRegion) ||
5060 EnclosingConstruct == OMPD_loop)) {
5061 int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
5062 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5063 << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
5064 << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5065 return true;
5066 }
5067 if (CurrentRegion == OMPD_cancellation_point ||
5068 CurrentRegion == OMPD_cancel) {
5069 // OpenMP [2.16, Nesting of Regions]
5070 // A cancellation point construct for which construct-type-clause is
5071 // taskgroup must be nested inside a task construct. A cancellation
5072 // point construct for which construct-type-clause is not taskgroup must
5073 // be closely nested inside an OpenMP construct that matches the type
5074 // specified in construct-type-clause.
5075 // A cancel construct for which construct-type-clause is taskgroup must be
5076 // nested inside a task construct. A cancel construct for which
5077 // construct-type-clause is not taskgroup must be closely nested inside an
5078 // OpenMP construct that matches the type specified in
5079 // construct-type-clause.
5080 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(ParentRegion);
5081 if (CancelRegion == OMPD_taskgroup) {
5082 NestingProhibited =
5083 EnclosingConstruct != OMPD_task &&
5084 (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
5085 } else if (CancelRegion == OMPD_sections) {
5086 NestingProhibited = EnclosingConstruct != OMPD_section &&
5087 EnclosingConstruct != OMPD_sections;
5088 } else {
5089 NestingProhibited = CancelRegion != Leafs.back();
5090 }
5091 OrphanSeen = ParentRegion == OMPD_unknown;
5092 } else if (CurrentRegion == OMPD_master || CurrentRegion == OMPD_masked) {
5093 // OpenMP 5.1 [2.22, Nesting of Regions]
5094 // A masked region may not be closely nested inside a worksharing, loop,
5095 // atomic, task, or taskloop region.
5096 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5097 isOpenMPGenericLoopDirective(ParentRegion) ||
5098 isOpenMPTaskingDirective(ParentRegion);
5099 } else if (CurrentRegion == OMPD_critical && CurrentName.getName()) {
5100 // OpenMP [2.16, Nesting of Regions]
5101 // A critical region may not be nested (closely or otherwise) inside a
5102 // critical region with the same name. Note that this restriction is not
5103 // sufficient to prevent deadlock.
5104 SourceLocation PreviousCriticalLoc;
5105 bool DeadLock = Stack->hasDirective(
5106 [CurrentName, &PreviousCriticalLoc](OpenMPDirectiveKind K,
5107 const DeclarationNameInfo &DNI,
5108 SourceLocation Loc) {
5109 if (K == OMPD_critical && DNI.getName() == CurrentName.getName()) {
5110 PreviousCriticalLoc = Loc;
5111 return true;
5112 }
5113 return false;
5114 },
5115 false /* skip top directive */);
5116 if (DeadLock) {
5117 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_critical_same_name)
5118 << CurrentName.getName();
5119 if (PreviousCriticalLoc.isValid())
5120 SemaRef.Diag(PreviousCriticalLoc,
5121 diag::note_omp_previous_critical_region);
5122 return true;
5123 }
5124 } else if (CurrentRegion == OMPD_barrier || CurrentRegion == OMPD_scope) {
5125 // OpenMP 5.1 [2.22, Nesting of Regions]
5126 // A scope region may not be closely nested inside a worksharing, loop,
5127 // task, taskloop, critical, ordered, atomic, or masked region.
5128 // OpenMP 5.1 [2.22, Nesting of Regions]
5129 // A barrier region may not be closely nested inside a worksharing, loop,
5130 // task, taskloop, critical, ordered, atomic, or masked region.
5131 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5132 isOpenMPGenericLoopDirective(ParentRegion) ||
5133 isOpenMPTaskingDirective(ParentRegion) ||
5134 llvm::is_contained({OMPD_masked, OMPD_master,
5135 OMPD_critical, OMPD_ordered},
5136 EnclosingConstruct);
5137 } else if (isOpenMPWorksharingDirective(CurrentRegion) &&
5138 !isOpenMPParallelDirective(CurrentRegion) &&
5139 !isOpenMPTeamsDirective(CurrentRegion)) {
5140 // OpenMP 5.1 [2.22, Nesting of Regions]
5141 // A loop region that binds to a parallel region or a worksharing region
5142 // may not be closely nested inside a worksharing, loop, task, taskloop,
5143 // critical, ordered, atomic, or masked region.
5144 NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
5145 isOpenMPGenericLoopDirective(ParentRegion) ||
5146 isOpenMPTaskingDirective(ParentRegion) ||
5147 llvm::is_contained({OMPD_masked, OMPD_master,
5148 OMPD_critical, OMPD_ordered},
5149 EnclosingConstruct);
5150 Recommend = ShouldBeInParallelRegion;
5151 } else if (CurrentRegion == OMPD_ordered) {
5152 // OpenMP [2.16, Nesting of Regions]
5153 // An ordered region may not be closely nested inside a critical,
5154 // atomic, or explicit task region.
5155 // An ordered region must be closely nested inside a loop region (or
5156 // parallel loop region) with an ordered clause.
5157 // OpenMP [2.8.1,simd Construct, Restrictions]
5158 // An ordered construct with the simd clause is the only OpenMP construct
5159 // that can appear in the simd region.
5160 NestingProhibited = EnclosingConstruct == OMPD_critical ||
5161 isOpenMPTaskingDirective(ParentRegion) ||
5162 !(isOpenMPSimdDirective(ParentRegion) ||
5163 Stack->isParentOrderedRegion());
5164 Recommend = ShouldBeInOrderedRegion;
5165 } else if (isOpenMPNestingTeamsDirective(CurrentRegion)) {
5166 // OpenMP [2.16, Nesting of Regions]
5167 // If specified, a teams construct must be contained within a target
5168 // construct.
5169 NestingProhibited =
5170 (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
5171 (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
5172 EnclosingConstruct != OMPD_target);
5173 OrphanSeen = ParentRegion == OMPD_unknown;
5174 Recommend = ShouldBeInTargetRegion;
5175 } else if (CurrentRegion == OMPD_scan) {
5176 if (OMPVersion >= 50) {
5177 // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
5178 // simd, or for simd. This has to take into account combined directives.
5179 // In 5.2 this seems to be implied by the fact that the specified
5180 // separated constructs are do, for, and simd.
5181 NestingProhibited = !llvm::is_contained(
5182 {OMPD_for, OMPD_simd, OMPD_for_simd}, EnclosingConstruct);
5183 } else {
5184 NestingProhibited = true;
5185 }
5186 OrphanSeen = ParentRegion == OMPD_unknown;
5187 Recommend = ShouldBeInLoopSimdRegion;
5188 }
5189 if (!NestingProhibited && !isOpenMPTargetExecutionDirective(CurrentRegion) &&
5190 !isOpenMPTargetDataManagementDirective(CurrentRegion) &&
5191 EnclosingConstruct == OMPD_teams) {
5192 // OpenMP [5.1, 2.22, Nesting of Regions]
5193 // distribute, distribute simd, distribute parallel worksharing-loop,
5194 // distribute parallel worksharing-loop SIMD, loop, parallel regions,
5195 // including any parallel regions arising from combined constructs,
5196 // omp_get_num_teams() regions, and omp_get_team_num() regions are the
5197 // only OpenMP regions that may be strictly nested inside the teams
5198 // region.
5199 //
5200 // As an extension, we permit atomic within teams as well.
5201 NestingProhibited = !isOpenMPParallelDirective(CurrentRegion) &&
5202 !isOpenMPDistributeDirective(CurrentRegion) &&
5203 CurrentRegion != OMPD_loop &&
5204 !(SemaRef.getLangOpts().OpenMPExtensions &&
5205 CurrentRegion == OMPD_atomic);
5206 Recommend = ShouldBeInParallelRegion;
5207 }
5208 if (!NestingProhibited && CurrentRegion == OMPD_loop) {
5209 // OpenMP [5.1, 2.11.7, loop Construct, Restrictions]
5210 // If the bind clause is present on the loop construct and binding is
5211 // teams then the corresponding loop region must be strictly nested inside
5212 // a teams region.
5213 NestingProhibited =
5214 BindKind == OMPC_BIND_teams && EnclosingConstruct != OMPD_teams;
5215 Recommend = ShouldBeInTeamsRegion;
5216 }
5217 if (!NestingProhibited && isOpenMPNestingDistributeDirective(CurrentRegion)) {
5218 // OpenMP 4.5 [2.17 Nesting of Regions]
5219 // The region associated with the distribute construct must be strictly
5220 // nested inside a teams region
5221 NestingProhibited = EnclosingConstruct != OMPD_teams;
5222 Recommend = ShouldBeInTeamsRegion;
5223 }
5224 if (!NestingProhibited &&
5225 (isOpenMPTargetExecutionDirective(CurrentRegion) ||
5226 isOpenMPTargetDataManagementDirective(CurrentRegion))) {
5227 // OpenMP 4.5 [2.17 Nesting of Regions]
5228 // If a target, target update, target data, target enter data, or
5229 // target exit data construct is encountered during execution of a
5230 // target region, the behavior is unspecified.
5231 NestingProhibited = Stack->hasDirective(
5232 [&OffendingRegion](OpenMPDirectiveKind K, const DeclarationNameInfo &,
5235 OffendingRegion = K;
5236 return true;
5237 }
5238 return false;
5239 },
5240 false /* don't skip top directive */);
5241 CloseNesting = false;
5242 }
5243 if (NestingProhibited) {
5244 if (OrphanSeen) {
5245 SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
5246 << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
5247 } else {
5248 SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
5249 << CloseNesting << getOpenMPDirectiveName(OffendingRegion, OMPVersion)
5250 << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
5251 }
5252 return true;
5253 }
5254 return false;
5255}
5256
5262 ArrayRef<OMPClause *> Clauses,
5263 ArrayRef<OpenMPDirectiveKind> AllowedNameModifiers) {
5264 bool ErrorFound = false;
5265 unsigned NamedModifiersNumber = 0;
5266 llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
5267 FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
5268 SmallVector<SourceLocation, 4> NameModifierLoc;
5269 unsigned OMPVersion = S.getLangOpts().OpenMP;
5270 for (const OMPClause *C : Clauses) {
5271 if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
5272 // At most one if clause without a directive-name-modifier can appear on
5273 // the directive.
5274 OpenMPDirectiveKind CurNM = IC->getNameModifier();
5275 auto &FNM = FoundNameModifiers[CurNM];
5276 if (FNM) {
5277 S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
5278 << getOpenMPDirectiveName(Kind, OMPVersion)
5279 << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
5280 << getOpenMPDirectiveName(CurNM, OMPVersion);
5281 ErrorFound = true;
5282 } else if (CurNM != OMPD_unknown) {
5283 NameModifierLoc.push_back(IC->getNameModifierLoc());
5284 ++NamedModifiersNumber;
5285 }
5286 FNM = IC;
5287 if (CurNM == OMPD_unknown)
5288 continue;
5289 // Check if the specified name modifier is allowed for the current
5290 // directive.
5291 // At most one if clause with the particular directive-name-modifier can
5292 // appear on the directive.
5293 if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
5294 S.Diag(IC->getNameModifierLoc(),
5295 diag::err_omp_wrong_if_directive_name_modifier)
5296 << getOpenMPDirectiveName(CurNM, OMPVersion)
5297 << getOpenMPDirectiveName(Kind, OMPVersion);
5298 ErrorFound = true;
5299 }
5300 }
5301 }
5302 // If any if clause on the directive includes a directive-name-modifier then
5303 // all if clauses on the directive must include a directive-name-modifier.
5304 if (FoundNameModifiers[OMPD_unknown] && NamedModifiersNumber > 0) {
5305 if (NamedModifiersNumber == AllowedNameModifiers.size()) {
5306 S.Diag(FoundNameModifiers[OMPD_unknown]->getBeginLoc(),
5307 diag::err_omp_no_more_if_clause);
5308 } else {
5309 std::string Values;
5310 std::string Sep(", ");
5311 unsigned AllowedCnt = 0;
5312 unsigned TotalAllowedNum =
5313 AllowedNameModifiers.size() - NamedModifiersNumber;
5314 for (unsigned Cnt = 0, End = AllowedNameModifiers.size(); Cnt < End;
5315 ++Cnt) {
5316 OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
5317 if (!FoundNameModifiers[NM]) {
5318 Values += "'";
5319 Values += getOpenMPDirectiveName(NM, OMPVersion);
5320 Values += "'";
5321 if (AllowedCnt + 2 == TotalAllowedNum)
5322 Values += " or ";
5323 else if (AllowedCnt + 1 != TotalAllowedNum)
5324 Values += Sep;
5325 ++AllowedCnt;
5326 }
5327 }
5328 S.Diag(FoundNameModifiers[OMPD_unknown]->getCondition()->getBeginLoc(),
5329 diag::err_omp_unnamed_if_clause)
5330 << (TotalAllowedNum > 1) << Values;
5331 }
5332 for (SourceLocation Loc : NameModifierLoc) {
5333 S.Diag(Loc, diag::note_omp_previous_named_if_clause);
5334 }
5335 ErrorFound = true;
5336 }
5337 return ErrorFound;
5338}
5339
5340static std::pair<ValueDecl *, bool>
5342 SourceRange &ERange, bool AllowArraySection,
5343 bool AllowAssumedSizeArray, StringRef DiagType) {
5344 if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
5346 return std::make_pair(nullptr, true);
5347
5348 // OpenMP [3.1, C/C++]
5349 // A list item is a variable name.
5350 // OpenMP [2.9.3.3, Restrictions, p.1]
5351 // A variable that is part of another variable (as an array or
5352 // structure element) cannot appear in a private clause.
5353 //
5354 // OpenMP [6.0]
5355 // 5.2.5 Array Sections, p. 166, L28-29
5356 // When the length is absent and the size of the dimension is not known,
5357 // the array section is an assumed-size array.
5358 // 2 Glossary, p. 23, L4-6
5359 // assumed-size array
5360 // For C/C++, an array section for which the length is absent and the
5361 // size of the dimensions is not known.
5362 // 5.2.5 Array Sections, p. 168, L11
5363 // An assumed-size array can appear only in clauses for which it is
5364 // explicitly allowed.
5365 // 7.4 List Item Privatization, Restrictions, p. 222, L15
5366 // Assumed-size arrays must not be privatized.
5367 RefExpr = RefExpr->IgnoreParens();
5368 enum {
5369 NoArrayExpr = -1,
5370 ArraySubscript = 0,
5371 OMPArraySection = 1
5372 } IsArrayExpr = NoArrayExpr;
5373 if (AllowArraySection) {
5374 if (auto *ASE = dyn_cast_or_null<ArraySubscriptExpr>(RefExpr)) {
5375 Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
5376 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5377 Base = TempASE->getBase()->IgnoreParenImpCasts();
5378 RefExpr = Base;
5379 IsArrayExpr = ArraySubscript;
5380 } else if (auto *OASE = dyn_cast_or_null<ArraySectionExpr>(RefExpr)) {
5381 Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
5382 if (S.getLangOpts().OpenMP >= 60 && !AllowAssumedSizeArray &&
5383 OASE->getColonLocFirst().isValid() && !OASE->getLength()) {
5385 if (BaseType.isNull() || (!BaseType->isConstantArrayType() &&
5386 !BaseType->isVariableArrayType())) {
5387 S.Diag(OASE->getColonLocFirst(),
5388 diag::err_omp_section_length_undefined)
5389 << (!BaseType.isNull() && BaseType->isArrayType());
5390 return std::make_pair(nullptr, false);
5391 }
5392 }
5393 while (auto *TempOASE = dyn_cast<ArraySectionExpr>(Base))
5394 Base = TempOASE->getBase()->IgnoreParenImpCasts();
5395 while (auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
5396 Base = TempASE->getBase()->IgnoreParenImpCasts();
5397 RefExpr = Base;
5398 IsArrayExpr = OMPArraySection;
5399 }
5400 }
5401 ELoc = RefExpr->getExprLoc();
5402 ERange = RefExpr->getSourceRange();
5403 RefExpr = RefExpr->IgnoreParenImpCasts();
5404 auto *DE = dyn_cast_or_null<DeclRefExpr>(RefExpr);
5405 auto *ME = dyn_cast_or_null<MemberExpr>(RefExpr);
5406 if ((!DE || !isa<VarDecl>(DE->getDecl())) &&
5407 (S.getCurrentThisType().isNull() || !ME ||
5408 !isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()) ||
5409 !isa<FieldDecl>(ME->getMemberDecl()))) {
5410 if (IsArrayExpr != NoArrayExpr) {
5411 S.Diag(ELoc, diag::err_omp_expected_base_var_name)
5412 << IsArrayExpr << ERange;
5413 } else if (!DiagType.empty()) {
5414 unsigned DiagSelect = S.getLangOpts().CPlusPlus
5415 ? (S.getCurrentThisType().isNull() ? 1 : 2)
5416 : 0;
5417 S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
5418 << DiagSelect << DiagType << ERange;
5419 } else {
5420 S.Diag(ELoc,
5421 AllowArraySection
5422 ? diag::err_omp_expected_var_name_member_expr_or_array_item
5423 : diag::err_omp_expected_var_name_member_expr)
5424 << (S.getCurrentThisType().isNull() ? 0 : 1) << ERange;
5425 }
5426 return std::make_pair(nullptr, false);
5427 }
5428 return std::make_pair(
5429 getCanonicalDecl(DE ? DE->getDecl() : ME->getMemberDecl()), false);
5430}
5431
5432namespace {
5433/// Checks if the allocator is used in uses_allocators clause to be allowed in
5434/// target regions.
5435class AllocatorChecker final : public ConstStmtVisitor<AllocatorChecker, bool> {
5436 DSAStackTy *S = nullptr;
5437
5438public:
5439 bool VisitDeclRefExpr(const DeclRefExpr *E) {
5440 return S->isUsesAllocatorsDecl(E->getDecl())
5441 .value_or(DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait) ==
5442 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait;
5443 }
5444 bool VisitStmt(const Stmt *S) {
5445 for (const Stmt *Child : S->children()) {
5446 if (Child && Visit(Child))
5447 return true;
5448 }
5449 return false;
5450 }
5451 explicit AllocatorChecker(DSAStackTy *S) : S(S) {}
5452};
5453} // namespace
5454
5455static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
5456 ArrayRef<OMPClause *> Clauses) {
5457 assert(!S.CurContext->isDependentContext() &&
5458 "Expected non-dependent context.");
5459 auto AllocateRange =
5460 llvm::make_filter_range(Clauses, OMPAllocateClause::classof);
5461 llvm::DenseMap<CanonicalDeclPtr<Decl>, CanonicalDeclPtr<VarDecl>> DeclToCopy;
5462 auto PrivateRange = llvm::make_filter_range(Clauses, [](const OMPClause *C) {
5463 return isOpenMPPrivate(C->getClauseKind());
5464 });
5465 for (OMPClause *Cl : PrivateRange) {
5467 if (Cl->getClauseKind() == OMPC_private) {
5468 auto *PC = cast<OMPPrivateClause>(Cl);
5469 I = PC->private_copies().begin();
5470 It = PC->varlist_begin();
5471 Et = PC->varlist_end();
5472 } else if (Cl->getClauseKind() == OMPC_firstprivate) {
5473 auto *PC = cast<OMPFirstprivateClause>(Cl);
5474 I = PC->private_copies().begin();
5475 It = PC->varlist_begin();
5476 Et = PC->varlist_end();
5477 } else if (Cl->getClauseKind() == OMPC_lastprivate) {
5478 auto *PC = cast<OMPLastprivateClause>(Cl);
5479 I = PC->private_copies().begin();
5480 It = PC->varlist_begin();
5481 Et = PC->varlist_end();
5482 } else if (Cl->getClauseKind() == OMPC_linear) {
5483 auto *PC = cast<OMPLinearClause>(Cl);
5484 I = PC->privates().begin();
5485 It = PC->varlist_begin();
5486 Et = PC->varlist_end();
5487 } else if (Cl->getClauseKind() == OMPC_reduction) {
5488 auto *PC = cast<OMPReductionClause>(Cl);
5489 I = PC->privates().begin();
5490 It = PC->varlist_begin();
5491 Et = PC->varlist_end();
5492 } else if (Cl->getClauseKind() == OMPC_task_reduction) {
5493 auto *PC = cast<OMPTaskReductionClause>(Cl);
5494 I = PC->privates().begin();
5495 It = PC->varlist_begin();
5496 Et = PC->varlist_end();
5497 } else if (Cl->getClauseKind() == OMPC_in_reduction) {
5498 auto *PC = cast<OMPInReductionClause>(Cl);
5499 I = PC->privates().begin();
5500 It = PC->varlist_begin();
5501 Et = PC->varlist_end();
5502 } else {
5503 llvm_unreachable("Expected private clause.");
5504 }
5505 for (Expr *E : llvm::make_range(It, Et)) {
5506 if (!*I) {
5507 ++I;
5508 continue;
5509 }
5510 SourceLocation ELoc;
5511 SourceRange ERange;
5512 Expr *SimpleRefExpr = E;
5513 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
5514 /*AllowArraySection=*/true);
5515 DeclToCopy.try_emplace(Res.first,
5516 cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()));
5517 ++I;
5518 }
5519 }
5520 for (OMPClause *C : AllocateRange) {
5521 auto *AC = cast<OMPAllocateClause>(C);
5522 if (S.getLangOpts().OpenMP >= 50 &&
5523 !Stack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>() &&
5524 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()) &&
5525 AC->getAllocator()) {
5526 Expr *Allocator = AC->getAllocator();
5527 // OpenMP, 2.12.5 target Construct
5528 // Memory allocators that do not appear in a uses_allocators clause cannot
5529 // appear as an allocator in an allocate clause or be used in the target
5530 // region unless a requires directive with the dynamic_allocators clause
5531 // is present in the same compilation unit.
5532 AllocatorChecker Checker(Stack);
5533 if (Checker.Visit(Allocator))
5534 S.Diag(Allocator->getExprLoc(),
5535 diag::err_omp_allocator_not_in_uses_allocators)
5536 << Allocator->getSourceRange();
5537 }
5538 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind =
5539 getAllocatorKind(S, Stack, AC->getAllocator());
5540 // OpenMP, 2.11.4 allocate Clause, Restrictions.
5541 // For task, taskloop or target directives, allocation requests to memory
5542 // allocators with the trait access set to thread result in unspecified
5543 // behavior.
5544 if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
5545 (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
5546 isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
5547 unsigned OMPVersion = S.getLangOpts().OpenMP;
5548 S.Diag(AC->getAllocator()->getExprLoc(),
5549 diag::warn_omp_allocate_thread_on_task_target_directive)
5550 << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
5551 }
5552 for (Expr *E : AC->varlist()) {
5553 SourceLocation ELoc;
5554 SourceRange ERange;
5555 Expr *SimpleRefExpr = E;
5556 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
5557 ValueDecl *VD = Res.first;
5558 if (!VD)
5559 continue;
5560 DSAStackTy::DSAVarData Data = Stack->getTopDSA(VD, /*FromParent=*/false);
5561 if (!isOpenMPPrivate(Data.CKind)) {
5562 S.Diag(E->getExprLoc(),
5563 diag::err_omp_expected_private_copy_for_allocate);
5564 continue;
5565 }
5566 VarDecl *PrivateVD = DeclToCopy[VD];
5567 if (checkPreviousOMPAllocateAttribute(S, Stack, E, PrivateVD,
5568 AllocatorKind, AC->getAllocator()))
5569 continue;
5570 applyOMPAllocateAttribute(S, PrivateVD, AllocatorKind, AC->getAllocator(),
5571 AC->getAlignment(), E->getSourceRange());
5572 }
5573 }
5574}
5575
5576namespace {
5577/// Rewrite statements and expressions for Sema \p Actions CurContext.
5578///
5579/// Used to wrap already parsed statements/expressions into a new CapturedStmt
5580/// context. DeclRefExpr used inside the new context are changed to refer to the
5581/// captured variable instead.
5582class CaptureVars : public TreeTransform<CaptureVars> {
5583 using BaseTransform = TreeTransform<CaptureVars>;
5584
5585public:
5586 CaptureVars(Sema &Actions) : BaseTransform(Actions) {}
5587
5588 bool AlwaysRebuild() { return true; }
5589};
5590} // namespace
5591
5592static VarDecl *precomputeExpr(Sema &Actions,
5593 SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
5594 StringRef Name) {
5595 Expr *NewE = AssertSuccess(CaptureVars(Actions).TransformExpr(E));
5596 VarDecl *NewVar = buildVarDecl(Actions, {}, NewE->getType(), Name, nullptr,
5597 dyn_cast<DeclRefExpr>(E->IgnoreImplicit()));
5598 auto *NewDeclStmt = cast<DeclStmt>(AssertSuccess(
5599 Actions.ActOnDeclStmt(Actions.ConvertDeclToDeclGroup(NewVar), {}, {})));
5600 Actions.AddInitializerToDecl(NewDeclStmt->getSingleDecl(), NewE, false);
5601 BodyStmts.push_back(NewDeclStmt);
5602 return NewVar;
5603}
5604
5605/// Create a closure that computes the number of iterations of a loop.
5606///
5607/// \param Actions The Sema object.
5608/// \param LogicalTy Type for the logical iteration number.
5609/// \param Rel Comparison operator of the loop condition.
5610/// \param StartExpr Value of the loop counter at the first iteration.
5611/// \param StopExpr Expression the loop counter is compared against in the loop
5612/// condition. \param StepExpr Amount of increment after each iteration.
5613///
5614/// \return Closure (CapturedStmt) of the distance calculation.
5615static CapturedStmt *buildDistanceFunc(Sema &Actions, QualType LogicalTy,
5617 Expr *StartExpr, Expr *StopExpr,
5618 Expr *StepExpr) {
5619 ASTContext &Ctx = Actions.getASTContext();
5620 TypeSourceInfo *LogicalTSI = Ctx.getTrivialTypeSourceInfo(LogicalTy);
5621
5622 // Captured regions currently don't support return values, we use an
5623 // out-parameter instead. All inputs are implicit captures.
5624 // TODO: Instead of capturing each DeclRefExpr occurring in
5625 // StartExpr/StopExpr/Step, these could also be passed as a value capture.
5626 QualType ResultTy = Ctx.getLValueReferenceType(LogicalTy);
5627 Sema::CapturedParamNameType Params[] = {{"Distance", ResultTy},
5628 {StringRef(), QualType()}};
5629 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5630
5631 Stmt *Body;
5632 {
5633 Sema::CompoundScopeRAII CompoundScope(Actions);
5635
5636 // Get the LValue expression for the result.
5637 ImplicitParamDecl *DistParam = CS->getParam(0);
5638 DeclRefExpr *DistRef = Actions.BuildDeclRefExpr(
5639 DistParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5640
5641 SmallVector<Stmt *, 4> BodyStmts;
5642
5643 // Capture all referenced variable references.
5644 // TODO: Instead of computing NewStart/NewStop/NewStep inside the
5645 // CapturedStmt, we could compute them before and capture the result, to be
5646 // used jointly with the LoopVar function.
5647 VarDecl *NewStart = precomputeExpr(Actions, BodyStmts, StartExpr, ".start");
5648 VarDecl *NewStop = precomputeExpr(Actions, BodyStmts, StopExpr, ".stop");
5649 VarDecl *NewStep = precomputeExpr(Actions, BodyStmts, StepExpr, ".step");
5650 auto BuildVarRef = [&](VarDecl *VD) {
5651 return buildDeclRefExpr(Actions, VD, VD->getType(), {});
5652 };
5653
5655 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 0), LogicalTy, {});
5657 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5658 Expr *Dist;
5659 if (Rel == BO_NE) {
5660 // When using a != comparison, the increment can be +1 or -1. This can be
5661 // dynamic at runtime, so we need to check for the direction.
5662 Expr *IsNegStep = AssertSuccess(
5663 Actions.BuildBinOp(nullptr, {}, BO_LT, BuildVarRef(NewStep), Zero));
5664
5665 // Positive increment.
5666 Expr *ForwardRange = AssertSuccess(Actions.BuildBinOp(
5667 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5668 ForwardRange = AssertSuccess(
5669 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, ForwardRange));
5670 Expr *ForwardDist = AssertSuccess(Actions.BuildBinOp(
5671 nullptr, {}, BO_Div, ForwardRange, BuildVarRef(NewStep)));
5672
5673 // Negative increment.
5674 Expr *BackwardRange = AssertSuccess(Actions.BuildBinOp(
5675 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5676 BackwardRange = AssertSuccess(
5677 Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, BackwardRange));
5678 Expr *NegIncAmount = AssertSuccess(
5679 Actions.BuildUnaryOp(nullptr, {}, UO_Minus, BuildVarRef(NewStep)));
5680 Expr *BackwardDist = AssertSuccess(
5681 Actions.BuildBinOp(nullptr, {}, BO_Div, BackwardRange, NegIncAmount));
5682
5683 // Use the appropriate case.
5684 Dist = AssertSuccess(Actions.ActOnConditionalOp(
5685 {}, {}, IsNegStep, BackwardDist, ForwardDist));
5686 } else {
5687 assert((Rel == BO_LT || Rel == BO_LE || Rel == BO_GE || Rel == BO_GT) &&
5688 "Expected one of these relational operators");
5689
5690 // We can derive the direction from any other comparison operator. It is
5691 // non well-formed OpenMP if Step increments/decrements in the other
5692 // directions. Whether at least the first iteration passes the loop
5693 // condition.
5694 Expr *HasAnyIteration = AssertSuccess(Actions.BuildBinOp(
5695 nullptr, {}, Rel, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5696
5697 // Compute the range between first and last counter value.
5698 Expr *Range;
5699 if (Rel == BO_GE || Rel == BO_GT)
5700 Range = AssertSuccess(Actions.BuildBinOp(
5701 nullptr, {}, BO_Sub, BuildVarRef(NewStart), BuildVarRef(NewStop)));
5702 else
5703 Range = AssertSuccess(Actions.BuildBinOp(
5704 nullptr, {}, BO_Sub, BuildVarRef(NewStop), BuildVarRef(NewStart)));
5705
5706 // Ensure unsigned range space.
5707 Range =
5708 AssertSuccess(Actions.BuildCStyleCastExpr({}, LogicalTSI, {}, Range));
5709
5710 if (Rel == BO_LE || Rel == BO_GE) {
5711 // Add one to the range if the relational operator is inclusive.
5712 Range =
5713 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, Range, One));
5714 }
5715
5716 // Divide by the absolute step amount. If the range is not a multiple of
5717 // the step size, rounding-up the effective upper bound ensures that the
5718 // last iteration is included.
5719 // Note that the rounding-up may cause an overflow in a temporary that
5720 // could be avoided, but would have occurred in a C-style for-loop as
5721 // well.
5722 Expr *Divisor = BuildVarRef(NewStep);
5723 if (Rel == BO_GE || Rel == BO_GT)
5724 Divisor =
5725 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Minus, Divisor));
5726 Expr *DivisorMinusOne =
5727 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Sub, Divisor, One));
5728 Expr *RangeRoundUp = AssertSuccess(
5729 Actions.BuildBinOp(nullptr, {}, BO_Add, Range, DivisorMinusOne));
5730 Dist = AssertSuccess(
5731 Actions.BuildBinOp(nullptr, {}, BO_Div, RangeRoundUp, Divisor));
5732
5733 // If there is not at least one iteration, the range contains garbage. Fix
5734 // to zero in this case.
5735 Dist = AssertSuccess(
5736 Actions.ActOnConditionalOp({}, {}, HasAnyIteration, Dist, Zero));
5737 }
5738
5739 // Assign the result to the out-parameter.
5740 Stmt *ResultAssign = AssertSuccess(Actions.BuildBinOp(
5741 Actions.getCurScope(), {}, BO_Assign, DistRef, Dist));
5742 BodyStmts.push_back(ResultAssign);
5743
5744 Body = AssertSuccess(Actions.ActOnCompoundStmt({}, {}, BodyStmts, false));
5745 }
5746
5747 return cast<CapturedStmt>(
5748 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5749}
5750
5751/// Create a closure that computes the loop variable from the logical iteration
5752/// number.
5753///
5754/// \param Actions The Sema object.
5755/// \param LoopVarTy Type for the loop variable used for result value.
5756/// \param LogicalTy Type for the logical iteration number.
5757/// \param StartExpr Value of the loop counter at the first iteration.
5758/// \param Step Amount of increment after each iteration.
5759/// \param Deref Whether the loop variable is a dereference of the loop
5760/// counter variable.
5761///
5762/// \return Closure (CapturedStmt) of the loop value calculation.
5763static CapturedStmt *buildLoopVarFunc(Sema &Actions, QualType LoopVarTy,
5764 QualType LogicalTy,
5765 DeclRefExpr *StartExpr, Expr *Step,
5766 bool Deref) {
5767 ASTContext &Ctx = Actions.getASTContext();
5768
5769 // Pass the result as an out-parameter. Passing as return value would require
5770 // the OpenMPIRBuilder to know additional C/C++ semantics, such as how to
5771 // invoke a copy constructor.
5772 QualType TargetParamTy = Ctx.getLValueReferenceType(LoopVarTy);
5773 SemaOpenMP::CapturedParamNameType Params[] = {{"LoopVar", TargetParamTy},
5774 {"Logical", LogicalTy},
5775 {StringRef(), QualType()}};
5776 Actions.ActOnCapturedRegionStart({}, nullptr, CR_Default, Params);
5777
5778 // Capture the initial iterator which represents the LoopVar value at the
5779 // zero's logical iteration. Since the original ForStmt/CXXForRangeStmt update
5780 // it in every iteration, capture it by value before it is modified.
5781 VarDecl *StartVar = cast<VarDecl>(StartExpr->getDecl());
5782 bool Invalid = Actions.tryCaptureVariable(StartVar, {},
5784 (void)Invalid;
5785 assert(!Invalid && "Expecting capture-by-value to work.");
5786
5787 Expr *Body;
5788 {
5789 Sema::CompoundScopeRAII CompoundScope(Actions);
5790 auto *CS = cast<CapturedDecl>(Actions.CurContext);
5791
5792 ImplicitParamDecl *TargetParam = CS->getParam(0);
5793 DeclRefExpr *TargetRef = Actions.BuildDeclRefExpr(
5794 TargetParam, LoopVarTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5795 ImplicitParamDecl *IndvarParam = CS->getParam(1);
5796 DeclRefExpr *LogicalRef = Actions.BuildDeclRefExpr(
5797 IndvarParam, LogicalTy, VK_LValue, {}, nullptr, nullptr, {}, nullptr);
5798
5799 // Capture the Start expression.
5800 CaptureVars Recap(Actions);
5801 Expr *NewStart = AssertSuccess(Recap.TransformExpr(StartExpr));
5802 Expr *NewStep = AssertSuccess(Recap.TransformExpr(Step));
5803
5805 Actions.BuildBinOp(nullptr, {}, BO_Mul, NewStep, LogicalRef));
5806 // TODO: Explicitly cast to the iterator's difference_type instead of
5807 // relying on implicit conversion.
5808 Expr *Advanced =
5809 AssertSuccess(Actions.BuildBinOp(nullptr, {}, BO_Add, NewStart, Skip));
5810
5811 if (Deref) {
5812 // For range-based for-loops convert the loop counter value to a concrete
5813 // loop variable value by dereferencing the iterator.
5814 Advanced =
5815 AssertSuccess(Actions.BuildUnaryOp(nullptr, {}, UO_Deref, Advanced));
5816 }
5817
5818 // Assign the result to the output parameter.
5819 Body = AssertSuccess(Actions.BuildBinOp(Actions.getCurScope(), {},
5820 BO_Assign, TargetRef, Advanced));
5821 }
5822 return cast<CapturedStmt>(
5823 AssertSuccess(Actions.ActOnCapturedRegionEnd(Body)));
5824}
5825
5827 ASTContext &Ctx = getASTContext();
5828
5829 // Extract the common elements of ForStmt and CXXForRangeStmt:
5830 // Loop variable, repeat condition, increment
5831 Expr *Cond, *Inc;
5832 VarDecl *LIVDecl, *LUVDecl;
5833 if (auto *For = dyn_cast<ForStmt>(AStmt)) {
5834 Stmt *Init = For->getInit();
5835 if (auto *LCVarDeclStmt = dyn_cast<DeclStmt>(Init)) {
5836 // For statement declares loop variable.
5837 LIVDecl = cast<VarDecl>(LCVarDeclStmt->getSingleDecl());
5838 } else if (auto *LCAssign = dyn_cast<BinaryOperator>(Init)) {
5839 // For statement reuses variable.
5840 assert(LCAssign->getOpcode() == BO_Assign &&
5841 "init part must be a loop variable assignment");
5842 auto *CounterRef = cast<DeclRefExpr>(LCAssign->getLHS());
5843 LIVDecl = cast<VarDecl>(CounterRef->getDecl());
5844 } else
5845 llvm_unreachable("Cannot determine loop variable");
5846 LUVDecl = LIVDecl;
5847
5848 Cond = For->getCond();
5849 Inc = For->getInc();
5850 } else if (auto *RangeFor = dyn_cast<CXXForRangeStmt>(AStmt)) {
5851 DeclStmt *BeginStmt = RangeFor->getBeginStmt();
5852 LIVDecl = cast<VarDecl>(BeginStmt->getSingleDecl());
5853 LUVDecl = RangeFor->getLoopVariable();
5854
5855 Cond = RangeFor->getCond();
5856 Inc = RangeFor->getInc();
5857 } else
5858 llvm_unreachable("unhandled kind of loop");
5859
5860 QualType CounterTy = LIVDecl->getType();
5861 QualType LVTy = LUVDecl->getType();
5862
5863 // Analyze the loop condition.
5864 Expr *LHS, *RHS;
5865 BinaryOperator::Opcode CondRel;
5866 Cond = Cond->IgnoreImplicit();
5867 if (auto *CondBinExpr = dyn_cast<BinaryOperator>(Cond)) {
5868 LHS = CondBinExpr->getLHS();
5869 RHS = CondBinExpr->getRHS();
5870 CondRel = CondBinExpr->getOpcode();
5871 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Cond)) {
5872 assert(CondCXXOp->getNumArgs() == 2 && "Comparison should have 2 operands");
5873 LHS = CondCXXOp->getArg(0);
5874 RHS = CondCXXOp->getArg(1);
5875 switch (CondCXXOp->getOperator()) {
5876 case OO_ExclaimEqual:
5877 CondRel = BO_NE;
5878 break;
5879 case OO_Less:
5880 CondRel = BO_LT;
5881 break;
5882 case OO_LessEqual:
5883 CondRel = BO_LE;
5884 break;
5885 case OO_Greater:
5886 CondRel = BO_GT;
5887 break;
5888 case OO_GreaterEqual:
5889 CondRel = BO_GE;
5890 break;
5891 default:
5892 llvm_unreachable("unexpected iterator operator");
5893 }
5894 } else
5895 llvm_unreachable("unexpected loop condition");
5896
5897 // Normalize such that the loop counter is on the LHS.
5898 if (!isa<DeclRefExpr>(LHS->IgnoreImplicit()) ||
5899 cast<DeclRefExpr>(LHS->IgnoreImplicit())->getDecl() != LIVDecl) {
5900 std::swap(LHS, RHS);
5901 CondRel = BinaryOperator::reverseComparisonOp(CondRel);
5902 }
5903 auto *CounterRef = cast<DeclRefExpr>(LHS->IgnoreImplicit());
5904
5905 // Decide the bit width for the logical iteration counter. By default use the
5906 // unsigned ptrdiff_t integer size (for iterators and pointers).
5907 // TODO: For iterators, use iterator::difference_type,
5908 // std::iterator_traits<>::difference_type or decltype(it - end).
5909 QualType LogicalTy = Ctx.getUnsignedPointerDiffType();
5910 if (CounterTy->isIntegerType()) {
5911 unsigned BitWidth = Ctx.getIntWidth(CounterTy);
5912 LogicalTy = Ctx.getIntTypeForBitwidth(BitWidth, false);
5913 }
5914
5915 // Analyze the loop increment.
5916 Expr *Step;
5917 if (auto *IncUn = dyn_cast<UnaryOperator>(Inc)) {
5918 int Direction;
5919 switch (IncUn->getOpcode()) {
5920 case UO_PreInc:
5921 case UO_PostInc:
5922 Direction = 1;
5923 break;
5924 case UO_PreDec:
5925 case UO_PostDec:
5926 Direction = -1;
5927 break;
5928 default:
5929 llvm_unreachable("unhandled unary increment operator");
5930 }
5932 Ctx,
5933 llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
5934 LogicalTy, {});
5935 } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
5936 if (IncBin->getOpcode() == BO_AddAssign) {
5937 Step = IncBin->getRHS();
5938 } else if (IncBin->getOpcode() == BO_SubAssign) {
5939 Step = AssertSuccess(
5940 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
5941 } else
5942 llvm_unreachable("unhandled binary increment operator");
5943 } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
5944 switch (CondCXXOp->getOperator()) {
5945 case OO_PlusPlus:
5947 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), 1), LogicalTy, {});
5948 break;
5949 case OO_MinusMinus:
5951 Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
5952 break;
5953 case OO_PlusEqual:
5954 Step = CondCXXOp->getArg(1);
5955 break;
5956 case OO_MinusEqual:
5957 Step = AssertSuccess(
5958 SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
5959 break;
5960 default:
5961 llvm_unreachable("unhandled overloaded increment operator");
5962 }
5963 } else
5964 llvm_unreachable("unknown increment expression");
5965
5966 CapturedStmt *DistanceFunc =
5967 buildDistanceFunc(SemaRef, LogicalTy, CondRel, LHS, RHS, Step);
5968 CapturedStmt *LoopVarFunc = buildLoopVarFunc(
5969 SemaRef, LVTy, LogicalTy, CounterRef, Step, isa<CXXForRangeStmt>(AStmt));
5970 DeclRefExpr *LVRef =
5971 SemaRef.BuildDeclRefExpr(LUVDecl, LUVDecl->getType(), VK_LValue, {},
5972 nullptr, nullptr, {}, nullptr);
5973 return OMPCanonicalLoop::create(getASTContext(), AStmt, DistanceFunc,
5974 LoopVarFunc, LVRef);
5975}
5976
5978 // Handle a literal loop.
5979 if (isa<ForStmt>(AStmt) || isa<CXXForRangeStmt>(AStmt))
5980 return ActOnOpenMPCanonicalLoop(AStmt);
5981
5982 // If not a literal loop, it must be the result of a loop transformation.
5984 assert(
5985 isOpenMPLoopTransformationDirective(LoopTransform->getDirectiveKind()) &&
5986 "Loop transformation directive expected");
5987 return LoopTransform;
5988}
5989
5991 CXXScopeSpec &MapperIdScopeSpec,
5992 const DeclarationNameInfo &MapperId,
5993 QualType Type,
5994 Expr *UnresolvedMapper);
5995
5996/// Perform DFS through the structure/class data members trying to find
5997/// member(s) with user-defined 'default' mapper and generate implicit map
5998/// clauses for such members with the found 'default' mapper.
5999static void
6002 // Check for the default mapper for data members.
6003 if (S.getLangOpts().OpenMP < 50)
6004 return;
6005 for (int Cnt = 0, EndCnt = Clauses.size(); Cnt < EndCnt; ++Cnt) {
6006 auto *C = dyn_cast<OMPMapClause>(Clauses[Cnt]);
6007 if (!C)
6008 continue;
6009 SmallVector<Expr *, 4> SubExprs;
6010 auto *MI = C->mapperlist_begin();
6011 for (auto I = C->varlist_begin(), End = C->varlist_end(); I != End;
6012 ++I, ++MI) {
6013 // Expression is mapped using mapper - skip it.
6014 if (*MI)
6015 continue;
6016 Expr *E = *I;
6017 // Expression is dependent - skip it, build the mapper when it gets
6018 // instantiated.
6019 if (E->isTypeDependent() || E->isValueDependent() ||
6021 continue;
6022 // Array section - need to check for the mapping of the array section
6023 // element.
6024 QualType CanonType = E->getType().getCanonicalType();
6025 if (CanonType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
6026 const auto *OASE = cast<ArraySectionExpr>(E->IgnoreParenImpCasts());
6027 QualType BaseType =
6029 QualType ElemType;
6030 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
6031 ElemType = ATy->getElementType();
6032 else
6033 ElemType = BaseType->getPointeeType();
6034 CanonType = ElemType;
6035 }
6036
6037 // DFS over data members in structures/classes.
6039 1, {CanonType, nullptr});
6040 llvm::DenseMap<const Type *, Expr *> Visited;
6042 1, {nullptr, 1});
6043 while (!Types.empty()) {
6044 QualType BaseType;
6045 FieldDecl *CurFD;
6046 std::tie(BaseType, CurFD) = Types.pop_back_val();
6047 while (ParentChain.back().second == 0)
6048 ParentChain.pop_back();
6049 --ParentChain.back().second;
6050 if (BaseType.isNull())
6051 continue;
6052 // Only structs/classes are allowed to have mappers.
6053 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
6054 if (!RD)
6055 continue;
6056 auto It = Visited.find(BaseType.getTypePtr());
6057 if (It == Visited.end()) {
6058 // Try to find the associated user-defined mapper.
6059 CXXScopeSpec MapperIdScopeSpec;
6060 DeclarationNameInfo DefaultMapperId;
6062 &S.Context.Idents.get("default")));
6063 DefaultMapperId.setLoc(E->getExprLoc());
6065 S, Stack->getCurScope(), MapperIdScopeSpec, DefaultMapperId,
6066 BaseType, /*UnresolvedMapper=*/nullptr);
6067 if (ER.isInvalid())
6068 continue;
6069 It = Visited.try_emplace(BaseType.getTypePtr(), ER.get()).first;
6070 }
6071 // Found default mapper.
6072 if (It->second) {
6073 auto *OE = new (S.Context) OpaqueValueExpr(E->getExprLoc(), CanonType,
6075 OE->setIsUnique(/*V=*/true);
6076 Expr *BaseExpr = OE;
6077 for (const auto &P : ParentChain) {
6078 if (P.first) {
6079 BaseExpr = S.BuildMemberExpr(
6080 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6082 DeclAccessPair::make(P.first, P.first->getAccess()),
6083 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6084 P.first->getType(), VK_LValue, OK_Ordinary);
6085 BaseExpr = S.DefaultLvalueConversion(BaseExpr).get();
6086 }
6087 }
6088 if (CurFD)
6089 BaseExpr = S.BuildMemberExpr(
6090 BaseExpr, /*IsArrow=*/false, E->getExprLoc(),
6092 DeclAccessPair::make(CurFD, CurFD->getAccess()),
6093 /*HadMultipleCandidates=*/false, DeclarationNameInfo(),
6094 CurFD->getType(), VK_LValue, OK_Ordinary);
6095 SubExprs.push_back(BaseExpr);
6096 continue;
6097 }
6098 // Check for the "default" mapper for data members.
6099 bool FirstIter = true;
6100 for (FieldDecl *FD : RD->fields()) {
6101 if (!FD)
6102 continue;
6103 QualType FieldTy = FD->getType();
6104 if (FieldTy.isNull() ||
6105 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
6106 continue;
6107 if (FirstIter) {
6108 FirstIter = false;
6109 ParentChain.emplace_back(CurFD, 1);
6110 } else {
6111 ++ParentChain.back().second;
6112 }
6113 Types.emplace_back(FieldTy, FD);
6114 }
6115 }
6116 }
6117 if (SubExprs.empty())
6118 continue;
6119 CXXScopeSpec MapperIdScopeSpec;
6120 DeclarationNameInfo MapperId;
6121 if (OMPClause *NewClause = S.OpenMP().ActOnOpenMPMapClause(
6122 nullptr, C->getMapTypeModifiers(), C->getMapTypeModifiersLoc(),
6123 MapperIdScopeSpec, MapperId, C->getMapType(),
6124 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6125 SubExprs, OMPVarListLocTy()))
6126 Clauses.push_back(NewClause);
6127 }
6128}
6129
6130namespace {
6131/// A 'teams loop' with a nested 'loop bind(parallel)' or generic function
6132/// call in the associated loop-nest cannot be a 'parallel for'.
6133class TeamsLoopChecker final : public ConstStmtVisitor<TeamsLoopChecker> {
6134 Sema &SemaRef;
6135
6136public:
6137 bool teamsLoopCanBeParallelFor() const { return TeamsLoopCanBeParallelFor; }
6138
6139 // Is there a nested OpenMP loop bind(parallel)
6140 void VisitOMPExecutableDirective(const OMPExecutableDirective *D) {
6141 if (D->getDirectiveKind() == llvm::omp::Directive::OMPD_loop) {
6142 if (const auto *C = D->getSingleClause<OMPBindClause>())
6143 if (C->getBindKind() == OMPC_BIND_parallel) {
6144 TeamsLoopCanBeParallelFor = false;
6145 // No need to continue visiting any more
6146 return;
6147 }
6148 }
6149 for (const Stmt *Child : D->children())
6150 if (Child)
6151 Visit(Child);
6152 }
6153
6154 void VisitCallExpr(const CallExpr *C) {
6155 // Function calls inhibit parallel loop translation of 'target teams loop'
6156 // unless the assume-no-nested-parallelism flag has been specified.
6157 // OpenMP API runtime library calls do not inhibit parallel loop
6158 // translation, regardless of the assume-no-nested-parallelism.
6159 bool IsOpenMPAPI = false;
6160 auto *FD = dyn_cast_or_null<FunctionDecl>(C->getCalleeDecl());
6161 if (FD) {
6162 std::string Name = FD->getNameInfo().getAsString();
6163 IsOpenMPAPI = Name.find("omp_") == 0;
6164 }
6165 TeamsLoopCanBeParallelFor =
6166 IsOpenMPAPI || SemaRef.getLangOpts().OpenMPNoNestedParallelism;
6167 if (!TeamsLoopCanBeParallelFor)
6168 return;
6169
6170 for (const Stmt *Child : C->children())
6171 if (Child)
6172 Visit(Child);
6173 }
6174
6175 void VisitCapturedStmt(const CapturedStmt *S) {
6176 if (!S)
6177 return;
6178 Visit(S->getCapturedDecl()->getBody());
6179 }
6180
6181 void VisitStmt(const Stmt *S) {
6182 if (!S)
6183 return;
6184 for (const Stmt *Child : S->children())
6185 if (Child)
6186 Visit(Child);
6187 }
6188 explicit TeamsLoopChecker(Sema &SemaRef)
6189 : SemaRef(SemaRef), TeamsLoopCanBeParallelFor(true) {}
6190
6191private:
6192 bool TeamsLoopCanBeParallelFor;
6193};
6194} // namespace
6195
6196static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef) {
6197 TeamsLoopChecker Checker(SemaRef);
6198 Checker.Visit(AStmt);
6199 return Checker.teamsLoopCanBeParallelFor();
6200}
6201
6203 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
6204 OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
6205 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
6206 assert(isOpenMPExecutableDirective(Kind) && "Unexpected directive category");
6207
6208 StmtResult Res = StmtError();
6210 llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
6211
6212 if (const OMPBindClause *BC =
6213 OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
6214 BindKind = BC->getBindKind();
6215
6216 if (Kind == OMPD_loop && BindKind == OMPC_BIND_unknown) {
6217 const OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
6218
6219 // Setting the enclosing teams or parallel construct for the loop
6220 // directive without bind clause.
6221 // [5.0:129:25-28] If the bind clause is not present on the construct and
6222 // the loop construct is closely nested inside a teams or parallel
6223 // construct, the binding region is the corresponding teams or parallel
6224 // region. If none of those conditions hold, the binding region is not
6225 // defined.
6226 BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
6227 ArrayRef<OpenMPDirectiveKind> ParentLeafs =
6228 getLeafConstructsOrSelf(ParentDirective);
6229
6230 if (ParentDirective == OMPD_unknown) {
6231 Diag(DSAStack->getDefaultDSALocation(),
6232 diag::err_omp_bind_required_on_loop);
6233 } else if (ParentLeafs.back() == OMPD_parallel) {
6234 BindKind = OMPC_BIND_parallel;
6235 } else if (ParentLeafs.back() == OMPD_teams) {
6236 BindKind = OMPC_BIND_teams;
6237 }
6238
6239 assert(BindKind != OMPC_BIND_unknown && "Expecting BindKind");
6240
6241 OMPClause *C =
6244 ClausesWithImplicit.push_back(C);
6245 }
6246
6247 // Diagnose "loop bind(teams)" with "reduction".
6248 if (Kind == OMPD_loop && BindKind == OMPC_BIND_teams) {
6249 for (OMPClause *C : Clauses) {
6250 if (C->getClauseKind() == OMPC_reduction)
6251 Diag(DSAStack->getDefaultDSALocation(),
6252 diag::err_omp_loop_reduction_clause);
6253 }
6254 }
6255
6256 // First check CancelRegion which is then used in checkNestingOfRegions.
6257 if (checkCancelRegion(SemaRef, Kind, CancelRegion, StartLoc) ||
6258 checkNestingOfRegions(SemaRef, DSAStack, Kind, DirName, CancelRegion,
6259 BindKind, StartLoc)) {
6260 return StmtError();
6261 }
6262
6263 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
6266 Diag(StartLoc, diag::warn_hip_omp_target_directives);
6267
6268 VarsWithInheritedDSAType VarsWithInheritedDSA;
6269 bool ErrorFound = false;
6270 ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
6271
6272 if (AStmt && !SemaRef.CurContext->isDependentContext() &&
6274 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
6275
6276 // Check default data sharing attributes for referenced variables.
6277 DSAAttrChecker DSAChecker(DSAStack, SemaRef, cast<CapturedStmt>(AStmt));
6278 int ThisCaptureLevel = getOpenMPCaptureLevels(Kind);
6279 Stmt *S = AStmt;
6280 while (--ThisCaptureLevel >= 0)
6281 S = cast<CapturedStmt>(S)->getCapturedStmt();
6282 DSAChecker.Visit(S);
6284 !isOpenMPTaskingDirective(Kind)) {
6285 // Visit subcaptures to generate implicit clauses for captured vars.
6286 auto *CS = cast<CapturedStmt>(AStmt);
6288 getOpenMPCaptureRegions(CaptureRegions, Kind);
6289 // Ignore outer tasking regions for target directives.
6290 if (CaptureRegions.size() > 1 && CaptureRegions.front() == OMPD_task)
6292 DSAChecker.visitSubCaptures(CS);
6293 }
6294 if (DSAChecker.isErrorFound())
6295 return StmtError();
6296 // Generate list of implicitly defined firstprivate variables.
6297 VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA();
6298 VariableImplicitInfo ImpInfo = DSAChecker.getImplicitInfo();
6299
6301 ImplicitMapModifiersLoc[VariableImplicitInfo::DefaultmapKindNum];
6302 // Get the original location of present modifier from Defaultmap clause.
6303 SourceLocation PresentModifierLocs[VariableImplicitInfo::DefaultmapKindNum];
6304 for (OMPClause *C : Clauses) {
6305 if (auto *DMC = dyn_cast<OMPDefaultmapClause>(C))
6306 if (DMC->getDefaultmapModifier() == OMPC_DEFAULTMAP_MODIFIER_present)
6307 PresentModifierLocs[DMC->getDefaultmapKind()] =
6308 DMC->getDefaultmapModifierLoc();
6309 }
6310
6312 llvm::enum_seq_inclusive<OpenMPDefaultmapClauseKind>(
6314 std::fill_n(std::back_inserter(ImplicitMapModifiersLoc[K]),
6315 ImpInfo.MapModifiers[K].size(), PresentModifierLocs[K]);
6316 }
6317 // Mark taskgroup task_reduction descriptors as implicitly firstprivate.
6318 for (OMPClause *C : Clauses) {
6319 if (auto *IRC = dyn_cast<OMPInReductionClause>(C)) {
6320 for (Expr *E : IRC->taskgroup_descriptors())
6321 if (E)
6322 ImpInfo.Firstprivates.insert(E);
6323 }
6324 // OpenMP 5.0, 2.10.1 task Construct
6325 // [detach clause]... The event-handle will be considered as if it was
6326 // specified on a firstprivate clause.
6327 if (auto *DC = dyn_cast<OMPDetachClause>(C))
6328 ImpInfo.Firstprivates.insert(DC->getEventHandler());
6329 }
6330 if (!ImpInfo.Firstprivates.empty()) {
6332 ImpInfo.Firstprivates.getArrayRef(), SourceLocation(),
6334 ClausesWithImplicit.push_back(Implicit);
6335 ErrorFound = cast<OMPFirstprivateClause>(Implicit)->varlist_size() !=
6336 ImpInfo.Firstprivates.size();
6337 } else {
6338 ErrorFound = true;
6339 }
6340 }
6341 if (!ImpInfo.Privates.empty()) {
6343 ImpInfo.Privates.getArrayRef(), SourceLocation(),
6345 ClausesWithImplicit.push_back(Implicit);
6346 ErrorFound = cast<OMPPrivateClause>(Implicit)->varlist_size() !=
6347 ImpInfo.Privates.size();
6348 } else {
6349 ErrorFound = true;
6350 }
6351 }
6352 // OpenMP 5.0 [2.19.7]
6353 // If a list item appears in a reduction, lastprivate or linear
6354 // clause on a combined target construct then it is treated as
6355 // if it also appears in a map clause with a map-type of tofrom
6356 if (getLangOpts().OpenMP >= 50 && Kind != OMPD_target &&
6358 SmallVector<Expr *, 4> ImplicitExprs;
6359 for (OMPClause *C : Clauses) {
6360 if (auto *RC = dyn_cast<OMPReductionClause>(C))
6361 for (Expr *E : RC->varlist())
6363 ImplicitExprs.emplace_back(E);
6364 }
6365 if (!ImplicitExprs.empty()) {
6366 ArrayRef<Expr *> Exprs = ImplicitExprs;
6367 CXXScopeSpec MapperIdScopeSpec;
6368 DeclarationNameInfo MapperId;
6371 MapperIdScopeSpec, MapperId, OMPC_MAP_tofrom,
6372 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(),
6373 Exprs, OMPVarListLocTy(), /*NoDiagnose=*/true))
6374 ClausesWithImplicit.emplace_back(Implicit);
6375 }
6376 }
6377 for (unsigned I = 0; I < VariableImplicitInfo::DefaultmapKindNum; ++I) {
6378 int ClauseKindCnt = -1;
6379 for (unsigned J = 0; J < VariableImplicitInfo::MapKindNum; ++J) {
6380 ArrayRef<Expr *> ImplicitMap = ImpInfo.Mappings[I][J].getArrayRef();
6381 ++ClauseKindCnt;
6382 if (ImplicitMap.empty())
6383 continue;
6384 CXXScopeSpec MapperIdScopeSpec;
6385 DeclarationNameInfo MapperId;
6386 auto K = static_cast<OpenMPMapClauseKind>(ClauseKindCnt);
6388 nullptr, ImpInfo.MapModifiers[I], ImplicitMapModifiersLoc[I],
6389 MapperIdScopeSpec, MapperId, K, /*IsMapTypeImplicit=*/true,
6390 SourceLocation(), SourceLocation(), ImplicitMap,
6391 OMPVarListLocTy())) {
6392 ClausesWithImplicit.emplace_back(Implicit);
6393 ErrorFound |= cast<OMPMapClause>(Implicit)->varlist_size() !=
6394 ImplicitMap.size();
6395 } else {
6396 ErrorFound = true;
6397 }
6398 }
6399 }
6400 // Build expressions for implicit maps of data members with 'default'
6401 // mappers.
6402 if (getLangOpts().OpenMP >= 50)
6404 ClausesWithImplicit);
6405 }
6406
6407 switch (Kind) {
6408 case OMPD_parallel:
6409 Res = ActOnOpenMPParallelDirective(ClausesWithImplicit, AStmt, StartLoc,
6410 EndLoc);
6411 break;
6412 case OMPD_simd:
6413 Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6414 VarsWithInheritedDSA);
6415 break;
6416 case OMPD_tile:
6417 Res =
6418 ActOnOpenMPTileDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6419 break;
6420 case OMPD_stripe:
6421 Res = ActOnOpenMPStripeDirective(ClausesWithImplicit, AStmt, StartLoc,
6422 EndLoc);
6423 break;
6424 case OMPD_unroll:
6425 Res = ActOnOpenMPUnrollDirective(ClausesWithImplicit, AStmt, StartLoc,
6426 EndLoc);
6427 break;
6428 case OMPD_reverse:
6429 assert(ClausesWithImplicit.empty() &&
6430 "reverse directive does not support any clauses");
6431 Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
6432 break;
6433 case OMPD_interchange:
6434 Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
6435 EndLoc);
6436 break;
6437 case OMPD_fuse:
6438 Res =
6439 ActOnOpenMPFuseDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6440 break;
6441 case OMPD_for:
6442 Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc,
6443 VarsWithInheritedDSA);
6444 break;
6445 case OMPD_for_simd:
6446 Res = ActOnOpenMPForSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6447 EndLoc, VarsWithInheritedDSA);
6448 break;
6449 case OMPD_sections:
6450 Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc,
6451 EndLoc);
6452 break;
6453 case OMPD_section:
6454 assert(ClausesWithImplicit.empty() &&
6455 "No clauses are allowed for 'omp section' directive");
6456 Res = ActOnOpenMPSectionDirective(AStmt, StartLoc, EndLoc);
6457 break;
6458 case OMPD_single:
6459 Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc,
6460 EndLoc);
6461 break;
6462 case OMPD_master:
6463 assert(ClausesWithImplicit.empty() &&
6464 "No clauses are allowed for 'omp master' directive");
6465 Res = ActOnOpenMPMasterDirective(AStmt, StartLoc, EndLoc);
6466 break;
6467 case OMPD_masked:
6468 Res = ActOnOpenMPMaskedDirective(ClausesWithImplicit, AStmt, StartLoc,
6469 EndLoc);
6470 break;
6471 case OMPD_critical:
6472 Res = ActOnOpenMPCriticalDirective(DirName, ClausesWithImplicit, AStmt,
6473 StartLoc, EndLoc);
6474 break;
6475 case OMPD_parallel_for:
6476 Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc,
6477 EndLoc, VarsWithInheritedDSA);
6478 break;
6479 case OMPD_parallel_for_simd:
6481 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6482 break;
6483 case OMPD_scope:
6484 Res =
6485 ActOnOpenMPScopeDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6486 break;
6487 case OMPD_parallel_master:
6488 Res = ActOnOpenMPParallelMasterDirective(ClausesWithImplicit, AStmt,
6489 StartLoc, EndLoc);
6490 break;
6491 case OMPD_parallel_masked:
6492 Res = ActOnOpenMPParallelMaskedDirective(ClausesWithImplicit, AStmt,
6493 StartLoc, EndLoc);
6494 break;
6495 case OMPD_parallel_sections:
6496 Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt,
6497 StartLoc, EndLoc);
6498 break;
6499 case OMPD_task:
6500 Res =
6501 ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6502 break;
6503 case OMPD_taskyield:
6504 assert(ClausesWithImplicit.empty() &&
6505 "No clauses are allowed for 'omp taskyield' directive");
6506 assert(AStmt == nullptr &&
6507 "No associated statement allowed for 'omp taskyield' directive");
6508 Res = ActOnOpenMPTaskyieldDirective(StartLoc, EndLoc);
6509 break;
6510 case OMPD_error:
6511 assert(AStmt == nullptr &&
6512 "No associated statement allowed for 'omp error' directive");
6513 Res = ActOnOpenMPErrorDirective(ClausesWithImplicit, StartLoc, EndLoc);
6514 break;
6515 case OMPD_barrier:
6516 assert(ClausesWithImplicit.empty() &&
6517 "No clauses are allowed for 'omp barrier' directive");
6518 assert(AStmt == nullptr &&
6519 "No associated statement allowed for 'omp barrier' directive");
6520 Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
6521 break;
6522 case OMPD_taskwait:
6523 assert(AStmt == nullptr &&
6524 "No associated statement allowed for 'omp taskwait' directive");
6525 Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
6526 break;
6527 case OMPD_taskgroup:
6528 Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
6529 EndLoc);
6530 break;
6531 case OMPD_flush:
6532 assert(AStmt == nullptr &&
6533 "No associated statement allowed for 'omp flush' directive");
6534 Res = ActOnOpenMPFlushDirective(ClausesWithImplicit, StartLoc, EndLoc);
6535 break;
6536 case OMPD_depobj:
6537 assert(AStmt == nullptr &&
6538 "No associated statement allowed for 'omp depobj' directive");
6539 Res = ActOnOpenMPDepobjDirective(ClausesWithImplicit, StartLoc, EndLoc);
6540 break;
6541 case OMPD_scan:
6542 assert(AStmt == nullptr &&
6543 "No associated statement allowed for 'omp scan' directive");
6544 Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
6545 break;
6546 case OMPD_ordered:
6547 Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
6548 EndLoc);
6549 break;
6550 case OMPD_atomic:
6551 Res = ActOnOpenMPAtomicDirective(ClausesWithImplicit, AStmt, StartLoc,
6552 EndLoc);
6553 break;
6554 case OMPD_teams:
6555 Res =
6556 ActOnOpenMPTeamsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
6557 break;
6558 case OMPD_target:
6559 Res = ActOnOpenMPTargetDirective(ClausesWithImplicit, AStmt, StartLoc,
6560 EndLoc);
6561 break;
6562 case OMPD_target_parallel:
6563 Res = ActOnOpenMPTargetParallelDirective(ClausesWithImplicit, AStmt,
6564 StartLoc, EndLoc);
6565 break;
6566 case OMPD_target_parallel_for:
6568 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6569 break;
6570 case OMPD_cancellation_point:
6571 assert(ClausesWithImplicit.empty() &&
6572 "No clauses are allowed for 'omp cancellation point' directive");
6573 assert(AStmt == nullptr && "No associated statement allowed for 'omp "
6574 "cancellation point' directive");
6575 Res = ActOnOpenMPCancellationPointDirective(StartLoc, EndLoc, CancelRegion);
6576 break;
6577 case OMPD_cancel:
6578 assert(AStmt == nullptr &&
6579 "No associated statement allowed for 'omp cancel' directive");
6580 Res = ActOnOpenMPCancelDirective(ClausesWithImplicit, StartLoc, EndLoc,
6581 CancelRegion);
6582 break;
6583 case OMPD_target_data:
6584 Res = ActOnOpenMPTargetDataDirective(ClausesWithImplicit, AStmt, StartLoc,
6585 EndLoc);
6586 break;
6587 case OMPD_target_enter_data:
6588 Res = ActOnOpenMPTargetEnterDataDirective(ClausesWithImplicit, StartLoc,
6589 EndLoc, AStmt);
6590 break;
6591 case OMPD_target_exit_data:
6592 Res = ActOnOpenMPTargetExitDataDirective(ClausesWithImplicit, StartLoc,
6593 EndLoc, AStmt);
6594 break;
6595 case OMPD_taskloop:
6596 Res = ActOnOpenMPTaskLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6597 EndLoc, VarsWithInheritedDSA);
6598 break;
6599 case OMPD_taskloop_simd:
6600 Res = ActOnOpenMPTaskLoopSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6601 EndLoc, VarsWithInheritedDSA);
6602 break;
6603 case OMPD_master_taskloop:
6605 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6606 break;
6607 case OMPD_masked_taskloop:
6609 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6610 break;
6611 case OMPD_master_taskloop_simd:
6613 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6614 break;
6615 case OMPD_masked_taskloop_simd:
6617 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6618 break;
6619 case OMPD_parallel_master_taskloop:
6621 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6622 break;
6623 case OMPD_parallel_masked_taskloop:
6625 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6626 break;
6627 case OMPD_parallel_master_taskloop_simd:
6629 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6630 break;
6631 case OMPD_parallel_masked_taskloop_simd:
6633 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6634 break;
6635 case OMPD_distribute:
6636 Res = ActOnOpenMPDistributeDirective(ClausesWithImplicit, AStmt, StartLoc,
6637 EndLoc, VarsWithInheritedDSA);
6638 break;
6639 case OMPD_target_update:
6640 Res = ActOnOpenMPTargetUpdateDirective(ClausesWithImplicit, StartLoc,
6641 EndLoc, AStmt);
6642 break;
6643 case OMPD_distribute_parallel_for:
6645 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6646 break;
6647 case OMPD_distribute_parallel_for_simd:
6649 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6650 break;
6651 case OMPD_distribute_simd:
6653 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6654 break;
6655 case OMPD_target_parallel_for_simd:
6657 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6658 break;
6659 case OMPD_target_simd:
6660 Res = ActOnOpenMPTargetSimdDirective(ClausesWithImplicit, AStmt, StartLoc,
6661 EndLoc, VarsWithInheritedDSA);
6662 break;
6663 case OMPD_teams_distribute:
6665 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6666 break;
6667 case OMPD_teams_distribute_simd:
6669 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6670 break;
6671 case OMPD_teams_distribute_parallel_for_simd:
6673 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6674 break;
6675 case OMPD_teams_distribute_parallel_for:
6677 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6678 break;
6679 case OMPD_target_teams:
6680 Res = ActOnOpenMPTargetTeamsDirective(ClausesWithImplicit, AStmt, StartLoc,
6681 EndLoc);
6682 break;
6683 case OMPD_target_teams_distribute:
6685 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6686 break;
6687 case OMPD_target_teams_distribute_parallel_for:
6689 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6690 break;
6691 case OMPD_target_teams_distribute_parallel_for_simd:
6693 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6694 break;
6695 case OMPD_target_teams_distribute_simd:
6697 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6698 break;
6699 case OMPD_interop:
6700 assert(AStmt == nullptr &&
6701 "No associated statement allowed for 'omp interop' directive");
6702 Res = ActOnOpenMPInteropDirective(ClausesWithImplicit, StartLoc, EndLoc);
6703 break;
6704 case OMPD_dispatch:
6705 Res = ActOnOpenMPDispatchDirective(ClausesWithImplicit, AStmt, StartLoc,
6706 EndLoc);
6707 break;
6708 case OMPD_loop:
6709 Res = ActOnOpenMPGenericLoopDirective(ClausesWithImplicit, AStmt, StartLoc,
6710 EndLoc, VarsWithInheritedDSA);
6711 break;
6712 case OMPD_teams_loop:
6714 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6715 break;
6716 case OMPD_target_teams_loop:
6718 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6719 break;
6720 case OMPD_parallel_loop:
6722 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6723 break;
6724 case OMPD_target_parallel_loop:
6726 ClausesWithImplicit, AStmt, StartLoc, EndLoc, VarsWithInheritedDSA);
6727 break;
6728 case OMPD_declare_target:
6729 case OMPD_end_declare_target:
6730 case OMPD_threadprivate:
6731 case OMPD_allocate:
6732 case OMPD_declare_reduction:
6733 case OMPD_declare_mapper:
6734 case OMPD_declare_simd:
6735 case OMPD_requires:
6736 case OMPD_declare_variant:
6737 case OMPD_begin_declare_variant:
6738 case OMPD_end_declare_variant:
6739 llvm_unreachable("OpenMP Directive is not allowed");
6740 case OMPD_unknown:
6741 default:
6742 llvm_unreachable("Unknown OpenMP directive");
6743 }
6744
6745 ErrorFound = Res.isInvalid() || ErrorFound;
6746
6747 // Check variables in the clauses if default(none) or
6748 // default(firstprivate) was specified.
6749 if (DSAStack->getDefaultDSA() == DSA_none ||
6750 DSAStack->getDefaultDSA() == DSA_private ||
6751 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6752 DSAAttrChecker DSAChecker(DSAStack, SemaRef, nullptr);
6753 for (OMPClause *C : Clauses) {
6754 switch (C->getClauseKind()) {
6755 case OMPC_num_threads:
6756 case OMPC_dist_schedule:
6757 // Do not analyze if no parent teams directive.
6758 if (isOpenMPTeamsDirective(Kind))
6759 break;
6760 continue;
6761 case OMPC_if:
6762 if (isOpenMPTeamsDirective(Kind) &&
6763 cast<OMPIfClause>(C)->getNameModifier() != OMPD_target)
6764 break;
6765 if (isOpenMPParallelDirective(Kind) &&
6767 cast<OMPIfClause>(C)->getNameModifier() != OMPD_parallel)
6768 break;
6769 continue;
6770 case OMPC_schedule:
6771 case OMPC_detach:
6772 break;
6773 case OMPC_grainsize:
6774 case OMPC_num_tasks:
6775 case OMPC_final:
6776 case OMPC_priority:
6777 case OMPC_novariants:
6778 case OMPC_nocontext:
6779 // Do not analyze if no parent parallel directive.
6780 if (isOpenMPParallelDirective(Kind))
6781 break;
6782 continue;
6783 case OMPC_ordered:
6784 case OMPC_device:
6785 case OMPC_num_teams:
6786 case OMPC_thread_limit:
6787 case OMPC_hint:
6788 case OMPC_collapse:
6789 case OMPC_safelen:
6790 case OMPC_simdlen:
6791 case OMPC_sizes:
6792 case OMPC_default:
6793 case OMPC_proc_bind:
6794 case OMPC_private:
6795 case OMPC_firstprivate:
6796 case OMPC_lastprivate:
6797 case OMPC_shared:
6798 case OMPC_reduction:
6799 case OMPC_task_reduction:
6800 case OMPC_in_reduction:
6801 case OMPC_linear:
6802 case OMPC_aligned:
6803 case OMPC_copyin:
6804 case OMPC_copyprivate:
6805 case OMPC_nowait:
6806 case OMPC_untied:
6807 case OMPC_mergeable:
6808 case OMPC_allocate:
6809 case OMPC_read:
6810 case OMPC_write:
6811 case OMPC_update:
6812 case OMPC_capture:
6813 case OMPC_compare:
6814 case OMPC_seq_cst:
6815 case OMPC_acq_rel:
6816 case OMPC_acquire:
6817 case OMPC_release:
6818 case OMPC_relaxed:
6819 case OMPC_depend:
6820 case OMPC_threads:
6821 case OMPC_simd:
6822 case OMPC_map:
6823 case OMPC_nogroup:
6824 case OMPC_defaultmap:
6825 case OMPC_to:
6826 case OMPC_from:
6827 case OMPC_use_device_ptr:
6828 case OMPC_use_device_addr:
6829 case OMPC_is_device_ptr:
6830 case OMPC_has_device_addr:
6831 case OMPC_nontemporal:
6832 case OMPC_order:
6833 case OMPC_destroy:
6834 case OMPC_inclusive:
6835 case OMPC_exclusive:
6836 case OMPC_uses_allocators:
6837 case OMPC_affinity:
6838 case OMPC_bind:
6839 case OMPC_filter:
6840 case OMPC_severity:
6841 case OMPC_message:
6842 continue;
6843 case OMPC_allocator:
6844 case OMPC_flush:
6845 case OMPC_depobj:
6846 case OMPC_threadprivate:
6847 case OMPC_groupprivate:
6848 case OMPC_uniform:
6849 case OMPC_unknown:
6850 case OMPC_unified_address:
6851 case OMPC_unified_shared_memory:
6852 case OMPC_reverse_offload:
6853 case OMPC_dynamic_allocators:
6854 case OMPC_atomic_default_mem_order:
6855 case OMPC_self_maps:
6856 case OMPC_device_type:
6857 case OMPC_match:
6858 case OMPC_when:
6859 case OMPC_at:
6860 default:
6861 llvm_unreachable("Unexpected clause");
6862 }
6863 for (Stmt *CC : C->children()) {
6864 if (CC)
6865 DSAChecker.Visit(CC);
6866 }
6867 }
6868 for (const auto &P : DSAChecker.getVarsWithInheritedDSA())
6869 VarsWithInheritedDSA[P.getFirst()] = P.getSecond();
6870 }
6871 for (const auto &P : VarsWithInheritedDSA) {
6872 if (P.getFirst()->isImplicit() || isa<OMPCapturedExprDecl>(P.getFirst()))
6873 continue;
6874 ErrorFound = true;
6875 if (DSAStack->getDefaultDSA() == DSA_none ||
6876 DSAStack->getDefaultDSA() == DSA_private ||
6877 DSAStack->getDefaultDSA() == DSA_firstprivate) {
6878 Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
6879 << P.first << P.second->getSourceRange();
6880 Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
6881 } else if (getLangOpts().OpenMP >= 50) {
6882 Diag(P.second->getExprLoc(),
6883 diag::err_omp_defaultmap_no_attr_for_variable)
6884 << P.first << P.second->getSourceRange();
6885 Diag(DSAStack->getDefaultDSALocation(),
6886 diag::note_omp_defaultmap_attr_none);
6887 }
6888 }
6889
6890 llvm::SmallVector<OpenMPDirectiveKind, 4> AllowedNameModifiers;
6891 for (OpenMPDirectiveKind D : getLeafConstructsOrSelf(Kind)) {
6892 if (isAllowedClauseForDirective(D, OMPC_if, getLangOpts().OpenMP))
6893 AllowedNameModifiers.push_back(D);
6894 }
6895 if (!AllowedNameModifiers.empty())
6896 ErrorFound = checkIfClauses(SemaRef, Kind, Clauses, AllowedNameModifiers) ||
6897 ErrorFound;
6898
6899 if (ErrorFound)
6900 return StmtError();
6901
6902 if (!SemaRef.CurContext->isDependentContext() &&
6904 !(DSAStack->hasRequiresDeclWithClause<OMPUnifiedSharedMemoryClause>() ||
6905 DSAStack->hasRequiresDeclWithClause<OMPUnifiedAddressClause>() ||
6906 DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>() ||
6907 DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())) {
6908 // Register target to DSA Stack.
6909 DSAStack->addTargetDirLocation(StartLoc);
6910 }
6911
6912 return Res;
6913}
6914
6916 DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen,
6917 ArrayRef<Expr *> Uniforms, ArrayRef<Expr *> Aligneds,
6918 ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
6919 ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR) {
6920 assert(Aligneds.size() == Alignments.size());
6921 assert(Linears.size() == LinModifiers.size());
6922 assert(Linears.size() == Steps.size());
6923 if (!DG || DG.get().isNull())
6924 return DeclGroupPtrTy();
6925
6926 const int SimdId = 0;
6927 if (!DG.get().isSingleDecl()) {
6928 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
6929 << SimdId;
6930 return DG;
6931 }
6932 Decl *ADecl = DG.get().getSingleDecl();
6933 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
6934 ADecl = FTD->getTemplatedDecl();
6935
6936 auto *FD = dyn_cast<FunctionDecl>(ADecl);
6937 if (!FD) {
6938 Diag(ADecl->getLocation(), diag::err_omp_function_expected) << SimdId;
6939 return DeclGroupPtrTy();
6940 }
6941
6942 // OpenMP [2.8.2, declare simd construct, Description]
6943 // The parameter of the simdlen clause must be a constant positive integer
6944 // expression.
6945 ExprResult SL;
6946 if (Simdlen)
6947 SL = VerifyPositiveIntegerConstantInClause(Simdlen, OMPC_simdlen);
6948 // OpenMP [2.8.2, declare simd construct, Description]
6949 // The special this pointer can be used as if was one of the arguments to the
6950 // function in any of the linear, aligned, or uniform clauses.
6951 // The uniform clause declares one or more arguments to have an invariant
6952 // value for all concurrent invocations of the function in the execution of a
6953 // single SIMD loop.
6954 llvm::DenseMap<const Decl *, const Expr *> UniformedArgs;
6955 const Expr *UniformedLinearThis = nullptr;
6956 for (const Expr *E : Uniforms) {
6957 E = E->IgnoreParenImpCasts();
6958 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6959 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl()))
6960 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6961 FD->getParamDecl(PVD->getFunctionScopeIndex())
6962 ->getCanonicalDecl() == PVD->getCanonicalDecl()) {
6963 UniformedArgs.try_emplace(PVD->getCanonicalDecl(), E);
6964 continue;
6965 }
6966 if (isa<CXXThisExpr>(E)) {
6967 UniformedLinearThis = E;
6968 continue;
6969 }
6970 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
6971 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
6972 }
6973 // OpenMP [2.8.2, declare simd construct, Description]
6974 // The aligned clause declares that the object to which each list item points
6975 // is aligned to the number of bytes expressed in the optional parameter of
6976 // the aligned clause.
6977 // The special this pointer can be used as if was one of the arguments to the
6978 // function in any of the linear, aligned, or uniform clauses.
6979 // The type of list items appearing in the aligned clause must be array,
6980 // pointer, reference to array, or reference to pointer.
6981 llvm::DenseMap<const Decl *, const Expr *> AlignedArgs;
6982 const Expr *AlignedThis = nullptr;
6983 for (const Expr *E : Aligneds) {
6984 E = E->IgnoreParenImpCasts();
6985 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
6986 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
6987 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
6988 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
6989 FD->getParamDecl(PVD->getFunctionScopeIndex())
6990 ->getCanonicalDecl() == CanonPVD) {
6991 // OpenMP [2.8.1, simd construct, Restrictions]
6992 // A list-item cannot appear in more than one aligned clause.
6993 auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E);
6994 if (!Inserted) {
6995 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
6996 << 1 << getOpenMPClauseNameForDiag(OMPC_aligned)
6997 << E->getSourceRange();
6998 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
6999 << getOpenMPClauseNameForDiag(OMPC_aligned);
7000 continue;
7001 }
7002 QualType QTy = PVD->getType()
7003 .getNonReferenceType()
7004 .getUnqualifiedType()
7005 .getCanonicalType();
7006 const Type *Ty = QTy.getTypePtrOrNull();
7007 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
7008 Diag(E->getExprLoc(), diag::err_omp_aligned_expected_array_or_ptr)
7009 << QTy << getLangOpts().CPlusPlus << E->getSourceRange();
7010 Diag(PVD->getLocation(), diag::note_previous_decl) << PVD;
7011 }
7012 continue;
7013 }
7014 }
7015 if (isa<CXXThisExpr>(E)) {
7016 if (AlignedThis) {
7017 Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice)
7018 << 2 << getOpenMPClauseNameForDiag(OMPC_aligned)
7019 << E->getSourceRange();
7020 Diag(AlignedThis->getExprLoc(), diag::note_omp_explicit_dsa)
7021 << getOpenMPClauseNameForDiag(OMPC_aligned);
7022 }
7023 AlignedThis = E;
7024 continue;
7025 }
7026 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7027 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7028 }
7029 // The optional parameter of the aligned clause, alignment, must be a constant
7030 // positive integer expression. If no optional parameter is specified,
7031 // implementation-defined default alignments for SIMD instructions on the
7032 // target platforms are assumed.
7034 for (Expr *E : Alignments) {
7035 ExprResult Align;
7036 if (E)
7037 Align = VerifyPositiveIntegerConstantInClause(E, OMPC_aligned);
7038 NewAligns.push_back(Align.get());
7039 }
7040 // OpenMP [2.8.2, declare simd construct, Description]
7041 // The linear clause declares one or more list items to be private to a SIMD
7042 // lane and to have a linear relationship with respect to the iteration space
7043 // of a loop.
7044 // The special this pointer can be used as if was one of the arguments to the
7045 // function in any of the linear, aligned, or uniform clauses.
7046 // When a linear-step expression is specified in a linear clause it must be
7047 // either a constant integer expression or an integer-typed parameter that is
7048 // specified in a uniform clause on the directive.
7049 llvm::DenseMap<const Decl *, const Expr *> LinearArgs;
7050 const bool IsUniformedThis = UniformedLinearThis != nullptr;
7051 auto MI = LinModifiers.begin();
7052 for (const Expr *E : Linears) {
7053 auto LinKind = static_cast<OpenMPLinearClauseKind>(*MI);
7054 ++MI;
7055 E = E->IgnoreParenImpCasts();
7056 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
7057 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7058 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7059 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7060 FD->getParamDecl(PVD->getFunctionScopeIndex())
7061 ->getCanonicalDecl() == CanonPVD) {
7062 // OpenMP [2.15.3.7, linear Clause, Restrictions]
7063 // A list-item cannot appear in more than one linear clause.
7064 if (auto It = LinearArgs.find(CanonPVD); It != LinearArgs.end()) {
7065 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7066 << getOpenMPClauseNameForDiag(OMPC_linear)
7067 << getOpenMPClauseNameForDiag(OMPC_linear)
7068 << E->getSourceRange();
7069 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7070 << getOpenMPClauseNameForDiag(OMPC_linear);
7071 continue;
7072 }
7073 // Each argument can appear in at most one uniform or linear clause.
7074 if (auto It = UniformedArgs.find(CanonPVD);
7075 It != UniformedArgs.end()) {
7076 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7077 << getOpenMPClauseNameForDiag(OMPC_linear)
7078 << getOpenMPClauseNameForDiag(OMPC_uniform)
7079 << E->getSourceRange();
7080 Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa)
7081 << getOpenMPClauseNameForDiag(OMPC_uniform);
7082 continue;
7083 }
7084 LinearArgs[CanonPVD] = E;
7085 if (E->isValueDependent() || E->isTypeDependent() ||
7088 continue;
7089 (void)CheckOpenMPLinearDecl(CanonPVD, E->getExprLoc(), LinKind,
7090 PVD->getOriginalType(),
7091 /*IsDeclareSimd=*/true);
7092 continue;
7093 }
7094 }
7095 if (isa<CXXThisExpr>(E)) {
7096 if (UniformedLinearThis) {
7097 Diag(E->getExprLoc(), diag::err_omp_wrong_dsa)
7098 << getOpenMPClauseNameForDiag(OMPC_linear)
7099 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7100 : OMPC_linear)
7101 << E->getSourceRange();
7102 Diag(UniformedLinearThis->getExprLoc(), diag::note_omp_explicit_dsa)
7103 << getOpenMPClauseNameForDiag(IsUniformedThis ? OMPC_uniform
7104 : OMPC_linear);
7105 continue;
7106 }
7107 UniformedLinearThis = E;
7108 if (E->isValueDependent() || E->isTypeDependent() ||
7110 continue;
7111 (void)CheckOpenMPLinearDecl(/*D=*/nullptr, E->getExprLoc(), LinKind,
7112 E->getType(), /*IsDeclareSimd=*/true);
7113 continue;
7114 }
7115 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause)
7116 << FD->getDeclName() << (isa<CXXMethodDecl>(ADecl) ? 1 : 0);
7117 }
7118 Expr *Step = nullptr;
7119 Expr *NewStep = nullptr;
7120 SmallVector<Expr *, 4> NewSteps;
7121 for (Expr *E : Steps) {
7122 // Skip the same step expression, it was checked already.
7123 if (Step == E || !E) {
7124 NewSteps.push_back(E ? NewStep : nullptr);
7125 continue;
7126 }
7127 Step = E;
7128 if (const auto *DRE = dyn_cast<DeclRefExpr>(Step))
7129 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7130 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7131 if (UniformedArgs.count(CanonPVD) == 0) {
7132 Diag(Step->getExprLoc(), diag::err_omp_expected_uniform_param)
7133 << Step->getSourceRange();
7134 } else if (E->isValueDependent() || E->isTypeDependent() ||
7137 CanonPVD->getType()->hasIntegerRepresentation()) {
7138 NewSteps.push_back(Step);
7139 } else {
7140 Diag(Step->getExprLoc(), diag::err_omp_expected_int_param)
7141 << Step->getSourceRange();
7142 }
7143 continue;
7144 }
7145 NewStep = Step;
7146 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
7147 !Step->isInstantiationDependent() &&
7149 NewStep = PerformOpenMPImplicitIntegerConversion(Step->getExprLoc(), Step)
7150 .get();
7151 if (NewStep)
7152 NewStep = SemaRef
7153 .VerifyIntegerConstantExpression(
7154 NewStep, /*FIXME*/ AllowFoldKind::Allow)
7155 .get();
7156 }
7157 NewSteps.push_back(NewStep);
7158 }
7159 auto *NewAttr = OMPDeclareSimdDeclAttr::CreateImplicit(
7160 getASTContext(), BS, SL.get(), const_cast<Expr **>(Uniforms.data()),
7161 Uniforms.size(), const_cast<Expr **>(Aligneds.data()), Aligneds.size(),
7162 const_cast<Expr **>(NewAligns.data()), NewAligns.size(),
7163 const_cast<Expr **>(Linears.data()), Linears.size(),
7164 const_cast<unsigned *>(LinModifiers.data()), LinModifiers.size(),
7165 NewSteps.data(), NewSteps.size(), SR);
7166 ADecl->addAttr(NewAttr);
7167 return DG;
7168}
7169
7171 OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
7172 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
7173 SourceLocation EndLoc) {
7174 assert(isOpenMPInformationalDirective(Kind) &&
7175 "Unexpected directive category");
7176
7177 StmtResult Res = StmtError();
7178
7179 switch (Kind) {
7180 case OMPD_assume:
7181 Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
7182 break;
7183 default:
7184 llvm_unreachable("Unknown OpenMP directive");
7185 }
7186
7187 return Res;
7188}
7189
7190static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
7191 QualType NewType) {
7192 assert(NewType->isFunctionProtoType() &&
7193 "Expected function type with prototype.");
7194 assert(FD->getType()->isFunctionNoProtoType() &&
7195 "Expected function with type with no prototype.");
7196 assert(FDWithProto->getType()->isFunctionProtoType() &&
7197 "Expected function with prototype.");
7198 // Synthesize parameters with the same types.
7199 FD->setType(NewType);
7201 for (const ParmVarDecl *P : FDWithProto->parameters()) {
7202 auto *Param = ParmVarDecl::Create(S.getASTContext(), FD, SourceLocation(),
7203 SourceLocation(), nullptr, P->getType(),
7204 /*TInfo=*/nullptr, SC_None, nullptr);
7205 Param->setScopeInfo(0, Params.size());
7206 Param->setImplicit();
7207 Params.push_back(Param);
7208 }
7209
7210 FD->setParams(Params);
7211}
7212
7214 if (D->isInvalidDecl())
7215 return;
7216 FunctionDecl *FD = nullptr;
7217 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7218 FD = UTemplDecl->getTemplatedDecl();
7219 else
7220 FD = cast<FunctionDecl>(D);
7221 assert(FD && "Expected a function declaration!");
7222
7223 // If we are instantiating templates we do *not* apply scoped assumptions but
7224 // only global ones. We apply scoped assumption to the template definition
7225 // though.
7226 if (!SemaRef.inTemplateInstantiation()) {
7227 for (OMPAssumeAttr *AA : OMPAssumeScoped)
7228 FD->addAttr(AA);
7229 }
7230 for (OMPAssumeAttr *AA : OMPAssumeGlobal)
7231 FD->addAttr(AA);
7232}
7233
7234SemaOpenMP::OMPDeclareVariantScope::OMPDeclareVariantScope(OMPTraitInfo &TI)
7235 : TI(&TI), NameSuffix(TI.getMangledName()) {}
7236
7238 Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists,
7240 if (!D.getIdentifier())
7241 return;
7242
7243 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7244
7245 // Template specialization is an extension, check if we do it.
7246 bool IsTemplated = !TemplateParamLists.empty();
7247 if (IsTemplated &&
7248 !DVScope.TI->isExtensionActive(
7249 llvm::omp::TraitProperty::implementation_extension_allow_templates))
7250 return;
7251
7252 const IdentifierInfo *BaseII = D.getIdentifier();
7255 SemaRef.LookupParsedName(Lookup, S, &D.getCXXScopeSpec(),
7256 /*ObjectType=*/QualType());
7257
7258 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
7259 QualType FType = TInfo->getType();
7260
7261 bool IsConstexpr =
7263 bool IsConsteval =
7265
7266 for (auto *Candidate : Lookup) {
7267 auto *CandidateDecl = Candidate->getUnderlyingDecl();
7268 FunctionDecl *UDecl = nullptr;
7269 if (IsTemplated && isa<FunctionTemplateDecl>(CandidateDecl)) {
7270 auto *FTD = cast<FunctionTemplateDecl>(CandidateDecl);
7271 // FIXME: Should this compare the template parameter lists on all levels?
7272 if (SemaRef.Context.isSameTemplateParameterList(
7273 FTD->getTemplateParameters(), TemplateParamLists.back()))
7274 UDecl = FTD->getTemplatedDecl();
7275 } else if (!IsTemplated)
7276 UDecl = dyn_cast<FunctionDecl>(CandidateDecl);
7277 if (!UDecl)
7278 continue;
7279
7280 // Don't specialize constexpr/consteval functions with
7281 // non-constexpr/consteval functions.
7282 if (UDecl->isConstexpr() && !IsConstexpr)
7283 continue;
7284 if (UDecl->isConsteval() && !IsConsteval)
7285 continue;
7286
7287 QualType UDeclTy = UDecl->getType();
7288 if (!UDeclTy->isDependentType()) {
7290 FType, UDeclTy, /*OfBlockPointer=*/false,
7291 /*Unqualified=*/false, /*AllowCXX=*/true);
7292 if (NewType.isNull())
7293 continue;
7294 }
7295
7296 // Found a base!
7297 Bases.push_back(UDecl);
7298 }
7299
7300 bool UseImplicitBase = !DVScope.TI->isExtensionActive(
7301 llvm::omp::TraitProperty::implementation_extension_disable_implicit_base);
7302 // If no base was found we create a declaration that we use as base.
7303 if (Bases.empty() && UseImplicitBase) {
7305 Decl *BaseD = SemaRef.HandleDeclarator(S, D, TemplateParamLists);
7306 BaseD->setImplicit(true);
7307 if (auto *BaseTemplD = dyn_cast<FunctionTemplateDecl>(BaseD))
7308 Bases.push_back(BaseTemplD->getTemplatedDecl());
7309 else
7310 Bases.push_back(cast<FunctionDecl>(BaseD));
7311 }
7312
7313 std::string MangledName;
7314 MangledName += D.getIdentifier()->getName();
7315 MangledName += getOpenMPVariantManglingSeparatorStr();
7316 MangledName += DVScope.NameSuffix;
7317 IdentifierInfo &VariantII = getASTContext().Idents.get(MangledName);
7318
7319 VariantII.setMangledOpenMPVariantName(true);
7320 D.SetIdentifier(&VariantII, D.getBeginLoc());
7321}
7322
7325 // Do not mark function as is used to prevent its emission if this is the
7326 // only place where it is used.
7329
7330 FunctionDecl *FD = nullptr;
7331 if (auto *UTemplDecl = dyn_cast<FunctionTemplateDecl>(D))
7332 FD = UTemplDecl->getTemplatedDecl();
7333 else
7334 FD = cast<FunctionDecl>(D);
7335 auto *VariantFuncRef = DeclRefExpr::Create(
7337 /*RefersToEnclosingVariableOrCapture=*/false,
7338 /*NameLoc=*/FD->getLocation(), FD->getType(), ExprValueKind::VK_PRValue);
7339
7340 OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
7341 auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
7342 getASTContext(), VariantFuncRef, DVScope.TI,
7343 /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
7344 /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0,
7345 /*NeedDeviceAddrArgs=*/nullptr, /*NeedDeviceAddrArgsSize=*/0,
7346 /*AppendArgs=*/nullptr, /*AppendArgsSize=*/0);
7347 for (FunctionDecl *BaseFD : Bases)
7348 BaseFD->addAttr(OMPDeclareVariantA);
7349}
7350
7352 SourceLocation LParenLoc,
7353 MultiExprArg ArgExprs,
7354 SourceLocation RParenLoc,
7355 Expr *ExecConfig) {
7356 // The common case is a regular call we do not want to specialize at all. Try
7357 // to make that case fast by bailing early.
7358 CallExpr *CE = dyn_cast<CallExpr>(Call.get());
7359 if (!CE)
7360 return Call;
7361
7362 FunctionDecl *CalleeFnDecl = CE->getDirectCallee();
7363
7364 // Mark indirect calls inside target regions, to allow for insertion of
7365 // __llvm_omp_indirect_call_lookup calls during codegen.
7366 if (!CalleeFnDecl) {
7368 Expr *E = CE->getCallee()->IgnoreParenImpCasts();
7369 DeclRefExpr *DRE = nullptr;
7370 while (E) {
7371 if ((DRE = dyn_cast<DeclRefExpr>(E)))
7372 break;
7373 if (auto *ME = dyn_cast<MemberExpr>(E))
7374 E = ME->getBase()->IgnoreParenImpCasts();
7375 else if (auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
7376 E = ASE->getBase()->IgnoreParenImpCasts();
7377 else
7378 break;
7379 }
7380 VarDecl *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) : nullptr;
7381 if (VD && !VD->hasAttr<OMPTargetIndirectCallAttr>()) {
7382 VD->addAttr(OMPTargetIndirectCallAttr::CreateImplicit(getASTContext()));
7383 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
7384 ML->DeclarationMarkedOpenMPIndirectCall(VD);
7385 }
7386 }
7387
7388 return Call;
7389 }
7390
7391 if (getLangOpts().OpenMP >= 50 && getLangOpts().OpenMP <= 60 &&
7392 CalleeFnDecl->getIdentifier() &&
7393 CalleeFnDecl->getName().starts_with_insensitive("omp_")) {
7394 // checking for any calls inside an Order region
7396 Diag(LParenLoc, diag::err_omp_unexpected_call_to_omp_runtime_api);
7397 }
7398
7399 if (!CalleeFnDecl->hasAttr<OMPDeclareVariantAttr>())
7400 return Call;
7401
7402 ASTContext &Context = getASTContext();
7403 std::function<void(StringRef)> DiagUnknownTrait = [this,
7404 CE](StringRef ISATrait) {
7405 // TODO Track the selector locations in a way that is accessible here to
7406 // improve the diagnostic location.
7407 Diag(CE->getBeginLoc(), diag::warn_unknown_declare_variant_isa_trait)
7408 << ISATrait;
7409 };
7410 TargetOMPContext OMPCtx(Context, std::move(DiagUnknownTrait),
7411 SemaRef.getCurFunctionDecl(),
7412 DSAStack->getConstructTraits(), getOpenMPDeviceNum());
7413
7414 QualType CalleeFnType = CalleeFnDecl->getType();
7415
7418 while (CalleeFnDecl) {
7419 for (OMPDeclareVariantAttr *A :
7420 CalleeFnDecl->specific_attrs<OMPDeclareVariantAttr>()) {
7421 Expr *VariantRef = A->getVariantFuncRef();
7422
7423 VariantMatchInfo VMI;
7424 OMPTraitInfo &TI = A->getTraitInfo();
7425 TI.getAsVariantMatchInfo(Context, VMI);
7426 if (!isVariantApplicableInContext(VMI, OMPCtx,
7427 /*DeviceSetOnly=*/false))
7428 continue;
7429
7430 VMIs.push_back(VMI);
7431 Exprs.push_back(VariantRef);
7432 }
7433
7434 CalleeFnDecl = CalleeFnDecl->getPreviousDecl();
7435 }
7436
7437 ExprResult NewCall;
7438 do {
7439 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
7440 if (BestIdx < 0)
7441 return Call;
7442 Expr *BestExpr = cast<DeclRefExpr>(Exprs[BestIdx]);
7443 Decl *BestDecl = cast<DeclRefExpr>(BestExpr)->getDecl();
7444
7445 {
7446 // Try to build a (member) call expression for the current best applicable
7447 // variant expression. We allow this to fail in which case we continue
7448 // with the next best variant expression. The fail case is part of the
7449 // implementation defined behavior in the OpenMP standard when it talks
7450 // about what differences in the function prototypes: "Any differences
7451 // that the specific OpenMP context requires in the prototype of the
7452 // variant from the base function prototype are implementation defined."
7453 // This wording is there to allow the specialized variant to have a
7454 // different type than the base function. This is intended and OK but if
7455 // we cannot create a call the difference is not in the "implementation
7456 // defined range" we allow.
7458
7459 if (auto *SpecializedMethod = dyn_cast<CXXMethodDecl>(BestDecl)) {
7460 auto *MemberCall = dyn_cast<CXXMemberCallExpr>(CE);
7461 BestExpr = MemberExpr::CreateImplicit(
7462 Context, MemberCall->getImplicitObjectArgument(),
7463 /*IsArrow=*/false, SpecializedMethod, Context.BoundMemberTy,
7464 MemberCall->getValueKind(), MemberCall->getObjectKind());
7465 }
7466 NewCall = SemaRef.BuildCallExpr(Scope, BestExpr, LParenLoc, ArgExprs,
7467 RParenLoc, ExecConfig);
7468 if (NewCall.isUsable()) {
7469 if (CallExpr *NCE = dyn_cast<CallExpr>(NewCall.get())) {
7470 FunctionDecl *NewCalleeFnDecl = NCE->getDirectCallee();
7472 CalleeFnType, NewCalleeFnDecl->getType(),
7473 /*OfBlockPointer=*/false,
7474 /*Unqualified=*/false, /*AllowCXX=*/true);
7475 if (!NewType.isNull())
7476 break;
7477 // Don't use the call if the function type was not compatible.
7478 NewCall = nullptr;
7479 }
7480 }
7481 }
7482
7483 VMIs.erase(VMIs.begin() + BestIdx);
7484 Exprs.erase(Exprs.begin() + BestIdx);
7485 } while (!VMIs.empty());
7486
7487 if (!NewCall.isUsable())
7488 return Call;
7489 return PseudoObjectExpr::Create(getASTContext(), CE, {NewCall.get()}, 0);
7490}
7491
7492std::optional<std::pair<FunctionDecl *, Expr *>>
7494 Expr *VariantRef,
7495 OMPTraitInfo &TI,
7496 unsigned NumAppendArgs,
7497 SourceRange SR) {
7498 ASTContext &Context = getASTContext();
7499 if (!DG || DG.get().isNull())
7500 return std::nullopt;
7501
7502 const int VariantId = 1;
7503 // Must be applied only to single decl.
7504 if (!DG.get().isSingleDecl()) {
7505 Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
7506 << VariantId << SR;
7507 return std::nullopt;
7508 }
7509 Decl *ADecl = DG.get().getSingleDecl();
7510 if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
7511 ADecl = FTD->getTemplatedDecl();
7512
7513 // Decl must be a function.
7514 auto *FD = dyn_cast<FunctionDecl>(ADecl);
7515 if (!FD) {
7516 Diag(ADecl->getLocation(), diag::err_omp_function_expected)
7517 << VariantId << SR;
7518 return std::nullopt;
7519 }
7520
7521 auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
7522 // The 'target' attribute needs to be separately checked because it does
7523 // not always signify a multiversion function declaration.
7524 return FD->isMultiVersion() || FD->hasAttr<TargetAttr>();
7525 };
7526 // OpenMP is not compatible with multiversion function attributes.
7527 if (HasMultiVersionAttributes(FD)) {
7528 Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
7529 << SR;
7530 return std::nullopt;
7531 }
7532
7533 // Allow #pragma omp declare variant only if the function is not used.
7534 if (FD->isUsed(false))
7535 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_used)
7536 << FD->getLocation();
7537
7538 // Check if the function was emitted already.
7539 const FunctionDecl *Definition;
7540 if (!FD->isThisDeclarationADefinition() && FD->isDefined(Definition) &&
7541 (getLangOpts().EmitAllDecls || Context.DeclMustBeEmitted(Definition)))
7542 Diag(SR.getBegin(), diag::warn_omp_declare_variant_after_emitted)
7543 << FD->getLocation();
7544
7545 // The VariantRef must point to function.
7546 if (!VariantRef) {
7547 Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
7548 return std::nullopt;
7549 }
7550
7551 auto ShouldDelayChecks = [](Expr *&E, bool) {
7552 return E && (E->isTypeDependent() || E->isValueDependent() ||
7555 };
7556 // Do not check templates, wait until instantiation.
7557 if (FD->isDependentContext() || ShouldDelayChecks(VariantRef, false) ||
7558 TI.anyScoreOrCondition(ShouldDelayChecks))
7559 return std::make_pair(FD, VariantRef);
7560
7561 // Deal with non-constant score and user condition expressions.
7562 auto HandleNonConstantScoresAndConditions = [this](Expr *&E,
7563 bool IsScore) -> bool {
7564 if (!E || E->isIntegerConstantExpr(getASTContext()))
7565 return false;
7566
7567 if (IsScore) {
7568 // We warn on non-constant scores and pretend they were not present.
7569 Diag(E->getExprLoc(), diag::warn_omp_declare_variant_score_not_constant)
7570 << E;
7571 E = nullptr;
7572 } else {
7573 // We could replace a non-constant user condition with "false" but we
7574 // will soon need to handle these anyway for the dynamic version of
7575 // OpenMP context selectors.
7576 Diag(E->getExprLoc(),
7577 diag::err_omp_declare_variant_user_condition_not_constant)
7578 << E;
7579 }
7580 return true;
7581 };
7582 if (TI.anyScoreOrCondition(HandleNonConstantScoresAndConditions))
7583 return std::nullopt;
7584
7585 QualType AdjustedFnType = FD->getType();
7586 if (NumAppendArgs) {
7587 const auto *PTy = AdjustedFnType->getAsAdjusted<FunctionProtoType>();
7588 if (!PTy) {
7589 Diag(FD->getLocation(), diag::err_omp_declare_variant_prototype_required)
7590 << SR;
7591 return std::nullopt;
7592 }
7593 // Adjust the function type to account for an extra omp_interop_t for each
7594 // specified in the append_args clause.
7595 const TypeDecl *TD = nullptr;
7596 LookupResult Result(SemaRef, &Context.Idents.get("omp_interop_t"),
7598 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
7599 NamedDecl *ND = Result.getFoundDecl();
7600 TD = dyn_cast_or_null<TypeDecl>(ND);
7601 }
7602 if (!TD) {
7603 Diag(SR.getBegin(), diag::err_omp_interop_type_not_found) << SR;
7604 return std::nullopt;
7605 }
7606 QualType InteropType =
7607 Context.getTypeDeclType(ElaboratedTypeKeyword::None,
7608 /*Qualifier=*/std::nullopt, TD);
7609 if (PTy->isVariadic()) {
7610 Diag(FD->getLocation(), diag::err_omp_append_args_with_varargs) << SR;
7611 return std::nullopt;
7612 }
7614 Params.append(PTy->param_type_begin(), PTy->param_type_end());
7615 Params.insert(Params.end(), NumAppendArgs, InteropType);
7616 AdjustedFnType = Context.getFunctionType(PTy->getReturnType(), Params,
7617 PTy->getExtProtoInfo());
7618 }
7619
7620 // Convert VariantRef expression to the type of the original function to
7621 // resolve possible conflicts.
7622 ExprResult VariantRefCast = VariantRef;
7623 if (getLangOpts().CPlusPlus) {
7624 QualType FnPtrType;
7625 auto *Method = dyn_cast<CXXMethodDecl>(FD);
7626 if (Method && !Method->isStatic()) {
7627 FnPtrType = Context.getMemberPointerType(
7628 AdjustedFnType, /*Qualifier=*/std::nullopt, Method->getParent());
7629 ExprResult ER;
7630 {
7631 // Build addr_of unary op to correctly handle type checks for member
7632 // functions.
7634 ER = SemaRef.CreateBuiltinUnaryOp(VariantRef->getBeginLoc(), UO_AddrOf,
7635 VariantRef);
7636 }
7637 if (!ER.isUsable()) {
7638 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7639 << VariantId << VariantRef->getSourceRange();
7640 return std::nullopt;
7641 }
7642 VariantRef = ER.get();
7643 } else {
7644 FnPtrType = Context.getPointerType(AdjustedFnType);
7645 }
7646 QualType VarianPtrType = Context.getPointerType(VariantRef->getType());
7647 if (VarianPtrType.getUnqualifiedType() != FnPtrType.getUnqualifiedType()) {
7648 ImplicitConversionSequence ICS = SemaRef.TryImplicitConversion(
7649 VariantRef, FnPtrType.getUnqualifiedType(),
7650 /*SuppressUserConversions=*/false, Sema::AllowedExplicit::None,
7651 /*InOverloadResolution=*/false,
7652 /*CStyle=*/false,
7653 /*AllowObjCWritebackConversion=*/false);
7654 if (ICS.isFailure()) {
7655 Diag(VariantRef->getExprLoc(),
7656 diag::err_omp_declare_variant_incompat_types)
7657 << VariantRef->getType()
7658 << ((Method && !Method->isStatic()) ? FnPtrType : FD->getType())
7659 << (NumAppendArgs ? 1 : 0) << VariantRef->getSourceRange();
7660 return std::nullopt;
7661 }
7662 VariantRefCast = SemaRef.PerformImplicitConversion(
7663 VariantRef, FnPtrType.getUnqualifiedType(),
7665 if (!VariantRefCast.isUsable())
7666 return std::nullopt;
7667 }
7668 // Drop previously built artificial addr_of unary op for member functions.
7669 if (Method && !Method->isStatic()) {
7670 Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
7671 if (auto *UO = dyn_cast<UnaryOperator>(
7672 PossibleAddrOfVariantRef->IgnoreImplicit()))
7673 VariantRefCast = UO->getSubExpr();
7674 }
7675 }
7676
7677 ExprResult ER = SemaRef.CheckPlaceholderExpr(VariantRefCast.get());
7678 if (!ER.isUsable() ||
7680 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7681 << VariantId << VariantRef->getSourceRange();
7682 return std::nullopt;
7683 }
7684
7685 // The VariantRef must point to function.
7686 auto *DRE = dyn_cast<DeclRefExpr>(ER.get()->IgnoreParenImpCasts());
7687 if (!DRE) {
7688 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7689 << VariantId << VariantRef->getSourceRange();
7690 return std::nullopt;
7691 }
7692 auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
7693 if (!NewFD) {
7694 Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
7695 << VariantId << VariantRef->getSourceRange();
7696 return std::nullopt;
7697 }
7698
7699 if (FD->getCanonicalDecl() == NewFD->getCanonicalDecl()) {
7700 Diag(VariantRef->getExprLoc(),
7701 diag::err_omp_declare_variant_same_base_function)
7702 << VariantRef->getSourceRange();
7703 return std::nullopt;
7704 }
7705
7706 // Check if function types are compatible in C.
7707 if (!getLangOpts().CPlusPlus) {
7708 QualType NewType =
7709 Context.mergeFunctionTypes(AdjustedFnType, NewFD->getType());
7710 if (NewType.isNull()) {
7711 Diag(VariantRef->getExprLoc(),
7712 diag::err_omp_declare_variant_incompat_types)
7713 << NewFD->getType() << FD->getType() << (NumAppendArgs ? 1 : 0)
7714 << VariantRef->getSourceRange();
7715 return std::nullopt;
7716 }
7717 if (NewType->isFunctionProtoType()) {
7718 if (FD->getType()->isFunctionNoProtoType())
7719 setPrototype(SemaRef, FD, NewFD, NewType);
7720 else if (NewFD->getType()->isFunctionNoProtoType())
7721 setPrototype(SemaRef, NewFD, FD, NewType);
7722 }
7723 }
7724
7725 // Check if variant function is not marked with declare variant directive.
7726 if (NewFD->hasAttrs() && NewFD->hasAttr<OMPDeclareVariantAttr>()) {
7727 Diag(VariantRef->getExprLoc(),
7728 diag::warn_omp_declare_variant_marked_as_declare_variant)
7729 << VariantRef->getSourceRange();
7730 SourceRange SR =
7731 NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
7732 Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
7733 return std::nullopt;
7734 }
7735
7736 enum DoesntSupport {
7737 VirtFuncs = 1,
7738 Constructors = 3,
7739 Destructors = 4,
7740 DeletedFuncs = 5,
7741 DefaultedFuncs = 6,
7742 ConstexprFuncs = 7,
7743 ConstevalFuncs = 8,
7744 };
7745 if (const auto *CXXFD = dyn_cast<CXXMethodDecl>(FD)) {
7746 if (CXXFD->isVirtual()) {
7747 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7748 << VirtFuncs;
7749 return std::nullopt;
7750 }
7751
7752 if (isa<CXXConstructorDecl>(FD)) {
7753 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7754 << Constructors;
7755 return std::nullopt;
7756 }
7757
7758 if (isa<CXXDestructorDecl>(FD)) {
7759 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7760 << Destructors;
7761 return std::nullopt;
7762 }
7763 }
7764
7765 if (FD->isDeleted()) {
7766 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7767 << DeletedFuncs;
7768 return std::nullopt;
7769 }
7770
7771 if (FD->isDefaulted()) {
7772 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7773 << DefaultedFuncs;
7774 return std::nullopt;
7775 }
7776
7777 if (FD->isConstexpr()) {
7778 Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
7779 << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
7780 return std::nullopt;
7781 }
7782
7783 // Check general compatibility.
7784 if (SemaRef.areMultiversionVariantFunctionsCompatible(
7789 VariantRef->getExprLoc(),
7790 SemaRef.PDiag(diag::err_omp_declare_variant_doesnt_support)),
7791 PartialDiagnosticAt(VariantRef->getExprLoc(),
7792 SemaRef.PDiag(diag::err_omp_declare_variant_diff)
7793 << FD->getLocation()),
7794 /*TemplatesSupported=*/true, /*ConstexprSupported=*/false,
7795 /*CLinkageMayDiffer=*/true))
7796 return std::nullopt;
7797 return std::make_pair(FD, cast<Expr>(DRE));
7798}
7799
7801 FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
7802 ArrayRef<Expr *> AdjustArgsNothing,
7803 ArrayRef<Expr *> AdjustArgsNeedDevicePtr,
7804 ArrayRef<Expr *> AdjustArgsNeedDeviceAddr,
7805 ArrayRef<OMPInteropInfo> AppendArgs, SourceLocation AdjustArgsLoc,
7806 SourceLocation AppendArgsLoc, SourceRange SR) {
7807
7808 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7809 // An adjust_args clause or append_args clause can only be specified if the
7810 // dispatch selector of the construct selector set appears in the match
7811 // clause.
7812
7813 SmallVector<Expr *, 8> AllAdjustArgs;
7814 llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
7815 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
7816 llvm::append_range(AllAdjustArgs, AdjustArgsNeedDeviceAddr);
7817
7818 if (!AllAdjustArgs.empty() || !AppendArgs.empty()) {
7819 VariantMatchInfo VMI;
7821 if (!llvm::is_contained(
7822 VMI.ConstructTraits,
7823 llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
7824 if (!AllAdjustArgs.empty())
7825 Diag(AdjustArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7826 << getOpenMPClauseNameForDiag(OMPC_adjust_args);
7827 if (!AppendArgs.empty())
7828 Diag(AppendArgsLoc, diag::err_omp_clause_requires_dispatch_construct)
7829 << getOpenMPClauseNameForDiag(OMPC_append_args);
7830 return;
7831 }
7832 }
7833
7834 // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
7835 // Each argument can only appear in a single adjust_args clause for each
7836 // declare variant directive.
7838
7839 for (Expr *E : AllAdjustArgs) {
7840 E = E->IgnoreParenImpCasts();
7841 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7842 if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
7843 const VarDecl *CanonPVD = PVD->getCanonicalDecl();
7844 if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
7845 FD->getParamDecl(PVD->getFunctionScopeIndex())
7846 ->getCanonicalDecl() == CanonPVD) {
7847 // It's a parameter of the function, check duplicates.
7848 if (!AdjustVars.insert(CanonPVD).second) {
7849 Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
7850 << PVD;
7851 return;
7852 }
7853 continue;
7854 }
7855 }
7856 }
7857 // Anything that is not a function parameter is an error.
7858 Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
7859 return;
7860 }
7861
7862 // OpenMP 6.0 [9.6.2 (page 332, line 31-33, adjust_args clause, Restrictions]
7863 // If the `need_device_addr` adjust-op modifier is present, each list item
7864 // that appears in the clause must refer to an argument in the declaration of
7865 // the function variant that has a reference type
7866 if (getLangOpts().OpenMP >= 60) {
7867 for (Expr *E : AdjustArgsNeedDeviceAddr) {
7868 E = E->IgnoreParenImpCasts();
7869 if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
7870 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
7871 if (!VD->getType()->isReferenceType())
7872 Diag(E->getExprLoc(),
7873 diag::err_omp_non_by_ref_need_device_addr_modifier_argument);
7874 }
7875 }
7876 }
7877 }
7878
7879 auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
7880 getASTContext(), VariantRef, &TI,
7881 const_cast<Expr **>(AdjustArgsNothing.data()), AdjustArgsNothing.size(),
7882 const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
7883 AdjustArgsNeedDevicePtr.size(),
7884 const_cast<Expr **>(AdjustArgsNeedDeviceAddr.data()),
7885 AdjustArgsNeedDeviceAddr.size(),
7886 const_cast<OMPInteropInfo *>(AppendArgs.data()), AppendArgs.size(), SR);
7887 FD->addAttr(NewAttr);
7888}
7889
7890static CapturedStmt *
7892 auto *CS = dyn_cast<CapturedStmt>(AStmt);
7893 assert(CS && "Captured statement expected");
7894 // 1.2.2 OpenMP Language Terminology
7895 // Structured block - An executable statement with a single entry at the
7896 // top and a single exit at the bottom.
7897 // The point of exit cannot be a branch out of the structured block.
7898 // longjmp() and throw() must not violate the entry/exit criteria.
7899 CS->getCapturedDecl()->setNothrow();
7900
7901 for (int ThisCaptureLevel = SemaRef.OpenMP().getOpenMPCaptureLevels(DKind);
7902 ThisCaptureLevel > 1; --ThisCaptureLevel) {
7904 // 1.2.2 OpenMP Language Terminology
7905 // Structured block - An executable statement with a single entry at the
7906 // top and a single exit at the bottom.
7907 // The point of exit cannot be a branch out of the structured block.
7908 // longjmp() and throw() must not violate the entry/exit criteria.
7909 CS->getCapturedDecl()->setNothrow();
7910 }
7912 return CS;
7913}
7914
7917 Stmt *AStmt, SourceLocation StartLoc,
7918 SourceLocation EndLoc) {
7919 if (!AStmt)
7920 return StmtError();
7921
7922 setBranchProtectedScope(SemaRef, OMPD_parallel, AStmt);
7923
7924 return OMPParallelDirective::Create(
7925 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
7926 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
7927}
7928
7929namespace {
7930/// Iteration space of a single for loop.
7931struct LoopIterationSpace final {
7932 /// True if the condition operator is the strict compare operator (<, > or
7933 /// !=).
7934 bool IsStrictCompare = false;
7935 /// Condition of the loop.
7936 Expr *PreCond = nullptr;
7937 /// This expression calculates the number of iterations in the loop.
7938 /// It is always possible to calculate it before starting the loop.
7939 Expr *NumIterations = nullptr;
7940 /// The loop counter variable.
7941 Expr *CounterVar = nullptr;
7942 /// Private loop counter variable.
7943 Expr *PrivateCounterVar = nullptr;
7944 /// This is initializer for the initial value of #CounterVar.
7945 Expr *CounterInit = nullptr;
7946 /// This is step for the #CounterVar used to generate its update:
7947 /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
7948 Expr *CounterStep = nullptr;
7949 /// Should step be subtracted?
7950 bool Subtract = false;
7951 /// Source range of the loop init.
7952 SourceRange InitSrcRange;
7953 /// Source range of the loop condition.
7954 SourceRange CondSrcRange;
7955 /// Source range of the loop increment.
7956 SourceRange IncSrcRange;
7957 /// Minimum value that can have the loop control variable. Used to support
7958 /// non-rectangular loops. Applied only for LCV with the non-iterator types,
7959 /// since only such variables can be used in non-loop invariant expressions.
7960 Expr *MinValue = nullptr;
7961 /// Maximum value that can have the loop control variable. Used to support
7962 /// non-rectangular loops. Applied only for LCV with the non-iterator type,
7963 /// since only such variables can be used in non-loop invariant expressions.
7964 Expr *MaxValue = nullptr;
7965 /// true, if the lower bound depends on the outer loop control var.
7966 bool IsNonRectangularLB = false;
7967 /// true, if the upper bound depends on the outer loop control var.
7968 bool IsNonRectangularUB = false;
7969 /// Index of the loop this loop depends on and forms non-rectangular loop
7970 /// nest.
7971 unsigned LoopDependentIdx = 0;
7972 /// Final condition for the non-rectangular loop nest support. It is used to
7973 /// check that the number of iterations for this particular counter must be
7974 /// finished.
7975 Expr *FinalCondition = nullptr;
7976};
7977
7978/// Scan an AST subtree, checking that no decls in the CollapsedLoopVarDecls
7979/// set are referenced. Used for verifying loop nest structure before
7980/// performing a loop collapse operation.
7981class ForSubExprChecker : public DynamicRecursiveASTVisitor {
7982 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
7983 VarDecl *ForbiddenVar = nullptr;
7984 SourceRange ErrLoc;
7985
7986public:
7987 explicit ForSubExprChecker(
7988 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls)
7989 : CollapsedLoopVarDecls(CollapsedLoopVarDecls) {
7990 // We want to visit implicit code, i.e. synthetic initialisation statements
7991 // created during range-for lowering.
7992 ShouldVisitImplicitCode = true;
7993 }
7994
7995 bool VisitDeclRefExpr(DeclRefExpr *E) override {
7996 ValueDecl *VD = E->getDecl();
7998 return true;
7999 VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
8000 if (V->getType()->isReferenceType()) {
8001 VarDecl *VD = V->getDefinition();
8002 if (VD->hasInit()) {
8003 Expr *I = VD->getInit();
8004 DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
8005 if (!DRE)
8006 return true;
8008 }
8009 }
8010 Decl *Canon = V->getCanonicalDecl();
8011 if (CollapsedLoopVarDecls.contains(Canon)) {
8012 ForbiddenVar = V;
8013 ErrLoc = E->getSourceRange();
8014 return false;
8015 }
8016
8017 return true;
8018 }
8019
8020 VarDecl *getForbiddenVar() const { return ForbiddenVar; }
8021 SourceRange getErrRange() const { return ErrLoc; }
8022};
8023
8024/// Helper class for checking canonical form of the OpenMP loops and
8025/// extracting iteration space of each loop in the loop nest, that will be used
8026/// for IR generation.
8027class OpenMPIterationSpaceChecker {
8028 /// Reference to Sema.
8029 Sema &SemaRef;
8030 /// Does the loop associated directive support non-rectangular loops?
8031 bool SupportsNonRectangular;
8032 /// Data-sharing stack.
8033 DSAStackTy &Stack;
8034 /// A location for diagnostics (when there is no some better location).
8035 SourceLocation DefaultLoc;
8036 /// A location for diagnostics (when increment is not compatible).
8037 SourceLocation ConditionLoc;
8038 /// The set of variables declared within the (to be collapsed) loop nest.
8039 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls;
8040 /// A source location for referring to loop init later.
8041 SourceRange InitSrcRange;
8042 /// A source location for referring to condition later.
8043 SourceRange ConditionSrcRange;
8044 /// A source location for referring to increment later.
8045 SourceRange IncrementSrcRange;
8046 /// Loop variable.
8047 ValueDecl *LCDecl = nullptr;
8048 /// Reference to loop variable.
8049 Expr *LCRef = nullptr;
8050 /// Lower bound (initializer for the var).
8051 Expr *LB = nullptr;
8052 /// Upper bound.
8053 Expr *UB = nullptr;
8054 /// Loop step (increment).
8055 Expr *Step = nullptr;
8056 /// This flag is true when condition is one of:
8057 /// Var < UB
8058 /// Var <= UB
8059 /// UB > Var
8060 /// UB >= Var
8061 /// This will have no value when the condition is !=
8062 std::optional<bool> TestIsLessOp;
8063 /// This flag is true when condition is strict ( < or > ).
8064 bool TestIsStrictOp = false;
8065 /// This flag is true when step is subtracted on each iteration.
8066 bool SubtractStep = false;
8067 /// The outer loop counter this loop depends on (if any).
8068 const ValueDecl *DepDecl = nullptr;
8069 /// Contains number of loop (starts from 1) on which loop counter init
8070 /// expression of this loop depends on.
8071 std::optional<unsigned> InitDependOnLC;
8072 /// Contains number of loop (starts from 1) on which loop counter condition
8073 /// expression of this loop depends on.
8074 std::optional<unsigned> CondDependOnLC;
8075 /// Checks if the provide statement depends on the loop counter.
8076 std::optional<unsigned> doesDependOnLoopCounter(const Stmt *S,
8077 bool IsInitializer);
8078 /// Original condition required for checking of the exit condition for
8079 /// non-rectangular loop.
8080 Expr *Condition = nullptr;
8081
8082public:
8083 OpenMPIterationSpaceChecker(
8084 Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
8085 SourceLocation DefaultLoc,
8086 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopDecls)
8087 : SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
8088 Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
8089 CollapsedLoopVarDecls(CollapsedLoopDecls) {}
8090 /// Check init-expr for canonical loop form and save loop counter
8091 /// variable - #Var and its initialization value - #LB.
8092 bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
8093 /// Check test-expr for canonical form, save upper-bound (#UB), flags
8094 /// for less/greater and for strict/non-strict comparison.
8095 bool checkAndSetCond(Expr *S);
8096 /// Check incr-expr for canonical loop form and return true if it
8097 /// does not conform, otherwise save loop step (#Step).
8098 bool checkAndSetInc(Expr *S);
8099 /// Return the loop counter variable.
8100 ValueDecl *getLoopDecl() const { return LCDecl; }
8101 /// Return the reference expression to loop counter variable.
8102 Expr *getLoopDeclRefExpr() const { return LCRef; }
8103 /// Source range of the loop init.
8104 SourceRange getInitSrcRange() const { return InitSrcRange; }
8105 /// Source range of the loop condition.
8106 SourceRange getConditionSrcRange() const { return ConditionSrcRange; }
8107 /// Source range of the loop increment.
8108 SourceRange getIncrementSrcRange() const { return IncrementSrcRange; }
8109 /// True if the step should be subtracted.
8110 bool shouldSubtractStep() const { return SubtractStep; }
8111 /// True, if the compare operator is strict (<, > or !=).
8112 bool isStrictTestOp() const { return TestIsStrictOp; }
8113 /// Build the expression to calculate the number of iterations.
8114 Expr *buildNumIterations(
8115 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8116 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8117 /// Build the precondition expression for the loops.
8118 Expr *
8119 buildPreCond(Scope *S, Expr *Cond,
8120 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8121 /// Build reference expression to the counter be used for codegen.
8122 DeclRefExpr *
8123 buildCounterVar(llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8124 DSAStackTy &DSA) const;
8125 /// Build reference expression to the private counter be used for
8126 /// codegen.
8127 Expr *buildPrivateCounterVar() const;
8128 /// Build initialization of the counter be used for codegen.
8129 Expr *buildCounterInit() const;
8130 /// Build step of the counter be used for codegen.
8131 Expr *buildCounterStep() const;
8132 /// Build loop data with counter value for depend clauses in ordered
8133 /// directives.
8134 Expr *
8135 buildOrderedLoopData(Scope *S, Expr *Counter,
8136 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8137 SourceLocation Loc, Expr *Inc = nullptr,
8138 OverloadedOperatorKind OOK = OO_Amp);
8139 /// Builds the minimum value for the loop counter.
8140 std::pair<Expr *, Expr *> buildMinMaxValues(
8141 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
8142 /// Builds final condition for the non-rectangular loops.
8143 Expr *buildFinalCondition(Scope *S) const;
8144 /// Return true if any expression is dependent.
8145 bool dependent() const;
8146 /// Returns true if the initializer forms non-rectangular loop.
8147 bool doesInitDependOnLC() const { return InitDependOnLC.has_value(); }
8148 /// Returns true if the condition forms non-rectangular loop.
8149 bool doesCondDependOnLC() const { return CondDependOnLC.has_value(); }
8150 /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
8151 unsigned getLoopDependentIdx() const {
8152 return InitDependOnLC.value_or(CondDependOnLC.value_or(0));
8153 }
8154
8155private:
8156 /// Check the right-hand side of an assignment in the increment
8157 /// expression.
8158 bool checkAndSetIncRHS(Expr *RHS);
8159 /// Helper to set loop counter variable and its initializer.
8160 bool setLCDeclAndLB(ValueDecl *NewLCDecl, Expr *NewDeclRefExpr, Expr *NewLB,
8161 bool EmitDiags);
8162 /// Helper to set upper bound.
8163 bool setUB(Expr *NewUB, std::optional<bool> LessOp, bool StrictOp,
8164 SourceRange SR, SourceLocation SL);
8165 /// Helper to set loop increment.
8166 bool setStep(Expr *NewStep, bool Subtract);
8167};
8168
8169bool OpenMPIterationSpaceChecker::dependent() const {
8170 if (!LCDecl) {
8171 assert(!LB && !UB && !Step);
8172 return false;
8173 }
8174 return LCDecl->getType()->isDependentType() ||
8175 (LB && LB->isValueDependent()) || (UB && UB->isValueDependent()) ||
8176 (Step && Step->isValueDependent());
8177}
8178
8179bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
8180 Expr *NewLCRefExpr,
8181 Expr *NewLB, bool EmitDiags) {
8182 // State consistency checking to ensure correct usage.
8183 assert(LCDecl == nullptr && LB == nullptr && LCRef == nullptr &&
8184 UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8185 if (!NewLCDecl || !NewLB || NewLB->containsErrors())
8186 return true;
8187 LCDecl = getCanonicalDecl(NewLCDecl);
8188 LCRef = NewLCRefExpr;
8189 if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
8190 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8191 if ((Ctor->isCopyOrMoveConstructor() ||
8192 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8193 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8194 NewLB = CE->getArg(0)->IgnoreParenImpCasts();
8195 LB = NewLB;
8196 if (EmitDiags)
8197 InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
8198 return false;
8199}
8200
8201bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB, std::optional<bool> LessOp,
8202 bool StrictOp, SourceRange SR,
8203 SourceLocation SL) {
8204 // State consistency checking to ensure correct usage.
8205 assert(LCDecl != nullptr && LB != nullptr && UB == nullptr &&
8206 Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
8207 if (!NewUB || NewUB->containsErrors())
8208 return true;
8209 UB = NewUB;
8210 if (LessOp)
8211 TestIsLessOp = LessOp;
8212 TestIsStrictOp = StrictOp;
8213 ConditionSrcRange = SR;
8214 ConditionLoc = SL;
8215 CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
8216 return false;
8217}
8218
8219bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) {
8220 // State consistency checking to ensure correct usage.
8221 assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
8222 if (!NewStep || NewStep->containsErrors())
8223 return true;
8224 if (!NewStep->isValueDependent()) {
8225 // Check that the step is integer expression.
8226 SourceLocation StepLoc = NewStep->getBeginLoc();
8228 StepLoc, getExprAsWritten(NewStep));
8229 if (Val.isInvalid())
8230 return true;
8231 NewStep = Val.get();
8232
8233 // OpenMP [2.6, Canonical Loop Form, Restrictions]
8234 // If test-expr is of form var relational-op b and relational-op is < or
8235 // <= then incr-expr must cause var to increase on each iteration of the
8236 // loop. If test-expr is of form var relational-op b and relational-op is
8237 // > or >= then incr-expr must cause var to decrease on each iteration of
8238 // the loop.
8239 // If test-expr is of form b relational-op var and relational-op is < or
8240 // <= then incr-expr must cause var to decrease on each iteration of the
8241 // loop. If test-expr is of form b relational-op var and relational-op is
8242 // > or >= then incr-expr must cause var to increase on each iteration of
8243 // the loop.
8244 std::optional<llvm::APSInt> Result =
8245 NewStep->getIntegerConstantExpr(SemaRef.Context);
8246 bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation();
8247 bool IsConstNeg =
8248 Result && Result->isSigned() && (Subtract != Result->isNegative());
8249 bool IsConstPos =
8250 Result && Result->isSigned() && (Subtract == Result->isNegative());
8251 bool IsConstZero = Result && !Result->getBoolValue();
8252
8253 // != with increment is treated as <; != with decrement is treated as >
8254 if (!TestIsLessOp)
8255 TestIsLessOp = IsConstPos || (IsUnsigned && !Subtract);
8256 if (UB && (IsConstZero ||
8257 (*TestIsLessOp ? (IsConstNeg || (IsUnsigned && Subtract))
8258 : (IsConstPos || (IsUnsigned && !Subtract))))) {
8259 SemaRef.Diag(NewStep->getExprLoc(),
8260 diag::err_omp_loop_incr_not_compatible)
8261 << LCDecl << *TestIsLessOp << NewStep->getSourceRange();
8262 SemaRef.Diag(ConditionLoc,
8263 diag::note_omp_loop_cond_requires_compatible_incr)
8264 << *TestIsLessOp << ConditionSrcRange;
8265 return true;
8266 }
8267 if (*TestIsLessOp == Subtract) {
8268 NewStep =
8269 SemaRef.CreateBuiltinUnaryOp(NewStep->getExprLoc(), UO_Minus, NewStep)
8270 .get();
8271 Subtract = !Subtract;
8272 }
8273 }
8274
8275 Step = NewStep;
8276 SubtractStep = Subtract;
8277 return false;
8278}
8279
8280namespace {
8281/// Checker for the non-rectangular loops. Checks if the initializer or
8282/// condition expression references loop counter variable.
8283class LoopCounterRefChecker final
8284 : public ConstStmtVisitor<LoopCounterRefChecker, bool> {
8285 Sema &SemaRef;
8286 DSAStackTy &Stack;
8287 const ValueDecl *CurLCDecl = nullptr;
8288 const ValueDecl *DepDecl = nullptr;
8289 const ValueDecl *PrevDepDecl = nullptr;
8290 bool IsInitializer = true;
8291 bool SupportsNonRectangular;
8292 unsigned BaseLoopId = 0;
8293 bool checkDecl(const Expr *E, const ValueDecl *VD) {
8294 if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
8295 SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
8296 << (IsInitializer ? 0 : 1);
8297 return false;
8298 }
8299 const auto &&Data = Stack.isLoopControlVariable(VD);
8300 // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
8301 // The type of the loop iterator on which we depend may not have a random
8302 // access iterator type.
8303 if (Data.first && VD->getType()->isRecordType()) {
8304 SmallString<128> Name;
8305 llvm::raw_svector_ostream OS(Name);
8306 VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8307 /*Qualified=*/true);
8308 SemaRef.Diag(E->getExprLoc(),
8309 diag::err_omp_wrong_dependency_iterator_type)
8310 << OS.str();
8311 SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
8312 return false;
8313 }
8314 if (Data.first && !SupportsNonRectangular) {
8315 SemaRef.Diag(E->getExprLoc(), diag::err_omp_invariant_dependency);
8316 return false;
8317 }
8318 if (Data.first &&
8319 (DepDecl || (PrevDepDecl &&
8320 getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
8321 if (!DepDecl && PrevDepDecl)
8322 DepDecl = PrevDepDecl;
8323 SmallString<128> Name;
8324 llvm::raw_svector_ostream OS(Name);
8325 DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
8326 /*Qualified=*/true);
8327 SemaRef.Diag(E->getExprLoc(),
8328 diag::err_omp_invariant_or_linear_dependency)
8329 << OS.str();
8330 return false;
8331 }
8332 if (Data.first) {
8333 DepDecl = VD;
8334 BaseLoopId = Data.first;
8335 }
8336 return Data.first;
8337 }
8338
8339public:
8340 bool VisitDeclRefExpr(const DeclRefExpr *E) {
8341 const ValueDecl *VD = E->getDecl();
8342 if (isa<VarDecl>(VD))
8343 return checkDecl(E, VD);
8344 return false;
8345 }
8346 bool VisitMemberExpr(const MemberExpr *E) {
8347 if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
8348 const ValueDecl *VD = E->getMemberDecl();
8349 if (isa<VarDecl>(VD) || isa<FieldDecl>(VD))
8350 return checkDecl(E, VD);
8351 }
8352 return false;
8353 }
8354 bool VisitStmt(const Stmt *S) {
8355 bool Res = false;
8356 for (const Stmt *Child : S->children())
8357 Res = (Child && Visit(Child)) || Res;
8358 return Res;
8359 }
8360 explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
8361 const ValueDecl *CurLCDecl, bool IsInitializer,
8362 const ValueDecl *PrevDepDecl = nullptr,
8363 bool SupportsNonRectangular = true)
8364 : SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
8365 PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer),
8366 SupportsNonRectangular(SupportsNonRectangular) {}
8367 unsigned getBaseLoopId() const {
8368 assert(CurLCDecl && "Expected loop dependency.");
8369 return BaseLoopId;
8370 }
8371 const ValueDecl *getDepDecl() const {
8372 assert(CurLCDecl && "Expected loop dependency.");
8373 return DepDecl;
8374 }
8375};
8376} // namespace
8377
8378std::optional<unsigned>
8379OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
8380 bool IsInitializer) {
8381 // Check for the non-rectangular loops.
8382 LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
8383 DepDecl, SupportsNonRectangular);
8384 if (LoopStmtChecker.Visit(S)) {
8385 DepDecl = LoopStmtChecker.getDepDecl();
8386 return LoopStmtChecker.getBaseLoopId();
8387 }
8388 return std::nullopt;
8389}
8390
8391bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8392 // Check init-expr for canonical loop form and save loop counter
8393 // variable - #Var and its initialization value - #LB.
8394 // OpenMP [2.6] Canonical loop form. init-expr may be one of the following:
8395 // var = lb
8396 // integer-type var = lb
8397 // random-access-iterator-type var = lb
8398 // pointer-type var = lb
8399 //
8400 if (!S) {
8401 if (EmitDiags) {
8402 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_init);
8403 }
8404 return true;
8405 }
8406 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8407 if (!ExprTemp->cleanupsHaveSideEffects())
8408 S = ExprTemp->getSubExpr();
8409
8410 if (!CollapsedLoopVarDecls.empty()) {
8411 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8412 if (!FSEC.TraverseStmt(S)) {
8413 SourceRange Range = FSEC.getErrRange();
8414 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8415 << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8416 return true;
8417 }
8418 }
8419
8420 InitSrcRange = S->getSourceRange();
8421 if (Expr *E = dyn_cast<Expr>(S))
8422 S = E->IgnoreParens();
8423 if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8424 if (BO->getOpcode() == BO_Assign) {
8425 Expr *LHS = BO->getLHS()->IgnoreParens();
8426 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8427 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8428 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8429 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8430 EmitDiags);
8431 return setLCDeclAndLB(DRE->getDecl(), DRE, BO->getRHS(), EmitDiags);
8432 }
8433 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8434 if (ME->isArrow() &&
8435 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8436 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8437 EmitDiags);
8438 }
8439 }
8440 } else if (auto *DS = dyn_cast<DeclStmt>(S)) {
8441 if (DS->isSingleDecl()) {
8442 if (auto *Var = dyn_cast_or_null<VarDecl>(DS->getSingleDecl())) {
8443 if (Var->hasInit() && !Var->getType()->isReferenceType()) {
8444 // Accept non-canonical init form here but emit ext. warning.
8445 if (Var->getInitStyle() != VarDecl::CInit && EmitDiags)
8446 SemaRef.Diag(S->getBeginLoc(),
8447 diag::ext_omp_loop_not_canonical_init)
8448 << S->getSourceRange();
8449 return setLCDeclAndLB(
8450 Var,
8451 buildDeclRefExpr(SemaRef, Var,
8452 Var->getType().getNonReferenceType(),
8453 DS->getBeginLoc()),
8454 Var->getInit(), EmitDiags);
8455 }
8456 }
8457 }
8458 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8459 if (CE->getOperator() == OO_Equal) {
8460 Expr *LHS = CE->getArg(0);
8461 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
8462 if (auto *CED = dyn_cast<OMPCapturedExprDecl>(DRE->getDecl()))
8463 if (auto *ME = dyn_cast<MemberExpr>(getExprAsWritten(CED->getInit())))
8464 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8465 EmitDiags);
8466 return setLCDeclAndLB(DRE->getDecl(), DRE, CE->getArg(1), EmitDiags);
8467 }
8468 if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
8469 if (ME->isArrow() &&
8470 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8471 return setLCDeclAndLB(ME->getMemberDecl(), ME, BO->getRHS(),
8472 EmitDiags);
8473 }
8474 }
8475 }
8476
8477 if (dependent() || SemaRef.CurContext->isDependentContext())
8478 return false;
8479 if (EmitDiags) {
8480 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
8481 << S->getSourceRange();
8482 }
8483 return true;
8484}
8485
8486/// Ignore parenthesizes, implicit casts, copy constructor and return the
8487/// variable (which may be the loop variable) if possible.
8488static const ValueDecl *getInitLCDecl(const Expr *E) {
8489 if (!E)
8490 return nullptr;
8491 E = getExprAsWritten(E);
8492 if (const auto *CE = dyn_cast_or_null<CXXConstructExpr>(E))
8493 if (const CXXConstructorDecl *Ctor = CE->getConstructor())
8494 if ((Ctor->isCopyOrMoveConstructor() ||
8495 Ctor->isConvertingConstructor(/*AllowExplicit=*/false)) &&
8496 CE->getNumArgs() > 0 && CE->getArg(0) != nullptr)
8497 E = CE->getArg(0)->IgnoreParenImpCasts();
8498 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(E)) {
8499 if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
8500 return getCanonicalDecl(VD);
8501 }
8502 if (const auto *ME = dyn_cast_or_null<MemberExpr>(E))
8503 if (ME->isArrow() && isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
8504 return getCanonicalDecl(ME->getMemberDecl());
8505 return nullptr;
8506}
8507
8508bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8509 // Check test-expr for canonical form, save upper-bound UB, flags for
8510 // less/greater and for strict/non-strict comparison.
8511 // OpenMP [2.9] Canonical loop form. Test-expr may be one of the following:
8512 // var relational-op b
8513 // b relational-op var
8514 //
8515 bool IneqCondIsCanonical = SemaRef.getLangOpts().OpenMP >= 50;
8516 if (!S) {
8517 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond)
8518 << (IneqCondIsCanonical ? 1 : 0) << LCDecl;
8519 return true;
8520 }
8521 Condition = S;
8522 S = getExprAsWritten(S);
8523
8524 if (!CollapsedLoopVarDecls.empty()) {
8525 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8526 if (!FSEC.TraverseStmt(S)) {
8527 SourceRange Range = FSEC.getErrRange();
8528 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8529 << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8530 return true;
8531 }
8532 }
8533
8534 SourceLocation CondLoc = S->getBeginLoc();
8535 auto &&CheckAndSetCond =
8536 [this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
8537 const Expr *RHS, SourceRange SR,
8538 SourceLocation OpLoc) -> std::optional<bool> {
8539 if (BinaryOperator::isRelationalOp(Opcode)) {
8540 if (getInitLCDecl(LHS) == LCDecl)
8541 return setUB(const_cast<Expr *>(RHS),
8542 (Opcode == BO_LT || Opcode == BO_LE),
8543 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8544 if (getInitLCDecl(RHS) == LCDecl)
8545 return setUB(const_cast<Expr *>(LHS),
8546 (Opcode == BO_GT || Opcode == BO_GE),
8547 (Opcode == BO_LT || Opcode == BO_GT), SR, OpLoc);
8548 } else if (IneqCondIsCanonical && Opcode == BO_NE) {
8549 return setUB(const_cast<Expr *>(getInitLCDecl(LHS) == LCDecl ? RHS : LHS),
8550 /*LessOp=*/std::nullopt,
8551 /*StrictOp=*/true, SR, OpLoc);
8552 }
8553 return std::nullopt;
8554 };
8555 std::optional<bool> Res;
8556 if (auto *RBO = dyn_cast<CXXRewrittenBinaryOperator>(S)) {
8557 CXXRewrittenBinaryOperator::DecomposedForm DF = RBO->getDecomposedForm();
8558 Res = CheckAndSetCond(DF.Opcode, DF.LHS, DF.RHS, RBO->getSourceRange(),
8559 RBO->getOperatorLoc());
8560 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8561 Res = CheckAndSetCond(BO->getOpcode(), BO->getLHS(), BO->getRHS(),
8562 BO->getSourceRange(), BO->getOperatorLoc());
8563 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8564 if (CE->getNumArgs() == 2) {
8565 Res = CheckAndSetCond(
8566 BinaryOperator::getOverloadedOpcode(CE->getOperator()), CE->getArg(0),
8567 CE->getArg(1), CE->getSourceRange(), CE->getOperatorLoc());
8568 }
8569 }
8570 if (Res)
8571 return *Res;
8572 if (dependent() || SemaRef.CurContext->isDependentContext())
8573 return false;
8574 SemaRef.Diag(CondLoc, diag::err_omp_loop_not_canonical_cond)
8575 << (IneqCondIsCanonical ? 1 : 0) << S->getSourceRange() << LCDecl;
8576 return true;
8577}
8578
8579bool OpenMPIterationSpaceChecker::checkAndSetIncRHS(Expr *RHS) {
8580 // RHS of canonical loop form increment can be:
8581 // var + incr
8582 // incr + var
8583 // var - incr
8584 //
8585 RHS = RHS->IgnoreParenImpCasts();
8586 if (auto *BO = dyn_cast<BinaryOperator>(RHS)) {
8587 if (BO->isAdditiveOp()) {
8588 bool IsAdd = BO->getOpcode() == BO_Add;
8589 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8590 return setStep(BO->getRHS(), !IsAdd);
8591 if (IsAdd && getInitLCDecl(BO->getRHS()) == LCDecl)
8592 return setStep(BO->getLHS(), /*Subtract=*/false);
8593 }
8594 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(RHS)) {
8595 bool IsAdd = CE->getOperator() == OO_Plus;
8596 if ((IsAdd || CE->getOperator() == OO_Minus) && CE->getNumArgs() == 2) {
8597 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8598 return setStep(CE->getArg(1), !IsAdd);
8599 if (IsAdd && getInitLCDecl(CE->getArg(1)) == LCDecl)
8600 return setStep(CE->getArg(0), /*Subtract=*/false);
8601 }
8602 }
8603 if (dependent() || SemaRef.CurContext->isDependentContext())
8604 return false;
8605 SemaRef.Diag(RHS->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8606 << RHS->getSourceRange() << LCDecl;
8607 return true;
8608}
8609
8610bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8611 // Check incr-expr for canonical loop form and return true if it
8612 // does not conform.
8613 // OpenMP [2.6] Canonical loop form. Test-expr may be one of the following:
8614 // ++var
8615 // var++
8616 // --var
8617 // var--
8618 // var += incr
8619 // var -= incr
8620 // var = var + incr
8621 // var = incr + var
8622 // var = var - incr
8623 //
8624 if (!S) {
8625 SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl;
8626 return true;
8627 }
8628 if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S))
8629 if (!ExprTemp->cleanupsHaveSideEffects())
8630 S = ExprTemp->getSubExpr();
8631
8632 if (!CollapsedLoopVarDecls.empty()) {
8633 ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8634 if (!FSEC.TraverseStmt(S)) {
8635 SourceRange Range = FSEC.getErrRange();
8636 SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8637 << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8638 return true;
8639 }
8640 }
8641
8642 IncrementSrcRange = S->getSourceRange();
8643 S = S->IgnoreParens();
8644 if (auto *UO = dyn_cast<UnaryOperator>(S)) {
8645 if (UO->isIncrementDecrementOp() &&
8646 getInitLCDecl(UO->getSubExpr()) == LCDecl)
8647 return setStep(SemaRef
8648 .ActOnIntegerConstant(UO->getBeginLoc(),
8649 (UO->isDecrementOp() ? -1 : 1))
8650 .get(),
8651 /*Subtract=*/false);
8652 } else if (auto *BO = dyn_cast<BinaryOperator>(S)) {
8653 switch (BO->getOpcode()) {
8654 case BO_AddAssign:
8655 case BO_SubAssign:
8656 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8657 return setStep(BO->getRHS(), BO->getOpcode() == BO_SubAssign);
8658 break;
8659 case BO_Assign:
8660 if (getInitLCDecl(BO->getLHS()) == LCDecl)
8661 return checkAndSetIncRHS(BO->getRHS());
8662 break;
8663 default:
8664 break;
8665 }
8666 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(S)) {
8667 switch (CE->getOperator()) {
8668 case OO_PlusPlus:
8669 case OO_MinusMinus:
8670 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8671 return setStep(SemaRef
8672 .ActOnIntegerConstant(
8673 CE->getBeginLoc(),
8674 ((CE->getOperator() == OO_MinusMinus) ? -1 : 1))
8675 .get(),
8676 /*Subtract=*/false);
8677 break;
8678 case OO_PlusEqual:
8679 case OO_MinusEqual:
8680 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8681 return setStep(CE->getArg(1), CE->getOperator() == OO_MinusEqual);
8682 break;
8683 case OO_Equal:
8684 if (getInitLCDecl(CE->getArg(0)) == LCDecl)
8685 return checkAndSetIncRHS(CE->getArg(1));
8686 break;
8687 default:
8688 break;
8689 }
8690 }
8691 if (dependent() || SemaRef.CurContext->isDependentContext())
8692 return false;
8693 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
8694 << S->getSourceRange() << LCDecl;
8695 return true;
8696}
8697
8698static ExprResult
8699tryBuildCapture(Sema &SemaRef, Expr *Capture,
8700 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8701 StringRef Name = ".capture_expr.") {
8702 if (SemaRef.CurContext->isDependentContext() || Capture->containsErrors())
8703 return Capture;
8704 if (Capture->isEvaluatable(SemaRef.Context, Expr::SE_AllowSideEffects))
8705 return SemaRef.PerformImplicitConversion(Capture->IgnoreImpCasts(),
8706 Capture->getType(),
8708 /*AllowExplicit=*/true);
8709 auto I = Captures.find(Capture);
8710 if (I != Captures.end())
8711 return buildCapture(SemaRef, Capture, I->second, Name);
8712 DeclRefExpr *Ref = nullptr;
8713 ExprResult Res = buildCapture(SemaRef, Capture, Ref, Name);
8714 Captures[Capture] = Ref;
8715 return Res;
8716}
8717
8718/// Calculate number of iterations, transforming to unsigned, if number of
8719/// iterations may be larger than the original type.
8720static Expr *
8721calculateNumIters(Sema &SemaRef, Scope *S, SourceLocation DefaultLoc,
8722 Expr *Lower, Expr *Upper, Expr *Step, QualType LCTy,
8723 bool TestIsStrictOp, bool RoundToStep,
8724 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
8725 std::optional<unsigned> InitDependOnLC,
8726 std::optional<unsigned> CondDependOnLC) {
8727 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
8728 if (!NewStep.isUsable())
8729 return nullptr;
8730 llvm::APSInt LRes, SRes;
8731 bool IsLowerConst = false, IsStepConst = false;
8732 if (std::optional<llvm::APSInt> Res =
8733 Lower->getIntegerConstantExpr(SemaRef.Context)) {
8734 LRes = *Res;
8735 IsLowerConst = true;
8736 }
8737 if (std::optional<llvm::APSInt> Res =
8738 Step->getIntegerConstantExpr(SemaRef.Context)) {
8739 SRes = *Res;
8740 IsStepConst = true;
8741 }
8742 bool NoNeedToConvert = IsLowerConst && !RoundToStep &&
8743 ((!TestIsStrictOp && LRes.isNonNegative()) ||
8744 (TestIsStrictOp && LRes.isStrictlyPositive()));
8745 bool NeedToReorganize = false;
8746 // Check if any subexpressions in Lower -Step [+ 1] lead to overflow.
8747 if (!NoNeedToConvert && IsLowerConst &&
8748 (TestIsStrictOp || (RoundToStep && IsStepConst))) {
8749 NoNeedToConvert = true;
8750 if (RoundToStep) {
8751 unsigned BW = LRes.getBitWidth() > SRes.getBitWidth()
8752 ? LRes.getBitWidth()
8753 : SRes.getBitWidth();
8754 LRes = LRes.extend(BW + 1);
8755 LRes.setIsSigned(true);
8756 SRes = SRes.extend(BW + 1);
8757 SRes.setIsSigned(true);
8758 LRes -= SRes;
8759 NoNeedToConvert = LRes.trunc(BW).extend(BW + 1) == LRes;
8760 LRes = LRes.trunc(BW);
8761 }
8762 if (TestIsStrictOp) {
8763 unsigned BW = LRes.getBitWidth();
8764 LRes = LRes.extend(BW + 1);
8765 LRes.setIsSigned(true);
8766 ++LRes;
8767 NoNeedToConvert =
8768 NoNeedToConvert && LRes.trunc(BW).extend(BW + 1) == LRes;
8769 // truncate to the original bitwidth.
8770 LRes = LRes.trunc(BW);
8771 }
8772 NeedToReorganize = NoNeedToConvert;
8773 }
8774 llvm::APSInt URes;
8775 bool IsUpperConst = false;
8776 if (std::optional<llvm::APSInt> Res =
8777 Upper->getIntegerConstantExpr(SemaRef.Context)) {
8778 URes = *Res;
8779 IsUpperConst = true;
8780 }
8781 if (NoNeedToConvert && IsLowerConst && IsUpperConst &&
8782 (!RoundToStep || IsStepConst)) {
8783 unsigned BW = LRes.getBitWidth() > URes.getBitWidth() ? LRes.getBitWidth()
8784 : URes.getBitWidth();
8785 LRes = LRes.extend(BW + 1);
8786 LRes.setIsSigned(true);
8787 URes = URes.extend(BW + 1);
8788 URes.setIsSigned(true);
8789 URes -= LRes;
8790 NoNeedToConvert = URes.trunc(BW).extend(BW + 1) == URes;
8791 NeedToReorganize = NoNeedToConvert;
8792 }
8793 // If the boundaries are not constant or (Lower - Step [+ 1]) is not constant
8794 // or less than zero (Upper - (Lower - Step [+ 1]) may overflow) - promote to
8795 // unsigned.
8796 if ((!NoNeedToConvert || (LRes.isNegative() && !IsUpperConst)) &&
8797 !LCTy->isDependentType() && LCTy->isIntegerType()) {
8798 QualType LowerTy = Lower->getType();
8799 QualType UpperTy = Upper->getType();
8800 uint64_t LowerSize = SemaRef.Context.getTypeSize(LowerTy);
8801 uint64_t UpperSize = SemaRef.Context.getTypeSize(UpperTy);
8802 if ((LowerSize <= UpperSize && UpperTy->hasSignedIntegerRepresentation()) ||
8803 (LowerSize > UpperSize && LowerTy->hasSignedIntegerRepresentation())) {
8805 LowerSize > UpperSize ? LowerSize : UpperSize, /*Signed=*/0);
8806 Upper =
8807 SemaRef
8809 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
8811 .get();
8812 Lower = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get();
8813 NewStep = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, NewStep.get());
8814 }
8815 }
8816 if (!Lower || !Upper || NewStep.isInvalid())
8817 return nullptr;
8818
8819 ExprResult Diff;
8820
8821 // For triangular loops, use already computed Upper and Lower bounds to
8822 // calculate the number of iterations: Upper - Lower + 1.
8823 if (TestIsStrictOp && InitDependOnLC.has_value() &&
8824 !CondDependOnLC.has_value()) {
8825 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8826 if (!Diff.isUsable())
8827 return nullptr;
8828 Diff =
8829 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(),
8830 SemaRef.ActOnIntegerConstant(DefaultLoc, 1).get());
8831 if (!Diff.isUsable())
8832 return nullptr;
8833 return Diff.get();
8834 }
8835
8836 // If need to reorganize, then calculate the form as Upper - (Lower - Step [+
8837 // 1]).
8838 if (NeedToReorganize) {
8839 Diff = Lower;
8840
8841 if (RoundToStep) {
8842 // Lower - Step
8843 Diff =
8844 SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Diff.get(), NewStep.get());
8845 if (!Diff.isUsable())
8846 return nullptr;
8847 }
8848
8849 // Lower - Step [+ 1]
8850 if (TestIsStrictOp)
8851 Diff = SemaRef.BuildBinOp(
8852 S, DefaultLoc, BO_Add, Diff.get(),
8853 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8854 if (!Diff.isUsable())
8855 return nullptr;
8856
8857 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8858 if (!Diff.isUsable())
8859 return nullptr;
8860
8861 // Upper - (Lower - Step [+ 1]).
8862 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
8863 if (!Diff.isUsable())
8864 return nullptr;
8865 } else {
8866 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
8867
8868 if (!Diff.isUsable() && LCTy->getAsCXXRecordDecl()) {
8869 // BuildBinOp already emitted error, this one is to point user to upper
8870 // and lower bound, and to tell what is passed to 'operator-'.
8871 SemaRef.Diag(Upper->getBeginLoc(), diag::err_omp_loop_diff_cxx)
8872 << Upper->getSourceRange() << Lower->getSourceRange();
8873 return nullptr;
8874 }
8875
8876 if (!Diff.isUsable())
8877 return nullptr;
8878
8879 // Upper - Lower [- 1]
8880 if (TestIsStrictOp)
8881 Diff = SemaRef.BuildBinOp(
8882 S, DefaultLoc, BO_Sub, Diff.get(),
8883 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
8884 if (!Diff.isUsable())
8885 return nullptr;
8886
8887 if (RoundToStep) {
8888 // Upper - Lower [- 1] + Step
8889 Diff =
8890 SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Diff.get(), NewStep.get());
8891 if (!Diff.isUsable())
8892 return nullptr;
8893 }
8894 }
8895
8896 // Parentheses (for dumping/debugging purposes only).
8897 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
8898 if (!Diff.isUsable())
8899 return nullptr;
8900
8901 // (Upper - Lower [- 1] + Step) / Step or (Upper - Lower) / Step
8902 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
8903 if (!Diff.isUsable())
8904 return nullptr;
8905
8906 return Diff.get();
8907}
8908
8909/// Build the expression to calculate the number of iterations.
8910Expr *OpenMPIterationSpaceChecker::buildNumIterations(
8911 Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
8912 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
8913 QualType VarType = LCDecl->getType().getNonReferenceType();
8914 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
8915 !SemaRef.getLangOpts().CPlusPlus)
8916 return nullptr;
8917 Expr *LBVal = LB;
8918 Expr *UBVal = UB;
8919 // OuterVar = (LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
8920 // max(LB(MinVal), LB(MaxVal)))
8921 if (InitDependOnLC) {
8922 const LoopIterationSpace &IS = ResultIterSpaces[*InitDependOnLC - 1];
8923 if (!IS.MinValue || !IS.MaxValue)
8924 return nullptr;
8925 // OuterVar = Min
8926 ExprResult MinValue =
8927 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
8928 if (!MinValue.isUsable())
8929 return nullptr;
8930
8931 ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8932 IS.CounterVar, MinValue.get());
8933 if (!LBMinVal.isUsable())
8934 return nullptr;
8935 // OuterVar = Min, LBVal
8936 LBMinVal =
8937 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
8938 if (!LBMinVal.isUsable())
8939 return nullptr;
8940 // (OuterVar = Min, LBVal)
8941 LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
8942 if (!LBMinVal.isUsable())
8943 return nullptr;
8944
8945 // OuterVar = Max
8946 ExprResult MaxValue =
8947 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
8948 if (!MaxValue.isUsable())
8949 return nullptr;
8950
8951 ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
8952 IS.CounterVar, MaxValue.get());
8953 if (!LBMaxVal.isUsable())
8954 return nullptr;
8955 // OuterVar = Max, LBVal
8956 LBMaxVal =
8957 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
8958 if (!LBMaxVal.isUsable())
8959 return nullptr;
8960 // (OuterVar = Max, LBVal)
8961 LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
8962 if (!LBMaxVal.isUsable())
8963 return nullptr;
8964
8965 Expr *LBMin =
8966 tryBuildCapture(SemaRef, LBMinVal.get(), Captures, ".lb_min").get();
8967 Expr *LBMax =
8968 tryBuildCapture(SemaRef, LBMaxVal.get(), Captures, ".lb_max").get();
8969 if (!LBMin || !LBMax)
8970 return nullptr;
8971 // LB(MinVal) < LB(MaxVal)
8972 ExprResult MinLessMaxRes =
8973 SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
8974 if (!MinLessMaxRes.isUsable())
8975 return nullptr;
8976 Expr *MinLessMax =
8977 tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures, ".min_less_max")
8978 .get();
8979 if (!MinLessMax)
8980 return nullptr;
8981 if (*TestIsLessOp) {
8982 // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
8983 // LB(MaxVal))
8984 ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8985 MinLessMax, LBMin, LBMax);
8986 if (!MinLB.isUsable())
8987 return nullptr;
8988 LBVal = MinLB.get();
8989 } else {
8990 // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
8991 // LB(MaxVal))
8992 ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
8993 MinLessMax, LBMax, LBMin);
8994 if (!MaxLB.isUsable())
8995 return nullptr;
8996 LBVal = MaxLB.get();
8997 }
8998 // OuterVar = LB
8999 LBMinVal =
9000 SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign, IS.CounterVar, LBVal);
9001 if (!LBMinVal.isUsable())
9002 return nullptr;
9003 LBVal = LBMinVal.get();
9004 }
9005 // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
9006 // min(UB(MinVal), UB(MaxVal))
9007 if (CondDependOnLC) {
9008 const LoopIterationSpace &IS = ResultIterSpaces[*CondDependOnLC - 1];
9009 if (!IS.MinValue || !IS.MaxValue)
9010 return nullptr;
9011 // OuterVar = Min
9012 ExprResult MinValue =
9013 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
9014 if (!MinValue.isUsable())
9015 return nullptr;
9016
9017 ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9018 IS.CounterVar, MinValue.get());
9019 if (!UBMinVal.isUsable())
9020 return nullptr;
9021 // OuterVar = Min, UBVal
9022 UBMinVal =
9023 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
9024 if (!UBMinVal.isUsable())
9025 return nullptr;
9026 // (OuterVar = Min, UBVal)
9027 UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
9028 if (!UBMinVal.isUsable())
9029 return nullptr;
9030
9031 // OuterVar = Max
9032 ExprResult MaxValue =
9033 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
9034 if (!MaxValue.isUsable())
9035 return nullptr;
9036
9037 ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
9038 IS.CounterVar, MaxValue.get());
9039 if (!UBMaxVal.isUsable())
9040 return nullptr;
9041 // OuterVar = Max, UBVal
9042 UBMaxVal =
9043 SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
9044 if (!UBMaxVal.isUsable())
9045 return nullptr;
9046 // (OuterVar = Max, UBVal)
9047 UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
9048 if (!UBMaxVal.isUsable())
9049 return nullptr;
9050
9051 Expr *UBMin =
9052 tryBuildCapture(SemaRef, UBMinVal.get(), Captures, ".ub_min").get();
9053 Expr *UBMax =
9054 tryBuildCapture(SemaRef, UBMaxVal.get(), Captures, ".ub_max").get();
9055 if (!UBMin || !UBMax)
9056 return nullptr;
9057 // UB(MinVal) > UB(MaxVal)
9058 ExprResult MinGreaterMaxRes =
9059 SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
9060 if (!MinGreaterMaxRes.isUsable())
9061 return nullptr;
9062 Expr *MinGreaterMax = tryBuildCapture(SemaRef, MinGreaterMaxRes.get(),
9063 Captures, ".min_greater_max")
9064 .get();
9065 if (!MinGreaterMax)
9066 return nullptr;
9067 if (*TestIsLessOp) {
9068 // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
9069 // UB(MaxVal))
9070 ExprResult MaxUB = SemaRef.ActOnConditionalOp(
9071 DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
9072 if (!MaxUB.isUsable())
9073 return nullptr;
9074 UBVal = MaxUB.get();
9075 } else {
9076 // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
9077 // UB(MaxVal))
9078 ExprResult MinUB = SemaRef.ActOnConditionalOp(
9079 DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
9080 if (!MinUB.isUsable())
9081 return nullptr;
9082 UBVal = MinUB.get();
9083 }
9084 }
9085 Expr *UBExpr = *TestIsLessOp ? UBVal : LBVal;
9086 Expr *LBExpr = *TestIsLessOp ? LBVal : UBVal;
9087 Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures, ".upper").get();
9088 Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures, ".lower").get();
9089 if (!Upper || !Lower)
9090 return nullptr;
9091
9092 ExprResult Diff = calculateNumIters(
9093 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9094 /*RoundToStep=*/true, Captures, InitDependOnLC, CondDependOnLC);
9095 if (!Diff.isUsable())
9096 return nullptr;
9097
9098 // OpenMP runtime requires 32-bit or 64-bit loop variables.
9099 QualType Type = Diff.get()->getType();
9100 ASTContext &C = SemaRef.Context;
9101 bool UseVarType = VarType->hasIntegerRepresentation() &&
9102 C.getTypeSize(Type) > C.getTypeSize(VarType);
9103 if (!Type->isIntegerType() || UseVarType) {
9104 unsigned NewSize =
9105 UseVarType ? C.getTypeSize(VarType) : C.getTypeSize(Type);
9106 bool IsSigned = UseVarType ? VarType->hasSignedIntegerRepresentation()
9108 Type = C.getIntTypeForBitwidth(NewSize, IsSigned);
9109 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), Type)) {
9110 Diff = SemaRef.PerformImplicitConversion(Diff.get(), Type,
9112 /*AllowExplicit=*/true);
9113 if (!Diff.isUsable())
9114 return nullptr;
9115 }
9116 }
9117 if (LimitedType) {
9118 unsigned NewSize = (C.getTypeSize(Type) > 32) ? 64 : 32;
9119 if (NewSize != C.getTypeSize(Type)) {
9120 if (NewSize < C.getTypeSize(Type)) {
9121 assert(NewSize == 64 && "incorrect loop var size");
9122 SemaRef.Diag(DefaultLoc, diag::warn_omp_loop_64_bit_var)
9123 << InitSrcRange << ConditionSrcRange;
9124 }
9125 QualType NewType = C.getIntTypeForBitwidth(
9127 C.getTypeSize(Type) < NewSize);
9128 if (!SemaRef.Context.hasSameType(Diff.get()->getType(), NewType)) {
9129 Diff = SemaRef.PerformImplicitConversion(Diff.get(), NewType,
9131 /*AllowExplicit=*/true);
9132 if (!Diff.isUsable())
9133 return nullptr;
9134 }
9135 }
9136 }
9137
9138 return Diff.get();
9139}
9140
9141std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
9142 Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9143 // Do not build for iterators, they cannot be used in non-rectangular loop
9144 // nests.
9145 if (LCDecl->getType()->isRecordType())
9146 return std::make_pair(nullptr, nullptr);
9147 // If we subtract, the min is in the condition, otherwise the min is in the
9148 // init value.
9149 Expr *MinExpr = nullptr;
9150 Expr *MaxExpr = nullptr;
9151 Expr *LBExpr = *TestIsLessOp ? LB : UB;
9152 Expr *UBExpr = *TestIsLessOp ? UB : LB;
9153 bool LBNonRect =
9154 *TestIsLessOp ? InitDependOnLC.has_value() : CondDependOnLC.has_value();
9155 bool UBNonRect =
9156 *TestIsLessOp ? CondDependOnLC.has_value() : InitDependOnLC.has_value();
9157 Expr *Lower =
9158 LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
9159 Expr *Upper =
9160 UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
9161 if (!Upper || !Lower)
9162 return std::make_pair(nullptr, nullptr);
9163
9164 if (*TestIsLessOp)
9165 MinExpr = Lower;
9166 else
9167 MaxExpr = Upper;
9168
9169 // Build minimum/maximum value based on number of iterations.
9170 QualType VarType = LCDecl->getType().getNonReferenceType();
9171
9172 ExprResult Diff = calculateNumIters(
9173 SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType, TestIsStrictOp,
9174 /*RoundToStep=*/false, Captures, InitDependOnLC, CondDependOnLC);
9175
9176 if (!Diff.isUsable())
9177 return std::make_pair(nullptr, nullptr);
9178
9179 // ((Upper - Lower [- 1]) / Step) * Step
9180 // Parentheses (for dumping/debugging purposes only).
9181 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9182 if (!Diff.isUsable())
9183 return std::make_pair(nullptr, nullptr);
9184
9185 ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures, ".new_step");
9186 if (!NewStep.isUsable())
9187 return std::make_pair(nullptr, nullptr);
9188 Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
9189 if (!Diff.isUsable())
9190 return std::make_pair(nullptr, nullptr);
9191
9192 // Parentheses (for dumping/debugging purposes only).
9193 Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
9194 if (!Diff.isUsable())
9195 return std::make_pair(nullptr, nullptr);
9196
9197 // Convert to the ptrdiff_t, if original type is pointer.
9198 if (VarType->isAnyPointerType() &&
9199 !SemaRef.Context.hasSameType(
9200 Diff.get()->getType(),
9202 Diff = SemaRef.PerformImplicitConversion(
9203 Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
9204 AssignmentAction::Converting, /*AllowExplicit=*/true);
9205 }
9206 if (!Diff.isUsable())
9207 return std::make_pair(nullptr, nullptr);
9208
9209 if (*TestIsLessOp) {
9210 // MinExpr = Lower;
9211 // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
9212 Diff = SemaRef.BuildBinOp(
9213 S, DefaultLoc, BO_Add,
9214 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Lower).get(),
9215 Diff.get());
9216 if (!Diff.isUsable())
9217 return std::make_pair(nullptr, nullptr);
9218 } else {
9219 // MaxExpr = Upper;
9220 // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
9221 Diff = SemaRef.BuildBinOp(
9222 S, DefaultLoc, BO_Sub,
9223 SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Upper).get(),
9224 Diff.get());
9225 if (!Diff.isUsable())
9226 return std::make_pair(nullptr, nullptr);
9227 }
9228
9229 // Convert to the original type.
9230 if (SemaRef.Context.hasSameType(Diff.get()->getType(), VarType))
9231 Diff = SemaRef.PerformImplicitConversion(Diff.get(), VarType,
9233 /*AllowExplicit=*/true);
9234 if (!Diff.isUsable())
9235 return std::make_pair(nullptr, nullptr);
9236
9237 Sema::TentativeAnalysisScope Trap(SemaRef);
9238 Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue=*/false);
9239 if (!Diff.isUsable())
9240 return std::make_pair(nullptr, nullptr);
9241
9242 if (*TestIsLessOp)
9243 MaxExpr = Diff.get();
9244 else
9245 MinExpr = Diff.get();
9246
9247 return std::make_pair(MinExpr, MaxExpr);
9248}
9249
9250Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
9251 if (InitDependOnLC || CondDependOnLC)
9252 return Condition;
9253 return nullptr;
9254}
9255
9256Expr *OpenMPIterationSpaceChecker::buildPreCond(
9257 Scope *S, Expr *Cond,
9258 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
9259 // Do not build a precondition when the condition/initialization is dependent
9260 // to prevent pessimistic early loop exit.
9261 // TODO: this can be improved by calculating min/max values but not sure that
9262 // it will be very effective.
9263 if (CondDependOnLC || InitDependOnLC)
9264 return SemaRef
9266 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get(),
9267 SemaRef.Context.BoolTy, /*Action=*/AssignmentAction::Casting,
9268 /*AllowExplicit=*/true)
9269 .get();
9270
9271 // Try to build LB <op> UB, where <op> is <, >, <=, or >=.
9272 Sema::TentativeAnalysisScope Trap(SemaRef);
9273
9274 ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
9275 ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
9276 if (!NewLB.isUsable() || !NewUB.isUsable())
9277 return nullptr;
9278
9279 ExprResult CondExpr =
9280 SemaRef.BuildBinOp(S, DefaultLoc,
9281 *TestIsLessOp ? (TestIsStrictOp ? BO_LT : BO_LE)
9282 : (TestIsStrictOp ? BO_GT : BO_GE),
9283 NewLB.get(), NewUB.get());
9284 if (CondExpr.isUsable()) {
9285 if (!SemaRef.Context.hasSameUnqualifiedType(CondExpr.get()->getType(),
9286 SemaRef.Context.BoolTy))
9287 CondExpr = SemaRef.PerformImplicitConversion(
9288 CondExpr.get(), SemaRef.Context.BoolTy,
9289 /*Action=*/AssignmentAction::Casting,
9290 /*AllowExplicit=*/true);
9291 }
9292
9293 // Otherwise use original loop condition and evaluate it in runtime.
9294 return CondExpr.isUsable() ? CondExpr.get() : Cond;
9295}
9296
9297/// Build reference expression to the counter be used for codegen.
9298DeclRefExpr *OpenMPIterationSpaceChecker::buildCounterVar(
9299 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9300 DSAStackTy &DSA) const {
9301 auto *VD = dyn_cast<VarDecl>(LCDecl);
9302 if (!VD) {
9303 VD = SemaRef.OpenMP().isOpenMPCapturedDecl(LCDecl);
9305 SemaRef, VD, VD->getType().getNonReferenceType(), DefaultLoc);
9306 const DSAStackTy::DSAVarData Data =
9307 DSA.getTopDSA(LCDecl, /*FromParent=*/false);
9308 // If the loop control decl is explicitly marked as private, do not mark it
9309 // as captured again.
9310 if (!isOpenMPPrivate(Data.CKind) || !Data.RefExpr)
9311 Captures.insert(std::make_pair(LCRef, Ref));
9312 return Ref;
9313 }
9314 return cast<DeclRefExpr>(LCRef);
9315}
9316
9317Expr *OpenMPIterationSpaceChecker::buildPrivateCounterVar() const {
9318 if (LCDecl && !LCDecl->isInvalidDecl()) {
9320 VarDecl *PrivateVar = buildVarDecl(
9321 SemaRef, DefaultLoc, Type, LCDecl->getName(),
9322 LCDecl->hasAttrs() ? &LCDecl->getAttrs() : nullptr,
9323 isa<VarDecl>(LCDecl)
9324 ? buildDeclRefExpr(SemaRef, cast<VarDecl>(LCDecl), Type, DefaultLoc)
9325 : nullptr);
9326 if (PrivateVar->isInvalidDecl())
9327 return nullptr;
9328 return buildDeclRefExpr(SemaRef, PrivateVar, Type, DefaultLoc);
9329 }
9330 return nullptr;
9331}
9332
9333/// Build initialization of the counter to be used for codegen.
9334Expr *OpenMPIterationSpaceChecker::buildCounterInit() const { return LB; }
9335
9336/// Build step of the counter be used for codegen.
9337Expr *OpenMPIterationSpaceChecker::buildCounterStep() const { return Step; }
9338
9339Expr *OpenMPIterationSpaceChecker::buildOrderedLoopData(
9340 Scope *S, Expr *Counter,
9341 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures, SourceLocation Loc,
9342 Expr *Inc, OverloadedOperatorKind OOK) {
9343 Expr *Cnt = SemaRef.DefaultLvalueConversion(Counter).get();
9344 if (!Cnt)
9345 return nullptr;
9346 if (Inc) {
9347 assert((OOK == OO_Plus || OOK == OO_Minus) &&
9348 "Expected only + or - operations for depend clauses.");
9349 BinaryOperatorKind BOK = (OOK == OO_Plus) ? BO_Add : BO_Sub;
9350 Cnt = SemaRef.BuildBinOp(S, Loc, BOK, Cnt, Inc).get();
9351 if (!Cnt)
9352 return nullptr;
9353 }
9354 QualType VarType = LCDecl->getType().getNonReferenceType();
9355 if (!VarType->isIntegerType() && !VarType->isPointerType() &&
9356 !SemaRef.getLangOpts().CPlusPlus)
9357 return nullptr;
9358 // Upper - Lower
9359 Expr *Upper =
9360 *TestIsLessOp ? Cnt : tryBuildCapture(SemaRef, LB, Captures).get();
9361 Expr *Lower =
9362 *TestIsLessOp ? tryBuildCapture(SemaRef, LB, Captures).get() : Cnt;
9363 if (!Upper || !Lower)
9364 return nullptr;
9365
9366 ExprResult Diff =
9367 calculateNumIters(SemaRef, S, DefaultLoc, Lower, Upper, Step, VarType,
9368 /*TestIsStrictOp=*/false, /*RoundToStep=*/false,
9369 Captures, InitDependOnLC, CondDependOnLC);
9370 if (!Diff.isUsable())
9371 return nullptr;
9372
9373 return Diff.get();
9374}
9375} // namespace
9376
9378 Stmt *Init) {
9379 assert(getLangOpts().OpenMP && "OpenMP is not active.");
9380 assert(Init && "Expected loop in canonical form.");
9381 unsigned AssociatedLoops = DSAStack->getAssociatedLoops();
9382 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
9383 if (AssociatedLoops == 0 || !isOpenMPLoopDirective(DKind))
9384 return;
9385
9386 DSAStack->loopStart();
9388 OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
9389 *DSAStack, ForLoc, EmptyDeclSet);
9390 if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
9391 if (ValueDecl *D = ISC.getLoopDecl()) {
9392 auto *VD = dyn_cast<VarDecl>(D);
9393 DeclRefExpr *PrivateRef = nullptr;
9394 if (!VD) {
9396 VD = Private;
9397 } else {
9398 PrivateRef = buildCapture(SemaRef, D, ISC.getLoopDeclRefExpr(),
9399 /*WithInit=*/false);
9400 VD = cast<VarDecl>(PrivateRef->getDecl());
9401 }
9402 }
9403 DSAStack->addLoopControlVariable(D, VD);
9404 const Decl *LD = DSAStack->getPossiblyLoopCounter();
9405 if (LD != D->getCanonicalDecl()) {
9406 DSAStack->resetPossibleLoopCounter();
9407 if (auto *Var = dyn_cast_or_null<VarDecl>(LD))
9408 SemaRef.MarkDeclarationsReferencedInExpr(buildDeclRefExpr(
9409 SemaRef, const_cast<VarDecl *>(Var),
9410 Var->getType().getNonLValueExprType(getASTContext()), ForLoc,
9411 /*RefersToCapture=*/true));
9412 }
9413 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables
9414 // Referenced in a Construct, C/C++]. The loop iteration variable in the
9415 // associated for-loop of a simd construct with just one associated
9416 // for-loop may be listed in a linear clause with a constant-linear-step
9417 // that is the increment of the associated for-loop. The loop iteration
9418 // variable(s) in the associated for-loop(s) of a for or parallel for
9419 // construct may be listed in a private or lastprivate clause.
9420 DSAStackTy::DSAVarData DVar =
9421 DSAStack->getTopDSA(D, /*FromParent=*/false);
9422 // If LoopVarRefExpr is nullptr it means the corresponding loop variable
9423 // is declared in the loop and it is predetermined as a private.
9424 Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr();
9425 OpenMPClauseKind PredeterminedCKind =
9427 ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear)
9428 : OMPC_private;
9429 auto IsOpenMPTaskloopDirective = [](OpenMPDirectiveKind DK) {
9430 return getLeafConstructsOrSelf(DK).back() == OMPD_taskloop;
9431 };
9432 if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9433 DVar.CKind != PredeterminedCKind && DVar.RefExpr &&
9434 (getLangOpts().OpenMP <= 45 ||
9435 (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) ||
9437 IsOpenMPTaskloopDirective(DKind) ||
9439 !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
9440 DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
9441 (DVar.CKind != OMPC_private || DVar.RefExpr)) {
9442 unsigned OMPVersion = getLangOpts().OpenMP;
9443 Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
9444 << getOpenMPClauseNameForDiag(DVar.CKind)
9445 << getOpenMPDirectiveName(DKind, OMPVersion)
9446 << getOpenMPClauseNameForDiag(PredeterminedCKind);
9447 if (DVar.RefExpr == nullptr)
9448 DVar.CKind = PredeterminedCKind;
9449 reportOriginalDsa(SemaRef, DSAStack, D, DVar, /*IsLoopIterVar=*/true);
9450 } else if (LoopDeclRefExpr) {
9451 // Make the loop iteration variable private (for worksharing
9452 // constructs), linear (for simd directives with the only one
9453 // associated loop) or lastprivate (for simd directives with several
9454 // collapsed or ordered loops).
9455 if (DVar.CKind == OMPC_unknown)
9456 DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, PrivateRef);
9457 }
9458 }
9459 }
9460 DSAStack->setAssociatedLoops(AssociatedLoops - 1);
9461}
9462
9463namespace {
9464// Utility for OpenMP doacross clause kind
9465class OMPDoacrossKind {
9466public:
9467 bool isSource(const OMPDoacrossClause *C) {
9468 return C->getDependenceType() == OMPC_DOACROSS_source ||
9469 C->getDependenceType() == OMPC_DOACROSS_source_omp_cur_iteration;
9470 }
9471 bool isSink(const OMPDoacrossClause *C) {
9472 return C->getDependenceType() == OMPC_DOACROSS_sink;
9473 }
9474 bool isSinkIter(const OMPDoacrossClause *C) {
9475 return C->getDependenceType() == OMPC_DOACROSS_sink_omp_cur_iteration;
9476 }
9477};
9478} // namespace
9479/// Called on a for stmt to check and extract its iteration space
9480/// for further processing (such as collapsing).
9482 OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA,
9483 unsigned CurrentNestedLoopCount, unsigned NestedLoopCount,
9484 unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
9485 Expr *OrderedLoopCountExpr,
9486 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9488 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9489 const llvm::SmallPtrSetImpl<const Decl *> &CollapsedLoopVarDecls) {
9490 bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9491 // OpenMP [2.9.1, Canonical Loop Form]
9492 // for (init-expr; test-expr; incr-expr) structured-block
9493 // for (range-decl: range-expr) structured-block
9494 if (auto *CanonLoop = dyn_cast_or_null<OMPCanonicalLoop>(S))
9495 S = CanonLoop->getLoopStmt();
9496 auto *For = dyn_cast_or_null<ForStmt>(S);
9497 auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
9498 // Ranged for is supported only in OpenMP 5.0.
9499 if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
9500 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
9501 SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
9502 << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
9503 << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
9504 << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
9505 if (TotalNestedLoopCount > 1) {
9506 if (CollapseLoopCountExpr && OrderedLoopCountExpr)
9507 SemaRef.Diag(DSA.getConstructLoc(),
9508 diag::note_omp_collapse_ordered_expr)
9509 << 2 << CollapseLoopCountExpr->getSourceRange()
9510 << OrderedLoopCountExpr->getSourceRange();
9511 else if (CollapseLoopCountExpr)
9512 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9513 diag::note_omp_collapse_ordered_expr)
9514 << 0 << CollapseLoopCountExpr->getSourceRange();
9515 else if (OrderedLoopCountExpr)
9516 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9517 diag::note_omp_collapse_ordered_expr)
9518 << 1 << OrderedLoopCountExpr->getSourceRange();
9519 }
9520 return true;
9521 }
9522 assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
9523 "No loop body.");
9524 // Postpone analysis in dependent contexts for ranged for loops.
9525 if (CXXFor && SemaRef.CurContext->isDependentContext())
9526 return false;
9527
9528 OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9529 For ? For->getForLoc() : CXXFor->getForLoc(),
9530 CollapsedLoopVarDecls);
9531
9532 // Check init.
9533 Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
9534 if (ISC.checkAndSetInit(Init))
9535 return true;
9536
9537 bool HasErrors = false;
9538
9539 // Check loop variable's type.
9540 if (ValueDecl *LCDecl = ISC.getLoopDecl()) {
9541 // OpenMP [2.6, Canonical Loop Form]
9542 // Var is one of the following:
9543 // A variable of signed or unsigned integer type.
9544 // For C++, a variable of a random access iterator type.
9545 // For C, a variable of a pointer type.
9546 QualType VarType = LCDecl->getType().getNonReferenceType();
9547 if (!VarType->isDependentType() && !VarType->isIntegerType() &&
9548 !VarType->isPointerType() &&
9549 !(SemaRef.getLangOpts().CPlusPlus && VarType->isOverloadableType())) {
9550 SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_variable_type)
9551 << SemaRef.getLangOpts().CPlusPlus;
9552 HasErrors = true;
9553 }
9554
9555 // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in
9556 // a Construct
9557 // The loop iteration variable(s) in the associated for-loop(s) of a for or
9558 // parallel for construct is (are) private.
9559 // The loop iteration variable in the associated for-loop of a simd
9560 // construct with just one associated for-loop is linear with a
9561 // constant-linear-step that is the increment of the associated for-loop.
9562 // Exclude loop var from the list of variables with implicitly defined data
9563 // sharing attributes.
9564 VarsWithImplicitDSA.erase(LCDecl);
9565
9566 assert((isOpenMPLoopDirective(DKind) ||
9568 "DSA for non-loop vars");
9569
9570 // Check test-expr.
9571 HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
9572
9573 // Check incr-expr.
9574 HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
9575 }
9576
9577 if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
9578 return HasErrors;
9579
9580 // Build the loop's iteration space representation.
9581 ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
9582 DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
9583 ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
9584 ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
9590 Captures);
9591 ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
9592 ISC.buildCounterVar(Captures, DSA);
9593 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
9594 ISC.buildPrivateCounterVar();
9595 ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
9596 ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
9597 ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
9598 ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
9599 ISC.getConditionSrcRange();
9600 ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
9601 ISC.getIncrementSrcRange();
9602 ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
9603 ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
9604 ISC.isStrictTestOp();
9605 std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
9606 ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
9607 ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
9608 ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
9609 ISC.buildFinalCondition(DSA.getCurScope());
9610 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
9611 ISC.doesInitDependOnLC();
9612 ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
9613 ISC.doesCondDependOnLC();
9614 ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
9615 ISC.getLoopDependentIdx();
9616
9617 HasErrors |=
9618 (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
9619 ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
9620 ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
9621 ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
9622 ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
9623 ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
9624 if (!HasErrors && DSA.isOrderedRegion()) {
9625 if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
9626 if (CurrentNestedLoopCount <
9627 DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
9628 DSA.getOrderedRegionParam().second->setLoopNumIterations(
9629 CurrentNestedLoopCount,
9630 ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
9631 DSA.getOrderedRegionParam().second->setLoopCounter(
9632 CurrentNestedLoopCount,
9633 ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
9634 }
9635 }
9636 for (auto &Pair : DSA.getDoacrossDependClauses()) {
9637 auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
9638 auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
9639 unsigned NumLoops =
9640 DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
9641 if (CurrentNestedLoopCount >= NumLoops) {
9642 // Erroneous case - clause has some problems.
9643 continue;
9644 }
9645 if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
9646 Pair.second.size() <= CurrentNestedLoopCount) {
9647 // Erroneous case - clause has some problems.
9648 DependC->setLoopData(CurrentNestedLoopCount, nullptr);
9649 continue;
9650 }
9651 OMPDoacrossKind ODK;
9652 if (DoacrossC && ODK.isSink(DoacrossC) &&
9653 Pair.second.size() <= CurrentNestedLoopCount) {
9654 // Erroneous case - clause has some problems.
9655 DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
9656 continue;
9657 }
9658 Expr *CntValue;
9659 SourceLocation DepLoc =
9660 DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
9661 if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
9662 (DoacrossC && ODK.isSource(DoacrossC)))
9663 CntValue = ISC.buildOrderedLoopData(
9664 DSA.getCurScope(),
9665 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9666 DepLoc);
9667 else if (DoacrossC && ODK.isSinkIter(DoacrossC)) {
9668 Expr *Cnt = SemaRef
9670 ResultIterSpaces[CurrentNestedLoopCount].CounterVar)
9671 .get();
9672 if (!Cnt)
9673 continue;
9674 // build CounterVar - 1
9675 Expr *Inc =
9676 SemaRef.ActOnIntegerConstant(DoacrossC->getColonLoc(), /*Val=*/1)
9677 .get();
9678 CntValue = ISC.buildOrderedLoopData(
9679 DSA.getCurScope(),
9680 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9681 DepLoc, Inc, clang::OO_Minus);
9682 } else
9683 CntValue = ISC.buildOrderedLoopData(
9684 DSA.getCurScope(),
9685 ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
9686 DepLoc, Pair.second[CurrentNestedLoopCount].first,
9687 Pair.second[CurrentNestedLoopCount].second);
9688 if (DependC)
9689 DependC->setLoopData(CurrentNestedLoopCount, CntValue);
9690 else
9691 DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
9692 }
9693 }
9694
9695 return HasErrors;
9696}
9697
9698/// Build 'VarRef = Start.
9699static ExprResult
9701 ExprResult Start, bool IsNonRectangularLB,
9702 llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9703 // Build 'VarRef = Start.
9704 ExprResult NewStart = IsNonRectangularLB
9705 ? Start.get()
9706 : tryBuildCapture(SemaRef, Start.get(), Captures);
9707 if (!NewStart.isUsable())
9708 return ExprError();
9709 if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
9710 VarRef.get()->getType())) {
9711 NewStart = SemaRef.PerformImplicitConversion(
9712 NewStart.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9713 /*AllowExplicit=*/true);
9714 if (!NewStart.isUsable())
9715 return ExprError();
9716 }
9717
9719 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9720 return Init;
9721}
9722
9723/// Build 'VarRef = Start + Iter * Step'.
9725 Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
9726 ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
9727 bool IsNonRectangularLB,
9728 llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
9729 // Add parentheses (for debugging purposes only).
9730 Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
9731 if (!VarRef.isUsable() || !Start.isUsable() || !Iter.isUsable() ||
9732 !Step.isUsable())
9733 return ExprError();
9734
9735 ExprResult NewStep = Step;
9736 if (Captures)
9737 NewStep = tryBuildCapture(SemaRef, Step.get(), *Captures);
9738 if (NewStep.isInvalid())
9739 return ExprError();
9741 SemaRef.BuildBinOp(S, Loc, BO_Mul, Iter.get(), NewStep.get());
9742 if (!Update.isUsable())
9743 return ExprError();
9744
9745 // Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
9746 // 'VarRef = Start (+|-) Iter * Step'.
9747 if (!Start.isUsable())
9748 return ExprError();
9749 ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
9750 if (!NewStart.isUsable())
9751 return ExprError();
9752 if (Captures && !IsNonRectangularLB)
9753 NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
9754 if (NewStart.isInvalid())
9755 return ExprError();
9756
9757 // First attempt: try to build 'VarRef = Start, VarRef += Iter * Step'.
9758 ExprResult SavedUpdate = Update;
9759 ExprResult UpdateVal;
9760 if (VarRef.get()->getType()->isOverloadableType() ||
9761 NewStart.get()->getType()->isOverloadableType() ||
9762 Update.get()->getType()->isOverloadableType()) {
9763 Sema::TentativeAnalysisScope Trap(SemaRef);
9764
9765 Update =
9766 SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), NewStart.get());
9767 if (Update.isUsable()) {
9768 UpdateVal =
9769 SemaRef.BuildBinOp(S, Loc, Subtract ? BO_SubAssign : BO_AddAssign,
9770 VarRef.get(), SavedUpdate.get());
9771 if (UpdateVal.isUsable()) {
9772 Update = SemaRef.CreateBuiltinBinOp(Loc, BO_Comma, Update.get(),
9773 UpdateVal.get());
9774 }
9775 }
9776 }
9777
9778 // Second attempt: try to build 'VarRef = Start (+|-) Iter * Step'.
9779 if (!Update.isUsable() || !UpdateVal.isUsable()) {
9780 Update = SemaRef.BuildBinOp(S, Loc, Subtract ? BO_Sub : BO_Add,
9781 NewStart.get(), SavedUpdate.get());
9782 if (!Update.isUsable())
9783 return ExprError();
9784
9785 if (!SemaRef.Context.hasSameType(Update.get()->getType(),
9786 VarRef.get()->getType())) {
9788 Update.get(), VarRef.get()->getType(), AssignmentAction::Converting,
9789 /*AllowExplicit=*/true);
9790 if (!Update.isUsable())
9791 return ExprError();
9792 }
9793
9794 Update = SemaRef.BuildBinOp(S, Loc, BO_Assign, VarRef.get(), Update.get());
9795 }
9796 return Update;
9797}
9798
9799/// Convert integer expression \a E to make it have at least \a Bits
9800/// bits.
9801static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) {
9802 if (E == nullptr)
9803 return ExprError();
9804 ASTContext &C = SemaRef.Context;
9805 QualType OldType = E->getType();
9806 unsigned HasBits = C.getTypeSize(OldType);
9807 if (HasBits >= Bits)
9808 return ExprResult(E);
9809 // OK to convert to signed, because new type has more bits than old.
9810 QualType NewType = C.getIntTypeForBitwidth(Bits, /*Signed=*/true);
9811 return SemaRef.PerformImplicitConversion(
9812 E, NewType, AssignmentAction::Converting, /*AllowExplicit=*/true);
9813}
9814
9815/// Check if the given expression \a E is a constant integer that fits
9816/// into \a Bits bits.
9817static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) {
9818 if (E == nullptr)
9819 return false;
9820 if (std::optional<llvm::APSInt> Result =
9821 E->getIntegerConstantExpr(SemaRef.Context))
9822 return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits);
9823 return false;
9824}
9825
9826/// Build preinits statement for the given declarations.
9828 MutableArrayRef<Decl *> PreInits) {
9829 if (!PreInits.empty()) {
9830 return new (Context) DeclStmt(
9831 DeclGroupRef::Create(Context, PreInits.begin(), PreInits.size()),
9833 }
9834 return nullptr;
9835}
9836
9837/// Append the \p Item or the content of a CompoundStmt to the list \p
9838/// TargetList.
9839///
9840/// A CompoundStmt is used as container in case multiple statements need to be
9841/// stored in lieu of using an explicit list. Flattening is necessary because
9842/// contained DeclStmts need to be visible after the execution of the list. Used
9843/// for OpenMP pre-init declarations/statements.
9845 Stmt *Item) {
9846 // nullptr represents an empty list.
9847 if (!Item)
9848 return;
9849
9850 if (auto *CS = dyn_cast<CompoundStmt>(Item))
9851 llvm::append_range(TargetList, CS->body());
9852 else
9853 TargetList.push_back(Item);
9854}
9855
9856/// Build preinits statement for the given declarations.
9857static Stmt *
9859 const llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9860 if (!Captures.empty()) {
9861 SmallVector<Decl *, 16> PreInits;
9862 for (const auto &Pair : Captures)
9863 PreInits.push_back(Pair.second->getDecl());
9864 return buildPreInits(Context, PreInits);
9865 }
9866 return nullptr;
9867}
9868
9869/// Build pre-init statement for the given statements.
9870static Stmt *buildPreInits(ASTContext &Context, ArrayRef<Stmt *> PreInits) {
9871 if (PreInits.empty())
9872 return nullptr;
9873
9874 SmallVector<Stmt *> Stmts;
9875 for (Stmt *S : PreInits)
9876 appendFlattenedStmtList(Stmts, S);
9877 return CompoundStmt::Create(Context, PreInits, FPOptionsOverride(), {}, {});
9878}
9879
9880/// Build postupdate expression for the given list of postupdates expressions.
9881static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9882 Expr *PostUpdate = nullptr;
9883 if (!PostUpdates.empty()) {
9884 for (Expr *E : PostUpdates) {
9885 Expr *ConvE = S.BuildCStyleCastExpr(
9886 E->getExprLoc(),
9888 E->getExprLoc(), E)
9889 .get();
9890 PostUpdate = PostUpdate
9891 ? S.CreateBuiltinBinOp(ConvE->getExprLoc(), BO_Comma,
9892 PostUpdate, ConvE)
9893 .get()
9894 : ConvE;
9895 }
9896 }
9897 return PostUpdate;
9898}
9899
9900/// Look for variables declared in the body parts of a for-loop nest. Used
9901/// for verifying loop nest structure before performing a loop collapse
9902/// operation.
9904 int NestingDepth = 0;
9905 llvm::SmallPtrSetImpl<const Decl *> &VarDecls;
9906
9907public:
9908 explicit ForVarDeclFinder(llvm::SmallPtrSetImpl<const Decl *> &VD)
9909 : VarDecls(VD) {}
9910
9911 bool VisitForStmt(ForStmt *F) override {
9912 ++NestingDepth;
9913 TraverseStmt(F->getBody());
9914 --NestingDepth;
9915 return false;
9916 }
9917
9919 ++NestingDepth;
9920 TraverseStmt(RF->getBody());
9921 --NestingDepth;
9922 return false;
9923 }
9924
9925 bool VisitVarDecl(VarDecl *D) override {
9926 Decl *C = D->getCanonicalDecl();
9927 if (NestingDepth > 0)
9928 VarDecls.insert(C);
9929 return true;
9930 }
9931};
9932
9933/// Called on a for stmt to check itself and nested loops (if any).
9934/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9935/// number of collapsed loops otherwise.
9936static unsigned
9937checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9938 Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef,
9939 DSAStackTy &DSA,
9940 SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9941 OMPLoopBasedDirective::HelperExprs &Built) {
9942 // If either of the loop expressions exist and contain errors, we bail out
9943 // early because diagnostics have already been emitted and we can't reliably
9944 // check more about the loop.
9945 if ((CollapseLoopCountExpr && CollapseLoopCountExpr->containsErrors()) ||
9946 (OrderedLoopCountExpr && OrderedLoopCountExpr->containsErrors()))
9947 return 0;
9948
9949 unsigned NestedLoopCount = 1;
9950 bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9952 llvm::SmallPtrSet<const Decl *, 4> CollapsedLoopVarDecls;
9953
9954 if (CollapseLoopCountExpr) {
9955 // Found 'collapse' clause - calculate collapse number.
9956 Expr::EvalResult Result;
9957 if (!CollapseLoopCountExpr->isValueDependent() &&
9958 CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9959 NestedLoopCount = Result.Val.getInt().getLimitedValue();
9960
9961 ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9962 FVDF.TraverseStmt(AStmt);
9963 } else {
9964 Built.clear(/*Size=*/1);
9965 return 1;
9966 }
9967 }
9968 unsigned OrderedLoopCount = 1;
9969 if (OrderedLoopCountExpr) {
9970 // Found 'ordered' clause - calculate collapse number.
9971 Expr::EvalResult EVResult;
9972 if (!OrderedLoopCountExpr->isValueDependent() &&
9973 OrderedLoopCountExpr->EvaluateAsInt(EVResult,
9974 SemaRef.getASTContext())) {
9975 llvm::APSInt Result = EVResult.Val.getInt();
9976 if (Result.getLimitedValue() < NestedLoopCount) {
9977 SemaRef.Diag(OrderedLoopCountExpr->getExprLoc(),
9978 diag::err_omp_wrong_ordered_loop_count)
9979 << OrderedLoopCountExpr->getSourceRange();
9980 SemaRef.Diag(CollapseLoopCountExpr->getExprLoc(),
9981 diag::note_collapse_loop_count)
9982 << CollapseLoopCountExpr->getSourceRange();
9983 }
9984 OrderedLoopCount = Result.getLimitedValue();
9985 } else {
9986 Built.clear(/*Size=*/1);
9987 return 1;
9988 }
9989 }
9990 // This is helper routine for loop directives (e.g., 'for', 'simd',
9991 // 'for simd', etc.).
9992 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
9993 unsigned NumLoops = std::max(OrderedLoopCount, NestedLoopCount);
9994 SmallVector<LoopIterationSpace, 4> IterSpaces(NumLoops);
9995 if (!OMPLoopBasedDirective::doForAllLoops(
9996 AStmt->IgnoreContainers(
9998 SupportsNonPerfectlyNested, NumLoops,
9999 [DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
10000 CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
10001 &IterSpaces, &Captures,
10002 &CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
10004 DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
10005 NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
10006 VarsWithImplicitDSA, IterSpaces, Captures,
10007 CollapsedLoopVarDecls))
10008 return true;
10009 if (Cnt > 0 && Cnt >= NestedLoopCount &&
10010 IterSpaces[Cnt].CounterVar) {
10011 // Handle initialization of captured loop iterator variables.
10012 auto *DRE = cast<DeclRefExpr>(IterSpaces[Cnt].CounterVar);
10013 if (isa<OMPCapturedExprDecl>(DRE->getDecl())) {
10014 Captures[DRE] = DRE;
10015 }
10016 }
10017 return false;
10018 },
10019 [&SemaRef, &Captures](OMPLoopTransformationDirective *Transform) {
10020 Stmt *DependentPreInits = Transform->getPreInits();
10021 if (!DependentPreInits)
10022 return;
10023
10024 // Search for pre-init declared variables that need to be captured
10025 // to be referenceable inside the directive.
10026 SmallVector<Stmt *> Constituents;
10027 appendFlattenedStmtList(Constituents, DependentPreInits);
10028 for (Stmt *S : Constituents) {
10029 if (auto *DC = dyn_cast<DeclStmt>(S)) {
10030 for (Decl *C : DC->decls()) {
10031 auto *D = cast<VarDecl>(C);
10033 SemaRef, D, D->getType().getNonReferenceType(),
10034 cast<OMPExecutableDirective>(Transform->getDirective())
10035 ->getBeginLoc());
10036 Captures[Ref] = Ref;
10037 }
10038 }
10039 }
10040 }))
10041 return 0;
10042
10043 Built.clear(/*size=*/NestedLoopCount);
10044
10045 if (SemaRef.CurContext->isDependentContext())
10046 return NestedLoopCount;
10047
10048 // An example of what is generated for the following code:
10049 //
10050 // #pragma omp simd collapse(2) ordered(2)
10051 // for (i = 0; i < NI; ++i)
10052 // for (k = 0; k < NK; ++k)
10053 // for (j = J0; j < NJ; j+=2) {
10054 // <loop body>
10055 // }
10056 //
10057 // We generate the code below.
10058 // Note: the loop body may be outlined in CodeGen.
10059 // Note: some counters may be C++ classes, operator- is used to find number of
10060 // iterations and operator+= to calculate counter value.
10061 // Note: decltype(NumIterations) must be integer type (in 'omp for', only i32
10062 // or i64 is currently supported).
10063 //
10064 // #define NumIterations (NI * ((NJ - J0 - 1 + 2) / 2))
10065 // for (int[32|64]_t IV = 0; IV < NumIterations; ++IV ) {
10066 // .local.i = IV / ((NJ - J0 - 1 + 2) / 2);
10067 // .local.j = J0 + (IV % ((NJ - J0 - 1 + 2) / 2)) * 2;
10068 // // similar updates for vars in clauses (e.g. 'linear')
10069 // <loop body (using local i and j)>
10070 // }
10071 // i = NI; // assign final values of counters
10072 // j = NJ;
10073 //
10074
10075 // Last iteration number is (I1 * I2 * ... In) - 1, where I1, I2 ... In are
10076 // the iteration counts of the collapsed for loops.
10077 // Precondition tests if there is at least one iteration (all conditions are
10078 // true).
10079 auto PreCond = ExprResult(IterSpaces[0].PreCond);
10080 Expr *N0 = IterSpaces[0].NumIterations;
10081 ExprResult LastIteration32 = widenIterationCount(
10082 /*Bits=*/32,
10083 SemaRef
10084 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10086 /*AllowExplicit=*/true)
10087 .get(),
10088 SemaRef);
10089 ExprResult LastIteration64 = widenIterationCount(
10090 /*Bits=*/64,
10091 SemaRef
10092 .PerformImplicitConversion(N0->IgnoreImpCasts(), N0->getType(),
10094 /*AllowExplicit=*/true)
10095 .get(),
10096 SemaRef);
10097
10098 if (!LastIteration32.isUsable() || !LastIteration64.isUsable())
10099 return NestedLoopCount;
10100
10101 ASTContext &C = SemaRef.Context;
10102 bool AllCountsNeedLessThan32Bits = C.getTypeSize(N0->getType()) < 32;
10103
10104 Scope *CurScope = DSA.getCurScope();
10105 for (unsigned Cnt = 1; Cnt < NestedLoopCount; ++Cnt) {
10106 if (PreCond.isUsable()) {
10107 PreCond =
10108 SemaRef.BuildBinOp(CurScope, PreCond.get()->getExprLoc(), BO_LAnd,
10109 PreCond.get(), IterSpaces[Cnt].PreCond);
10110 }
10111 Expr *N = IterSpaces[Cnt].NumIterations;
10112 SourceLocation Loc = N->getExprLoc();
10113 AllCountsNeedLessThan32Bits &= C.getTypeSize(N->getType()) < 32;
10114 if (LastIteration32.isUsable())
10115 LastIteration32 = SemaRef.BuildBinOp(
10116 CurScope, Loc, BO_Mul, LastIteration32.get(),
10117 SemaRef
10120 /*AllowExplicit=*/true)
10121 .get());
10122 if (LastIteration64.isUsable())
10123 LastIteration64 = SemaRef.BuildBinOp(
10124 CurScope, Loc, BO_Mul, LastIteration64.get(),
10125 SemaRef
10128 /*AllowExplicit=*/true)
10129 .get());
10130 }
10131
10132 // Choose either the 32-bit or 64-bit version.
10133 ExprResult LastIteration = LastIteration64;
10134 if (SemaRef.getLangOpts().OpenMPOptimisticCollapse ||
10135 (LastIteration32.isUsable() &&
10136 C.getTypeSize(LastIteration32.get()->getType()) == 32 &&
10137 (AllCountsNeedLessThan32Bits || NestedLoopCount == 1 ||
10138 fitsInto(
10139 /*Bits=*/32,
10140 LastIteration32.get()->getType()->hasSignedIntegerRepresentation(),
10141 LastIteration64.get(), SemaRef))))
10142 LastIteration = LastIteration32;
10143 QualType VType = LastIteration.get()->getType();
10144 QualType RealVType = VType;
10145 QualType StrideVType = VType;
10146 if (isOpenMPTaskLoopDirective(DKind)) {
10147 VType =
10148 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
10149 StrideVType =
10150 SemaRef.Context.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
10151 }
10152
10153 if (!LastIteration.isUsable())
10154 return 0;
10155
10156 // Save the number of iterations.
10157 ExprResult NumIterations = LastIteration;
10158 {
10159 LastIteration = SemaRef.BuildBinOp(
10160 CurScope, LastIteration.get()->getExprLoc(), BO_Sub,
10161 LastIteration.get(),
10162 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10163 if (!LastIteration.isUsable())
10164 return 0;
10165 }
10166
10167 // Calculate the last iteration number beforehand instead of doing this on
10168 // each iteration. Do not do this if the number of iterations may be kfold-ed.
10169 bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context);
10170 ExprResult CalcLastIteration;
10171 if (!IsConstant) {
10172 ExprResult SaveRef =
10173 tryBuildCapture(SemaRef, LastIteration.get(), Captures);
10174 LastIteration = SaveRef;
10175
10176 // Prepare SaveRef + 1.
10177 NumIterations = SemaRef.BuildBinOp(
10178 CurScope, SaveRef.get()->getExprLoc(), BO_Add, SaveRef.get(),
10179 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
10180 if (!NumIterations.isUsable())
10181 return 0;
10182 }
10183
10184 SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin();
10185
10186 // Build variables passed into runtime, necessary for worksharing directives.
10187 ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB;
10192 // Lower bound variable, initialized with zero.
10193 VarDecl *LBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.lb");
10194 LB = buildDeclRefExpr(SemaRef, LBDecl, VType, InitLoc);
10195 SemaRef.AddInitializerToDecl(LBDecl,
10196 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10197 /*DirectInit=*/false);
10198
10199 // Upper bound variable, initialized with last iteration number.
10200 VarDecl *UBDecl = buildVarDecl(SemaRef, InitLoc, VType, ".omp.ub");
10201 UB = buildDeclRefExpr(SemaRef, UBDecl, VType, InitLoc);
10202 SemaRef.AddInitializerToDecl(UBDecl, LastIteration.get(),
10203 /*DirectInit=*/false);
10204
10205 // A 32-bit variable-flag where runtime returns 1 for the last iteration.
10206 // This will be used to implement clause 'lastprivate'.
10207 QualType Int32Ty = SemaRef.Context.getIntTypeForBitwidth(32, true);
10208 VarDecl *ILDecl = buildVarDecl(SemaRef, InitLoc, Int32Ty, ".omp.is_last");
10209 IL = buildDeclRefExpr(SemaRef, ILDecl, Int32Ty, InitLoc);
10210 SemaRef.AddInitializerToDecl(ILDecl,
10211 SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10212 /*DirectInit=*/false);
10213
10214 // Stride variable returned by runtime (we initialize it to 1 by default).
10215 VarDecl *STDecl =
10216 buildVarDecl(SemaRef, InitLoc, StrideVType, ".omp.stride");
10217 ST = buildDeclRefExpr(SemaRef, STDecl, StrideVType, InitLoc);
10218 SemaRef.AddInitializerToDecl(STDecl,
10219 SemaRef.ActOnIntegerConstant(InitLoc, 1).get(),
10220 /*DirectInit=*/false);
10221
10222 // Build expression: UB = min(UB, LastIteration)
10223 // It is necessary for CodeGen of directives with static scheduling.
10224 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, InitLoc, BO_GT,
10225 UB.get(), LastIteration.get());
10226 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10227 LastIteration.get()->getExprLoc(), InitLoc, IsUBGreater.get(),
10228 LastIteration.get(), UB.get());
10229 EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(),
10230 CondOp.get());
10231 EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue=*/false);
10232
10233 // If we have a combined directive that combines 'distribute', 'for' or
10234 // 'simd' we need to be able to access the bounds of the schedule of the
10235 // enclosing region. E.g. in 'distribute parallel for' the bounds obtained
10236 // by scheduling 'distribute' have to be passed to the schedule of 'for'.
10238 // Lower bound variable, initialized with zero.
10239 VarDecl *CombLBDecl =
10240 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb");
10241 CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc);
10242 SemaRef.AddInitializerToDecl(
10243 CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(),
10244 /*DirectInit=*/false);
10245
10246 // Upper bound variable, initialized with last iteration number.
10247 VarDecl *CombUBDecl =
10248 buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub");
10249 CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc);
10250 SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(),
10251 /*DirectInit=*/false);
10252
10253 ExprResult CombIsUBGreater = SemaRef.BuildBinOp(
10254 CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get());
10255 ExprResult CombCondOp =
10256 SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(),
10257 LastIteration.get(), CombUB.get());
10258 CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(),
10259 CombCondOp.get());
10260 CombEUB =
10261 SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue=*/false);
10262
10263 const CapturedDecl *CD = cast<CapturedStmt>(AStmt)->getCapturedDecl();
10264 // We expect to have at least 2 more parameters than the 'parallel'
10265 // directive does - the lower and upper bounds of the previous schedule.
10266 assert(CD->getNumParams() >= 4 &&
10267 "Unexpected number of parameters in loop combined directive");
10268
10269 // Set the proper type for the bounds given what we learned from the
10270 // enclosed loops.
10271 ImplicitParamDecl *PrevLBDecl = CD->getParam(/*PrevLB=*/2);
10272 ImplicitParamDecl *PrevUBDecl = CD->getParam(/*PrevUB=*/3);
10273
10274 // Previous lower and upper bounds are obtained from the region
10275 // parameters.
10276 PrevLB =
10277 buildDeclRefExpr(SemaRef, PrevLBDecl, PrevLBDecl->getType(), InitLoc);
10278 PrevUB =
10279 buildDeclRefExpr(SemaRef, PrevUBDecl, PrevUBDecl->getType(), InitLoc);
10280 }
10281 }
10282
10283 // Build the iteration variable and its initialization before loop.
10284 ExprResult IV;
10285 ExprResult Init, CombInit;
10286 {
10287 VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv");
10288 IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc);
10289 Expr *RHS = (isOpenMPWorksharingDirective(DKind) ||
10294 ? LB.get()
10295 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10296 Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS);
10297 Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue=*/false);
10298
10300 Expr *CombRHS =
10305 ? CombLB.get()
10306 : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get();
10307 CombInit =
10308 SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS);
10309 CombInit =
10310 SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue=*/false);
10311 }
10312 }
10313
10314 bool UseStrictCompare =
10315 RealVType->hasUnsignedIntegerRepresentation() &&
10316 llvm::all_of(IterSpaces, [](const LoopIterationSpace &LIS) {
10317 return LIS.IsStrictCompare;
10318 });
10319 // Loop condition (IV < NumIterations) or (IV <= UB or IV < UB + 1 (for
10320 // unsigned IV)) for worksharing loops.
10321 SourceLocation CondLoc = AStmt->getBeginLoc();
10322 Expr *BoundUB = UB.get();
10323 if (UseStrictCompare) {
10324 BoundUB =
10325 SemaRef
10326 .BuildBinOp(CurScope, CondLoc, BO_Add, BoundUB,
10327 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10328 .get();
10329 BoundUB =
10330 SemaRef.ActOnFinishFullExpr(BoundUB, /*DiscardedValue=*/false).get();
10331 }
10337 ? SemaRef.BuildBinOp(CurScope, CondLoc,
10338 UseStrictCompare ? BO_LT : BO_LE, IV.get(),
10339 BoundUB)
10340 : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10341 NumIterations.get());
10342 ExprResult CombDistCond;
10344 CombDistCond = SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(),
10345 NumIterations.get());
10346 }
10347
10348 ExprResult CombCond;
10350 Expr *BoundCombUB = CombUB.get();
10351 if (UseStrictCompare) {
10352 BoundCombUB =
10353 SemaRef
10354 .BuildBinOp(
10355 CurScope, CondLoc, BO_Add, BoundCombUB,
10356 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10357 .get();
10358 BoundCombUB =
10359 SemaRef.ActOnFinishFullExpr(BoundCombUB, /*DiscardedValue=*/false)
10360 .get();
10361 }
10362 CombCond =
10363 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10364 IV.get(), BoundCombUB);
10365 }
10366 // Loop increment (IV = IV + 1)
10367 SourceLocation IncLoc = AStmt->getBeginLoc();
10368 ExprResult Inc =
10369 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, IV.get(),
10370 SemaRef.ActOnIntegerConstant(IncLoc, 1).get());
10371 if (!Inc.isUsable())
10372 return 0;
10373 Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get());
10374 Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue=*/false);
10375 if (!Inc.isUsable())
10376 return 0;
10377
10378 // Increments for worksharing loops (LB = LB + ST; UB = UB + ST).
10379 // Used for directives with static scheduling.
10380 // In combined construct, add combined version that use CombLB and CombUB
10381 // base variables for the update
10382 ExprResult NextLB, NextUB, CombNextLB, CombNextUB;
10387 // LB + ST
10388 NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, LB.get(), ST.get());
10389 if (!NextLB.isUsable())
10390 return 0;
10391 // LB = LB + ST
10392 NextLB =
10393 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get());
10394 NextLB =
10395 SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue=*/false);
10396 if (!NextLB.isUsable())
10397 return 0;
10398 // UB + ST
10399 NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, UB.get(), ST.get());
10400 if (!NextUB.isUsable())
10401 return 0;
10402 // UB = UB + ST
10403 NextUB =
10404 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get());
10405 NextUB =
10406 SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue=*/false);
10407 if (!NextUB.isUsable())
10408 return 0;
10410 CombNextLB =
10411 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get());
10412 if (!NextLB.isUsable())
10413 return 0;
10414 // LB = LB + ST
10415 CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(),
10416 CombNextLB.get());
10417 CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(),
10418 /*DiscardedValue=*/false);
10419 if (!CombNextLB.isUsable())
10420 return 0;
10421 // UB + ST
10422 CombNextUB =
10423 SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get());
10424 if (!CombNextUB.isUsable())
10425 return 0;
10426 // UB = UB + ST
10427 CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(),
10428 CombNextUB.get());
10429 CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(),
10430 /*DiscardedValue=*/false);
10431 if (!CombNextUB.isUsable())
10432 return 0;
10433 }
10434 }
10435
10436 // Create increment expression for distribute loop when combined in a same
10437 // directive with for as IV = IV + ST; ensure upper bound expression based
10438 // on PrevUB instead of NumIterations - used to implement 'for' when found
10439 // in combination with 'distribute', like in 'distribute parallel for'
10440 SourceLocation DistIncLoc = AStmt->getBeginLoc();
10441 ExprResult DistCond, DistInc, PrevEUB, ParForInDistCond;
10443 DistCond = SemaRef.BuildBinOp(
10444 CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE, IV.get(), BoundUB);
10445 assert(DistCond.isUsable() && "distribute cond expr was not built");
10446
10447 DistInc =
10448 SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Add, IV.get(), ST.get());
10449 assert(DistInc.isUsable() && "distribute inc expr was not built");
10450 DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(),
10451 DistInc.get());
10452 DistInc =
10453 SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue=*/false);
10454 assert(DistInc.isUsable() && "distribute inc expr was not built");
10455
10456 // Build expression: UB = min(UB, prevUB) for #for in composite or combined
10457 // construct
10458 ExprResult NewPrevUB = PrevUB;
10459 SourceLocation DistEUBLoc = AStmt->getBeginLoc();
10460 if (!SemaRef.Context.hasSameType(UB.get()->getType(),
10461 PrevUB.get()->getType())) {
10462 NewPrevUB = SemaRef.BuildCStyleCastExpr(
10463 DistEUBLoc,
10465 DistEUBLoc, NewPrevUB.get());
10466 if (!NewPrevUB.isUsable())
10467 return 0;
10468 }
10469 ExprResult IsUBGreater = SemaRef.BuildBinOp(CurScope, DistEUBLoc, BO_GT,
10470 UB.get(), NewPrevUB.get());
10471 ExprResult CondOp = SemaRef.ActOnConditionalOp(
10472 DistEUBLoc, DistEUBLoc, IsUBGreater.get(), NewPrevUB.get(), UB.get());
10473 PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(),
10474 CondOp.get());
10475 PrevEUB =
10476 SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue=*/false);
10477
10478 // Build IV <= PrevUB or IV < PrevUB + 1 for unsigned IV to be used in
10479 // parallel for is in combination with a distribute directive with
10480 // schedule(static, 1)
10481 Expr *BoundPrevUB = PrevUB.get();
10482 if (UseStrictCompare) {
10483 BoundPrevUB =
10484 SemaRef
10485 .BuildBinOp(
10486 CurScope, CondLoc, BO_Add, BoundPrevUB,
10487 SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get())
10488 .get();
10489 BoundPrevUB =
10490 SemaRef.ActOnFinishFullExpr(BoundPrevUB, /*DiscardedValue=*/false)
10491 .get();
10492 }
10493 ParForInDistCond =
10494 SemaRef.BuildBinOp(CurScope, CondLoc, UseStrictCompare ? BO_LT : BO_LE,
10495 IV.get(), BoundPrevUB);
10496 }
10497
10498 // Build updates and final values of the loop counters.
10499 bool HasErrors = false;
10500 Built.Counters.resize(NestedLoopCount);
10501 Built.Inits.resize(NestedLoopCount);
10502 Built.Updates.resize(NestedLoopCount);
10503 Built.Finals.resize(NestedLoopCount);
10504 Built.DependentCounters.resize(NestedLoopCount);
10505 Built.DependentInits.resize(NestedLoopCount);
10506 Built.FinalsConditions.resize(NestedLoopCount);
10507 {
10508 // We implement the following algorithm for obtaining the
10509 // original loop iteration variable values based on the
10510 // value of the collapsed loop iteration variable IV.
10511 //
10512 // Let n+1 be the number of collapsed loops in the nest.
10513 // Iteration variables (I0, I1, .... In)
10514 // Iteration counts (N0, N1, ... Nn)
10515 //
10516 // Acc = IV;
10517 //
10518 // To compute Ik for loop k, 0 <= k <= n, generate:
10519 // Prod = N(k+1) * N(k+2) * ... * Nn;
10520 // Ik = Acc / Prod;
10521 // Acc -= Ik * Prod;
10522 //
10523 ExprResult Acc = IV;
10524 for (unsigned int Cnt = 0; Cnt < NestedLoopCount; ++Cnt) {
10525 LoopIterationSpace &IS = IterSpaces[Cnt];
10526 SourceLocation UpdLoc = IS.IncSrcRange.getBegin();
10527 ExprResult Iter;
10528
10529 // Compute prod
10530 ExprResult Prod = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
10531 for (unsigned int K = Cnt + 1; K < NestedLoopCount; ++K)
10532 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Prod.get(),
10533 IterSpaces[K].NumIterations);
10534
10535 // Iter = Acc / Prod
10536 // If there is at least one more inner loop to avoid
10537 // multiplication by 1.
10538 if (Cnt + 1 < NestedLoopCount)
10539 Iter =
10540 SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Div, Acc.get(), Prod.get());
10541 else
10542 Iter = Acc;
10543 if (!Iter.isUsable()) {
10544 HasErrors = true;
10545 break;
10546 }
10547
10548 // Update Acc:
10549 // Acc -= Iter * Prod
10550 // Check if there is at least one more inner loop to avoid
10551 // multiplication by 1.
10552 if (Cnt + 1 < NestedLoopCount)
10553 Prod = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Mul, Iter.get(),
10554 Prod.get());
10555 else
10556 Prod = Iter;
10557 Acc = SemaRef.BuildBinOp(CurScope, UpdLoc, BO_Sub, Acc.get(), Prod.get());
10558
10559 // Build update: IS.CounterVar(Private) = IS.Start + Iter * IS.Step
10560 auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IS.CounterVar)->getDecl());
10561 DeclRefExpr *CounterVar = buildDeclRefExpr(
10562 SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
10563 /*RefersToCapture=*/true);
10565 buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
10566 IS.CounterInit, IS.IsNonRectangularLB, Captures);
10567 if (!Init.isUsable()) {
10568 HasErrors = true;
10569 break;
10570 }
10572 SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
10573 IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
10574 if (!Update.isUsable()) {
10575 HasErrors = true;
10576 break;
10577 }
10578
10579 // Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
10580 ExprResult Final =
10581 buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
10582 IS.CounterInit, IS.NumIterations, IS.CounterStep,
10583 IS.Subtract, IS.IsNonRectangularLB, &Captures);
10584 if (!Final.isUsable()) {
10585 HasErrors = true;
10586 break;
10587 }
10588
10589 if (!Update.isUsable() || !Final.isUsable()) {
10590 HasErrors = true;
10591 break;
10592 }
10593 // Save results
10594 Built.Counters[Cnt] = IS.CounterVar;
10595 Built.PrivateCounters[Cnt] = IS.PrivateCounterVar;
10596 Built.Inits[Cnt] = Init.get();
10597 Built.Updates[Cnt] = Update.get();
10598 Built.Finals[Cnt] = Final.get();
10599 Built.DependentCounters[Cnt] = nullptr;
10600 Built.DependentInits[Cnt] = nullptr;
10601 Built.FinalsConditions[Cnt] = nullptr;
10602 if (IS.IsNonRectangularLB || IS.IsNonRectangularUB) {
10603 Built.DependentCounters[Cnt] = Built.Counters[IS.LoopDependentIdx - 1];
10604 Built.DependentInits[Cnt] = Built.Inits[IS.LoopDependentIdx - 1];
10605 Built.FinalsConditions[Cnt] = IS.FinalCondition;
10606 }
10607 }
10608 }
10609
10610 if (HasErrors)
10611 return 0;
10612
10613 // Save results
10614 Built.IterationVarRef = IV.get();
10615 Built.LastIteration = LastIteration.get();
10616 Built.NumIterations = NumIterations.get();
10617 Built.CalcLastIteration = SemaRef
10618 .ActOnFinishFullExpr(CalcLastIteration.get(),
10619 /*DiscardedValue=*/false)
10620 .get();
10621 Built.PreCond = PreCond.get();
10622 Built.PreInits = buildPreInits(C, Captures);
10623 Built.Cond = Cond.get();
10624 Built.Init = Init.get();
10625 Built.Inc = Inc.get();
10626 Built.LB = LB.get();
10627 Built.UB = UB.get();
10628 Built.IL = IL.get();
10629 Built.ST = ST.get();
10630 Built.EUB = EUB.get();
10631 Built.NLB = NextLB.get();
10632 Built.NUB = NextUB.get();
10633 Built.PrevLB = PrevLB.get();
10634 Built.PrevUB = PrevUB.get();
10635 Built.DistInc = DistInc.get();
10636 Built.PrevEUB = PrevEUB.get();
10637 Built.DistCombinedFields.LB = CombLB.get();
10638 Built.DistCombinedFields.UB = CombUB.get();
10639 Built.DistCombinedFields.EUB = CombEUB.get();
10640 Built.DistCombinedFields.Init = CombInit.get();
10641 Built.DistCombinedFields.Cond = CombCond.get();
10642 Built.DistCombinedFields.NLB = CombNextLB.get();
10643 Built.DistCombinedFields.NUB = CombNextUB.get();
10644 Built.DistCombinedFields.DistCond = CombDistCond.get();
10645 Built.DistCombinedFields.ParForInDistCond = ParForInDistCond.get();
10646
10647 return NestedLoopCount;
10648}
10649
10651 auto CollapseClauses =
10652 OMPExecutableDirective::getClausesOfKind<OMPCollapseClause>(Clauses);
10653 if (CollapseClauses.begin() != CollapseClauses.end())
10654 return (*CollapseClauses.begin())->getNumForLoops();
10655 return nullptr;
10656}
10657
10659 auto OrderedClauses =
10660 OMPExecutableDirective::getClausesOfKind<OMPOrderedClause>(Clauses);
10661 if (OrderedClauses.begin() != OrderedClauses.end())
10662 return (*OrderedClauses.begin())->getNumForLoops();
10663 return nullptr;
10664}
10665
10667 const ArrayRef<OMPClause *> Clauses) {
10668 const OMPSafelenClause *Safelen = nullptr;
10669 const OMPSimdlenClause *Simdlen = nullptr;
10670
10671 for (const OMPClause *Clause : Clauses) {
10672 if (Clause->getClauseKind() == OMPC_safelen)
10673 Safelen = cast<OMPSafelenClause>(Clause);
10674 else if (Clause->getClauseKind() == OMPC_simdlen)
10675 Simdlen = cast<OMPSimdlenClause>(Clause);
10676 if (Safelen && Simdlen)
10677 break;
10678 }
10679
10680 if (Simdlen && Safelen) {
10681 const Expr *SimdlenLength = Simdlen->getSimdlen();
10682 const Expr *SafelenLength = Safelen->getSafelen();
10683 if (SimdlenLength->isValueDependent() || SimdlenLength->isTypeDependent() ||
10684 SimdlenLength->isInstantiationDependent() ||
10685 SimdlenLength->containsUnexpandedParameterPack())
10686 return false;
10687 if (SafelenLength->isValueDependent() || SafelenLength->isTypeDependent() ||
10688 SafelenLength->isInstantiationDependent() ||
10689 SafelenLength->containsUnexpandedParameterPack())
10690 return false;
10691 Expr::EvalResult SimdlenResult, SafelenResult;
10692 SimdlenLength->EvaluateAsInt(SimdlenResult, S.Context);
10693 SafelenLength->EvaluateAsInt(SafelenResult, S.Context);
10694 llvm::APSInt SimdlenRes = SimdlenResult.Val.getInt();
10695 llvm::APSInt SafelenRes = SafelenResult.Val.getInt();
10696 // OpenMP 4.5 [2.8.1, simd Construct, Restrictions]
10697 // If both simdlen and safelen clauses are specified, the value of the
10698 // simdlen parameter must be less than or equal to the value of the safelen
10699 // parameter.
10700 if (SimdlenRes > SafelenRes) {
10701 S.Diag(SimdlenLength->getExprLoc(),
10702 diag::err_omp_wrong_simdlen_safelen_values)
10703 << SimdlenLength->getSourceRange() << SafelenLength->getSourceRange();
10704 return true;
10705 }
10706 }
10707 return false;
10708}
10709
10711 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10712 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10713 if (!AStmt)
10714 return StmtError();
10715
10716 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_simd, AStmt);
10717
10718 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10719 OMPLoopBasedDirective::HelperExprs B;
10720 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10721 // define the nested loops number.
10722 unsigned NestedLoopCount = checkOpenMPLoop(
10723 OMPD_simd, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10724 CS, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10725 if (NestedLoopCount == 0)
10726 return StmtError();
10727
10728 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10729 return StmtError();
10730
10732 return StmtError();
10733
10734 auto *SimdDirective = OMPSimdDirective::Create(
10735 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10736 return SimdDirective;
10737}
10738
10740 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10741 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10742 if (!AStmt)
10743 return StmtError();
10744
10745 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10746 OMPLoopBasedDirective::HelperExprs B;
10747 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10748 // define the nested loops number.
10749 unsigned NestedLoopCount = checkOpenMPLoop(
10750 OMPD_for, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10751 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10752 if (NestedLoopCount == 0)
10753 return StmtError();
10754
10755 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10756 return StmtError();
10757
10758 auto *ForDirective = OMPForDirective::Create(
10759 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
10760 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10761 return ForDirective;
10762}
10763
10765 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10766 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10767 if (!AStmt)
10768 return StmtError();
10769
10770 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_for_simd, AStmt);
10771
10772 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10773 OMPLoopBasedDirective::HelperExprs B;
10774 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
10775 // define the nested loops number.
10776 unsigned NestedLoopCount =
10777 checkOpenMPLoop(OMPD_for_simd, getCollapseNumberExpr(Clauses),
10778 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
10779 VarsWithImplicitDSA, B);
10780 if (NestedLoopCount == 0)
10781 return StmtError();
10782
10783 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
10784 return StmtError();
10785
10787 return StmtError();
10788
10789 return OMPForSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
10790 NestedLoopCount, Clauses, AStmt, B);
10791}
10792
10794 Stmt *AStmt, DSAStackTy *Stack) {
10795 if (!AStmt)
10796 return true;
10797
10798 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
10799 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
10800 auto BaseStmt = AStmt;
10801 while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
10802 BaseStmt = CS->getCapturedStmt();
10803 if (auto *C = dyn_cast_or_null<CompoundStmt>(BaseStmt)) {
10804 auto S = C->children();
10805 if (S.begin() == S.end())
10806 return true;
10807 // All associated statements must be '#pragma omp section' except for
10808 // the first one.
10809 for (Stmt *SectionStmt : llvm::drop_begin(S)) {
10810 if (!SectionStmt || !isa<OMPSectionDirective>(SectionStmt)) {
10811 if (SectionStmt)
10812 SemaRef.Diag(SectionStmt->getBeginLoc(),
10813 diag::err_omp_sections_substmt_not_section)
10814 << getOpenMPDirectiveName(DKind, OMPVersion);
10815 return true;
10816 }
10817 cast<OMPSectionDirective>(SectionStmt)
10818 ->setHasCancel(Stack->isCancelRegion());
10819 }
10820 } else {
10821 SemaRef.Diag(AStmt->getBeginLoc(), diag::err_omp_sections_not_compound_stmt)
10822 << getOpenMPDirectiveName(DKind, OMPVersion);
10823 return true;
10824 }
10825 return false;
10826}
10827
10830 Stmt *AStmt, SourceLocation StartLoc,
10831 SourceLocation EndLoc) {
10832 if (checkSectionsDirective(SemaRef, OMPD_sections, AStmt, DSAStack))
10833 return StmtError();
10834
10835 SemaRef.setFunctionHasBranchProtectedScope();
10836
10837 return OMPSectionsDirective::Create(
10838 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
10839 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
10840}
10841
10843 SourceLocation StartLoc,
10844 SourceLocation EndLoc) {
10845 if (!AStmt)
10846 return StmtError();
10847
10848 SemaRef.setFunctionHasBranchProtectedScope();
10849 DSAStack->setParentCancelRegion(DSAStack->isCancelRegion());
10850
10851 return OMPSectionDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt,
10852 DSAStack->isCancelRegion());
10853}
10854
10856 E = E->IgnoreParenCasts()->IgnoreImplicit();
10857 if (auto *CE = dyn_cast<CallExpr>(E))
10858 if (CE->getDirectCallee())
10859 return E;
10860 return nullptr;
10861}
10862
10865 Stmt *AStmt, SourceLocation StartLoc,
10866 SourceLocation EndLoc) {
10867 if (!AStmt)
10868 return StmtError();
10869
10870 Stmt *S = cast<CapturedStmt>(AStmt)->getCapturedStmt();
10871
10872 // 5.1 OpenMP
10873 // expression-stmt : an expression statement with one of the following forms:
10874 // expression = target-call ( [expression-list] );
10875 // target-call ( [expression-list] );
10876
10877 SourceLocation TargetCallLoc;
10878
10879 if (!SemaRef.CurContext->isDependentContext()) {
10880 Expr *TargetCall = nullptr;
10881
10882 auto *E = dyn_cast<Expr>(S);
10883 if (!E) {
10884 Diag(S->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10885 return StmtError();
10886 }
10887
10888 E = E->IgnoreParenCasts()->IgnoreImplicit();
10889
10890 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
10891 if (BO->getOpcode() == BO_Assign)
10892 TargetCall = getDirectCallExpr(BO->getRHS());
10893 } else {
10894 if (auto *COCE = dyn_cast<CXXOperatorCallExpr>(E))
10895 if (COCE->getOperator() == OO_Equal)
10896 TargetCall = getDirectCallExpr(COCE->getArg(1));
10897 if (!TargetCall)
10898 TargetCall = getDirectCallExpr(E);
10899 }
10900 if (!TargetCall) {
10901 Diag(E->getBeginLoc(), diag::err_omp_dispatch_statement_call);
10902 return StmtError();
10903 }
10904 TargetCallLoc = TargetCall->getExprLoc();
10905 }
10906
10907 SemaRef.setFunctionHasBranchProtectedScope();
10908
10909 return OMPDispatchDirective::Create(getASTContext(), StartLoc, EndLoc,
10910 Clauses, AStmt, TargetCallLoc);
10911}
10912
10915 DSAStackTy *Stack) {
10916 bool ErrorFound = false;
10917 for (OMPClause *C : Clauses) {
10918 if (auto *LPC = dyn_cast<OMPLastprivateClause>(C)) {
10919 for (Expr *RefExpr : LPC->varlist()) {
10920 SourceLocation ELoc;
10921 SourceRange ERange;
10922 Expr *SimpleRefExpr = RefExpr;
10923 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange);
10924 if (ValueDecl *D = Res.first) {
10925 auto &&Info = Stack->isLoopControlVariable(D);
10926 if (!Info.first) {
10927 unsigned OMPVersion = S.getLangOpts().OpenMP;
10928 S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
10929 << getOpenMPDirectiveName(K, OMPVersion);
10930 ErrorFound = true;
10931 }
10932 }
10933 }
10934 }
10935 }
10936 return ErrorFound;
10937}
10938
10940 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10941 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10942 if (!AStmt)
10943 return StmtError();
10944
10945 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10946 // A list item may not appear in a lastprivate clause unless it is the
10947 // loop iteration variable of a loop that is associated with the construct.
10948 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_loop, DSAStack))
10949 return StmtError();
10950
10951 setBranchProtectedScope(SemaRef, OMPD_loop, AStmt);
10952
10953 OMPLoopDirective::HelperExprs B;
10954 // In presence of clause 'collapse', it will define the nested loops number.
10955 unsigned NestedLoopCount = checkOpenMPLoop(
10956 OMPD_loop, getCollapseNumberExpr(Clauses), getOrderedNumberExpr(Clauses),
10957 AStmt, SemaRef, *DSAStack, VarsWithImplicitDSA, B);
10958 if (NestedLoopCount == 0)
10959 return StmtError();
10960
10961 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10962 "omp loop exprs were not built");
10963
10964 return OMPGenericLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
10965 NestedLoopCount, Clauses, AStmt, B);
10966}
10967
10969 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
10970 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
10971 if (!AStmt)
10972 return StmtError();
10973
10974 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
10975 // A list item may not appear in a lastprivate clause unless it is the
10976 // loop iteration variable of a loop that is associated with the construct.
10977 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_teams_loop, DSAStack))
10978 return StmtError();
10979
10980 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_teams_loop, AStmt);
10981
10982 OMPLoopDirective::HelperExprs B;
10983 // In presence of clause 'collapse', it will define the nested loops number.
10984 unsigned NestedLoopCount =
10985 checkOpenMPLoop(OMPD_teams_loop, getCollapseNumberExpr(Clauses),
10986 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
10987 VarsWithImplicitDSA, B);
10988 if (NestedLoopCount == 0)
10989 return StmtError();
10990
10991 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
10992 "omp loop exprs were not built");
10993
10994 DSAStack->setParentTeamsRegionLoc(StartLoc);
10995
10997 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
10998}
10999
11001 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11002 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11003 if (!AStmt)
11004 return StmtError();
11005
11006 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11007 // A list item may not appear in a lastprivate clause unless it is the
11008 // loop iteration variable of a loop that is associated with the construct.
11009 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_teams_loop,
11010 DSAStack))
11011 return StmtError();
11012
11013 CapturedStmt *CS =
11014 setBranchProtectedScope(SemaRef, OMPD_target_teams_loop, AStmt);
11015
11016 OMPLoopDirective::HelperExprs B;
11017 // In presence of clause 'collapse', it will define the nested loops number.
11018 unsigned NestedLoopCount =
11019 checkOpenMPLoop(OMPD_target_teams_loop, getCollapseNumberExpr(Clauses),
11020 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11021 VarsWithImplicitDSA, B);
11022 if (NestedLoopCount == 0)
11023 return StmtError();
11024
11025 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11026 "omp loop exprs were not built");
11027
11029 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11031}
11032
11034 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11035 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11036 if (!AStmt)
11037 return StmtError();
11038
11039 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11040 // A list item may not appear in a lastprivate clause unless it is the
11041 // loop iteration variable of a loop that is associated with the construct.
11042 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_parallel_loop,
11043 DSAStack))
11044 return StmtError();
11045
11046 CapturedStmt *CS =
11047 setBranchProtectedScope(SemaRef, OMPD_parallel_loop, AStmt);
11048
11049 OMPLoopDirective::HelperExprs B;
11050 // In presence of clause 'collapse', it will define the nested loops number.
11051 unsigned NestedLoopCount =
11052 checkOpenMPLoop(OMPD_parallel_loop, getCollapseNumberExpr(Clauses),
11053 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11054 VarsWithImplicitDSA, B);
11055 if (NestedLoopCount == 0)
11056 return StmtError();
11057
11058 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11059 "omp loop exprs were not built");
11060
11062 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11063}
11064
11066 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11067 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11068 if (!AStmt)
11069 return StmtError();
11070
11071 // OpenMP 5.1 [2.11.7, loop construct, Restrictions]
11072 // A list item may not appear in a lastprivate clause unless it is the
11073 // loop iteration variable of a loop that is associated with the construct.
11074 if (checkGenericLoopLastprivate(SemaRef, Clauses, OMPD_target_parallel_loop,
11075 DSAStack))
11076 return StmtError();
11077
11078 CapturedStmt *CS =
11079 setBranchProtectedScope(SemaRef, OMPD_target_parallel_loop, AStmt);
11080
11081 OMPLoopDirective::HelperExprs B;
11082 // In presence of clause 'collapse', it will define the nested loops number.
11083 unsigned NestedLoopCount =
11084 checkOpenMPLoop(OMPD_target_parallel_loop, getCollapseNumberExpr(Clauses),
11085 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
11086 VarsWithImplicitDSA, B);
11087 if (NestedLoopCount == 0)
11088 return StmtError();
11089
11090 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
11091 "omp loop exprs were not built");
11092
11094 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11095}
11096
11098 Stmt *AStmt,
11099 SourceLocation StartLoc,
11100 SourceLocation EndLoc) {
11101 if (!AStmt)
11102 return StmtError();
11103
11104 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11105
11106 SemaRef.setFunctionHasBranchProtectedScope();
11107
11108 // OpenMP [2.7.3, single Construct, Restrictions]
11109 // The copyprivate clause must not be used with the nowait clause.
11110 const OMPClause *Nowait = nullptr;
11111 const OMPClause *Copyprivate = nullptr;
11112 for (const OMPClause *Clause : Clauses) {
11113 if (Clause->getClauseKind() == OMPC_nowait)
11114 Nowait = Clause;
11115 else if (Clause->getClauseKind() == OMPC_copyprivate)
11116 Copyprivate = Clause;
11117 if (Copyprivate && Nowait) {
11118 Diag(Copyprivate->getBeginLoc(),
11119 diag::err_omp_single_copyprivate_with_nowait);
11120 Diag(Nowait->getBeginLoc(), diag::note_omp_nowait_clause_here);
11121 return StmtError();
11122 }
11123 }
11124
11125 return OMPSingleDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11126 AStmt);
11127}
11128
11130 SourceLocation StartLoc,
11131 SourceLocation EndLoc) {
11132 if (!AStmt)
11133 return StmtError();
11134
11135 SemaRef.setFunctionHasBranchProtectedScope();
11136
11137 return OMPMasterDirective::Create(getASTContext(), StartLoc, EndLoc, AStmt);
11138}
11139
11141 Stmt *AStmt,
11142 SourceLocation StartLoc,
11143 SourceLocation EndLoc) {
11144 if (!AStmt)
11145 return StmtError();
11146
11147 SemaRef.setFunctionHasBranchProtectedScope();
11148
11149 return OMPMaskedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11150 AStmt);
11151}
11152
11154 const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses,
11155 Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
11156 if (!AStmt)
11157 return StmtError();
11158
11159 bool ErrorFound = false;
11160 llvm::APSInt Hint;
11161 SourceLocation HintLoc;
11162 bool DependentHint = false;
11163 for (const OMPClause *C : Clauses) {
11164 if (C->getClauseKind() == OMPC_hint) {
11165 if (!DirName.getName()) {
11166 Diag(C->getBeginLoc(), diag::err_omp_hint_clause_no_name);
11167 ErrorFound = true;
11168 }
11169 Expr *E = cast<OMPHintClause>(C)->getHint();
11170 if (E->isTypeDependent() || E->isValueDependent() ||
11172 DependentHint = true;
11173 } else {
11175 HintLoc = C->getBeginLoc();
11176 }
11177 }
11178 }
11179 if (ErrorFound)
11180 return StmtError();
11181 const auto Pair = DSAStack->getCriticalWithHint(DirName);
11182 if (Pair.first && DirName.getName() && !DependentHint) {
11183 if (llvm::APSInt::compareValues(Hint, Pair.second) != 0) {
11184 Diag(StartLoc, diag::err_omp_critical_with_hint);
11185 if (HintLoc.isValid())
11186 Diag(HintLoc, diag::note_omp_critical_hint_here)
11187 << 0 << toString(Hint, /*Radix=*/10, /*Signed=*/false);
11188 else
11189 Diag(StartLoc, diag::note_omp_critical_no_hint) << 0;
11190 if (const auto *C = Pair.first->getSingleClause<OMPHintClause>()) {
11191 Diag(C->getBeginLoc(), diag::note_omp_critical_hint_here)
11192 << 1
11193 << toString(C->getHint()->EvaluateKnownConstInt(getASTContext()),
11194 /*Radix=*/10, /*Signed=*/false);
11195 } else {
11196 Diag(Pair.first->getBeginLoc(), diag::note_omp_critical_no_hint) << 1;
11197 }
11198 }
11199 }
11200
11201 SemaRef.setFunctionHasBranchProtectedScope();
11202
11203 auto *Dir = OMPCriticalDirective::Create(getASTContext(), DirName, StartLoc,
11204 EndLoc, Clauses, AStmt);
11205 if (!Pair.first && DirName.getName() && !DependentHint)
11206 DSAStack->addCriticalWithHint(Dir, Hint);
11207 return Dir;
11208}
11209
11211 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11212 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11213 if (!AStmt)
11214 return StmtError();
11215
11216 setBranchProtectedScope(SemaRef, OMPD_parallel_for, AStmt);
11217
11218 OMPLoopBasedDirective::HelperExprs B;
11219 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11220 // define the nested loops number.
11221 unsigned NestedLoopCount =
11222 checkOpenMPLoop(OMPD_parallel_for, getCollapseNumberExpr(Clauses),
11223 getOrderedNumberExpr(Clauses), AStmt, SemaRef, *DSAStack,
11224 VarsWithImplicitDSA, B);
11225 if (NestedLoopCount == 0)
11226 return StmtError();
11227
11228 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11229 return StmtError();
11230
11231 return OMPParallelForDirective::Create(
11232 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
11233 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11234}
11235
11237 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11238 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
11239 if (!AStmt)
11240 return StmtError();
11241
11242 CapturedStmt *CS =
11243 setBranchProtectedScope(SemaRef, OMPD_parallel_for_simd, AStmt);
11244
11245 OMPLoopBasedDirective::HelperExprs B;
11246 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
11247 // define the nested loops number.
11248 unsigned NestedLoopCount =
11249 checkOpenMPLoop(OMPD_parallel_for_simd, getCollapseNumberExpr(Clauses),
11250 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
11251 VarsWithImplicitDSA, B);
11252 if (NestedLoopCount == 0)
11253 return StmtError();
11254
11255 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
11256 return StmtError();
11257
11259 return StmtError();
11260
11261 return OMPParallelForSimdDirective::Create(
11262 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
11263}
11264
11266 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11267 SourceLocation EndLoc) {
11268 if (!AStmt)
11269 return StmtError();
11270
11271 setBranchProtectedScope(SemaRef, OMPD_parallel_master, AStmt);
11272
11273 return OMPParallelMasterDirective::Create(
11274 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11275 DSAStack->getTaskgroupReductionRef());
11276}
11277
11279 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11280 SourceLocation EndLoc) {
11281 if (!AStmt)
11282 return StmtError();
11283
11284 setBranchProtectedScope(SemaRef, OMPD_parallel_masked, AStmt);
11285
11286 return OMPParallelMaskedDirective::Create(
11287 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11288 DSAStack->getTaskgroupReductionRef());
11289}
11290
11292 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
11293 SourceLocation EndLoc) {
11294 if (checkSectionsDirective(SemaRef, OMPD_parallel_sections, AStmt, DSAStack))
11295 return StmtError();
11296
11297 SemaRef.setFunctionHasBranchProtectedScope();
11298
11299 return OMPParallelSectionsDirective::Create(
11300 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
11301 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
11302}
11303
11304/// Find and diagnose mutually exclusive clause kinds.
11306 Sema &S, ArrayRef<OMPClause *> Clauses,
11307 ArrayRef<OpenMPClauseKind> MutuallyExclusiveClauses) {
11308 const OMPClause *PrevClause = nullptr;
11309 bool ErrorFound = false;
11310 for (const OMPClause *C : Clauses) {
11311 if (llvm::is_contained(MutuallyExclusiveClauses, C->getClauseKind())) {
11312 if (!PrevClause) {
11313 PrevClause = C;
11314 } else if (PrevClause->getClauseKind() != C->getClauseKind()) {
11315 S.Diag(C->getBeginLoc(), diag::err_omp_clauses_mutually_exclusive)
11316 << getOpenMPClauseNameForDiag(C->getClauseKind())
11317 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11318 S.Diag(PrevClause->getBeginLoc(), diag::note_omp_previous_clause)
11319 << getOpenMPClauseNameForDiag(PrevClause->getClauseKind());
11320 ErrorFound = true;
11321 }
11322 }
11323 }
11324 return ErrorFound;
11325}
11326
11328 Stmt *AStmt,
11329 SourceLocation StartLoc,
11330 SourceLocation EndLoc) {
11331 if (!AStmt)
11332 return StmtError();
11333
11334 // OpenMP 5.0, 2.10.1 task Construct
11335 // If a detach clause appears on the directive, then a mergeable clause cannot
11336 // appear on the same directive.
11338 {OMPC_detach, OMPC_mergeable}))
11339 return StmtError();
11340
11341 setBranchProtectedScope(SemaRef, OMPD_task, AStmt);
11342
11343 return OMPTaskDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11344 AStmt, DSAStack->isCancelRegion());
11345}
11346
11348 SourceLocation EndLoc) {
11349 return OMPTaskyieldDirective::Create(getASTContext(), StartLoc, EndLoc);
11350}
11351
11353 SourceLocation EndLoc) {
11354 return OMPBarrierDirective::Create(getASTContext(), StartLoc, EndLoc);
11355}
11356
11358 SourceLocation StartLoc,
11359 SourceLocation EndLoc,
11360 bool InExContext) {
11361 const OMPAtClause *AtC =
11362 OMPExecutableDirective::getSingleClause<OMPAtClause>(Clauses);
11363
11364 if (AtC && !InExContext && AtC->getAtKind() == OMPC_AT_execution) {
11365 Diag(AtC->getAtKindKwLoc(), diag::err_omp_unexpected_execution_modifier);
11366 return StmtError();
11367 }
11368
11369 if (!AtC || AtC->getAtKind() == OMPC_AT_compilation) {
11370 const OMPSeverityClause *SeverityC =
11371 OMPExecutableDirective::getSingleClause<OMPSeverityClause>(Clauses);
11372 const OMPMessageClause *MessageC =
11373 OMPExecutableDirective::getSingleClause<OMPMessageClause>(Clauses);
11374 std::optional<std::string> SL =
11375 MessageC ? MessageC->tryEvaluateString(getASTContext()) : std::nullopt;
11376
11377 if (MessageC && !SL)
11378 Diag(MessageC->getMessageString()->getBeginLoc(),
11379 diag::warn_clause_expected_string)
11380 << getOpenMPClauseNameForDiag(OMPC_message) << 1;
11381 if (SeverityC && SeverityC->getSeverityKind() == OMPC_SEVERITY_warning)
11382 Diag(SeverityC->getSeverityKindKwLoc(), diag::warn_diagnose_if_succeeded)
11383 << SL.value_or("WARNING");
11384 else
11385 Diag(StartLoc, diag::err_diagnose_if_succeeded) << SL.value_or("ERROR");
11386 if (!SeverityC || SeverityC->getSeverityKind() != OMPC_SEVERITY_warning)
11387 return StmtError();
11388 }
11389
11390 return OMPErrorDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11391}
11392
11395 SourceLocation StartLoc,
11396 SourceLocation EndLoc) {
11397 const OMPNowaitClause *NowaitC =
11398 OMPExecutableDirective::getSingleClause<OMPNowaitClause>(Clauses);
11399 bool HasDependC =
11400 !OMPExecutableDirective::getClausesOfKind<OMPDependClause>(Clauses)
11401 .empty();
11402 if (NowaitC && !HasDependC) {
11403 Diag(StartLoc, diag::err_omp_nowait_clause_without_depend);
11404 return StmtError();
11405 }
11406
11407 return OMPTaskwaitDirective::Create(getASTContext(), StartLoc, EndLoc,
11408 Clauses);
11409}
11410
11413 Stmt *AStmt, SourceLocation StartLoc,
11414 SourceLocation EndLoc) {
11415 if (!AStmt)
11416 return StmtError();
11417
11418 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11419
11420 SemaRef.setFunctionHasBranchProtectedScope();
11421
11422 return OMPTaskgroupDirective::Create(getASTContext(), StartLoc, EndLoc,
11423 Clauses, AStmt,
11424 DSAStack->getTaskgroupReductionRef());
11425}
11426
11428 SourceLocation StartLoc,
11429 SourceLocation EndLoc) {
11430 OMPFlushClause *FC = nullptr;
11431 OMPClause *OrderClause = nullptr;
11432 for (OMPClause *C : Clauses) {
11433 if (C->getClauseKind() == OMPC_flush)
11434 FC = cast<OMPFlushClause>(C);
11435 else
11436 OrderClause = C;
11437 }
11438 unsigned OMPVersion = getLangOpts().OpenMP;
11439 OpenMPClauseKind MemOrderKind = OMPC_unknown;
11440 SourceLocation MemOrderLoc;
11441 for (const OMPClause *C : Clauses) {
11442 if (C->getClauseKind() == OMPC_acq_rel ||
11443 C->getClauseKind() == OMPC_acquire ||
11444 C->getClauseKind() == OMPC_release ||
11445 C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
11446 if (MemOrderKind != OMPC_unknown) {
11447 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
11448 << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
11449 << SourceRange(C->getBeginLoc(), C->getEndLoc());
11450 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
11451 << getOpenMPClauseNameForDiag(MemOrderKind);
11452 } else {
11453 MemOrderKind = C->getClauseKind();
11454 MemOrderLoc = C->getBeginLoc();
11455 }
11456 }
11457 }
11458 if (FC && OrderClause) {
11459 Diag(FC->getLParenLoc(), diag::err_omp_flush_order_clause_and_list)
11460 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11461 Diag(OrderClause->getBeginLoc(), diag::note_omp_flush_order_clause_here)
11462 << getOpenMPClauseNameForDiag(OrderClause->getClauseKind());
11463 return StmtError();
11464 }
11465 return OMPFlushDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11466}
11467
11469 SourceLocation StartLoc,
11470 SourceLocation EndLoc) {
11471 if (Clauses.empty()) {
11472 Diag(StartLoc, diag::err_omp_depobj_expected);
11473 return StmtError();
11474 } else if (Clauses[0]->getClauseKind() != OMPC_depobj) {
11475 Diag(Clauses[0]->getBeginLoc(), diag::err_omp_depobj_expected);
11476 return StmtError();
11477 }
11478 // Only depobj expression and another single clause is allowed.
11479 if (Clauses.size() > 2) {
11480 Diag(Clauses[2]->getBeginLoc(),
11481 diag::err_omp_depobj_single_clause_expected);
11482 return StmtError();
11483 } else if (Clauses.size() < 1) {
11484 Diag(Clauses[0]->getEndLoc(), diag::err_omp_depobj_single_clause_expected);
11485 return StmtError();
11486 }
11487 return OMPDepobjDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11488}
11489
11491 SourceLocation StartLoc,
11492 SourceLocation EndLoc) {
11493 // Check that exactly one clause is specified.
11494 if (Clauses.size() != 1) {
11495 Diag(Clauses.empty() ? EndLoc : Clauses[1]->getBeginLoc(),
11496 diag::err_omp_scan_single_clause_expected);
11497 return StmtError();
11498 }
11499 // Check that scan directive is used in the scope of the OpenMP loop body.
11500 if (Scope *S = DSAStack->getCurScope()) {
11501 Scope *ParentS = S->getParent();
11502 if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
11503 !ParentS->getBreakParent()->isOpenMPLoopScope()) {
11504 unsigned OMPVersion = getLangOpts().OpenMP;
11505 return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
11506 << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
11507 }
11508 }
11509 // Check that only one instance of scan directives is used in the same outer
11510 // region.
11511 if (DSAStack->doesParentHasScanDirective()) {
11512 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
11513 Diag(DSAStack->getParentScanDirectiveLoc(),
11514 diag::note_omp_previous_directive)
11515 << "scan";
11516 return StmtError();
11517 }
11518 DSAStack->setParentHasScanDirective(StartLoc);
11519 return OMPScanDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses);
11520}
11521
11524 Stmt *AStmt, SourceLocation StartLoc,
11525 SourceLocation EndLoc) {
11526 const OMPClause *DependFound = nullptr;
11527 const OMPClause *DependSourceClause = nullptr;
11528 const OMPClause *DependSinkClause = nullptr;
11529 const OMPClause *DoacrossFound = nullptr;
11530 const OMPClause *DoacrossSourceClause = nullptr;
11531 const OMPClause *DoacrossSinkClause = nullptr;
11532 bool ErrorFound = false;
11533 const OMPThreadsClause *TC = nullptr;
11534 const OMPSIMDClause *SC = nullptr;
11535 for (const OMPClause *C : Clauses) {
11536 auto DOC = dyn_cast<OMPDoacrossClause>(C);
11537 auto DC = dyn_cast<OMPDependClause>(C);
11538 if (DC || DOC) {
11539 DependFound = DC ? C : nullptr;
11540 DoacrossFound = DOC ? C : nullptr;
11541 OMPDoacrossKind ODK;
11542 if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
11543 (DOC && (ODK.isSource(DOC)))) {
11544 if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
11545 unsigned OMPVersion = getLangOpts().OpenMP;
11546 Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
11547 << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
11548 << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
11549 << 2;
11550 ErrorFound = true;
11551 } else {
11552 if (DC)
11553 DependSourceClause = C;
11554 else
11555 DoacrossSourceClause = C;
11556 }
11557 if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
11558 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11559 << (DC ? "depend" : "doacross") << 0;
11560 ErrorFound = true;
11561 }
11562 } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
11563 (DOC && (ODK.isSink(DOC) || ODK.isSinkIter(DOC)))) {
11564 if (DependSourceClause || DoacrossSourceClause) {
11565 Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
11566 << (DC ? "depend" : "doacross") << 1;
11567 ErrorFound = true;
11568 }
11569 if (DC)
11570 DependSinkClause = C;
11571 else
11572 DoacrossSinkClause = C;
11573 }
11574 } else if (C->getClauseKind() == OMPC_threads) {
11576 } else if (C->getClauseKind() == OMPC_simd) {
11577 SC = cast<OMPSIMDClause>(C);
11578 }
11579 }
11580 if (!ErrorFound && !SC &&
11581 isOpenMPSimdDirective(DSAStack->getParentDirective())) {
11582 // OpenMP [2.8.1,simd Construct, Restrictions]
11583 // An ordered construct with the simd clause is the only OpenMP construct
11584 // that can appear in the simd region.
11585 Diag(StartLoc, diag::err_omp_prohibited_region_simd)
11586 << (getLangOpts().OpenMP >= 50 ? 1 : 0);
11587 ErrorFound = true;
11588 } else if ((DependFound || DoacrossFound) && (TC || SC)) {
11589 SourceLocation Loc =
11590 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11591 Diag(Loc, diag::err_omp_depend_clause_thread_simd)
11592 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend : OMPC_doacross)
11593 << getOpenMPClauseNameForDiag(TC ? TC->getClauseKind()
11594 : SC->getClauseKind());
11595 ErrorFound = true;
11596 } else if ((DependFound || DoacrossFound) &&
11597 !DSAStack->getParentOrderedRegionParam().first) {
11598 SourceLocation Loc =
11599 DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
11600 Diag(Loc, diag::err_omp_ordered_directive_without_param)
11601 << getOpenMPClauseNameForDiag(DependFound ? OMPC_depend
11602 : OMPC_doacross);
11603 ErrorFound = true;
11604 } else if (TC || Clauses.empty()) {
11605 if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
11606 SourceLocation ErrLoc = TC ? TC->getBeginLoc() : StartLoc;
11607 Diag(ErrLoc, diag::err_omp_ordered_directive_with_param)
11608 << (TC != nullptr);
11609 Diag(Param->getBeginLoc(), diag::note_omp_ordered_param) << 1;
11610 ErrorFound = true;
11611 }
11612 }
11613 if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
11614 return StmtError();
11615
11616 // OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
11617 // During execution of an iteration of a worksharing-loop or a loop nest
11618 // within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
11619 // must not execute more than one ordered region corresponding to an ordered
11620 // construct without a depend clause.
11621 if (!DependFound && !DoacrossFound) {
11622 if (DSAStack->doesParentHasOrderedDirective()) {
11623 Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
11624 Diag(DSAStack->getParentOrderedDirectiveLoc(),
11625 diag::note_omp_previous_directive)
11626 << "ordered";
11627 return StmtError();
11628 }
11629 DSAStack->setParentHasOrderedDirective(StartLoc);
11630 }
11631
11632 if (AStmt) {
11633 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
11634
11635 SemaRef.setFunctionHasBranchProtectedScope();
11636 }
11637
11638 return OMPOrderedDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
11639 AStmt);
11640}
11641
11642namespace {
11643/// Helper class for checking expression in 'omp atomic [update]'
11644/// construct.
11645class OpenMPAtomicUpdateChecker {
11646 /// Error results for atomic update expressions.
11647 enum ExprAnalysisErrorCode {
11648 /// A statement is not an expression statement.
11649 NotAnExpression,
11650 /// Expression is not builtin binary or unary operation.
11651 NotABinaryOrUnaryExpression,
11652 /// Unary operation is not post-/pre- increment/decrement operation.
11653 NotAnUnaryIncDecExpression,
11654 /// An expression is not of scalar type.
11655 NotAScalarType,
11656 /// A binary operation is not an assignment operation.
11657 NotAnAssignmentOp,
11658 /// RHS part of the binary operation is not a binary expression.
11659 NotABinaryExpression,
11660 /// RHS part is not additive/multiplicative/shift/bitwise binary
11661 /// expression.
11662 NotABinaryOperator,
11663 /// RHS binary operation does not have reference to the updated LHS
11664 /// part.
11665 NotAnUpdateExpression,
11666 /// An expression contains semantical error not related to
11667 /// 'omp atomic [update]'
11668 NotAValidExpression,
11669 /// No errors is found.
11670 NoError
11671 };
11672 /// Reference to Sema.
11673 Sema &SemaRef;
11674 /// A location for note diagnostics (when error is found).
11675 SourceLocation NoteLoc;
11676 /// 'x' lvalue part of the source atomic expression.
11677 Expr *X;
11678 /// 'expr' rvalue part of the source atomic expression.
11679 Expr *E;
11680 /// Helper expression of the form
11681 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11682 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11683 Expr *UpdateExpr;
11684 /// Is 'x' a LHS in a RHS part of full update expression. It is
11685 /// important for non-associative operations.
11686 bool IsXLHSInRHSPart;
11688 SourceLocation OpLoc;
11689 /// true if the source expression is a postfix unary operation, false
11690 /// if it is a prefix unary operation.
11691 bool IsPostfixUpdate;
11692
11693public:
11694 OpenMPAtomicUpdateChecker(Sema &SemaRef)
11695 : SemaRef(SemaRef), X(nullptr), E(nullptr), UpdateExpr(nullptr),
11696 IsXLHSInRHSPart(false), Op(BO_PtrMemD), IsPostfixUpdate(false) {}
11697 /// Check specified statement that it is suitable for 'atomic update'
11698 /// constructs and extract 'x', 'expr' and Operation from the original
11699 /// expression. If DiagId and NoteId == 0, then only check is performed
11700 /// without error notification.
11701 /// \param DiagId Diagnostic which should be emitted if error is found.
11702 /// \param NoteId Diagnostic note for the main error message.
11703 /// \return true if statement is not an update expression, false otherwise.
11704 bool checkStatement(Stmt *S, unsigned DiagId = 0, unsigned NoteId = 0);
11705 /// Return the 'x' lvalue part of the source atomic expression.
11706 Expr *getX() const { return X; }
11707 /// Return the 'expr' rvalue part of the source atomic expression.
11708 Expr *getExpr() const { return E; }
11709 /// Return the update expression used in calculation of the updated
11710 /// value. Always has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
11711 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
11712 Expr *getUpdateExpr() const { return UpdateExpr; }
11713 /// Return true if 'x' is LHS in RHS part of full update expression,
11714 /// false otherwise.
11715 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
11716
11717 /// true if the source expression is a postfix unary operation, false
11718 /// if it is a prefix unary operation.
11719 bool isPostfixUpdate() const { return IsPostfixUpdate; }
11720
11721private:
11722 bool checkBinaryOperation(BinaryOperator *AtomicBinOp, unsigned DiagId = 0,
11723 unsigned NoteId = 0);
11724};
11725
11726bool OpenMPAtomicUpdateChecker::checkBinaryOperation(
11727 BinaryOperator *AtomicBinOp, unsigned DiagId, unsigned NoteId) {
11728 ExprAnalysisErrorCode ErrorFound = NoError;
11729 SourceLocation ErrorLoc, NoteLoc;
11730 SourceRange ErrorRange, NoteRange;
11731 // Allowed constructs are:
11732 // x = x binop expr;
11733 // x = expr binop x;
11734 if (AtomicBinOp->getOpcode() == BO_Assign) {
11735 X = AtomicBinOp->getLHS();
11736 if (const auto *AtomicInnerBinOp = dyn_cast<BinaryOperator>(
11737 AtomicBinOp->getRHS()->IgnoreParenImpCasts())) {
11738 if (AtomicInnerBinOp->isMultiplicativeOp() ||
11739 AtomicInnerBinOp->isAdditiveOp() || AtomicInnerBinOp->isShiftOp() ||
11740 AtomicInnerBinOp->isBitwiseOp()) {
11741 Op = AtomicInnerBinOp->getOpcode();
11742 OpLoc = AtomicInnerBinOp->getOperatorLoc();
11743 Expr *LHS = AtomicInnerBinOp->getLHS();
11744 Expr *RHS = AtomicInnerBinOp->getRHS();
11745 llvm::FoldingSetNodeID XId, LHSId, RHSId;
11746 X->IgnoreParenImpCasts()->Profile(XId, SemaRef.getASTContext(),
11747 /*Canonical=*/true);
11748 LHS->IgnoreParenImpCasts()->Profile(LHSId, SemaRef.getASTContext(),
11749 /*Canonical=*/true);
11750 RHS->IgnoreParenImpCasts()->Profile(RHSId, SemaRef.getASTContext(),
11751 /*Canonical=*/true);
11752 if (XId == LHSId) {
11753 E = RHS;
11754 IsXLHSInRHSPart = true;
11755 } else if (XId == RHSId) {
11756 E = LHS;
11757 IsXLHSInRHSPart = false;
11758 } else {
11759 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11760 ErrorRange = AtomicInnerBinOp->getSourceRange();
11761 NoteLoc = X->getExprLoc();
11762 NoteRange = X->getSourceRange();
11763 ErrorFound = NotAnUpdateExpression;
11764 }
11765 } else {
11766 ErrorLoc = AtomicInnerBinOp->getExprLoc();
11767 ErrorRange = AtomicInnerBinOp->getSourceRange();
11768 NoteLoc = AtomicInnerBinOp->getOperatorLoc();
11769 NoteRange = SourceRange(NoteLoc, NoteLoc);
11770 ErrorFound = NotABinaryOperator;
11771 }
11772 } else {
11773 NoteLoc = ErrorLoc = AtomicBinOp->getRHS()->getExprLoc();
11774 NoteRange = ErrorRange = AtomicBinOp->getRHS()->getSourceRange();
11775 ErrorFound = NotABinaryExpression;
11776 }
11777 } else {
11778 ErrorLoc = AtomicBinOp->getExprLoc();
11779 ErrorRange = AtomicBinOp->getSourceRange();
11780 NoteLoc = AtomicBinOp->getOperatorLoc();
11781 NoteRange = SourceRange(NoteLoc, NoteLoc);
11782 ErrorFound = NotAnAssignmentOp;
11783 }
11784 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11785 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11786 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11787 return true;
11788 }
11789 if (SemaRef.CurContext->isDependentContext())
11790 E = X = UpdateExpr = nullptr;
11791 return ErrorFound != NoError;
11792}
11793
11794bool OpenMPAtomicUpdateChecker::checkStatement(Stmt *S, unsigned DiagId,
11795 unsigned NoteId) {
11796 ExprAnalysisErrorCode ErrorFound = NoError;
11797 SourceLocation ErrorLoc, NoteLoc;
11798 SourceRange ErrorRange, NoteRange;
11799 // Allowed constructs are:
11800 // x++;
11801 // x--;
11802 // ++x;
11803 // --x;
11804 // x binop= expr;
11805 // x = x binop expr;
11806 // x = expr binop x;
11807 if (auto *AtomicBody = dyn_cast<Expr>(S)) {
11808 AtomicBody = AtomicBody->IgnoreParenImpCasts();
11809 if (AtomicBody->getType()->isScalarType() ||
11810 AtomicBody->isInstantiationDependent()) {
11811 if (const auto *AtomicCompAssignOp = dyn_cast<CompoundAssignOperator>(
11812 AtomicBody->IgnoreParenImpCasts())) {
11813 // Check for Compound Assignment Operation
11815 AtomicCompAssignOp->getOpcode());
11816 OpLoc = AtomicCompAssignOp->getOperatorLoc();
11817 E = AtomicCompAssignOp->getRHS();
11818 X = AtomicCompAssignOp->getLHS()->IgnoreParens();
11819 IsXLHSInRHSPart = true;
11820 } else if (auto *AtomicBinOp = dyn_cast<BinaryOperator>(
11821 AtomicBody->IgnoreParenImpCasts())) {
11822 // Check for Binary Operation
11823 if (checkBinaryOperation(AtomicBinOp, DiagId, NoteId))
11824 return true;
11825 } else if (const auto *AtomicUnaryOp = dyn_cast<UnaryOperator>(
11826 AtomicBody->IgnoreParenImpCasts())) {
11827 // Check for Unary Operation
11828 if (AtomicUnaryOp->isIncrementDecrementOp()) {
11829 IsPostfixUpdate = AtomicUnaryOp->isPostfix();
11830 Op = AtomicUnaryOp->isIncrementOp() ? BO_Add : BO_Sub;
11831 OpLoc = AtomicUnaryOp->getOperatorLoc();
11832 X = AtomicUnaryOp->getSubExpr()->IgnoreParens();
11833 E = SemaRef.ActOnIntegerConstant(OpLoc, /*uint64_t Val=*/1).get();
11834 IsXLHSInRHSPart = true;
11835 } else {
11836 ErrorFound = NotAnUnaryIncDecExpression;
11837 ErrorLoc = AtomicUnaryOp->getExprLoc();
11838 ErrorRange = AtomicUnaryOp->getSourceRange();
11839 NoteLoc = AtomicUnaryOp->getOperatorLoc();
11840 NoteRange = SourceRange(NoteLoc, NoteLoc);
11841 }
11842 } else if (!AtomicBody->isInstantiationDependent()) {
11843 ErrorFound = NotABinaryOrUnaryExpression;
11844 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11845 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11846 } else if (AtomicBody->containsErrors()) {
11847 ErrorFound = NotAValidExpression;
11848 NoteLoc = ErrorLoc = AtomicBody->getExprLoc();
11849 NoteRange = ErrorRange = AtomicBody->getSourceRange();
11850 }
11851 } else {
11852 ErrorFound = NotAScalarType;
11853 NoteLoc = ErrorLoc = AtomicBody->getBeginLoc();
11854 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11855 }
11856 } else {
11857 ErrorFound = NotAnExpression;
11858 NoteLoc = ErrorLoc = S->getBeginLoc();
11859 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
11860 }
11861 if (ErrorFound != NoError && DiagId != 0 && NoteId != 0) {
11862 SemaRef.Diag(ErrorLoc, DiagId) << ErrorRange;
11863 SemaRef.Diag(NoteLoc, NoteId) << ErrorFound << NoteRange;
11864 return true;
11865 }
11866 if (SemaRef.CurContext->isDependentContext())
11867 E = X = UpdateExpr = nullptr;
11868 if (ErrorFound == NoError && E && X) {
11869 // Build an update expression of form 'OpaqueValueExpr(x) binop
11870 // OpaqueValueExpr(expr)' or 'OpaqueValueExpr(expr) binop
11871 // OpaqueValueExpr(x)' and then cast it to the type of the 'x' expression.
11872 auto *OVEX = new (SemaRef.getASTContext())
11873 OpaqueValueExpr(X->getExprLoc(), X->getType(), VK_PRValue);
11874 auto *OVEExpr = new (SemaRef.getASTContext())
11877 SemaRef.CreateBuiltinBinOp(OpLoc, Op, IsXLHSInRHSPart ? OVEX : OVEExpr,
11878 IsXLHSInRHSPart ? OVEExpr : OVEX);
11879 if (Update.isInvalid())
11880 return true;
11881 Update = SemaRef.PerformImplicitConversion(Update.get(), X->getType(),
11883 if (Update.isInvalid())
11884 return true;
11885 UpdateExpr = Update.get();
11886 }
11887 return ErrorFound != NoError;
11888}
11889
11890/// Get the node id of the fixed point of an expression \a S.
11891llvm::FoldingSetNodeID getNodeId(ASTContext &Context, const Expr *S) {
11892 llvm::FoldingSetNodeID Id;
11893 S->IgnoreParenImpCasts()->Profile(Id, Context, true);
11894 return Id;
11895}
11896
11897/// Check if two expressions are same.
11898bool checkIfTwoExprsAreSame(ASTContext &Context, const Expr *LHS,
11899 const Expr *RHS) {
11900 return getNodeId(Context, LHS) == getNodeId(Context, RHS);
11901}
11902
11903class OpenMPAtomicCompareChecker {
11904public:
11905 /// All kinds of errors that can occur in `atomic compare`
11906 enum ErrorTy {
11907 /// Empty compound statement.
11908 NoStmt = 0,
11909 /// More than one statement in a compound statement.
11910 MoreThanOneStmt,
11911 /// Not an assignment binary operator.
11912 NotAnAssignment,
11913 /// Not a conditional operator.
11914 NotCondOp,
11915 /// Wrong false expr. According to the spec, 'x' should be at the false
11916 /// expression of a conditional expression.
11917 WrongFalseExpr,
11918 /// The condition of a conditional expression is not a binary operator.
11919 NotABinaryOp,
11920 /// Invalid binary operator (not <, >, or ==).
11921 InvalidBinaryOp,
11922 /// Invalid comparison (not x == e, e == x, x ordop expr, or expr ordop x).
11923 InvalidComparison,
11924 /// X is not a lvalue.
11925 XNotLValue,
11926 /// Not a scalar.
11927 NotScalar,
11928 /// Not an integer.
11929 NotInteger,
11930 /// 'else' statement is not expected.
11931 UnexpectedElse,
11932 /// Not an equality operator.
11933 NotEQ,
11934 /// Invalid assignment (not v == x).
11935 InvalidAssignment,
11936 /// Not if statement
11937 NotIfStmt,
11938 /// More than two statements in a compound statement.
11939 MoreThanTwoStmts,
11940 /// Not a compound statement.
11941 NotCompoundStmt,
11942 /// No else statement.
11943 NoElse,
11944 /// Not 'if (r)'.
11945 InvalidCondition,
11946 /// No error.
11947 NoError,
11948 };
11949
11950 struct ErrorInfoTy {
11951 ErrorTy Error;
11952 SourceLocation ErrorLoc;
11953 SourceRange ErrorRange;
11954 SourceLocation NoteLoc;
11955 SourceRange NoteRange;
11956 };
11957
11958 OpenMPAtomicCompareChecker(Sema &S) : ContextRef(S.getASTContext()) {}
11959
11960 /// Check if statement \a S is valid for <tt>atomic compare</tt>.
11961 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11962
11963 Expr *getX() const { return X; }
11964 Expr *getE() const { return E; }
11965 Expr *getD() const { return D; }
11966 Expr *getCond() const { return C; }
11967 bool isXBinopExpr() const { return IsXBinopExpr; }
11968
11969protected:
11970 /// Reference to ASTContext
11971 ASTContext &ContextRef;
11972 /// 'x' lvalue part of the source atomic expression.
11973 Expr *X = nullptr;
11974 /// 'expr' or 'e' rvalue part of the source atomic expression.
11975 Expr *E = nullptr;
11976 /// 'd' rvalue part of the source atomic expression.
11977 Expr *D = nullptr;
11978 /// 'cond' part of the source atomic expression. It is in one of the following
11979 /// forms:
11980 /// expr ordop x
11981 /// x ordop expr
11982 /// x == e
11983 /// e == x
11984 Expr *C = nullptr;
11985 /// True if the cond expr is in the form of 'x ordop expr'.
11986 bool IsXBinopExpr = true;
11987
11988 /// Check if it is a valid conditional update statement (cond-update-stmt).
11989 bool checkCondUpdateStmt(IfStmt *S, ErrorInfoTy &ErrorInfo);
11990
11991 /// Check if it is a valid conditional expression statement (cond-expr-stmt).
11992 bool checkCondExprStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
11993
11994 /// Check if all captured values have right type.
11995 bool checkType(ErrorInfoTy &ErrorInfo) const;
11996
11997 static bool CheckValue(const Expr *E, ErrorInfoTy &ErrorInfo,
11998 bool ShouldBeLValue, bool ShouldBeInteger = false) {
11999 if (E->isInstantiationDependent())
12000 return true;
12001
12002 if (ShouldBeLValue && !E->isLValue()) {
12003 ErrorInfo.Error = ErrorTy::XNotLValue;
12004 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12005 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12006 return false;
12007 }
12008
12009 QualType QTy = E->getType();
12010 if (!QTy->isScalarType()) {
12011 ErrorInfo.Error = ErrorTy::NotScalar;
12012 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12013 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12014 return false;
12015 }
12016 if (ShouldBeInteger && !QTy->isIntegerType()) {
12017 ErrorInfo.Error = ErrorTy::NotInteger;
12018 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = E->getExprLoc();
12019 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = E->getSourceRange();
12020 return false;
12021 }
12022
12023 return true;
12024 }
12025};
12026
12027bool OpenMPAtomicCompareChecker::checkCondUpdateStmt(IfStmt *S,
12028 ErrorInfoTy &ErrorInfo) {
12029 auto *Then = S->getThen();
12030 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12031 if (CS->body_empty()) {
12032 ErrorInfo.Error = ErrorTy::NoStmt;
12033 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12034 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12035 return false;
12036 }
12037 if (CS->size() > 1) {
12038 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12039 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12040 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12041 return false;
12042 }
12043 Then = CS->body_front();
12044 }
12045
12046 auto *BO = dyn_cast<BinaryOperator>(Then);
12047 if (!BO) {
12048 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12049 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12050 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12051 return false;
12052 }
12053 if (BO->getOpcode() != BO_Assign) {
12054 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12055 ErrorInfo.ErrorLoc = BO->getExprLoc();
12056 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12057 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12058 return false;
12059 }
12060
12061 X = BO->getLHS();
12062
12063 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12064 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12065 Expr *LHS = nullptr;
12066 Expr *RHS = nullptr;
12067 if (Cond) {
12068 LHS = Cond->getLHS();
12069 RHS = Cond->getRHS();
12070 } else if (Call) {
12071 LHS = Call->getArg(0);
12072 RHS = Call->getArg(1);
12073 } else {
12074 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12075 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12076 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12077 return false;
12078 }
12079
12080 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12081 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12082 C = S->getCond();
12083 D = BO->getRHS();
12084 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12085 E = RHS;
12086 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12087 E = LHS;
12088 } else {
12089 ErrorInfo.Error = ErrorTy::InvalidComparison;
12090 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12091 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12092 S->getCond()->getSourceRange();
12093 return false;
12094 }
12095 } else if ((Cond &&
12096 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12097 (Call &&
12098 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12099 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12100 E = BO->getRHS();
12101 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12102 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12103 C = S->getCond();
12104 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12105 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12106 C = S->getCond();
12107 IsXBinopExpr = false;
12108 } else {
12109 ErrorInfo.Error = ErrorTy::InvalidComparison;
12110 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12111 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12112 S->getCond()->getSourceRange();
12113 return false;
12114 }
12115 } else {
12116 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12117 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12118 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12119 return false;
12120 }
12121
12122 if (S->getElse()) {
12123 ErrorInfo.Error = ErrorTy::UnexpectedElse;
12124 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getElse()->getBeginLoc();
12125 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getElse()->getSourceRange();
12126 return false;
12127 }
12128
12129 return true;
12130}
12131
12132bool OpenMPAtomicCompareChecker::checkCondExprStmt(Stmt *S,
12133 ErrorInfoTy &ErrorInfo) {
12134 auto *BO = dyn_cast<BinaryOperator>(S);
12135 if (!BO) {
12136 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12137 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12138 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12139 return false;
12140 }
12141 if (BO->getOpcode() != BO_Assign) {
12142 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12143 ErrorInfo.ErrorLoc = BO->getExprLoc();
12144 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12145 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12146 return false;
12147 }
12148
12149 X = BO->getLHS();
12150
12151 auto *CO = dyn_cast<ConditionalOperator>(BO->getRHS()->IgnoreParenImpCasts());
12152 if (!CO) {
12153 ErrorInfo.Error = ErrorTy::NotCondOp;
12154 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getRHS()->getExprLoc();
12155 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getRHS()->getSourceRange();
12156 return false;
12157 }
12158
12159 if (!checkIfTwoExprsAreSame(ContextRef, X, CO->getFalseExpr())) {
12160 ErrorInfo.Error = ErrorTy::WrongFalseExpr;
12161 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getFalseExpr()->getExprLoc();
12162 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12163 CO->getFalseExpr()->getSourceRange();
12164 return false;
12165 }
12166
12167 auto *Cond = dyn_cast<BinaryOperator>(CO->getCond());
12168 auto *Call = dyn_cast<CXXOperatorCallExpr>(CO->getCond());
12169 Expr *LHS = nullptr;
12170 Expr *RHS = nullptr;
12171 if (Cond) {
12172 LHS = Cond->getLHS();
12173 RHS = Cond->getRHS();
12174 } else if (Call) {
12175 LHS = Call->getArg(0);
12176 RHS = Call->getArg(1);
12177 } else {
12178 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12179 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12180 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12181 CO->getCond()->getSourceRange();
12182 return false;
12183 }
12184
12185 if ((Cond && Cond->getOpcode() == BO_EQ) ||
12186 (Call && Call->getOperator() == OverloadedOperatorKind::OO_EqualEqual)) {
12187 C = CO->getCond();
12188 D = CO->getTrueExpr();
12189 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12190 E = RHS;
12191 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12192 E = LHS;
12193 } else {
12194 ErrorInfo.Error = ErrorTy::InvalidComparison;
12195 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12196 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12197 CO->getCond()->getSourceRange();
12198 return false;
12199 }
12200 } else if ((Cond &&
12201 (Cond->getOpcode() == BO_LT || Cond->getOpcode() == BO_GT)) ||
12202 (Call &&
12203 (Call->getOperator() == OverloadedOperatorKind::OO_Less ||
12204 Call->getOperator() == OverloadedOperatorKind::OO_Greater))) {
12205
12206 E = CO->getTrueExpr();
12207 if (checkIfTwoExprsAreSame(ContextRef, X, LHS) &&
12208 checkIfTwoExprsAreSame(ContextRef, E, RHS)) {
12209 C = CO->getCond();
12210 } else if (checkIfTwoExprsAreSame(ContextRef, E, LHS) &&
12211 checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12212 C = CO->getCond();
12213 IsXBinopExpr = false;
12214 } else {
12215 ErrorInfo.Error = ErrorTy::InvalidComparison;
12216 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12217 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12218 CO->getCond()->getSourceRange();
12219 return false;
12220 }
12221 } else {
12222 ErrorInfo.Error = ErrorTy::InvalidBinaryOp;
12223 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CO->getCond()->getExprLoc();
12224 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12225 CO->getCond()->getSourceRange();
12226 return false;
12227 }
12228
12229 return true;
12230}
12231
12232bool OpenMPAtomicCompareChecker::checkType(ErrorInfoTy &ErrorInfo) const {
12233 // 'x' and 'e' cannot be nullptr
12234 assert(X && E && "X and E cannot be nullptr");
12235
12236 if (!CheckValue(X, ErrorInfo, true))
12237 return false;
12238
12239 if (!CheckValue(E, ErrorInfo, false))
12240 return false;
12241
12242 if (D && !CheckValue(D, ErrorInfo, false))
12243 return false;
12244
12245 return true;
12246}
12247
12248bool OpenMPAtomicCompareChecker::checkStmt(
12249 Stmt *S, OpenMPAtomicCompareChecker::ErrorInfoTy &ErrorInfo) {
12250 auto *CS = dyn_cast<CompoundStmt>(S);
12251 if (CS) {
12252 if (CS->body_empty()) {
12253 ErrorInfo.Error = ErrorTy::NoStmt;
12254 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12255 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12256 return false;
12257 }
12258
12259 if (CS->size() != 1) {
12260 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12261 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12262 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12263 return false;
12264 }
12265 S = CS->body_front();
12266 }
12267
12268 auto Res = false;
12269
12270 if (auto *IS = dyn_cast<IfStmt>(S)) {
12271 // Check if the statement is in one of the following forms
12272 // (cond-update-stmt):
12273 // if (expr ordop x) { x = expr; }
12274 // if (x ordop expr) { x = expr; }
12275 // if (x == e) { x = d; }
12276 Res = checkCondUpdateStmt(IS, ErrorInfo);
12277 } else {
12278 // Check if the statement is in one of the following forms (cond-expr-stmt):
12279 // x = expr ordop x ? expr : x;
12280 // x = x ordop expr ? expr : x;
12281 // x = x == e ? d : x;
12282 Res = checkCondExprStmt(S, ErrorInfo);
12283 }
12284
12285 if (!Res)
12286 return false;
12287
12288 return checkType(ErrorInfo);
12289}
12290
12291class OpenMPAtomicCompareCaptureChecker final
12292 : public OpenMPAtomicCompareChecker {
12293public:
12294 OpenMPAtomicCompareCaptureChecker(Sema &S) : OpenMPAtomicCompareChecker(S) {}
12295
12296 Expr *getV() const { return V; }
12297 Expr *getR() const { return R; }
12298 bool isFailOnly() const { return IsFailOnly; }
12299 bool isPostfixUpdate() const { return IsPostfixUpdate; }
12300
12301 /// Check if statement \a S is valid for <tt>atomic compare capture</tt>.
12302 bool checkStmt(Stmt *S, ErrorInfoTy &ErrorInfo);
12303
12304private:
12305 bool checkType(ErrorInfoTy &ErrorInfo);
12306
12307 // NOTE: Form 3, 4, 5 in the following comments mean the 3rd, 4th, and 5th
12308 // form of 'conditional-update-capture-atomic' structured block on the v5.2
12309 // spec p.p. 82:
12310 // (1) { v = x; cond-update-stmt }
12311 // (2) { cond-update-stmt v = x; }
12312 // (3) if(x == e) { x = d; } else { v = x; }
12313 // (4) { r = x == e; if(r) { x = d; } }
12314 // (5) { r = x == e; if(r) { x = d; } else { v = x; } }
12315
12316 /// Check if it is valid 'if(x == e) { x = d; } else { v = x; }' (form 3)
12317 bool checkForm3(IfStmt *S, ErrorInfoTy &ErrorInfo);
12318
12319 /// Check if it is valid '{ r = x == e; if(r) { x = d; } }',
12320 /// or '{ r = x == e; if(r) { x = d; } else { v = x; } }' (form 4 and 5)
12321 bool checkForm45(Stmt *S, ErrorInfoTy &ErrorInfo);
12322
12323 /// 'v' lvalue part of the source atomic expression.
12324 Expr *V = nullptr;
12325 /// 'r' lvalue part of the source atomic expression.
12326 Expr *R = nullptr;
12327 /// If 'v' is only updated when the comparison fails.
12328 bool IsFailOnly = false;
12329 /// If original value of 'x' must be stored in 'v', not an updated one.
12330 bool IsPostfixUpdate = false;
12331};
12332
12333bool OpenMPAtomicCompareCaptureChecker::checkType(ErrorInfoTy &ErrorInfo) {
12334 if (!OpenMPAtomicCompareChecker::checkType(ErrorInfo))
12335 return false;
12336
12337 if (V && !CheckValue(V, ErrorInfo, true))
12338 return false;
12339
12340 if (R && !CheckValue(R, ErrorInfo, true, true))
12341 return false;
12342
12343 return true;
12344}
12345
12346bool OpenMPAtomicCompareCaptureChecker::checkForm3(IfStmt *S,
12347 ErrorInfoTy &ErrorInfo) {
12348 IsFailOnly = true;
12349
12350 auto *Then = S->getThen();
12351 if (auto *CS = dyn_cast<CompoundStmt>(Then)) {
12352 if (CS->body_empty()) {
12353 ErrorInfo.Error = ErrorTy::NoStmt;
12354 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12355 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12356 return false;
12357 }
12358 if (CS->size() > 1) {
12359 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12360 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12361 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12362 return false;
12363 }
12364 Then = CS->body_front();
12365 }
12366
12367 auto *BO = dyn_cast<BinaryOperator>(Then);
12368 if (!BO) {
12369 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12370 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Then->getBeginLoc();
12371 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Then->getSourceRange();
12372 return false;
12373 }
12374 if (BO->getOpcode() != BO_Assign) {
12375 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12376 ErrorInfo.ErrorLoc = BO->getExprLoc();
12377 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12378 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12379 return false;
12380 }
12381
12382 X = BO->getLHS();
12383 D = BO->getRHS();
12384
12385 auto *Cond = dyn_cast<BinaryOperator>(S->getCond());
12386 auto *Call = dyn_cast<CXXOperatorCallExpr>(S->getCond());
12387 Expr *LHS = nullptr;
12388 Expr *RHS = nullptr;
12389 if (Cond) {
12390 LHS = Cond->getLHS();
12391 RHS = Cond->getRHS();
12392 } else if (Call) {
12393 LHS = Call->getArg(0);
12394 RHS = Call->getArg(1);
12395 } else {
12396 ErrorInfo.Error = ErrorTy::NotABinaryOp;
12397 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12398 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12399 return false;
12400 }
12401 if ((Cond && Cond->getOpcode() != BO_EQ) ||
12402 (Call && Call->getOperator() != OverloadedOperatorKind::OO_EqualEqual)) {
12403 ErrorInfo.Error = ErrorTy::NotEQ;
12404 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12405 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12406 return false;
12407 }
12408
12409 if (checkIfTwoExprsAreSame(ContextRef, X, LHS)) {
12410 E = RHS;
12411 } else if (checkIfTwoExprsAreSame(ContextRef, X, RHS)) {
12412 E = LHS;
12413 } else {
12414 ErrorInfo.Error = ErrorTy::InvalidComparison;
12415 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getCond()->getExprLoc();
12416 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getCond()->getSourceRange();
12417 return false;
12418 }
12419
12420 C = S->getCond();
12421
12422 if (!S->getElse()) {
12423 ErrorInfo.Error = ErrorTy::NoElse;
12424 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12425 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12426 return false;
12427 }
12428
12429 auto *Else = S->getElse();
12430 if (auto *CS = dyn_cast<CompoundStmt>(Else)) {
12431 if (CS->body_empty()) {
12432 ErrorInfo.Error = ErrorTy::NoStmt;
12433 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12434 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12435 return false;
12436 }
12437 if (CS->size() > 1) {
12438 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12439 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12440 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12441 return false;
12442 }
12443 Else = CS->body_front();
12444 }
12445
12446 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12447 if (!ElseBO) {
12448 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12449 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12450 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12451 return false;
12452 }
12453 if (ElseBO->getOpcode() != BO_Assign) {
12454 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12455 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12456 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12457 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12458 return false;
12459 }
12460
12461 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12462 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12463 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseBO->getRHS()->getExprLoc();
12464 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12465 ElseBO->getRHS()->getSourceRange();
12466 return false;
12467 }
12468
12469 V = ElseBO->getLHS();
12470
12471 return checkType(ErrorInfo);
12472}
12473
12474bool OpenMPAtomicCompareCaptureChecker::checkForm45(Stmt *S,
12475 ErrorInfoTy &ErrorInfo) {
12476 // We don't check here as they should be already done before call this
12477 // function.
12478 auto *CS = cast<CompoundStmt>(S);
12479 assert(CS->size() == 2 && "CompoundStmt size is not expected");
12480 auto *S1 = cast<BinaryOperator>(CS->body_front());
12481 auto *S2 = cast<IfStmt>(CS->body_back());
12482 assert(S1->getOpcode() == BO_Assign && "unexpected binary operator");
12483
12484 if (!checkIfTwoExprsAreSame(ContextRef, S1->getLHS(), S2->getCond())) {
12485 ErrorInfo.Error = ErrorTy::InvalidCondition;
12486 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getCond()->getExprLoc();
12487 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S1->getLHS()->getSourceRange();
12488 return false;
12489 }
12490
12491 R = S1->getLHS();
12492
12493 auto *Then = S2->getThen();
12494 if (auto *ThenCS = dyn_cast<CompoundStmt>(Then)) {
12495 if (ThenCS->body_empty()) {
12496 ErrorInfo.Error = ErrorTy::NoStmt;
12497 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12498 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12499 return false;
12500 }
12501 if (ThenCS->size() > 1) {
12502 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12503 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ThenCS->getBeginLoc();
12504 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenCS->getSourceRange();
12505 return false;
12506 }
12507 Then = ThenCS->body_front();
12508 }
12509
12510 auto *ThenBO = dyn_cast<BinaryOperator>(Then);
12511 if (!ThenBO) {
12512 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12513 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S2->getBeginLoc();
12514 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S2->getSourceRange();
12515 return false;
12516 }
12517 if (ThenBO->getOpcode() != BO_Assign) {
12518 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12519 ErrorInfo.ErrorLoc = ThenBO->getExprLoc();
12520 ErrorInfo.NoteLoc = ThenBO->getOperatorLoc();
12521 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ThenBO->getSourceRange();
12522 return false;
12523 }
12524
12525 X = ThenBO->getLHS();
12526 D = ThenBO->getRHS();
12527
12528 auto *BO = cast<BinaryOperator>(S1->getRHS()->IgnoreImpCasts());
12529 if (BO->getOpcode() != BO_EQ) {
12530 ErrorInfo.Error = ErrorTy::NotEQ;
12531 ErrorInfo.ErrorLoc = BO->getExprLoc();
12532 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12533 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12534 return false;
12535 }
12536
12537 C = BO;
12538
12539 if (checkIfTwoExprsAreSame(ContextRef, X, BO->getLHS())) {
12540 E = BO->getRHS();
12541 } else if (checkIfTwoExprsAreSame(ContextRef, X, BO->getRHS())) {
12542 E = BO->getLHS();
12543 } else {
12544 ErrorInfo.Error = ErrorTy::InvalidComparison;
12545 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = BO->getExprLoc();
12546 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12547 return false;
12548 }
12549
12550 if (S2->getElse()) {
12551 IsFailOnly = true;
12552
12553 auto *Else = S2->getElse();
12554 if (auto *ElseCS = dyn_cast<CompoundStmt>(Else)) {
12555 if (ElseCS->body_empty()) {
12556 ErrorInfo.Error = ErrorTy::NoStmt;
12557 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12558 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12559 return false;
12560 }
12561 if (ElseCS->size() > 1) {
12562 ErrorInfo.Error = ErrorTy::MoreThanOneStmt;
12563 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = ElseCS->getBeginLoc();
12564 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseCS->getSourceRange();
12565 return false;
12566 }
12567 Else = ElseCS->body_front();
12568 }
12569
12570 auto *ElseBO = dyn_cast<BinaryOperator>(Else);
12571 if (!ElseBO) {
12572 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12573 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = Else->getBeginLoc();
12574 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Else->getSourceRange();
12575 return false;
12576 }
12577 if (ElseBO->getOpcode() != BO_Assign) {
12578 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12579 ErrorInfo.ErrorLoc = ElseBO->getExprLoc();
12580 ErrorInfo.NoteLoc = ElseBO->getOperatorLoc();
12581 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = ElseBO->getSourceRange();
12582 return false;
12583 }
12584 if (!checkIfTwoExprsAreSame(ContextRef, X, ElseBO->getRHS())) {
12585 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12586 ErrorInfo.ErrorLoc = ElseBO->getRHS()->getExprLoc();
12587 ErrorInfo.NoteLoc = X->getExprLoc();
12588 ErrorInfo.ErrorRange = ElseBO->getRHS()->getSourceRange();
12589 ErrorInfo.NoteRange = X->getSourceRange();
12590 return false;
12591 }
12592
12593 V = ElseBO->getLHS();
12594 }
12595
12596 return checkType(ErrorInfo);
12597}
12598
12599bool OpenMPAtomicCompareCaptureChecker::checkStmt(Stmt *S,
12600 ErrorInfoTy &ErrorInfo) {
12601 // if(x == e) { x = d; } else { v = x; }
12602 if (auto *IS = dyn_cast<IfStmt>(S))
12603 return checkForm3(IS, ErrorInfo);
12604
12605 auto *CS = dyn_cast<CompoundStmt>(S);
12606 if (!CS) {
12607 ErrorInfo.Error = ErrorTy::NotCompoundStmt;
12608 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = S->getBeginLoc();
12609 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = S->getSourceRange();
12610 return false;
12611 }
12612 if (CS->body_empty()) {
12613 ErrorInfo.Error = ErrorTy::NoStmt;
12614 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12615 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12616 return false;
12617 }
12618
12619 // { if(x == e) { x = d; } else { v = x; } }
12620 if (CS->size() == 1) {
12621 auto *IS = dyn_cast<IfStmt>(CS->body_front());
12622 if (!IS) {
12623 ErrorInfo.Error = ErrorTy::NotIfStmt;
12624 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->body_front()->getBeginLoc();
12625 ErrorInfo.ErrorRange = ErrorInfo.NoteRange =
12626 CS->body_front()->getSourceRange();
12627 return false;
12628 }
12629
12630 return checkForm3(IS, ErrorInfo);
12631 } else if (CS->size() == 2) {
12632 auto *S1 = CS->body_front();
12633 auto *S2 = CS->body_back();
12634
12635 Stmt *UpdateStmt = nullptr;
12636 Stmt *CondUpdateStmt = nullptr;
12637 Stmt *CondExprStmt = nullptr;
12638
12639 if (auto *BO = dyn_cast<BinaryOperator>(S1)) {
12640 // It could be one of the following cases:
12641 // { v = x; cond-update-stmt }
12642 // { v = x; cond-expr-stmt }
12643 // { cond-expr-stmt; v = x; }
12644 // form 45
12645 if (isa<BinaryOperator>(BO->getRHS()->IgnoreImpCasts()) ||
12646 isa<ConditionalOperator>(BO->getRHS()->IgnoreImpCasts())) {
12647 // check if form 45
12648 if (isa<IfStmt>(S2))
12649 return checkForm45(CS, ErrorInfo);
12650 // { cond-expr-stmt; v = x; }
12651 CondExprStmt = S1;
12652 UpdateStmt = S2;
12653 } else {
12654 IsPostfixUpdate = true;
12655 UpdateStmt = S1;
12656 if (isa<IfStmt>(S2)) {
12657 // { v = x; cond-update-stmt }
12658 CondUpdateStmt = S2;
12659 } else {
12660 // { v = x; cond-expr-stmt }
12661 CondExprStmt = S2;
12662 }
12663 }
12664 } else {
12665 // { cond-update-stmt v = x; }
12666 UpdateStmt = S2;
12667 CondUpdateStmt = S1;
12668 }
12669
12670 auto CheckCondUpdateStmt = [this, &ErrorInfo](Stmt *CUS) {
12671 auto *IS = dyn_cast<IfStmt>(CUS);
12672 if (!IS) {
12673 ErrorInfo.Error = ErrorTy::NotIfStmt;
12674 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CUS->getBeginLoc();
12675 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CUS->getSourceRange();
12676 return false;
12677 }
12678
12679 return checkCondUpdateStmt(IS, ErrorInfo);
12680 };
12681
12682 // CheckUpdateStmt has to be called *after* CheckCondUpdateStmt.
12683 auto CheckUpdateStmt = [this, &ErrorInfo](Stmt *US) {
12684 auto *BO = dyn_cast<BinaryOperator>(US);
12685 if (!BO) {
12686 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12687 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = US->getBeginLoc();
12688 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = US->getSourceRange();
12689 return false;
12690 }
12691 if (BO->getOpcode() != BO_Assign) {
12692 ErrorInfo.Error = ErrorTy::NotAnAssignment;
12693 ErrorInfo.ErrorLoc = BO->getExprLoc();
12694 ErrorInfo.NoteLoc = BO->getOperatorLoc();
12695 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = BO->getSourceRange();
12696 return false;
12697 }
12698 if (!checkIfTwoExprsAreSame(ContextRef, this->X, BO->getRHS())) {
12699 ErrorInfo.Error = ErrorTy::InvalidAssignment;
12700 ErrorInfo.ErrorLoc = BO->getRHS()->getExprLoc();
12701 ErrorInfo.NoteLoc = this->X->getExprLoc();
12702 ErrorInfo.ErrorRange = BO->getRHS()->getSourceRange();
12703 ErrorInfo.NoteRange = this->X->getSourceRange();
12704 return false;
12705 }
12706
12707 this->V = BO->getLHS();
12708
12709 return true;
12710 };
12711
12712 if (CondUpdateStmt && !CheckCondUpdateStmt(CondUpdateStmt))
12713 return false;
12714 if (CondExprStmt && !checkCondExprStmt(CondExprStmt, ErrorInfo))
12715 return false;
12716 if (!CheckUpdateStmt(UpdateStmt))
12717 return false;
12718 } else {
12719 ErrorInfo.Error = ErrorTy::MoreThanTwoStmts;
12720 ErrorInfo.ErrorLoc = ErrorInfo.NoteLoc = CS->getBeginLoc();
12721 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = CS->getSourceRange();
12722 return false;
12723 }
12724
12725 return checkType(ErrorInfo);
12726}
12727} // namespace
12728
12730 Stmt *AStmt,
12731 SourceLocation StartLoc,
12732 SourceLocation EndLoc) {
12733 ASTContext &Context = getASTContext();
12734 unsigned OMPVersion = getLangOpts().OpenMP;
12735 // Register location of the first atomic directive.
12736 DSAStack->addAtomicDirectiveLoc(StartLoc);
12737 if (!AStmt)
12738 return StmtError();
12739
12740 // 1.2.2 OpenMP Language Terminology
12741 // Structured block - An executable statement with a single entry at the
12742 // top and a single exit at the bottom.
12743 // The point of exit cannot be a branch out of the structured block.
12744 // longjmp() and throw() must not violate the entry/exit criteria.
12745 OpenMPClauseKind AtomicKind = OMPC_unknown;
12746 SourceLocation AtomicKindLoc;
12747 OpenMPClauseKind MemOrderKind = OMPC_unknown;
12748 SourceLocation MemOrderLoc;
12749 bool MutexClauseEncountered = false;
12750 llvm::SmallSet<OpenMPClauseKind, 2> EncounteredAtomicKinds;
12751 for (const OMPClause *C : Clauses) {
12752 switch (C->getClauseKind()) {
12753 case OMPC_read:
12754 case OMPC_write:
12755 case OMPC_update:
12756 MutexClauseEncountered = true;
12757 [[fallthrough]];
12758 case OMPC_capture:
12759 case OMPC_compare: {
12760 if (AtomicKind != OMPC_unknown && MutexClauseEncountered) {
12761 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12762 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12763 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12764 << getOpenMPClauseNameForDiag(AtomicKind);
12765 } else {
12766 AtomicKind = C->getClauseKind();
12767 AtomicKindLoc = C->getBeginLoc();
12768 if (!EncounteredAtomicKinds.insert(C->getClauseKind()).second) {
12769 Diag(C->getBeginLoc(), diag::err_omp_atomic_several_clauses)
12770 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12771 Diag(AtomicKindLoc, diag::note_omp_previous_mem_order_clause)
12772 << getOpenMPClauseNameForDiag(AtomicKind);
12773 }
12774 }
12775 break;
12776 }
12777 case OMPC_weak:
12778 case OMPC_fail: {
12779 if (!EncounteredAtomicKinds.contains(OMPC_compare)) {
12780 Diag(C->getBeginLoc(), diag::err_omp_atomic_no_compare)
12781 << getOpenMPClauseNameForDiag(C->getClauseKind())
12782 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12783 return StmtError();
12784 }
12785 break;
12786 }
12787 case OMPC_seq_cst:
12788 case OMPC_acq_rel:
12789 case OMPC_acquire:
12790 case OMPC_release:
12791 case OMPC_relaxed: {
12792 if (MemOrderKind != OMPC_unknown) {
12793 Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
12794 << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
12795 << SourceRange(C->getBeginLoc(), C->getEndLoc());
12796 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12797 << getOpenMPClauseNameForDiag(MemOrderKind);
12798 } else {
12799 MemOrderKind = C->getClauseKind();
12800 MemOrderLoc = C->getBeginLoc();
12801 }
12802 break;
12803 }
12804 // The following clauses are allowed, but we don't need to do anything here.
12805 case OMPC_hint:
12806 break;
12807 default:
12808 llvm_unreachable("unknown clause is encountered");
12809 }
12810 }
12811 bool IsCompareCapture = false;
12812 if (EncounteredAtomicKinds.contains(OMPC_compare) &&
12813 EncounteredAtomicKinds.contains(OMPC_capture)) {
12814 IsCompareCapture = true;
12815 AtomicKind = OMPC_compare;
12816 }
12817 // OpenMP 5.0, 2.17.7 atomic Construct, Restrictions
12818 // If atomic-clause is read then memory-order-clause must not be acq_rel or
12819 // release.
12820 // If atomic-clause is write then memory-order-clause must not be acq_rel or
12821 // acquire.
12822 // If atomic-clause is update or not present then memory-order-clause must not
12823 // be acq_rel or acquire.
12824 if ((AtomicKind == OMPC_read &&
12825 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_release)) ||
12826 ((AtomicKind == OMPC_write || AtomicKind == OMPC_update ||
12827 AtomicKind == OMPC_unknown) &&
12828 (MemOrderKind == OMPC_acq_rel || MemOrderKind == OMPC_acquire))) {
12829 SourceLocation Loc = AtomicKindLoc;
12830 if (AtomicKind == OMPC_unknown)
12831 Loc = StartLoc;
12832 Diag(Loc, diag::err_omp_atomic_incompatible_mem_order_clause)
12833 << getOpenMPClauseNameForDiag(AtomicKind)
12834 << (AtomicKind == OMPC_unknown ? 1 : 0)
12835 << getOpenMPClauseNameForDiag(MemOrderKind);
12836 Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
12837 << getOpenMPClauseNameForDiag(MemOrderKind);
12838 }
12839
12840 Stmt *Body = AStmt;
12841 if (auto *EWC = dyn_cast<ExprWithCleanups>(Body))
12842 Body = EWC->getSubExpr();
12843
12844 Expr *X = nullptr;
12845 Expr *V = nullptr;
12846 Expr *E = nullptr;
12847 Expr *UE = nullptr;
12848 Expr *D = nullptr;
12849 Expr *CE = nullptr;
12850 Expr *R = nullptr;
12851 bool IsXLHSInRHSPart = false;
12852 bool IsPostfixUpdate = false;
12853 bool IsFailOnly = false;
12854 // OpenMP [2.12.6, atomic Construct]
12855 // In the next expressions:
12856 // * x and v (as applicable) are both l-value expressions with scalar type.
12857 // * During the execution of an atomic region, multiple syntactic
12858 // occurrences of x must designate the same storage location.
12859 // * Neither of v and expr (as applicable) may access the storage location
12860 // designated by x.
12861 // * Neither of x and expr (as applicable) may access the storage location
12862 // designated by v.
12863 // * expr is an expression with scalar type.
12864 // * binop is one of +, *, -, /, &, ^, |, <<, or >>.
12865 // * binop, binop=, ++, and -- are not overloaded operators.
12866 // * The expression x binop expr must be numerically equivalent to x binop
12867 // (expr). This requirement is satisfied if the operators in expr have
12868 // precedence greater than binop, or by using parentheses around expr or
12869 // subexpressions of expr.
12870 // * The expression expr binop x must be numerically equivalent to (expr)
12871 // binop x. This requirement is satisfied if the operators in expr have
12872 // precedence equal to or greater than binop, or by using parentheses around
12873 // expr or subexpressions of expr.
12874 // * For forms that allow multiple occurrences of x, the number of times
12875 // that x is evaluated is unspecified.
12876 if (AtomicKind == OMPC_read) {
12877 enum {
12878 NotAnExpression,
12879 NotAnAssignmentOp,
12880 NotAScalarType,
12881 NotAnLValue,
12882 NoError
12883 } ErrorFound = NoError;
12884 SourceLocation ErrorLoc, NoteLoc;
12885 SourceRange ErrorRange, NoteRange;
12886 // If clause is read:
12887 // v = x;
12888 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12889 const auto *AtomicBinOp =
12890 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12891 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12892 X = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
12893 V = AtomicBinOp->getLHS()->IgnoreParenImpCasts();
12894 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12895 (V->isInstantiationDependent() || V->getType()->isScalarType())) {
12896 if (!X->isLValue() || !V->isLValue()) {
12897 const Expr *NotLValueExpr = X->isLValue() ? V : X;
12898 ErrorFound = NotAnLValue;
12899 ErrorLoc = AtomicBinOp->getExprLoc();
12900 ErrorRange = AtomicBinOp->getSourceRange();
12901 NoteLoc = NotLValueExpr->getExprLoc();
12902 NoteRange = NotLValueExpr->getSourceRange();
12903 }
12904 } else if (!X->isInstantiationDependent() ||
12905 !V->isInstantiationDependent()) {
12906 const Expr *NotScalarExpr =
12907 (X->isInstantiationDependent() || X->getType()->isScalarType())
12908 ? V
12909 : X;
12910 ErrorFound = NotAScalarType;
12911 ErrorLoc = AtomicBinOp->getExprLoc();
12912 ErrorRange = AtomicBinOp->getSourceRange();
12913 NoteLoc = NotScalarExpr->getExprLoc();
12914 NoteRange = NotScalarExpr->getSourceRange();
12915 }
12916 } else if (!AtomicBody->isInstantiationDependent()) {
12917 ErrorFound = NotAnAssignmentOp;
12918 ErrorLoc = AtomicBody->getExprLoc();
12919 ErrorRange = AtomicBody->getSourceRange();
12920 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12921 : AtomicBody->getExprLoc();
12922 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12923 : AtomicBody->getSourceRange();
12924 }
12925 } else {
12926 ErrorFound = NotAnExpression;
12927 NoteLoc = ErrorLoc = Body->getBeginLoc();
12928 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12929 }
12930 if (ErrorFound != NoError) {
12931 Diag(ErrorLoc, diag::err_omp_atomic_read_not_expression_statement)
12932 << ErrorRange;
12933 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12934 << ErrorFound << NoteRange;
12935 return StmtError();
12936 }
12937 if (SemaRef.CurContext->isDependentContext())
12938 V = X = nullptr;
12939 } else if (AtomicKind == OMPC_write) {
12940 enum {
12941 NotAnExpression,
12942 NotAnAssignmentOp,
12943 NotAScalarType,
12944 NotAnLValue,
12945 NoError
12946 } ErrorFound = NoError;
12947 SourceLocation ErrorLoc, NoteLoc;
12948 SourceRange ErrorRange, NoteRange;
12949 // If clause is write:
12950 // x = expr;
12951 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
12952 const auto *AtomicBinOp =
12953 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
12954 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
12955 X = AtomicBinOp->getLHS();
12956 E = AtomicBinOp->getRHS();
12957 if ((X->isInstantiationDependent() || X->getType()->isScalarType()) &&
12958 (E->isInstantiationDependent() || E->getType()->isScalarType())) {
12959 if (!X->isLValue()) {
12960 ErrorFound = NotAnLValue;
12961 ErrorLoc = AtomicBinOp->getExprLoc();
12962 ErrorRange = AtomicBinOp->getSourceRange();
12963 NoteLoc = X->getExprLoc();
12964 NoteRange = X->getSourceRange();
12965 }
12966 } else if (!X->isInstantiationDependent() ||
12968 const Expr *NotScalarExpr =
12969 (X->isInstantiationDependent() || X->getType()->isScalarType())
12970 ? E
12971 : X;
12972 ErrorFound = NotAScalarType;
12973 ErrorLoc = AtomicBinOp->getExprLoc();
12974 ErrorRange = AtomicBinOp->getSourceRange();
12975 NoteLoc = NotScalarExpr->getExprLoc();
12976 NoteRange = NotScalarExpr->getSourceRange();
12977 }
12978 } else if (!AtomicBody->isInstantiationDependent()) {
12979 ErrorFound = NotAnAssignmentOp;
12980 ErrorLoc = AtomicBody->getExprLoc();
12981 ErrorRange = AtomicBody->getSourceRange();
12982 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
12983 : AtomicBody->getExprLoc();
12984 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
12985 : AtomicBody->getSourceRange();
12986 }
12987 } else {
12988 ErrorFound = NotAnExpression;
12989 NoteLoc = ErrorLoc = Body->getBeginLoc();
12990 NoteRange = ErrorRange = SourceRange(NoteLoc, NoteLoc);
12991 }
12992 if (ErrorFound != NoError) {
12993 Diag(ErrorLoc, diag::err_omp_atomic_write_not_expression_statement)
12994 << ErrorRange;
12995 Diag(NoteLoc, diag::note_omp_atomic_read_write)
12996 << ErrorFound << NoteRange;
12997 return StmtError();
12998 }
12999 if (SemaRef.CurContext->isDependentContext())
13000 E = X = nullptr;
13001 } else if (AtomicKind == OMPC_update || AtomicKind == OMPC_unknown) {
13002 // If clause is update:
13003 // x++;
13004 // x--;
13005 // ++x;
13006 // --x;
13007 // x binop= expr;
13008 // x = x binop expr;
13009 // x = expr binop x;
13010 OpenMPAtomicUpdateChecker Checker(SemaRef);
13011 if (Checker.checkStatement(
13012 Body,
13013 (AtomicKind == OMPC_update)
13014 ? diag::err_omp_atomic_update_not_expression_statement
13015 : diag::err_omp_atomic_not_expression_statement,
13016 diag::note_omp_atomic_update))
13017 return StmtError();
13018 if (!SemaRef.CurContext->isDependentContext()) {
13019 E = Checker.getExpr();
13020 X = Checker.getX();
13021 UE = Checker.getUpdateExpr();
13022 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13023 }
13024 } else if (AtomicKind == OMPC_capture) {
13025 enum {
13026 NotAnAssignmentOp,
13027 NotACompoundStatement,
13028 NotTwoSubstatements,
13029 NotASpecificExpression,
13030 NoError
13031 } ErrorFound = NoError;
13032 SourceLocation ErrorLoc, NoteLoc;
13033 SourceRange ErrorRange, NoteRange;
13034 if (const auto *AtomicBody = dyn_cast<Expr>(Body)) {
13035 // If clause is a capture:
13036 // v = x++;
13037 // v = x--;
13038 // v = ++x;
13039 // v = --x;
13040 // v = x binop= expr;
13041 // v = x = x binop expr;
13042 // v = x = expr binop x;
13043 const auto *AtomicBinOp =
13044 dyn_cast<BinaryOperator>(AtomicBody->IgnoreParenImpCasts());
13045 if (AtomicBinOp && AtomicBinOp->getOpcode() == BO_Assign) {
13046 V = AtomicBinOp->getLHS();
13047 Body = AtomicBinOp->getRHS()->IgnoreParenImpCasts();
13048 OpenMPAtomicUpdateChecker Checker(SemaRef);
13049 if (Checker.checkStatement(
13050 Body, diag::err_omp_atomic_capture_not_expression_statement,
13051 diag::note_omp_atomic_update))
13052 return StmtError();
13053 E = Checker.getExpr();
13054 X = Checker.getX();
13055 UE = Checker.getUpdateExpr();
13056 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13057 IsPostfixUpdate = Checker.isPostfixUpdate();
13058 } else if (!AtomicBody->isInstantiationDependent()) {
13059 ErrorLoc = AtomicBody->getExprLoc();
13060 ErrorRange = AtomicBody->getSourceRange();
13061 NoteLoc = AtomicBinOp ? AtomicBinOp->getOperatorLoc()
13062 : AtomicBody->getExprLoc();
13063 NoteRange = AtomicBinOp ? AtomicBinOp->getSourceRange()
13064 : AtomicBody->getSourceRange();
13065 ErrorFound = NotAnAssignmentOp;
13066 }
13067 if (ErrorFound != NoError) {
13068 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_expression_statement)
13069 << ErrorRange;
13070 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13071 return StmtError();
13072 }
13073 if (SemaRef.CurContext->isDependentContext())
13074 UE = V = E = X = nullptr;
13075 } else {
13076 // If clause is a capture:
13077 // { v = x; x = expr; }
13078 // { v = x; x++; }
13079 // { v = x; x--; }
13080 // { v = x; ++x; }
13081 // { v = x; --x; }
13082 // { v = x; x binop= expr; }
13083 // { v = x; x = x binop expr; }
13084 // { v = x; x = expr binop x; }
13085 // { x++; v = x; }
13086 // { x--; v = x; }
13087 // { ++x; v = x; }
13088 // { --x; v = x; }
13089 // { x binop= expr; v = x; }
13090 // { x = x binop expr; v = x; }
13091 // { x = expr binop x; v = x; }
13092 if (auto *CS = dyn_cast<CompoundStmt>(Body)) {
13093 // Check that this is { expr1; expr2; }
13094 if (CS->size() == 2) {
13095 Stmt *First = CS->body_front();
13096 Stmt *Second = CS->body_back();
13097 if (auto *EWC = dyn_cast<ExprWithCleanups>(First))
13098 First = EWC->getSubExpr()->IgnoreParenImpCasts();
13099 if (auto *EWC = dyn_cast<ExprWithCleanups>(Second))
13100 Second = EWC->getSubExpr()->IgnoreParenImpCasts();
13101 // Need to find what subexpression is 'v' and what is 'x'.
13102 OpenMPAtomicUpdateChecker Checker(SemaRef);
13103 bool IsUpdateExprFound = !Checker.checkStatement(Second);
13104 BinaryOperator *BinOp = nullptr;
13105 if (IsUpdateExprFound) {
13106 BinOp = dyn_cast<BinaryOperator>(First);
13107 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13108 }
13109 if (IsUpdateExprFound && !SemaRef.CurContext->isDependentContext()) {
13110 // { v = x; x++; }
13111 // { v = x; x--; }
13112 // { v = x; ++x; }
13113 // { v = x; --x; }
13114 // { v = x; x binop= expr; }
13115 // { v = x; x = x binop expr; }
13116 // { v = x; x = expr binop x; }
13117 // Check that the first expression has form v = x.
13118 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13119 llvm::FoldingSetNodeID XId, PossibleXId;
13120 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13121 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13122 IsUpdateExprFound = XId == PossibleXId;
13123 if (IsUpdateExprFound) {
13124 V = BinOp->getLHS();
13125 X = Checker.getX();
13126 E = Checker.getExpr();
13127 UE = Checker.getUpdateExpr();
13128 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13129 IsPostfixUpdate = true;
13130 }
13131 }
13132 if (!IsUpdateExprFound) {
13133 IsUpdateExprFound = !Checker.checkStatement(First);
13134 BinOp = nullptr;
13135 if (IsUpdateExprFound) {
13136 BinOp = dyn_cast<BinaryOperator>(Second);
13137 IsUpdateExprFound = BinOp && BinOp->getOpcode() == BO_Assign;
13138 }
13139 if (IsUpdateExprFound &&
13140 !SemaRef.CurContext->isDependentContext()) {
13141 // { x++; v = x; }
13142 // { x--; v = x; }
13143 // { ++x; v = x; }
13144 // { --x; v = x; }
13145 // { x binop= expr; v = x; }
13146 // { x = x binop expr; v = x; }
13147 // { x = expr binop x; v = x; }
13148 // Check that the second expression has form v = x.
13149 Expr *PossibleX = BinOp->getRHS()->IgnoreParenImpCasts();
13150 llvm::FoldingSetNodeID XId, PossibleXId;
13151 Checker.getX()->Profile(XId, Context, /*Canonical=*/true);
13152 PossibleX->Profile(PossibleXId, Context, /*Canonical=*/true);
13153 IsUpdateExprFound = XId == PossibleXId;
13154 if (IsUpdateExprFound) {
13155 V = BinOp->getLHS();
13156 X = Checker.getX();
13157 E = Checker.getExpr();
13158 UE = Checker.getUpdateExpr();
13159 IsXLHSInRHSPart = Checker.isXLHSInRHSPart();
13160 IsPostfixUpdate = false;
13161 }
13162 }
13163 }
13164 if (!IsUpdateExprFound) {
13165 // { v = x; x = expr; }
13166 auto *FirstExpr = dyn_cast<Expr>(First);
13167 auto *SecondExpr = dyn_cast<Expr>(Second);
13168 if (!FirstExpr || !SecondExpr ||
13169 !(FirstExpr->isInstantiationDependent() ||
13170 SecondExpr->isInstantiationDependent())) {
13171 auto *FirstBinOp = dyn_cast<BinaryOperator>(First);
13172 if (!FirstBinOp || FirstBinOp->getOpcode() != BO_Assign) {
13173 ErrorFound = NotAnAssignmentOp;
13174 NoteLoc = ErrorLoc = FirstBinOp ? FirstBinOp->getOperatorLoc()
13175 : First->getBeginLoc();
13176 NoteRange = ErrorRange = FirstBinOp
13177 ? FirstBinOp->getSourceRange()
13178 : SourceRange(ErrorLoc, ErrorLoc);
13179 } else {
13180 auto *SecondBinOp = dyn_cast<BinaryOperator>(Second);
13181 if (!SecondBinOp || SecondBinOp->getOpcode() != BO_Assign) {
13182 ErrorFound = NotAnAssignmentOp;
13183 NoteLoc = ErrorLoc = SecondBinOp
13184 ? SecondBinOp->getOperatorLoc()
13185 : Second->getBeginLoc();
13186 NoteRange = ErrorRange =
13187 SecondBinOp ? SecondBinOp->getSourceRange()
13188 : SourceRange(ErrorLoc, ErrorLoc);
13189 } else {
13190 Expr *PossibleXRHSInFirst =
13191 FirstBinOp->getRHS()->IgnoreParenImpCasts();
13192 Expr *PossibleXLHSInSecond =
13193 SecondBinOp->getLHS()->IgnoreParenImpCasts();
13194 llvm::FoldingSetNodeID X1Id, X2Id;
13195 PossibleXRHSInFirst->Profile(X1Id, Context,
13196 /*Canonical=*/true);
13197 PossibleXLHSInSecond->Profile(X2Id, Context,
13198 /*Canonical=*/true);
13199 IsUpdateExprFound = X1Id == X2Id;
13200 if (IsUpdateExprFound) {
13201 V = FirstBinOp->getLHS();
13202 X = SecondBinOp->getLHS();
13203 E = SecondBinOp->getRHS();
13204 UE = nullptr;
13205 IsXLHSInRHSPart = false;
13206 IsPostfixUpdate = true;
13207 } else {
13208 ErrorFound = NotASpecificExpression;
13209 ErrorLoc = FirstBinOp->getExprLoc();
13210 ErrorRange = FirstBinOp->getSourceRange();
13211 NoteLoc = SecondBinOp->getLHS()->getExprLoc();
13212 NoteRange = SecondBinOp->getRHS()->getSourceRange();
13213 }
13214 }
13215 }
13216 }
13217 }
13218 } else {
13219 NoteLoc = ErrorLoc = Body->getBeginLoc();
13220 NoteRange = ErrorRange =
13221 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13222 ErrorFound = NotTwoSubstatements;
13223 }
13224 } else {
13225 NoteLoc = ErrorLoc = Body->getBeginLoc();
13226 NoteRange = ErrorRange =
13227 SourceRange(Body->getBeginLoc(), Body->getBeginLoc());
13228 ErrorFound = NotACompoundStatement;
13229 }
13230 }
13231 if (ErrorFound != NoError) {
13232 Diag(ErrorLoc, diag::err_omp_atomic_capture_not_compound_statement)
13233 << ErrorRange;
13234 Diag(NoteLoc, diag::note_omp_atomic_capture) << ErrorFound << NoteRange;
13235 return StmtError();
13236 }
13237 if (SemaRef.CurContext->isDependentContext())
13238 UE = V = E = X = nullptr;
13239 } else if (AtomicKind == OMPC_compare) {
13240 if (IsCompareCapture) {
13241 OpenMPAtomicCompareCaptureChecker::ErrorInfoTy ErrorInfo;
13242 OpenMPAtomicCompareCaptureChecker Checker(SemaRef);
13243 if (!Checker.checkStmt(Body, ErrorInfo)) {
13244 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare_capture)
13245 << ErrorInfo.ErrorRange;
13246 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13247 << ErrorInfo.Error << ErrorInfo.NoteRange;
13248 return StmtError();
13249 }
13250 X = Checker.getX();
13251 E = Checker.getE();
13252 D = Checker.getD();
13253 CE = Checker.getCond();
13254 V = Checker.getV();
13255 R = Checker.getR();
13256 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13257 IsXLHSInRHSPart = Checker.isXBinopExpr();
13258 IsFailOnly = Checker.isFailOnly();
13259 IsPostfixUpdate = Checker.isPostfixUpdate();
13260 } else {
13261 OpenMPAtomicCompareChecker::ErrorInfoTy ErrorInfo;
13262 OpenMPAtomicCompareChecker Checker(SemaRef);
13263 if (!Checker.checkStmt(Body, ErrorInfo)) {
13264 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_compare)
13265 << ErrorInfo.ErrorRange;
13266 Diag(ErrorInfo.NoteLoc, diag::note_omp_atomic_compare)
13267 << ErrorInfo.Error << ErrorInfo.NoteRange;
13268 return StmtError();
13269 }
13270 X = Checker.getX();
13271 E = Checker.getE();
13272 D = Checker.getD();
13273 CE = Checker.getCond();
13274 // The weak clause may only appear if the resulting atomic operation is
13275 // an atomic conditional update for which the comparison tests for
13276 // equality. It was not possible to do this check in
13277 // OpenMPAtomicCompareChecker::checkStmt() as the check for OMPC_weak
13278 // could not be performed (Clauses are not available).
13279 auto *It = find_if(Clauses, [](OMPClause *C) {
13280 return C->getClauseKind() == llvm::omp::Clause::OMPC_weak;
13281 });
13282 if (It != Clauses.end()) {
13283 auto *Cond = dyn_cast<BinaryOperator>(CE);
13284 if (Cond->getOpcode() != BO_EQ) {
13285 ErrorInfo.Error = Checker.ErrorTy::NotAnAssignment;
13286 ErrorInfo.ErrorLoc = Cond->getExprLoc();
13287 ErrorInfo.NoteLoc = Cond->getOperatorLoc();
13288 ErrorInfo.ErrorRange = ErrorInfo.NoteRange = Cond->getSourceRange();
13289
13290 Diag(ErrorInfo.ErrorLoc, diag::err_omp_atomic_weak_no_equality)
13291 << ErrorInfo.ErrorRange;
13292 return StmtError();
13293 }
13294 }
13295 // We reuse IsXLHSInRHSPart to tell if it is in the form 'x ordop expr'.
13296 IsXLHSInRHSPart = Checker.isXBinopExpr();
13297 }
13298 }
13299
13300 SemaRef.setFunctionHasBranchProtectedScope();
13301
13302 return OMPAtomicDirective::Create(
13303 Context, StartLoc, EndLoc, Clauses, AStmt,
13304 {X, V, R, E, UE, D, CE, IsXLHSInRHSPart, IsPostfixUpdate, IsFailOnly});
13305}
13306
13308 Stmt *AStmt,
13309 SourceLocation StartLoc,
13310 SourceLocation EndLoc) {
13311 if (!AStmt)
13312 return StmtError();
13313
13314 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target, AStmt);
13315
13316 // OpenMP [2.16, Nesting of Regions]
13317 // If specified, a teams construct must be contained within a target
13318 // construct. That target construct must contain no statements or directives
13319 // outside of the teams construct.
13320 if (DSAStack->hasInnerTeamsRegion()) {
13321 const Stmt *S = CS->IgnoreContainers(/*IgnoreCaptured=*/true);
13322 bool OMPTeamsFound = true;
13323 if (const auto *CS = dyn_cast<CompoundStmt>(S)) {
13324 auto I = CS->body_begin();
13325 while (I != CS->body_end()) {
13326 const auto *OED = dyn_cast<OMPExecutableDirective>(*I);
13327 bool IsTeams = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13328 if (!IsTeams || I != CS->body_begin()) {
13329 OMPTeamsFound = false;
13330 if (IsTeams && I != CS->body_begin()) {
13331 // This is the two teams case. Since the InnerTeamsRegionLoc will
13332 // point to this second one reset the iterator to the other teams.
13333 --I;
13334 }
13335 break;
13336 }
13337 ++I;
13338 }
13339 assert(I != CS->body_end() && "Not found statement");
13340 S = *I;
13341 } else {
13342 const auto *OED = dyn_cast<OMPExecutableDirective>(S);
13343 OMPTeamsFound = OED && isOpenMPTeamsDirective(OED->getDirectiveKind());
13344 }
13345 if (!OMPTeamsFound) {
13346 Diag(StartLoc, diag::err_omp_target_contains_not_only_teams);
13347 Diag(DSAStack->getInnerTeamsRegionLoc(),
13348 diag::note_omp_nested_teams_construct_here);
13349 Diag(S->getBeginLoc(), diag::note_omp_nested_statement_here)
13351 return StmtError();
13352 }
13353 }
13354
13355 return OMPTargetDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13356 AStmt);
13357}
13358
13360 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13361 SourceLocation EndLoc) {
13362 if (!AStmt)
13363 return StmtError();
13364
13365 setBranchProtectedScope(SemaRef, OMPD_target_parallel, AStmt);
13366
13368 getASTContext(), StartLoc, EndLoc, Clauses, AStmt,
13369 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13370}
13371
13373 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13374 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13375 if (!AStmt)
13376 return StmtError();
13377
13378 CapturedStmt *CS =
13379 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for, AStmt);
13380
13381 OMPLoopBasedDirective::HelperExprs B;
13382 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13383 // define the nested loops number.
13384 unsigned NestedLoopCount =
13385 checkOpenMPLoop(OMPD_target_parallel_for, getCollapseNumberExpr(Clauses),
13386 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
13387 VarsWithImplicitDSA, B);
13388 if (NestedLoopCount == 0)
13389 return StmtError();
13390
13391 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13392 return StmtError();
13393
13395 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13396 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
13397}
13398
13399/// Check for existence of a map clause in the list of clauses.
13401 const OpenMPClauseKind K) {
13402 return llvm::any_of(
13403 Clauses, [K](const OMPClause *C) { return C->getClauseKind() == K; });
13404}
13405
13406template <typename... Params>
13408 const Params... ClauseTypes) {
13409 return hasClauses(Clauses, K) || hasClauses(Clauses, ClauseTypes...);
13410}
13411
13412/// Check if the variables in the mapping clause are externally visible.
13414 for (const OMPClause *C : Clauses) {
13415 if (auto *TC = dyn_cast<OMPToClause>(C))
13416 return llvm::all_of(TC->all_decls(), [](ValueDecl *VD) {
13417 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13418 (VD->isExternallyVisible() &&
13419 VD->getVisibility() != HiddenVisibility);
13420 });
13421 else if (auto *FC = dyn_cast<OMPFromClause>(C))
13422 return llvm::all_of(FC->all_decls(), [](ValueDecl *VD) {
13423 return !VD || !VD->hasAttr<OMPDeclareTargetDeclAttr>() ||
13424 (VD->isExternallyVisible() &&
13425 VD->getVisibility() != HiddenVisibility);
13426 });
13427 }
13428
13429 return true;
13430}
13431
13434 Stmt *AStmt, SourceLocation StartLoc,
13435 SourceLocation EndLoc) {
13436 if (!AStmt)
13437 return StmtError();
13438
13439 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13440
13441 // OpenMP [2.12.2, target data Construct, Restrictions]
13442 // At least one map, use_device_addr or use_device_ptr clause must appear on
13443 // the directive.
13444 if (!hasClauses(Clauses, OMPC_map, OMPC_use_device_ptr) &&
13445 (getLangOpts().OpenMP < 50 ||
13446 !hasClauses(Clauses, OMPC_use_device_addr))) {
13447 StringRef Expected;
13448 if (getLangOpts().OpenMP < 50)
13449 Expected = "'map' or 'use_device_ptr'";
13450 else
13451 Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
13452 unsigned OMPVersion = getLangOpts().OpenMP;
13453 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13454 << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
13455 return StmtError();
13456 }
13457
13458 SemaRef.setFunctionHasBranchProtectedScope();
13459
13460 return OMPTargetDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13461 Clauses, AStmt);
13462}
13463
13465 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13466 SourceLocation EndLoc, Stmt *AStmt) {
13467 if (!AStmt)
13468 return StmtError();
13469
13470 setBranchProtectedScope(SemaRef, OMPD_target_enter_data, AStmt);
13471
13472 // OpenMP [2.10.2, Restrictions, p. 99]
13473 // At least one map clause must appear on the directive.
13474 if (!hasClauses(Clauses, OMPC_map)) {
13475 unsigned OMPVersion = getLangOpts().OpenMP;
13476 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13477 << "'map'"
13478 << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
13479 return StmtError();
13480 }
13481
13482 return OMPTargetEnterDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13483 Clauses, AStmt);
13484}
13485
13487 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13488 SourceLocation EndLoc, Stmt *AStmt) {
13489 if (!AStmt)
13490 return StmtError();
13491
13492 setBranchProtectedScope(SemaRef, OMPD_target_exit_data, AStmt);
13493
13494 // OpenMP [2.10.3, Restrictions, p. 102]
13495 // At least one map clause must appear on the directive.
13496 if (!hasClauses(Clauses, OMPC_map)) {
13497 unsigned OMPVersion = getLangOpts().OpenMP;
13498 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
13499 << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, OMPVersion);
13500 return StmtError();
13501 }
13502
13503 return OMPTargetExitDataDirective::Create(getASTContext(), StartLoc, EndLoc,
13504 Clauses, AStmt);
13505}
13506
13508 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13509 SourceLocation EndLoc, Stmt *AStmt) {
13510 if (!AStmt)
13511 return StmtError();
13512
13513 setBranchProtectedScope(SemaRef, OMPD_target_update, AStmt);
13514
13515 if (!hasClauses(Clauses, OMPC_to, OMPC_from)) {
13516 Diag(StartLoc, diag::err_omp_at_least_one_motion_clause_required);
13517 return StmtError();
13518 }
13519
13520 if (!isClauseMappable(Clauses)) {
13521 Diag(StartLoc, diag::err_omp_cannot_update_with_internal_linkage);
13522 return StmtError();
13523 }
13524
13525 return OMPTargetUpdateDirective::Create(getASTContext(), StartLoc, EndLoc,
13526 Clauses, AStmt);
13527}
13528
13529/// This checks whether a \p ClauseType clause \p C has at most \p Max
13530/// expression. If not, a diag of number \p Diag will be emitted.
13531template <typename ClauseType>
13532static bool checkNumExprsInClause(SemaBase &SemaRef,
13533 ArrayRef<OMPClause *> Clauses,
13534 unsigned MaxNum, unsigned Diag) {
13535 auto ClauseItr = llvm::find_if(Clauses, llvm::IsaPred<ClauseType>);
13536 if (ClauseItr == Clauses.end())
13537 return true;
13538 const auto *C = cast<ClauseType>(*ClauseItr);
13539 auto VarList = C->getVarRefs();
13540 if (VarList.size() > MaxNum) {
13541 SemaRef.Diag(VarList[MaxNum]->getBeginLoc(), Diag)
13542 << getOpenMPClauseNameForDiag(C->getClauseKind());
13543 return false;
13544 }
13545 return true;
13546}
13547
13549 Stmt *AStmt,
13550 SourceLocation StartLoc,
13551 SourceLocation EndLoc) {
13552 if (!AStmt)
13553 return StmtError();
13554
13556 *this, Clauses, /*MaxNum=*/2,
13557 diag::err_omp_num_teams_multi_expr_not_allowed) ||
13559 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
13560 return StmtError();
13561
13562 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
13563 if (getLangOpts().HIP && (DSAStack->getParentDirective() == OMPD_target))
13564 Diag(StartLoc, diag::warn_hip_omp_target_directives);
13565
13566 setBranchProtectedScope(SemaRef, OMPD_teams, AStmt);
13567
13568 DSAStack->setParentTeamsRegionLoc(StartLoc);
13569
13570 return OMPTeamsDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13571 AStmt);
13572}
13573
13575 SourceLocation StartLoc, SourceLocation EndLoc,
13576 OpenMPDirectiveKind CancelRegion) {
13577 if (DSAStack->isParentNowaitRegion()) {
13578 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 0;
13579 return StmtError();
13580 }
13581 if (DSAStack->isParentOrderedRegion()) {
13582 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 0;
13583 return StmtError();
13584 }
13586 EndLoc, CancelRegion);
13587}
13588
13590 ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc,
13591 SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion) {
13592 if (DSAStack->isParentNowaitRegion()) {
13593 Diag(StartLoc, diag::err_omp_parent_cancel_region_nowait) << 1;
13594 return StmtError();
13595 }
13596 if (DSAStack->isParentOrderedRegion()) {
13597 Diag(StartLoc, diag::err_omp_parent_cancel_region_ordered) << 1;
13598 return StmtError();
13599 }
13600 DSAStack->setParentCancelRegion(/*Cancel=*/true);
13601 return OMPCancelDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
13602 CancelRegion);
13603}
13604
13606 ArrayRef<OMPClause *> Clauses) {
13607 const OMPClause *ReductionClause = nullptr;
13608 const OMPClause *NogroupClause = nullptr;
13609 for (const OMPClause *C : Clauses) {
13610 if (C->getClauseKind() == OMPC_reduction) {
13611 ReductionClause = C;
13612 if (NogroupClause)
13613 break;
13614 continue;
13615 }
13616 if (C->getClauseKind() == OMPC_nogroup) {
13617 NogroupClause = C;
13618 if (ReductionClause)
13619 break;
13620 continue;
13621 }
13622 }
13623 if (ReductionClause && NogroupClause) {
13624 S.Diag(ReductionClause->getBeginLoc(), diag::err_omp_reduction_with_nogroup)
13625 << SourceRange(NogroupClause->getBeginLoc(),
13626 NogroupClause->getEndLoc());
13627 return true;
13628 }
13629 return false;
13630}
13631
13633 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13634 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13635 if (!AStmt)
13636 return StmtError();
13637
13638 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13639 OMPLoopBasedDirective::HelperExprs B;
13640 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13641 // define the nested loops number.
13642 unsigned NestedLoopCount =
13643 checkOpenMPLoop(OMPD_taskloop, getCollapseNumberExpr(Clauses),
13644 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13645 *DSAStack, VarsWithImplicitDSA, B);
13646 if (NestedLoopCount == 0)
13647 return StmtError();
13648
13649 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13650 "omp for loop exprs were not built");
13651
13652 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13653 // The grainsize clause and num_tasks clause are mutually exclusive and may
13654 // not appear on the same taskloop directive.
13656 {OMPC_grainsize, OMPC_num_tasks}))
13657 return StmtError();
13658 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13659 // If a reduction clause is present on the taskloop directive, the nogroup
13660 // clause must not be specified.
13662 return StmtError();
13663
13664 SemaRef.setFunctionHasBranchProtectedScope();
13665 return OMPTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13666 NestedLoopCount, Clauses, AStmt, B,
13667 DSAStack->isCancelRegion());
13668}
13669
13671 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13672 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13673 if (!AStmt)
13674 return StmtError();
13675
13676 CapturedStmt *CS =
13677 setBranchProtectedScope(SemaRef, OMPD_taskloop_simd, AStmt);
13678
13679 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13680 OMPLoopBasedDirective::HelperExprs B;
13681 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13682 // define the nested loops number.
13683 unsigned NestedLoopCount =
13684 checkOpenMPLoop(OMPD_taskloop_simd, getCollapseNumberExpr(Clauses),
13685 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13686 VarsWithImplicitDSA, B);
13687 if (NestedLoopCount == 0)
13688 return StmtError();
13689
13690 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13691 return StmtError();
13692
13693 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13694 // The grainsize clause and num_tasks clause are mutually exclusive and may
13695 // not appear on the same taskloop directive.
13697 {OMPC_grainsize, OMPC_num_tasks}))
13698 return StmtError();
13699 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13700 // If a reduction clause is present on the taskloop directive, the nogroup
13701 // clause must not be specified.
13703 return StmtError();
13705 return StmtError();
13706
13707 return OMPTaskLoopSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
13708 NestedLoopCount, Clauses, AStmt, B);
13709}
13710
13712 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13713 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13714 if (!AStmt)
13715 return StmtError();
13716
13717 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13718 OMPLoopBasedDirective::HelperExprs B;
13719 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13720 // define the nested loops number.
13721 unsigned NestedLoopCount =
13722 checkOpenMPLoop(OMPD_master_taskloop, getCollapseNumberExpr(Clauses),
13723 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13724 *DSAStack, VarsWithImplicitDSA, B);
13725 if (NestedLoopCount == 0)
13726 return StmtError();
13727
13728 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13729 "omp for loop exprs were not built");
13730
13731 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13732 // The grainsize clause and num_tasks clause are mutually exclusive and may
13733 // not appear on the same taskloop directive.
13735 {OMPC_grainsize, OMPC_num_tasks}))
13736 return StmtError();
13737 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13738 // If a reduction clause is present on the taskloop directive, the nogroup
13739 // clause must not be specified.
13741 return StmtError();
13742
13743 SemaRef.setFunctionHasBranchProtectedScope();
13744 return OMPMasterTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13745 NestedLoopCount, Clauses, AStmt, B,
13746 DSAStack->isCancelRegion());
13747}
13748
13750 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13751 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13752 if (!AStmt)
13753 return StmtError();
13754
13755 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13756 OMPLoopBasedDirective::HelperExprs B;
13757 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13758 // define the nested loops number.
13759 unsigned NestedLoopCount =
13760 checkOpenMPLoop(OMPD_masked_taskloop, getCollapseNumberExpr(Clauses),
13761 /*OrderedLoopCountExpr=*/nullptr, AStmt, SemaRef,
13762 *DSAStack, VarsWithImplicitDSA, B);
13763 if (NestedLoopCount == 0)
13764 return StmtError();
13765
13766 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13767 "omp for loop exprs were not built");
13768
13769 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13770 // The grainsize clause and num_tasks clause are mutually exclusive and may
13771 // not appear on the same taskloop directive.
13773 {OMPC_grainsize, OMPC_num_tasks}))
13774 return StmtError();
13775 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13776 // If a reduction clause is present on the taskloop directive, the nogroup
13777 // clause must not be specified.
13779 return StmtError();
13780
13781 SemaRef.setFunctionHasBranchProtectedScope();
13782 return OMPMaskedTaskLoopDirective::Create(getASTContext(), StartLoc, EndLoc,
13783 NestedLoopCount, Clauses, AStmt, B,
13784 DSAStack->isCancelRegion());
13785}
13786
13788 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13789 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13790 if (!AStmt)
13791 return StmtError();
13792
13793 CapturedStmt *CS =
13794 setBranchProtectedScope(SemaRef, OMPD_master_taskloop_simd, AStmt);
13795
13796 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13797 OMPLoopBasedDirective::HelperExprs B;
13798 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13799 // define the nested loops number.
13800 unsigned NestedLoopCount =
13801 checkOpenMPLoop(OMPD_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13802 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13803 VarsWithImplicitDSA, B);
13804 if (NestedLoopCount == 0)
13805 return StmtError();
13806
13807 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13808 return StmtError();
13809
13810 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13811 // The grainsize clause and num_tasks clause are mutually exclusive and may
13812 // not appear on the same taskloop directive.
13814 {OMPC_grainsize, OMPC_num_tasks}))
13815 return StmtError();
13816 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13817 // If a reduction clause is present on the taskloop directive, the nogroup
13818 // clause must not be specified.
13820 return StmtError();
13822 return StmtError();
13823
13825 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13826}
13827
13829 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13830 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13831 if (!AStmt)
13832 return StmtError();
13833
13834 CapturedStmt *CS =
13835 setBranchProtectedScope(SemaRef, OMPD_masked_taskloop_simd, AStmt);
13836
13837 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
13838 OMPLoopBasedDirective::HelperExprs B;
13839 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13840 // define the nested loops number.
13841 unsigned NestedLoopCount =
13842 checkOpenMPLoop(OMPD_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
13843 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13844 VarsWithImplicitDSA, B);
13845 if (NestedLoopCount == 0)
13846 return StmtError();
13847
13848 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13849 return StmtError();
13850
13851 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13852 // The grainsize clause and num_tasks clause are mutually exclusive and may
13853 // not appear on the same taskloop directive.
13855 {OMPC_grainsize, OMPC_num_tasks}))
13856 return StmtError();
13857 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13858 // If a reduction clause is present on the taskloop directive, the nogroup
13859 // clause must not be specified.
13861 return StmtError();
13863 return StmtError();
13864
13866 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13867}
13868
13870 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13871 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13872 if (!AStmt)
13873 return StmtError();
13874
13875 CapturedStmt *CS =
13876 setBranchProtectedScope(SemaRef, OMPD_parallel_master_taskloop, AStmt);
13877
13878 OMPLoopBasedDirective::HelperExprs B;
13879 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13880 // define the nested loops number.
13881 unsigned NestedLoopCount = checkOpenMPLoop(
13882 OMPD_parallel_master_taskloop, getCollapseNumberExpr(Clauses),
13883 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13884 VarsWithImplicitDSA, B);
13885 if (NestedLoopCount == 0)
13886 return StmtError();
13887
13888 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13889 "omp for loop exprs were not built");
13890
13891 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13892 // The grainsize clause and num_tasks clause are mutually exclusive and may
13893 // not appear on the same taskloop directive.
13895 {OMPC_grainsize, OMPC_num_tasks}))
13896 return StmtError();
13897 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13898 // If a reduction clause is present on the taskloop directive, the nogroup
13899 // clause must not be specified.
13901 return StmtError();
13902
13904 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13905 DSAStack->isCancelRegion());
13906}
13907
13909 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13910 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13911 if (!AStmt)
13912 return StmtError();
13913
13914 CapturedStmt *CS =
13915 setBranchProtectedScope(SemaRef, OMPD_parallel_masked_taskloop, AStmt);
13916
13917 OMPLoopBasedDirective::HelperExprs B;
13918 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13919 // define the nested loops number.
13920 unsigned NestedLoopCount = checkOpenMPLoop(
13921 OMPD_parallel_masked_taskloop, getCollapseNumberExpr(Clauses),
13922 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13923 VarsWithImplicitDSA, B);
13924 if (NestedLoopCount == 0)
13925 return StmtError();
13926
13927 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
13928 "omp for loop exprs were not built");
13929
13930 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13931 // The grainsize clause and num_tasks clause are mutually exclusive and may
13932 // not appear on the same taskloop directive.
13934 {OMPC_grainsize, OMPC_num_tasks}))
13935 return StmtError();
13936 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13937 // If a reduction clause is present on the taskloop directive, the nogroup
13938 // clause must not be specified.
13940 return StmtError();
13941
13943 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
13944 DSAStack->isCancelRegion());
13945}
13946
13948 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13949 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13950 if (!AStmt)
13951 return StmtError();
13952
13954 SemaRef, OMPD_parallel_master_taskloop_simd, AStmt);
13955
13956 OMPLoopBasedDirective::HelperExprs B;
13957 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13958 // define the nested loops number.
13959 unsigned NestedLoopCount = checkOpenMPLoop(
13960 OMPD_parallel_master_taskloop_simd, getCollapseNumberExpr(Clauses),
13961 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
13962 VarsWithImplicitDSA, B);
13963 if (NestedLoopCount == 0)
13964 return StmtError();
13965
13966 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
13967 return StmtError();
13968
13969 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13970 // The grainsize clause and num_tasks clause are mutually exclusive and may
13971 // not appear on the same taskloop directive.
13973 {OMPC_grainsize, OMPC_num_tasks}))
13974 return StmtError();
13975 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
13976 // If a reduction clause is present on the taskloop directive, the nogroup
13977 // clause must not be specified.
13979 return StmtError();
13981 return StmtError();
13982
13984 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
13985}
13986
13988 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
13989 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
13990 if (!AStmt)
13991 return StmtError();
13992
13994 SemaRef, OMPD_parallel_masked_taskloop_simd, AStmt);
13995
13996 OMPLoopBasedDirective::HelperExprs B;
13997 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
13998 // define the nested loops number.
13999 unsigned NestedLoopCount = checkOpenMPLoop(
14000 OMPD_parallel_masked_taskloop_simd, getCollapseNumberExpr(Clauses),
14001 /*OrderedLoopCountExpr=*/nullptr, CS, SemaRef, *DSAStack,
14002 VarsWithImplicitDSA, B);
14003 if (NestedLoopCount == 0)
14004 return StmtError();
14005
14006 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14007 return StmtError();
14008
14009 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14010 // The grainsize clause and num_tasks clause are mutually exclusive and may
14011 // not appear on the same taskloop directive.
14013 {OMPC_grainsize, OMPC_num_tasks}))
14014 return StmtError();
14015 // OpenMP, [2.9.2 taskloop Construct, Restrictions]
14016 // If a reduction clause is present on the taskloop directive, the nogroup
14017 // clause must not be specified.
14019 return StmtError();
14021 return StmtError();
14022
14024 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14025}
14026
14028 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14029 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14030 if (!AStmt)
14031 return StmtError();
14032
14033 assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
14034 OMPLoopBasedDirective::HelperExprs B;
14035 // In presence of clause 'collapse' with number of loops, it will
14036 // define the nested loops number.
14037 unsigned NestedLoopCount =
14038 checkOpenMPLoop(OMPD_distribute, getCollapseNumberExpr(Clauses),
14039 nullptr /*ordered not a clause on distribute*/, AStmt,
14040 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14041 if (NestedLoopCount == 0)
14042 return StmtError();
14043
14044 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14045 "omp for loop exprs were not built");
14046
14047 SemaRef.setFunctionHasBranchProtectedScope();
14048 auto *DistributeDirective = OMPDistributeDirective::Create(
14049 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14050 return DistributeDirective;
14051}
14052
14054 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14055 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14056 if (!AStmt)
14057 return StmtError();
14058
14059 CapturedStmt *CS =
14060 setBranchProtectedScope(SemaRef, OMPD_distribute_parallel_for, AStmt);
14061
14062 OMPLoopBasedDirective::HelperExprs B;
14063 // In presence of clause 'collapse' with number of loops, it will
14064 // define the nested loops number.
14065 unsigned NestedLoopCount = checkOpenMPLoop(
14066 OMPD_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14067 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14068 VarsWithImplicitDSA, B);
14069 if (NestedLoopCount == 0)
14070 return StmtError();
14071
14072 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14073 "omp for loop exprs were not built");
14074
14076 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14077 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14078}
14079
14081 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14082 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14083 if (!AStmt)
14084 return StmtError();
14085
14087 SemaRef, OMPD_distribute_parallel_for_simd, AStmt);
14088
14089 OMPLoopBasedDirective::HelperExprs B;
14090 // In presence of clause 'collapse' with number of loops, it will
14091 // define the nested loops number.
14092 unsigned NestedLoopCount = checkOpenMPLoop(
14093 OMPD_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14094 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14095 VarsWithImplicitDSA, B);
14096 if (NestedLoopCount == 0)
14097 return StmtError();
14098
14099 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14100 return StmtError();
14101
14103 return StmtError();
14104
14106 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14107}
14108
14110 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14111 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14112 if (!AStmt)
14113 return StmtError();
14114
14115 CapturedStmt *CS =
14116 setBranchProtectedScope(SemaRef, OMPD_distribute_simd, AStmt);
14117
14118 OMPLoopBasedDirective::HelperExprs B;
14119 // In presence of clause 'collapse' with number of loops, it will
14120 // define the nested loops number.
14121 unsigned NestedLoopCount =
14122 checkOpenMPLoop(OMPD_distribute_simd, getCollapseNumberExpr(Clauses),
14123 nullptr /*ordered not a clause on distribute*/, CS,
14124 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14125 if (NestedLoopCount == 0)
14126 return StmtError();
14127
14128 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14129 return StmtError();
14130
14132 return StmtError();
14133
14134 return OMPDistributeSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14135 NestedLoopCount, Clauses, AStmt, B);
14136}
14137
14139 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14140 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14141 if (!AStmt)
14142 return StmtError();
14143
14144 CapturedStmt *CS =
14145 setBranchProtectedScope(SemaRef, OMPD_target_parallel_for_simd, AStmt);
14146
14147 OMPLoopBasedDirective::HelperExprs B;
14148 // In presence of clause 'collapse' or 'ordered' with number of loops, it will
14149 // define the nested loops number.
14150 unsigned NestedLoopCount = checkOpenMPLoop(
14151 OMPD_target_parallel_for_simd, getCollapseNumberExpr(Clauses),
14152 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14153 VarsWithImplicitDSA, B);
14154 if (NestedLoopCount == 0)
14155 return StmtError();
14156
14157 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14158 return StmtError();
14159
14161 return StmtError();
14162
14164 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14165}
14166
14168 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14169 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14170 if (!AStmt)
14171 return StmtError();
14172
14173 CapturedStmt *CS = setBranchProtectedScope(SemaRef, OMPD_target_simd, AStmt);
14174
14175 OMPLoopBasedDirective::HelperExprs B;
14176 // In presence of clause 'collapse' with number of loops, it will define the
14177 // nested loops number.
14178 unsigned NestedLoopCount =
14179 checkOpenMPLoop(OMPD_target_simd, getCollapseNumberExpr(Clauses),
14180 getOrderedNumberExpr(Clauses), CS, SemaRef, *DSAStack,
14181 VarsWithImplicitDSA, B);
14182 if (NestedLoopCount == 0)
14183 return StmtError();
14184
14185 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14186 return StmtError();
14187
14189 return StmtError();
14190
14191 return OMPTargetSimdDirective::Create(getASTContext(), StartLoc, EndLoc,
14192 NestedLoopCount, Clauses, AStmt, B);
14193}
14194
14196 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14197 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14198 if (!AStmt)
14199 return StmtError();
14200
14201 CapturedStmt *CS =
14202 setBranchProtectedScope(SemaRef, OMPD_teams_distribute, AStmt);
14203
14204 OMPLoopBasedDirective::HelperExprs B;
14205 // In presence of clause 'collapse' with number of loops, it will
14206 // define the nested loops number.
14207 unsigned NestedLoopCount =
14208 checkOpenMPLoop(OMPD_teams_distribute, getCollapseNumberExpr(Clauses),
14209 nullptr /*ordered not a clause on distribute*/, CS,
14210 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14211 if (NestedLoopCount == 0)
14212 return StmtError();
14213
14214 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14215 "omp teams distribute loop exprs were not built");
14216
14217 DSAStack->setParentTeamsRegionLoc(StartLoc);
14218
14220 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14221}
14222
14224 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14225 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14226 if (!AStmt)
14227 return StmtError();
14228
14229 CapturedStmt *CS =
14230 setBranchProtectedScope(SemaRef, OMPD_teams_distribute_simd, AStmt);
14231
14232 OMPLoopBasedDirective::HelperExprs B;
14233 // In presence of clause 'collapse' with number of loops, it will
14234 // define the nested loops number.
14235 unsigned NestedLoopCount = checkOpenMPLoop(
14236 OMPD_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14237 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14238 VarsWithImplicitDSA, B);
14239 if (NestedLoopCount == 0)
14240 return StmtError();
14241
14242 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14243 return StmtError();
14244
14246 return StmtError();
14247
14248 DSAStack->setParentTeamsRegionLoc(StartLoc);
14249
14251 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14252}
14253
14255 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14256 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14257 if (!AStmt)
14258 return StmtError();
14259
14261 SemaRef, OMPD_teams_distribute_parallel_for_simd, AStmt);
14262
14263 OMPLoopBasedDirective::HelperExprs B;
14264 // In presence of clause 'collapse' with number of loops, it will
14265 // define the nested loops number.
14266 unsigned NestedLoopCount = checkOpenMPLoop(
14267 OMPD_teams_distribute_parallel_for_simd, getCollapseNumberExpr(Clauses),
14268 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14269 VarsWithImplicitDSA, B);
14270 if (NestedLoopCount == 0)
14271 return StmtError();
14272
14273 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14274 return StmtError();
14275
14277 return StmtError();
14278
14279 DSAStack->setParentTeamsRegionLoc(StartLoc);
14280
14282 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14283}
14284
14286 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14287 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14288 if (!AStmt)
14289 return StmtError();
14290
14292 SemaRef, OMPD_teams_distribute_parallel_for, AStmt);
14293
14294 OMPLoopBasedDirective::HelperExprs B;
14295 // In presence of clause 'collapse' with number of loops, it will
14296 // define the nested loops number.
14297 unsigned NestedLoopCount = checkOpenMPLoop(
14298 OMPD_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14299 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14300 VarsWithImplicitDSA, B);
14301
14302 if (NestedLoopCount == 0)
14303 return StmtError();
14304
14305 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14306 "omp for loop exprs were not built");
14307
14308 DSAStack->setParentTeamsRegionLoc(StartLoc);
14309
14311 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14312 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14313}
14314
14316 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14317 SourceLocation EndLoc) {
14318 if (!AStmt)
14319 return StmtError();
14320
14321 setBranchProtectedScope(SemaRef, OMPD_target_teams, AStmt);
14322
14323 const OMPClause *BareClause = nullptr;
14324 bool HasThreadLimitAndNumTeamsClause = hasClauses(Clauses, OMPC_num_teams) &&
14325 hasClauses(Clauses, OMPC_thread_limit);
14326 bool HasBareClause = llvm::any_of(Clauses, [&](const OMPClause *C) {
14327 BareClause = C;
14328 return C->getClauseKind() == OMPC_ompx_bare;
14329 });
14330
14331 if (HasBareClause && !HasThreadLimitAndNumTeamsClause) {
14332 Diag(BareClause->getBeginLoc(), diag::err_ompx_bare_no_grid);
14333 return StmtError();
14334 }
14335
14336 unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 2;
14337 unsigned NumTeamsDiag = HasBareClause
14338 ? diag::err_ompx_more_than_three_expr_not_allowed
14339 : diag::err_omp_num_teams_multi_expr_not_allowed;
14340 unsigned ThreadLimitDiag =
14341 HasBareClause ? diag::err_ompx_more_than_three_expr_not_allowed
14342 : diag::err_omp_multi_expr_not_allowed;
14343
14345 *this, Clauses, ClauseMaxNumExprs, NumTeamsDiag) ||
14347 *this, Clauses, ClauseMaxNumExprs, ThreadLimitDiag)) {
14348 return StmtError();
14349 }
14350 return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
14351 Clauses, AStmt);
14352}
14353
14355 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14356 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14357 if (!AStmt)
14358 return StmtError();
14359
14361 *this, Clauses, /*MaxNum=*/2,
14362 diag::err_omp_num_teams_multi_expr_not_allowed) ||
14364 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14365 return StmtError();
14366
14367 CapturedStmt *CS =
14368 setBranchProtectedScope(SemaRef, OMPD_target_teams_distribute, AStmt);
14369
14370 OMPLoopBasedDirective::HelperExprs B;
14371 // In presence of clause 'collapse' with number of loops, it will
14372 // define the nested loops number.
14373 unsigned NestedLoopCount = checkOpenMPLoop(
14374 OMPD_target_teams_distribute, getCollapseNumberExpr(Clauses),
14375 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14376 VarsWithImplicitDSA, B);
14377 if (NestedLoopCount == 0)
14378 return StmtError();
14379
14380 assert((SemaRef.CurContext->isDependentContext() || B.builtAll()) &&
14381 "omp target teams distribute loop exprs were not built");
14382
14384 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14385}
14386
14388 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14389 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14390 if (!AStmt)
14391 return StmtError();
14392
14394 *this, Clauses, /*MaxNum=*/2,
14395 diag::err_omp_num_teams_multi_expr_not_allowed) ||
14397 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14398 return StmtError();
14399
14401 SemaRef, OMPD_target_teams_distribute_parallel_for, AStmt);
14402
14403 OMPLoopBasedDirective::HelperExprs B;
14404 // In presence of clause 'collapse' with number of loops, it will
14405 // define the nested loops number.
14406 unsigned NestedLoopCount = checkOpenMPLoop(
14407 OMPD_target_teams_distribute_parallel_for, getCollapseNumberExpr(Clauses),
14408 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14409 VarsWithImplicitDSA, B);
14410 if (NestedLoopCount == 0)
14411 return StmtError();
14412
14413 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14414 return StmtError();
14415
14417 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B,
14418 DSAStack->getTaskgroupReductionRef(), DSAStack->isCancelRegion());
14419}
14420
14422 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14423 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14424 if (!AStmt)
14425 return StmtError();
14426
14428 *this, Clauses, /*MaxNum=*/2,
14429 diag::err_omp_num_teams_multi_expr_not_allowed) ||
14431 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14432 return StmtError();
14433
14435 SemaRef, OMPD_target_teams_distribute_parallel_for_simd, AStmt);
14436
14437 OMPLoopBasedDirective::HelperExprs B;
14438 // In presence of clause 'collapse' with number of loops, it will
14439 // define the nested loops number.
14440 unsigned NestedLoopCount =
14441 checkOpenMPLoop(OMPD_target_teams_distribute_parallel_for_simd,
14442 getCollapseNumberExpr(Clauses),
14443 nullptr /*ordered not a clause on distribute*/, CS,
14444 SemaRef, *DSAStack, VarsWithImplicitDSA, B);
14445 if (NestedLoopCount == 0)
14446 return StmtError();
14447
14448 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14449 return StmtError();
14450
14452 return StmtError();
14453
14455 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14456}
14457
14459 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
14460 SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA) {
14461 if (!AStmt)
14462 return StmtError();
14463
14465 *this, Clauses, /*MaxNum=*/2,
14466 diag::err_omp_num_teams_multi_expr_not_allowed) ||
14468 *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
14469 return StmtError();
14470
14472 SemaRef, OMPD_target_teams_distribute_simd, AStmt);
14473
14474 OMPLoopBasedDirective::HelperExprs B;
14475 // In presence of clause 'collapse' with number of loops, it will
14476 // define the nested loops number.
14477 unsigned NestedLoopCount = checkOpenMPLoop(
14478 OMPD_target_teams_distribute_simd, getCollapseNumberExpr(Clauses),
14479 nullptr /*ordered not a clause on distribute*/, CS, SemaRef, *DSAStack,
14480 VarsWithImplicitDSA, B);
14481 if (NestedLoopCount == 0)
14482 return StmtError();
14483
14484 if (finishLinearClauses(SemaRef, Clauses, B, DSAStack))
14485 return StmtError();
14486
14488 return StmtError();
14489
14491 getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B);
14492}
14493
14494/// Updates OriginalInits by checking Transform against loop transformation
14495/// directives and appending their pre-inits if a match is found.
14497 SmallVectorImpl<Stmt *> &PreInits) {
14498 Stmt *Dir = Transform->getDirective();
14499 switch (Dir->getStmtClass()) {
14500#define STMT(CLASS, PARENT)
14501#define ABSTRACT_STMT(CLASS)
14502#define COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT) \
14503 case Stmt::CLASS##Class: \
14504 appendFlattenedStmtList(PreInits, \
14505 static_cast<const CLASS *>(Dir)->getPreInits()); \
14506 break;
14507#define OMPCANONICALLOOPNESTTRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14508 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14509#define OMPCANONICALLOOPSEQUENCETRANSFORMATIONDIRECTIVE(CLASS, PARENT) \
14510 COMMON_OMP_LOOP_TRANSFORMATION(CLASS, PARENT)
14511#include "clang/AST/StmtNodes.inc"
14512#undef COMMON_OMP_LOOP_TRANSFORMATION
14513 default:
14514 llvm_unreachable("Not a loop transformation");
14515 }
14516}
14517
14518bool SemaOpenMP::checkTransformableLoopNest(
14519 OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops,
14521 Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *>> &OriginalInits) {
14522 OriginalInits.emplace_back();
14523 bool Result = OMPLoopBasedDirective::doForAllLoops(
14524 AStmt->IgnoreContainers(), /*TryImperfectlyNestedLoops=*/false, NumLoops,
14525 [this, &LoopHelpers, &Body, &OriginalInits, Kind](unsigned Cnt,
14526 Stmt *CurStmt) {
14527 VarsWithInheritedDSAType TmpDSA;
14528 unsigned SingleNumLoops =
14529 checkOpenMPLoop(Kind, nullptr, nullptr, CurStmt, SemaRef, *DSAStack,
14530 TmpDSA, LoopHelpers[Cnt]);
14531 if (SingleNumLoops == 0)
14532 return true;
14533 assert(SingleNumLoops == 1 && "Expect single loop iteration space");
14534 if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
14535 OriginalInits.back().push_back(For->getInit());
14536 Body = For->getBody();
14537 } else {
14538 assert(isa<CXXForRangeStmt>(CurStmt) &&
14539 "Expected canonical for or range-based for loops.");
14540 auto *CXXFor = cast<CXXForRangeStmt>(CurStmt);
14541 OriginalInits.back().push_back(CXXFor->getBeginStmt());
14542 Body = CXXFor->getBody();
14543 }
14544 OriginalInits.emplace_back();
14545 return false;
14546 },
14547 [&OriginalInits](OMPLoopTransformationDirective *Transform) {
14548 updatePreInits(Transform, OriginalInits.back());
14549 });
14550 assert(OriginalInits.back().empty() && "No preinit after innermost loop");
14551 OriginalInits.pop_back();
14552 return Result;
14553}
14554
14555/// Counts the total number of OpenMP canonical nested loops, including the
14556/// outermost loop (the original loop). PRECONDITION of this visitor is that it
14557/// must be invoked from the original loop to be analyzed. The traversal stops
14558/// for Decl's and Expr's given that they may contain inner loops that must not
14559/// be counted.
14560///
14561/// Example AST structure for the code:
14562///
14563/// int main() {
14564/// #pragma omp fuse
14565/// {
14566/// for (int i = 0; i < 100; i++) { <-- Outer loop
14567/// []() {
14568/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (1)
14569/// };
14570/// for(int j = 0; j < 5; ++j) {} <-- Inner loop
14571/// }
14572/// for (int r = 0; i < 100; i++) { <-- Outer loop
14573/// struct LocalClass {
14574/// void bar() {
14575/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP (2)
14576/// }
14577/// };
14578/// for(int k = 0; k < 10; ++k) {} <-- Inner loop
14579/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP (3)
14580/// }
14581/// }
14582/// }
14583/// (1) because in a different function (here: a lambda)
14584/// (2) because in a different function (here: class method)
14585/// (3) because considered to be intervening-code of non-perfectly nested loop
14586/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops.
14588private:
14589 unsigned NestedLoopCount = 0;
14590
14591public:
14592 explicit NestedLoopCounterVisitor() = default;
14593
14594 unsigned getNestedLoopCount() const { return NestedLoopCount; }
14595
14596 bool VisitForStmt(ForStmt *FS) override {
14597 ++NestedLoopCount;
14598 return true;
14599 }
14600
14602 ++NestedLoopCount;
14603 return true;
14604 }
14605
14606 bool TraverseStmt(Stmt *S) override {
14607 if (!S)
14608 return true;
14609
14610 // Skip traversal of all expressions, including special cases like
14611 // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14612 // may contain inner statements (and even loops), but they are not part
14613 // of the syntactic body of the surrounding loop structure.
14614 // Therefore must not be counted.
14615 if (isa<Expr>(S))
14616 return true;
14617
14618 // Only recurse into CompoundStmt (block {}) and loop bodies.
14621 }
14622
14623 // Stop traversal of the rest of statements, that break perfect
14624 // loop nesting, such as control flow (IfStmt, SwitchStmt...).
14625 return true;
14626 }
14627
14628 bool TraverseDecl(Decl *D) override {
14629 // Stop in the case of finding a declaration, it is not important
14630 // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14631 // FunctionDecl...).
14632 return true;
14633 }
14634};
14635
14636bool SemaOpenMP::analyzeLoopSequence(Stmt *LoopSeqStmt,
14637 LoopSequenceAnalysis &SeqAnalysis,
14638 ASTContext &Context,
14639 OpenMPDirectiveKind Kind) {
14641 // Helper Lambda to handle storing initialization and body statements for
14642 // both ForStmt and CXXForRangeStmt.
14643 auto StoreLoopStatements = [](LoopAnalysis &Analysis, Stmt *LoopStmt) {
14644 if (auto *For = dyn_cast<ForStmt>(LoopStmt)) {
14645 Analysis.OriginalInits.push_back(For->getInit());
14646 Analysis.TheForStmt = For;
14647 } else {
14648 auto *CXXFor = cast<CXXForRangeStmt>(LoopStmt);
14649 Analysis.OriginalInits.push_back(CXXFor->getBeginStmt());
14650 Analysis.TheForStmt = CXXFor;
14651 }
14652 };
14653
14654 // Helper lambda functions to encapsulate the processing of different
14655 // derivations of the canonical loop sequence grammar
14656 // Modularized code for handling loop generation and transformations.
14657 auto AnalyzeLoopGeneration = [&](Stmt *Child) {
14658 auto *LoopTransform = cast<OMPLoopTransformationDirective>(Child);
14659 Stmt *TransformedStmt = LoopTransform->getTransformedStmt();
14660 unsigned NumGeneratedTopLevelLoops =
14661 LoopTransform->getNumGeneratedTopLevelLoops();
14662 // Handle the case where transformed statement is not available due to
14663 // dependent contexts
14664 if (!TransformedStmt) {
14665 if (NumGeneratedTopLevelLoops > 0) {
14666 SeqAnalysis.LoopSeqSize += NumGeneratedTopLevelLoops;
14667 return true;
14668 }
14669 // Unroll full (0 loops produced)
14670 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14671 << 0 << getOpenMPDirectiveName(Kind);
14672 return false;
14673 }
14674 // Handle loop transformations with multiple loop nests
14675 // Unroll full
14676 if (!NumGeneratedTopLevelLoops) {
14677 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14678 << 0 << getOpenMPDirectiveName(Kind);
14679 return false;
14680 }
14681 // Loop transformatons such as split or loopranged fuse
14682 if (NumGeneratedTopLevelLoops > 1) {
14683 // Get the preinits related to this loop sequence generating
14684 // loop transformation (i.e loopranged fuse, split...)
14685 // These preinits differ slightly from regular inits/pre-inits related
14686 // to single loop generating loop transformations (interchange, unroll)
14687 // given that they are not bounded to a particular loop nest
14688 // so they need to be treated independently
14689 updatePreInits(LoopTransform, SeqAnalysis.LoopSequencePreInits);
14690 return analyzeLoopSequence(TransformedStmt, SeqAnalysis, Context, Kind);
14691 }
14692 // Vast majority: (Tile, Unroll, Stripe, Reverse, Interchange, Fuse all)
14693 // Process the transformed loop statement
14694 LoopAnalysis &NewTransformedSingleLoop =
14695 SeqAnalysis.Loops.emplace_back(Child);
14696 unsigned IsCanonical = checkOpenMPLoop(
14697 Kind, nullptr, nullptr, TransformedStmt, SemaRef, *DSAStack, TmpDSA,
14698 NewTransformedSingleLoop.HelperExprs);
14699
14700 if (!IsCanonical)
14701 return false;
14702
14703 StoreLoopStatements(NewTransformedSingleLoop, TransformedStmt);
14704 updatePreInits(LoopTransform, NewTransformedSingleLoop.TransformsPreInits);
14705
14706 SeqAnalysis.LoopSeqSize++;
14707 return true;
14708 };
14709
14710 // Modularized code for handling regular canonical loops.
14711 auto AnalyzeRegularLoop = [&](Stmt *Child) {
14712 LoopAnalysis &NewRegularLoop = SeqAnalysis.Loops.emplace_back(Child);
14713 unsigned IsCanonical =
14714 checkOpenMPLoop(Kind, nullptr, nullptr, Child, SemaRef, *DSAStack,
14715 TmpDSA, NewRegularLoop.HelperExprs);
14716
14717 if (!IsCanonical)
14718 return false;
14719
14720 StoreLoopStatements(NewRegularLoop, Child);
14721 NestedLoopCounterVisitor NLCV;
14722 NLCV.TraverseStmt(Child);
14723 return true;
14724 };
14725
14726 // High level grammar validation.
14727 for (Stmt *Child : LoopSeqStmt->children()) {
14728 if (!Child)
14729 continue;
14730 // Skip over non-loop-sequence statements.
14731 if (!LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14732 Child = Child->IgnoreContainers();
14733 // Ignore empty compound statement.
14734 if (!Child)
14735 continue;
14736 // In the case of a nested loop sequence ignoring containers would not
14737 // be enough, a recurisve transversal of the loop sequence is required.
14738 if (isa<CompoundStmt>(Child)) {
14739 if (!analyzeLoopSequence(Child, SeqAnalysis, Context, Kind))
14740 return false;
14741 // Already been treated, skip this children
14742 continue;
14743 }
14744 }
14745 // Regular loop sequence handling.
14746 if (LoopSequenceAnalysis::isLoopSequenceDerivation(Child)) {
14747 if (LoopAnalysis::isLoopTransformation(Child)) {
14748 if (!AnalyzeLoopGeneration(Child))
14749 return false;
14750 // AnalyzeLoopGeneration updates SeqAnalysis.LoopSeqSize accordingly.
14751 } else {
14752 if (!AnalyzeRegularLoop(Child))
14753 return false;
14754 SeqAnalysis.LoopSeqSize++;
14755 }
14756 } else {
14757 // Report error for invalid statement inside canonical loop sequence.
14758 Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14759 << 0 << getOpenMPDirectiveName(Kind);
14760 return false;
14761 }
14762 }
14763 return true;
14764}
14765
14766bool SemaOpenMP::checkTransformableLoopSequence(
14767 OpenMPDirectiveKind Kind, Stmt *AStmt, LoopSequenceAnalysis &SeqAnalysis,
14768 ASTContext &Context) {
14769 // Following OpenMP 6.0 API Specification, a Canonical Loop Sequence follows
14770 // the grammar:
14771 //
14772 // canonical-loop-sequence:
14773 // {
14774 // loop-sequence+
14775 // }
14776 // where loop-sequence can be any of the following:
14777 // 1. canonical-loop-sequence
14778 // 2. loop-nest
14779 // 3. loop-sequence-generating-construct (i.e OMPLoopTransformationDirective)
14780 //
14781 // To recognise and traverse this structure the helper function
14782 // analyzeLoopSequence serves as the recurisve entry point
14783 // and tries to match the input AST to the canonical loop sequence grammar
14784 // structure. This function will perform both a semantic and syntactical
14785 // analysis of the given statement according to OpenMP 6.0 definition of
14786 // the aforementioned canonical loop sequence.
14787
14788 // We expect an outer compound statement.
14789 if (!isa<CompoundStmt>(AStmt)) {
14790 Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14791 << getOpenMPDirectiveName(Kind);
14792 return false;
14793 }
14794
14795 // Recursive entry point to process the main loop sequence
14796 if (!analyzeLoopSequence(AStmt, SeqAnalysis, Context, Kind))
14797 return false;
14798
14799 // Diagnose an empty loop sequence.
14800 if (!SeqAnalysis.LoopSeqSize) {
14801 Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
14802 << getOpenMPDirectiveName(Kind);
14803 return false;
14804 }
14805 return true;
14806}
14807
14808/// Add preinit statements that need to be propagated from the selected loop.
14809static void addLoopPreInits(ASTContext &Context,
14810 OMPLoopBasedDirective::HelperExprs &LoopHelper,
14811 Stmt *LoopStmt, ArrayRef<Stmt *> OriginalInit,
14812 SmallVectorImpl<Stmt *> &PreInits) {
14813
14814 // For range-based for-statements, ensure that their syntactic sugar is
14815 // executed by adding them as pre-init statements.
14816 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
14817 Stmt *RangeInit = CXXRangeFor->getInit();
14818 if (RangeInit)
14819 PreInits.push_back(RangeInit);
14820
14821 DeclStmt *RangeStmt = CXXRangeFor->getRangeStmt();
14822 PreInits.push_back(new (Context) DeclStmt(RangeStmt->getDeclGroup(),
14823 RangeStmt->getBeginLoc(),
14824 RangeStmt->getEndLoc()));
14825
14826 DeclStmt *RangeEnd = CXXRangeFor->getEndStmt();
14827 PreInits.push_back(new (Context) DeclStmt(RangeEnd->getDeclGroup(),
14828 RangeEnd->getBeginLoc(),
14829 RangeEnd->getEndLoc()));
14830 }
14831
14832 llvm::append_range(PreInits, OriginalInit);
14833
14834 // List of OMPCapturedExprDecl, for __begin, __end, and NumIterations
14835 if (auto *PI = cast_or_null<DeclStmt>(LoopHelper.PreInits)) {
14836 PreInits.push_back(new (Context) DeclStmt(
14837 PI->getDeclGroup(), PI->getBeginLoc(), PI->getEndLoc()));
14838 }
14839
14840 // Gather declarations for the data members used as counters.
14841 for (Expr *CounterRef : LoopHelper.Counters) {
14842 auto *CounterDecl = cast<DeclRefExpr>(CounterRef)->getDecl();
14843 if (isa<OMPCapturedExprDecl>(CounterDecl))
14844 PreInits.push_back(new (Context) DeclStmt(
14845 DeclGroupRef(CounterDecl), SourceLocation(), SourceLocation()));
14846 }
14847}
14848
14849/// Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected
14850/// loop of a construct.
14851static void collectLoopStmts(Stmt *AStmt, MutableArrayRef<Stmt *> LoopStmts) {
14852 size_t NumLoops = LoopStmts.size();
14853 OMPLoopBasedDirective::doForAllLoops(
14854 AStmt, /*TryImperfectlyNestedLoops=*/false, NumLoops,
14855 [LoopStmts](unsigned Cnt, Stmt *CurStmt) {
14856 assert(!LoopStmts[Cnt] && "Loop statement must not yet be assigned");
14857 LoopStmts[Cnt] = CurStmt;
14858 return false;
14859 });
14860 assert(!is_contained(LoopStmts, nullptr) &&
14861 "Expecting a loop statement for each affected loop");
14862}
14863
14864/// Build and return a DeclRefExpr for the floor induction variable using the
14865/// SemaRef and the provided parameters.
14866static Expr *makeFloorIVRef(Sema &SemaRef, ArrayRef<VarDecl *> FloorIndVars,
14867 int I, QualType IVTy, DeclRefExpr *OrigCntVar) {
14868 return buildDeclRefExpr(SemaRef, FloorIndVars[I], IVTy,
14869 OrigCntVar->getExprLoc());
14870}
14871
14873 Stmt *AStmt,
14874 SourceLocation StartLoc,
14875 SourceLocation EndLoc) {
14876 ASTContext &Context = getASTContext();
14877 Scope *CurScope = SemaRef.getCurScope();
14878
14879 const auto *SizesClause =
14880 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
14881 if (!SizesClause ||
14882 llvm::any_of(SizesClause->getSizesRefs(), [](Expr *E) { return !E; }))
14883 return StmtError();
14884 unsigned NumLoops = SizesClause->getNumSizes();
14885
14886 // Empty statement should only be possible if there already was an error.
14887 if (!AStmt)
14888 return StmtError();
14889
14890 // Verify and diagnose loop nest.
14892 Stmt *Body = nullptr;
14893 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
14894 if (!checkTransformableLoopNest(OMPD_tile, AStmt, NumLoops, LoopHelpers, Body,
14895 OriginalInits))
14896 return StmtError();
14897
14898 // Delay tiling to when template is completely instantiated.
14899 if (SemaRef.CurContext->isDependentContext())
14900 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses,
14901 NumLoops, AStmt, nullptr, nullptr);
14902
14903 assert(LoopHelpers.size() == NumLoops &&
14904 "Expecting loop iteration space dimensionality to match number of "
14905 "affected loops");
14906 assert(OriginalInits.size() == NumLoops &&
14907 "Expecting loop iteration space dimensionality to match number of "
14908 "affected loops");
14909
14910 // Collect all affected loop statements.
14911 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
14912 collectLoopStmts(AStmt, LoopStmts);
14913
14914 SmallVector<Stmt *, 4> PreInits;
14915 CaptureVars CopyTransformer(SemaRef);
14916
14917 // Create iteration variables for the generated loops.
14918 SmallVector<VarDecl *, 4> FloorIndVars;
14919 SmallVector<VarDecl *, 4> TileIndVars;
14920 FloorIndVars.resize(NumLoops);
14921 TileIndVars.resize(NumLoops);
14922 for (unsigned I = 0; I < NumLoops; ++I) {
14923 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
14924
14925 assert(LoopHelper.Counters.size() == 1 &&
14926 "Expect single-dimensional loop iteration space");
14927 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
14928 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
14929 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
14930 QualType CntTy = IterVarRef->getType();
14931
14932 // Iteration variable for the floor (i.e. outer) loop.
14933 {
14934 std::string FloorCntName =
14935 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14936 VarDecl *FloorCntDecl =
14937 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
14938 FloorIndVars[I] = FloorCntDecl;
14939 }
14940
14941 // Iteration variable for the tile (i.e. inner) loop.
14942 {
14943 std::string TileCntName =
14944 (Twine(".tile_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
14945
14946 // Reuse the iteration variable created by checkOpenMPLoop. It is also
14947 // used by the expressions to derive the original iteration variable's
14948 // value from the logical iteration number.
14949 auto *TileCntDecl = cast<VarDecl>(IterVarRef->getDecl());
14950 TileCntDecl->setDeclName(
14951 &SemaRef.PP.getIdentifierTable().get(TileCntName));
14952 TileIndVars[I] = TileCntDecl;
14953 }
14954
14955 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
14956 PreInits);
14957 }
14958
14959 // Once the original iteration values are set, append the innermost body.
14960 Stmt *Inner = Body;
14961
14962 auto MakeDimTileSize = [&SemaRef = this->SemaRef, &CopyTransformer, &Context,
14963 SizesClause, CurScope](int I) -> Expr * {
14964 Expr *DimTileSizeExpr = SizesClause->getSizesRefs()[I];
14965
14966 if (DimTileSizeExpr->containsErrors())
14967 return nullptr;
14968
14969 if (isa<ConstantExpr>(DimTileSizeExpr))
14970 return AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr));
14971
14972 // When the tile size is not a constant but a variable, it is possible to
14973 // pass non-positive numbers. For instance:
14974 // \code{c}
14975 // int a = 0;
14976 // #pragma omp tile sizes(a)
14977 // for (int i = 0; i < 42; ++i)
14978 // body(i);
14979 // \endcode
14980 // Although there is no meaningful interpretation of the tile size, the body
14981 // should still be executed 42 times to avoid surprises. To preserve the
14982 // invariant that every loop iteration is executed exactly once and not
14983 // cause an infinite loop, apply a minimum tile size of one.
14984 // Build expr:
14985 // \code{c}
14986 // (TS <= 0) ? 1 : TS
14987 // \endcode
14988 QualType DimTy = DimTileSizeExpr->getType();
14989 uint64_t DimWidth = Context.getTypeSize(DimTy);
14991 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
14992 IntegerLiteral *One =
14993 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
14994 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
14995 CurScope, {}, BO_LE,
14996 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), Zero));
14997 Expr *MinOne = new (Context) ConditionalOperator(
14998 Cond, {}, One, {},
14999 AssertSuccess(CopyTransformer.TransformExpr(DimTileSizeExpr)), DimTy,
15001 return MinOne;
15002 };
15003
15004 // Create tile loops from the inside to the outside.
15005 for (int I = NumLoops - 1; I >= 0; --I) {
15006 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15007 Expr *NumIterations = LoopHelper.NumIterations;
15008 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15009 QualType IVTy = NumIterations->getType();
15010 Stmt *LoopStmt = LoopStmts[I];
15011
15012 // Commonly used variables. One of the constraints of an AST is that every
15013 // node object must appear at most once, hence we define a lambda that
15014 // creates a new AST node at every use.
15015 auto MakeTileIVRef = [&SemaRef = this->SemaRef, &TileIndVars, I, IVTy,
15016 OrigCntVar]() {
15017 return buildDeclRefExpr(SemaRef, TileIndVars[I], IVTy,
15018 OrigCntVar->getExprLoc());
15019 };
15020
15021 // For init-statement: auto .tile.iv = .floor.iv
15022 SemaRef.AddInitializerToDecl(
15023 TileIndVars[I],
15024 SemaRef
15025 .DefaultLvalueConversion(
15026 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15027 .get(),
15028 /*DirectInit=*/false);
15029 Decl *CounterDecl = TileIndVars[I];
15030 StmtResult InitStmt = new (Context)
15031 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15032 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15033 if (!InitStmt.isUsable())
15034 return StmtError();
15035
15036 // For cond-expression:
15037 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations)
15038 Expr *DimTileSize = MakeDimTileSize(I);
15039 if (!DimTileSize)
15040 return StmtError();
15041 ExprResult EndOfTile = SemaRef.BuildBinOp(
15042 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15043 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15044 DimTileSize);
15045 if (!EndOfTile.isUsable())
15046 return StmtError();
15047 ExprResult IsPartialTile =
15048 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15049 NumIterations, EndOfTile.get());
15050 if (!IsPartialTile.isUsable())
15051 return StmtError();
15052 ExprResult MinTileAndIterSpace = SemaRef.ActOnConditionalOp(
15053 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15054 IsPartialTile.get(), NumIterations, EndOfTile.get());
15055 if (!MinTileAndIterSpace.isUsable())
15056 return StmtError();
15057 ExprResult CondExpr =
15058 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15059 MakeTileIVRef(), MinTileAndIterSpace.get());
15060 if (!CondExpr.isUsable())
15061 return StmtError();
15062
15063 // For incr-statement: ++.tile.iv
15064 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15065 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeTileIVRef());
15066 if (!IncrStmt.isUsable())
15067 return StmtError();
15068
15069 // Statements to set the original iteration variable's value from the
15070 // logical iteration number.
15071 // Generated for loop is:
15072 // \code
15073 // Original_for_init;
15074 // for (auto .tile.iv = .floor.iv;
15075 // .tile.iv < min(.floor.iv + DimTileSize, NumIterations);
15076 // ++.tile.iv) {
15077 // Original_Body;
15078 // Original_counter_update;
15079 // }
15080 // \endcode
15081 // FIXME: If the innermost body is an loop itself, inserting these
15082 // statements stops it being recognized as a perfectly nested loop (e.g.
15083 // for applying tiling again). If this is the case, sink the expressions
15084 // further into the inner loop.
15085 SmallVector<Stmt *, 4> BodyParts;
15086 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15087 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15088 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15089 BodyParts.push_back(Inner);
15090 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15091 Inner->getBeginLoc(), Inner->getEndLoc());
15092 Inner = new (Context)
15093 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15094 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15095 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15096 }
15097
15098 // Create floor loops from the inside to the outside.
15099 for (int I = NumLoops - 1; I >= 0; --I) {
15100 auto &LoopHelper = LoopHelpers[I];
15101 Expr *NumIterations = LoopHelper.NumIterations;
15102 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15103 QualType IVTy = NumIterations->getType();
15104
15105 // For init-statement: auto .floor.iv = 0
15106 SemaRef.AddInitializerToDecl(
15107 FloorIndVars[I],
15108 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15109 /*DirectInit=*/false);
15110 Decl *CounterDecl = FloorIndVars[I];
15111 StmtResult InitStmt = new (Context)
15112 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15113 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15114 if (!InitStmt.isUsable())
15115 return StmtError();
15116
15117 // For cond-expression: .floor.iv < NumIterations
15118 ExprResult CondExpr = SemaRef.BuildBinOp(
15119 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15120 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15121 NumIterations);
15122 if (!CondExpr.isUsable())
15123 return StmtError();
15124
15125 // For incr-statement: .floor.iv += DimTileSize
15126 Expr *DimTileSize = MakeDimTileSize(I);
15127 if (!DimTileSize)
15128 return StmtError();
15129 ExprResult IncrStmt = SemaRef.BuildBinOp(
15130 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15131 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15132 DimTileSize);
15133 if (!IncrStmt.isUsable())
15134 return StmtError();
15135
15136 Inner = new (Context)
15137 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15138 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15139 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15140 }
15141
15142 return OMPTileDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
15143 AStmt, Inner,
15144 buildPreInits(Context, PreInits));
15145}
15146
15148 Stmt *AStmt,
15149 SourceLocation StartLoc,
15150 SourceLocation EndLoc) {
15151 ASTContext &Context = getASTContext();
15152 Scope *CurScope = SemaRef.getCurScope();
15153
15154 const auto *SizesClause =
15155 OMPExecutableDirective::getSingleClause<OMPSizesClause>(Clauses);
15156 if (!SizesClause ||
15157 llvm::any_of(SizesClause->getSizesRefs(), [](const Expr *SizeExpr) {
15158 return !SizeExpr || SizeExpr->containsErrors();
15159 }))
15160 return StmtError();
15161 unsigned NumLoops = SizesClause->getNumSizes();
15162
15163 // Empty statement should only be possible if there already was an error.
15164 if (!AStmt)
15165 return StmtError();
15166
15167 // Verify and diagnose loop nest.
15169 Stmt *Body = nullptr;
15170 SmallVector<SmallVector<Stmt *>, 4> OriginalInits;
15171 if (!checkTransformableLoopNest(OMPD_stripe, AStmt, NumLoops, LoopHelpers,
15172 Body, OriginalInits))
15173 return StmtError();
15174
15175 // Delay striping to when template is completely instantiated.
15176 if (SemaRef.CurContext->isDependentContext())
15177 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15178 NumLoops, AStmt, nullptr, nullptr);
15179
15180 assert(LoopHelpers.size() == NumLoops &&
15181 "Expecting loop iteration space dimensionality to match number of "
15182 "affected loops");
15183 assert(OriginalInits.size() == NumLoops &&
15184 "Expecting loop iteration space dimensionality to match number of "
15185 "affected loops");
15186
15187 // Collect all affected loop statements.
15188 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15189 collectLoopStmts(AStmt, LoopStmts);
15190
15191 SmallVector<Stmt *, 4> PreInits;
15192 CaptureVars CopyTransformer(SemaRef);
15193
15194 // Create iteration variables for the generated loops.
15195 SmallVector<VarDecl *, 4> FloorIndVars;
15196 SmallVector<VarDecl *, 4> StripeIndVars;
15197 FloorIndVars.resize(NumLoops);
15198 StripeIndVars.resize(NumLoops);
15199 for (unsigned I : llvm::seq<unsigned>(NumLoops)) {
15200 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15201
15202 assert(LoopHelper.Counters.size() == 1 &&
15203 "Expect single-dimensional loop iteration space");
15204 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15205 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15206 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15207 QualType CntTy = IterVarRef->getType();
15208
15209 // Iteration variable for the stripe (i.e. outer) loop.
15210 {
15211 std::string FloorCntName =
15212 (Twine(".floor_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15213 VarDecl *FloorCntDecl =
15214 buildVarDecl(SemaRef, {}, CntTy, FloorCntName, nullptr, OrigCntVar);
15215 FloorIndVars[I] = FloorCntDecl;
15216 }
15217
15218 // Iteration variable for the stripe (i.e. inner) loop.
15219 {
15220 std::string StripeCntName =
15221 (Twine(".stripe_") + llvm::utostr(I) + ".iv." + OrigVarName).str();
15222
15223 // Reuse the iteration variable created by checkOpenMPLoop. It is also
15224 // used by the expressions to derive the original iteration variable's
15225 // value from the logical iteration number.
15226 auto *StripeCntDecl = cast<VarDecl>(IterVarRef->getDecl());
15227 StripeCntDecl->setDeclName(
15228 &SemaRef.PP.getIdentifierTable().get(StripeCntName));
15229 StripeIndVars[I] = StripeCntDecl;
15230 }
15231
15232 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15233 PreInits);
15234 }
15235
15236 // Once the original iteration values are set, append the innermost body.
15237 Stmt *Inner = Body;
15238
15239 auto MakeDimStripeSize = [&](int I) -> Expr * {
15240 Expr *DimStripeSizeExpr = SizesClause->getSizesRefs()[I];
15241 if (isa<ConstantExpr>(DimStripeSizeExpr))
15242 return AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr));
15243
15244 // When the stripe size is not a constant but a variable, it is possible to
15245 // pass non-positive numbers. For instance:
15246 // \code{c}
15247 // int a = 0;
15248 // #pragma omp stripe sizes(a)
15249 // for (int i = 0; i < 42; ++i)
15250 // body(i);
15251 // \endcode
15252 // Although there is no meaningful interpretation of the stripe size, the
15253 // body should still be executed 42 times to avoid surprises. To preserve
15254 // the invariant that every loop iteration is executed exactly once and not
15255 // cause an infinite loop, apply a minimum stripe size of one.
15256 // Build expr:
15257 // \code{c}
15258 // (TS <= 0) ? 1 : TS
15259 // \endcode
15260 QualType DimTy = DimStripeSizeExpr->getType();
15261 uint64_t DimWidth = Context.getTypeSize(DimTy);
15263 Context, llvm::APInt::getZero(DimWidth), DimTy, {});
15264 IntegerLiteral *One =
15265 IntegerLiteral::Create(Context, llvm::APInt(DimWidth, 1), DimTy, {});
15266 Expr *Cond = AssertSuccess(SemaRef.BuildBinOp(
15267 CurScope, {}, BO_LE,
15268 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), Zero));
15269 Expr *MinOne = new (Context) ConditionalOperator(
15270 Cond, {}, One, {},
15271 AssertSuccess(CopyTransformer.TransformExpr(DimStripeSizeExpr)), DimTy,
15273 return MinOne;
15274 };
15275
15276 // Create stripe loops from the inside to the outside.
15277 for (int I = NumLoops - 1; I >= 0; --I) {
15278 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15279 Expr *NumIterations = LoopHelper.NumIterations;
15280 auto *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15281 QualType IVTy = NumIterations->getType();
15282 Stmt *LoopStmt = LoopStmts[I];
15283
15284 // For init-statement: auto .stripe.iv = .floor.iv
15285 SemaRef.AddInitializerToDecl(
15286 StripeIndVars[I],
15287 SemaRef
15288 .DefaultLvalueConversion(
15289 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar))
15290 .get(),
15291 /*DirectInit=*/false);
15292 Decl *CounterDecl = StripeIndVars[I];
15293 StmtResult InitStmt = new (Context)
15294 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15295 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15296 if (!InitStmt.isUsable())
15297 return StmtError();
15298
15299 // For cond-expression:
15300 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations)
15301 ExprResult EndOfStripe = SemaRef.BuildBinOp(
15302 CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15303 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15304 MakeDimStripeSize(I));
15305 if (!EndOfStripe.isUsable())
15306 return StmtError();
15307 ExprResult IsPartialStripe =
15308 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15309 NumIterations, EndOfStripe.get());
15310 if (!IsPartialStripe.isUsable())
15311 return StmtError();
15312 ExprResult MinStripeAndIterSpace = SemaRef.ActOnConditionalOp(
15313 LoopHelper.Cond->getBeginLoc(), LoopHelper.Cond->getEndLoc(),
15314 IsPartialStripe.get(), NumIterations, EndOfStripe.get());
15315 if (!MinStripeAndIterSpace.isUsable())
15316 return StmtError();
15317 ExprResult CondExpr = SemaRef.BuildBinOp(
15318 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15319 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar),
15320 MinStripeAndIterSpace.get());
15321 if (!CondExpr.isUsable())
15322 return StmtError();
15323
15324 // For incr-statement: ++.stripe.iv
15325 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
15326 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc,
15327 makeFloorIVRef(SemaRef, StripeIndVars, I, IVTy, OrigCntVar));
15328 if (!IncrStmt.isUsable())
15329 return StmtError();
15330
15331 // Statements to set the original iteration variable's value from the
15332 // logical iteration number.
15333 // Generated for loop is:
15334 // \code
15335 // Original_for_init;
15336 // for (auto .stripe.iv = .floor.iv;
15337 // .stripe.iv < min(.floor.iv + DimStripeSize, NumIterations);
15338 // ++.stripe.iv) {
15339 // Original_Body;
15340 // Original_counter_update;
15341 // }
15342 // \endcode
15343 // FIXME: If the innermost body is a loop itself, inserting these
15344 // statements stops it being recognized as a perfectly nested loop (e.g.
15345 // for applying another loop transformation). If this is the case, sink the
15346 // expressions further into the inner loop.
15347 SmallVector<Stmt *, 4> BodyParts;
15348 BodyParts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15349 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15350 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
15351 BodyParts.push_back(Inner);
15352 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
15353 Inner->getBeginLoc(), Inner->getEndLoc());
15354 Inner = new (Context)
15355 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15356 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15357 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15358 }
15359
15360 // Create grid loops from the inside to the outside.
15361 for (int I = NumLoops - 1; I >= 0; --I) {
15362 auto &LoopHelper = LoopHelpers[I];
15363 Expr *NumIterations = LoopHelper.NumIterations;
15364 DeclRefExpr *OrigCntVar = cast<DeclRefExpr>(LoopHelper.Counters[0]);
15365 QualType IVTy = NumIterations->getType();
15366
15367 // For init-statement: auto .grid.iv = 0
15368 SemaRef.AddInitializerToDecl(
15369 FloorIndVars[I],
15370 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15371 /*DirectInit=*/false);
15372 Decl *CounterDecl = FloorIndVars[I];
15373 StmtResult InitStmt = new (Context)
15374 DeclStmt(DeclGroupRef::Create(Context, &CounterDecl, 1),
15375 OrigCntVar->getBeginLoc(), OrigCntVar->getEndLoc());
15376 if (!InitStmt.isUsable())
15377 return StmtError();
15378
15379 // For cond-expression: .floor.iv < NumIterations
15380 ExprResult CondExpr = SemaRef.BuildBinOp(
15381 CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15382 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15383 NumIterations);
15384 if (!CondExpr.isUsable())
15385 return StmtError();
15386
15387 // For incr-statement: .floor.iv += DimStripeSize
15388 ExprResult IncrStmt = SemaRef.BuildBinOp(
15389 CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15390 makeFloorIVRef(SemaRef, FloorIndVars, I, IVTy, OrigCntVar),
15391 MakeDimStripeSize(I));
15392 if (!IncrStmt.isUsable())
15393 return StmtError();
15394
15395 Inner = new (Context)
15396 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
15397 IncrStmt.get(), Inner, LoopHelper.Init->getBeginLoc(),
15398 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15399 }
15400
15401 return OMPStripeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15402 NumLoops, AStmt, Inner,
15403 buildPreInits(Context, PreInits));
15404}
15405
15407 Stmt *AStmt,
15408 SourceLocation StartLoc,
15409 SourceLocation EndLoc) {
15410 ASTContext &Context = getASTContext();
15411 Scope *CurScope = SemaRef.getCurScope();
15412 // Empty statement should only be possible if there already was an error.
15413 if (!AStmt)
15414 return StmtError();
15415
15417 {OMPC_partial, OMPC_full}))
15418 return StmtError();
15419
15420 const OMPFullClause *FullClause =
15421 OMPExecutableDirective::getSingleClause<OMPFullClause>(Clauses);
15422 const OMPPartialClause *PartialClause =
15423 OMPExecutableDirective::getSingleClause<OMPPartialClause>(Clauses);
15424 assert(!(FullClause && PartialClause) &&
15425 "mutual exclusivity must have been checked before");
15426
15427 constexpr unsigned NumLoops = 1;
15428 Stmt *Body = nullptr;
15430 NumLoops);
15431 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15432 if (!checkTransformableLoopNest(OMPD_unroll, AStmt, NumLoops, LoopHelpers,
15433 Body, OriginalInits))
15434 return StmtError();
15435
15436 unsigned NumGeneratedTopLevelLoops = PartialClause ? 1 : 0;
15437
15438 // Delay unrolling to when template is completely instantiated.
15439 if (SemaRef.CurContext->isDependentContext())
15440 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15441 NumGeneratedTopLevelLoops, nullptr,
15442 nullptr);
15443
15444 assert(LoopHelpers.size() == NumLoops &&
15445 "Expecting a single-dimensional loop iteration space");
15446 assert(OriginalInits.size() == NumLoops &&
15447 "Expecting a single-dimensional loop iteration space");
15448 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15449
15450 if (FullClause) {
15452 LoopHelper.NumIterations, OMPC_full, /*StrictlyPositive=*/false,
15453 /*SuppressExprDiags=*/true)
15454 .isUsable()) {
15455 Diag(AStmt->getBeginLoc(), diag::err_omp_unroll_full_variable_trip_count);
15456 Diag(FullClause->getBeginLoc(), diag::note_omp_directive_here)
15457 << "#pragma omp unroll full";
15458 return StmtError();
15459 }
15460 }
15461
15462 // The generated loop may only be passed to other loop-associated directive
15463 // when a partial clause is specified. Without the requirement it is
15464 // sufficient to generate loop unroll metadata at code-generation.
15465 if (NumGeneratedTopLevelLoops == 0)
15466 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15467 NumGeneratedTopLevelLoops, nullptr,
15468 nullptr);
15469
15470 // Otherwise, we need to provide a de-sugared/transformed AST that can be
15471 // associated with another loop directive.
15472 //
15473 // The canonical loop analysis return by checkTransformableLoopNest assumes
15474 // the following structure to be the same loop without transformations or
15475 // directives applied: \code OriginalInits; LoopHelper.PreInits;
15476 // LoopHelper.Counters;
15477 // for (; IV < LoopHelper.NumIterations; ++IV) {
15478 // LoopHelper.Updates;
15479 // Body;
15480 // }
15481 // \endcode
15482 // where IV is a variable declared and initialized to 0 in LoopHelper.PreInits
15483 // and referenced by LoopHelper.IterationVarRef.
15484 //
15485 // The unrolling directive transforms this into the following loop:
15486 // \code
15487 // OriginalInits; \
15488 // LoopHelper.PreInits; > NewPreInits
15489 // LoopHelper.Counters; /
15490 // for (auto UIV = 0; UIV < LoopHelper.NumIterations; UIV+=Factor) {
15491 // #pragma clang loop unroll_count(Factor)
15492 // for (IV = UIV; IV < UIV + Factor && UIV < LoopHelper.NumIterations; ++IV)
15493 // {
15494 // LoopHelper.Updates;
15495 // Body;
15496 // }
15497 // }
15498 // \endcode
15499 // where UIV is a new logical iteration counter. IV must be the same VarDecl
15500 // as the original LoopHelper.IterationVarRef because LoopHelper.Updates
15501 // references it. If the partially unrolled loop is associated with another
15502 // loop directive (like an OMPForDirective), it will use checkOpenMPLoop to
15503 // analyze this loop, i.e. the outer loop must fulfill the constraints of an
15504 // OpenMP canonical loop. The inner loop is not an associable canonical loop
15505 // and only exists to defer its unrolling to LLVM's LoopUnroll instead of
15506 // doing it in the frontend (by adding loop metadata). NewPreInits becomes a
15507 // property of the OMPLoopBasedDirective instead of statements in
15508 // CompoundStatement. This is to allow the loop to become a non-outermost loop
15509 // of a canonical loop nest where these PreInits are emitted before the
15510 // outermost directive.
15511
15512 // Find the loop statement.
15513 Stmt *LoopStmt = nullptr;
15514 collectLoopStmts(AStmt, {LoopStmt});
15515
15516 // Determine the PreInit declarations.
15517 SmallVector<Stmt *, 4> PreInits;
15518 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15519
15520 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15521 QualType IVTy = IterationVarRef->getType();
15522 assert(LoopHelper.Counters.size() == 1 &&
15523 "Expecting a single-dimensional loop iteration space");
15524 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15525
15526 // Determine the unroll factor.
15527 uint64_t Factor;
15528 SourceLocation FactorLoc;
15529 if (Expr *FactorVal = PartialClause->getFactor();
15530 FactorVal && !FactorVal->containsErrors()) {
15531 Factor = FactorVal->getIntegerConstantExpr(Context)->getZExtValue();
15532 FactorLoc = FactorVal->getExprLoc();
15533 } else {
15534 // TODO: Use a better profitability model.
15535 Factor = 2;
15536 }
15537 assert(Factor > 0 && "Expected positive unroll factor");
15538 auto MakeFactorExpr = [this, Factor, IVTy, FactorLoc]() {
15540 getASTContext(), llvm::APInt(getASTContext().getIntWidth(IVTy), Factor),
15541 IVTy, FactorLoc);
15542 };
15543
15544 // Iteration variable SourceLocations.
15545 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15546 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15547 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15548
15549 // Internal variable names.
15550 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15551 std::string OuterIVName = (Twine(".unrolled.iv.") + OrigVarName).str();
15552 std::string InnerIVName = (Twine(".unroll_inner.iv.") + OrigVarName).str();
15553
15554 // Create the iteration variable for the unrolled loop.
15555 VarDecl *OuterIVDecl =
15556 buildVarDecl(SemaRef, {}, IVTy, OuterIVName, nullptr, OrigVar);
15557 auto MakeOuterRef = [this, OuterIVDecl, IVTy, OrigVarLoc]() {
15558 return buildDeclRefExpr(SemaRef, OuterIVDecl, IVTy, OrigVarLoc);
15559 };
15560
15561 // Iteration variable for the inner loop: Reuse the iteration variable created
15562 // by checkOpenMPLoop.
15563 auto *InnerIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15564 InnerIVDecl->setDeclName(&SemaRef.PP.getIdentifierTable().get(InnerIVName));
15565 auto MakeInnerRef = [this, InnerIVDecl, IVTy, OrigVarLoc]() {
15566 return buildDeclRefExpr(SemaRef, InnerIVDecl, IVTy, OrigVarLoc);
15567 };
15568
15569 // Make a copy of the NumIterations expression for each use: By the AST
15570 // constraints, every expression object in a DeclContext must be unique.
15571 CaptureVars CopyTransformer(SemaRef);
15572 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15573 return AssertSuccess(
15574 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15575 };
15576
15577 // Inner For init-statement: auto .unroll_inner.iv = .unrolled.iv
15578 ExprResult LValueConv = SemaRef.DefaultLvalueConversion(MakeOuterRef());
15579 SemaRef.AddInitializerToDecl(InnerIVDecl, LValueConv.get(),
15580 /*DirectInit=*/false);
15581 StmtResult InnerInit = new (Context)
15582 DeclStmt(DeclGroupRef(InnerIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15583 if (!InnerInit.isUsable())
15584 return StmtError();
15585
15586 // Inner For cond-expression:
15587 // \code
15588 // .unroll_inner.iv < .unrolled.iv + Factor &&
15589 // .unroll_inner.iv < NumIterations
15590 // \endcode
15591 // This conjunction of two conditions allows ScalarEvolution to derive the
15592 // maximum trip count of the inner loop.
15593 ExprResult EndOfTile =
15594 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_Add,
15595 MakeOuterRef(), MakeFactorExpr());
15596 if (!EndOfTile.isUsable())
15597 return StmtError();
15598 ExprResult InnerCond1 =
15599 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15600 MakeInnerRef(), EndOfTile.get());
15601 if (!InnerCond1.isUsable())
15602 return StmtError();
15603 ExprResult InnerCond2 =
15604 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15605 MakeInnerRef(), MakeNumIterations());
15606 if (!InnerCond2.isUsable())
15607 return StmtError();
15608 ExprResult InnerCond =
15609 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LAnd,
15610 InnerCond1.get(), InnerCond2.get());
15611 if (!InnerCond.isUsable())
15612 return StmtError();
15613
15614 // Inner For incr-statement: ++.unroll_inner.iv
15615 ExprResult InnerIncr = SemaRef.BuildUnaryOp(
15616 CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeInnerRef());
15617 if (!InnerIncr.isUsable())
15618 return StmtError();
15619
15620 // Inner For statement.
15621 SmallVector<Stmt *> InnerBodyStmts;
15622 InnerBodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
15623 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15624 InnerBodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15625 InnerBodyStmts.push_back(Body);
15626 CompoundStmt *InnerBody =
15628 Body->getBeginLoc(), Body->getEndLoc());
15629 ForStmt *InnerFor = new (Context)
15630 ForStmt(Context, InnerInit.get(), InnerCond.get(), nullptr,
15631 InnerIncr.get(), InnerBody, LoopHelper.Init->getBeginLoc(),
15632 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15633
15634 // Unroll metadata for the inner loop.
15635 // This needs to take into account the remainder portion of the unrolled loop,
15636 // hence `unroll(full)` does not apply here, even though the LoopUnroll pass
15637 // supports multiple loop exits. Instead, unroll using a factor equivalent to
15638 // the maximum trip count, which will also generate a remainder loop. Just
15639 // `unroll(enable)` (which could have been useful if the user has not
15640 // specified a concrete factor; even though the outer loop cannot be
15641 // influenced anymore, would avoid more code bloat than necessary) will refuse
15642 // the loop because "Won't unroll; remainder loop could not be generated when
15643 // assuming runtime trip count". Even if it did work, it must not choose a
15644 // larger unroll factor than the maximum loop length, or it would always just
15645 // execute the remainder loop.
15646 LoopHintAttr *UnrollHintAttr =
15647 LoopHintAttr::CreateImplicit(Context, LoopHintAttr::UnrollCount,
15648 LoopHintAttr::Numeric, MakeFactorExpr());
15649 AttributedStmt *InnerUnrolled = AttributedStmt::Create(
15650 getASTContext(), StartLoc, {UnrollHintAttr}, InnerFor);
15651
15652 // Outer For init-statement: auto .unrolled.iv = 0
15653 SemaRef.AddInitializerToDecl(
15654 OuterIVDecl,
15655 SemaRef.ActOnIntegerConstant(LoopHelper.Init->getExprLoc(), 0).get(),
15656 /*DirectInit=*/false);
15657 StmtResult OuterInit = new (Context)
15658 DeclStmt(DeclGroupRef(OuterIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15659 if (!OuterInit.isUsable())
15660 return StmtError();
15661
15662 // Outer For cond-expression: .unrolled.iv < NumIterations
15663 ExprResult OuterConde =
15664 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15665 MakeOuterRef(), MakeNumIterations());
15666 if (!OuterConde.isUsable())
15667 return StmtError();
15668
15669 // Outer For incr-statement: .unrolled.iv += Factor
15670 ExprResult OuterIncr =
15671 SemaRef.BuildBinOp(CurScope, LoopHelper.Inc->getExprLoc(), BO_AddAssign,
15672 MakeOuterRef(), MakeFactorExpr());
15673 if (!OuterIncr.isUsable())
15674 return StmtError();
15675
15676 // Outer For statement.
15677 ForStmt *OuterFor = new (Context)
15678 ForStmt(Context, OuterInit.get(), OuterConde.get(), nullptr,
15679 OuterIncr.get(), InnerUnrolled, LoopHelper.Init->getBeginLoc(),
15680 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15681
15682 return OMPUnrollDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt,
15683 NumGeneratedTopLevelLoops, OuterFor,
15684 buildPreInits(Context, PreInits));
15685}
15686
15688 SourceLocation StartLoc,
15689 SourceLocation EndLoc) {
15690 ASTContext &Context = getASTContext();
15691 Scope *CurScope = SemaRef.getCurScope();
15692
15693 // Empty statement should only be possible if there already was an error.
15694 if (!AStmt)
15695 return StmtError();
15696
15697 constexpr unsigned NumLoops = 1;
15698 Stmt *Body = nullptr;
15700 NumLoops);
15701 SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
15702 if (!checkTransformableLoopNest(OMPD_reverse, AStmt, NumLoops, LoopHelpers,
15703 Body, OriginalInits))
15704 return StmtError();
15705
15706 // Delay applying the transformation to when template is completely
15707 // instantiated.
15708 if (SemaRef.CurContext->isDependentContext())
15709 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt,
15710 NumLoops, nullptr, nullptr);
15711
15712 assert(LoopHelpers.size() == NumLoops &&
15713 "Expecting a single-dimensional loop iteration space");
15714 assert(OriginalInits.size() == NumLoops &&
15715 "Expecting a single-dimensional loop iteration space");
15716 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
15717
15718 // Find the loop statement.
15719 Stmt *LoopStmt = nullptr;
15720 collectLoopStmts(AStmt, {LoopStmt});
15721
15722 // Determine the PreInit declarations.
15723 SmallVector<Stmt *> PreInits;
15724 addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15725
15726 auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
15727 QualType IVTy = IterationVarRef->getType();
15728 uint64_t IVWidth = Context.getTypeSize(IVTy);
15729 auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
15730
15731 // Iteration variable SourceLocations.
15732 SourceLocation OrigVarLoc = OrigVar->getExprLoc();
15733 SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
15734 SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
15735
15736 // Locations pointing to the transformation.
15737 SourceLocation TransformLoc = StartLoc;
15738 SourceLocation TransformLocBegin = StartLoc;
15739 SourceLocation TransformLocEnd = EndLoc;
15740
15741 // Internal variable names.
15742 std::string OrigVarName = OrigVar->getNameInfo().getAsString();
15743 SmallString<64> ForwardIVName(".forward.iv.");
15744 ForwardIVName += OrigVarName;
15745 SmallString<64> ReversedIVName(".reversed.iv.");
15746 ReversedIVName += OrigVarName;
15747
15748 // LoopHelper.Updates will read the logical iteration number from
15749 // LoopHelper.IterationVarRef, compute the value of the user loop counter of
15750 // that logical iteration from it, then assign it to the user loop counter
15751 // variable. We cannot directly use LoopHelper.IterationVarRef as the
15752 // induction variable of the generated loop because it may cause an underflow:
15753 // \code{.c}
15754 // for (unsigned i = 0; i < n; ++i)
15755 // body(i);
15756 // \endcode
15757 //
15758 // Naive reversal:
15759 // \code{.c}
15760 // for (unsigned i = n-1; i >= 0; --i)
15761 // body(i);
15762 // \endcode
15763 //
15764 // Instead, we introduce a new iteration variable representing the logical
15765 // iteration counter of the original loop, convert it to the logical iteration
15766 // number of the reversed loop, then let LoopHelper.Updates compute the user's
15767 // loop iteration variable from it.
15768 // \code{.cpp}
15769 // for (auto .forward.iv = 0; .forward.iv < n; ++.forward.iv) {
15770 // auto .reversed.iv = n - .forward.iv - 1;
15771 // i = (.reversed.iv + 0) * 1; // LoopHelper.Updates
15772 // body(i); // Body
15773 // }
15774 // \endcode
15775
15776 // Subexpressions with more than one use. One of the constraints of an AST is
15777 // that every node object must appear at most once, hence we define a lambda
15778 // that creates a new AST node at every use.
15779 CaptureVars CopyTransformer(SemaRef);
15780 auto MakeNumIterations = [&CopyTransformer, &LoopHelper]() -> Expr * {
15781 return AssertSuccess(
15782 CopyTransformer.TransformExpr(LoopHelper.NumIterations));
15783 };
15784
15785 // Create the iteration variable for the forward loop (from 0 to n-1).
15786 VarDecl *ForwardIVDecl =
15787 buildVarDecl(SemaRef, {}, IVTy, ForwardIVName, nullptr, OrigVar);
15788 auto MakeForwardRef = [&SemaRef = this->SemaRef, ForwardIVDecl, IVTy,
15789 OrigVarLoc]() {
15790 return buildDeclRefExpr(SemaRef, ForwardIVDecl, IVTy, OrigVarLoc);
15791 };
15792
15793 // Iteration variable for the reversed induction variable (from n-1 downto 0):
15794 // Reuse the iteration variable created by checkOpenMPLoop.
15795 auto *ReversedIVDecl = cast<VarDecl>(IterationVarRef->getDecl());
15796 ReversedIVDecl->setDeclName(
15797 &SemaRef.PP.getIdentifierTable().get(ReversedIVName));
15798
15799 // For init-statement:
15800 // \code{.cpp}
15801 // auto .forward.iv = 0;
15802 // \endcode
15803 auto *Zero = IntegerLiteral::Create(Context, llvm::APInt::getZero(IVWidth),
15804 ForwardIVDecl->getType(), OrigVarLoc);
15805 SemaRef.AddInitializerToDecl(ForwardIVDecl, Zero, /*DirectInit=*/false);
15806 StmtResult Init = new (Context)
15807 DeclStmt(DeclGroupRef(ForwardIVDecl), OrigVarLocBegin, OrigVarLocEnd);
15808 if (!Init.isUsable())
15809 return StmtError();
15810
15811 // Forward iv cond-expression:
15812 // \code{.cpp}
15813 // .forward.iv < MakeNumIterations()
15814 // \endcode
15816 SemaRef.BuildBinOp(CurScope, LoopHelper.Cond->getExprLoc(), BO_LT,
15817 MakeForwardRef(), MakeNumIterations());
15818 if (!Cond.isUsable())
15819 return StmtError();
15820
15821 // Forward incr-statement:
15822 // \code{.c}
15823 // ++.forward.iv
15824 // \endcode
15825 ExprResult Incr = SemaRef.BuildUnaryOp(CurScope, LoopHelper.Inc->getExprLoc(),
15826 UO_PreInc, MakeForwardRef());
15827 if (!Incr.isUsable())
15828 return StmtError();
15829
15830 // Reverse the forward-iv:
15831 // \code{.cpp}
15832 // auto .reversed.iv = MakeNumIterations() - 1 - .forward.iv
15833 // \endcode
15834 auto *One = IntegerLiteral::Create(Context, llvm::APInt(IVWidth, 1), IVTy,
15835 TransformLoc);
15836 ExprResult Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub,
15837 MakeNumIterations(), One);
15838 if (!Minus.isUsable())
15839 return StmtError();
15840 Minus = SemaRef.BuildBinOp(CurScope, TransformLoc, BO_Sub, Minus.get(),
15841 MakeForwardRef());
15842 if (!Minus.isUsable())
15843 return StmtError();
15844 StmtResult InitReversed = new (Context) DeclStmt(
15845 DeclGroupRef(ReversedIVDecl), TransformLocBegin, TransformLocEnd);
15846 if (!InitReversed.isUsable())
15847 return StmtError();
15848 SemaRef.AddInitializerToDecl(ReversedIVDecl, Minus.get(),
15849 /*DirectInit=*/false);
15850
15851 // The new loop body.
15852 SmallVector<Stmt *, 4> BodyStmts;
15853 BodyStmts.reserve(LoopHelper.Updates.size() + 2 +
15854 (isa<CXXForRangeStmt>(LoopStmt) ? 1 : 0));
15855 BodyStmts.push_back(InitReversed.get());
15856 llvm::append_range(BodyStmts, LoopHelper.Updates);
15857 if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt))
15858 BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
15859 BodyStmts.push_back(Body);
15860 auto *ReversedBody =
15861 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
15862 Body->getBeginLoc(), Body->getEndLoc());
15863
15864 // Finally create the reversed For-statement.
15865 auto *ReversedFor = new (Context)
15866 ForStmt(Context, Init.get(), Cond.get(), nullptr, Incr.get(),
15867 ReversedBody, LoopHelper.Init->getBeginLoc(),
15868 LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
15869 return OMPReverseDirective::Create(Context, StartLoc, EndLoc, AStmt, NumLoops,
15870 ReversedFor,
15871 buildPreInits(Context, PreInits));
15872}
15873
15875 ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
15876 SourceLocation EndLoc) {
15877 ASTContext &Context = getASTContext();
15878 DeclContext *CurContext = SemaRef.CurContext;
15879 Scope *CurScope = SemaRef.getCurScope();
15880
15881 // Empty statement should only be possible if there already was an error.
15882 if (!AStmt)
15883 return StmtError();
15884
15885 // interchange without permutation clause swaps two loops.
15886 const OMPPermutationClause *PermutationClause =
15887 OMPExecutableDirective::getSingleClause<OMPPermutationClause>(Clauses);
15888 size_t NumLoops = PermutationClause ? PermutationClause->getNumLoops() : 2;
15889
15890 // Verify and diagnose loop nest.
15892 Stmt *Body = nullptr;
15893 SmallVector<SmallVector<Stmt *>, 2> OriginalInits;
15894 if (!checkTransformableLoopNest(OMPD_interchange, AStmt, NumLoops,
15895 LoopHelpers, Body, OriginalInits))
15896 return StmtError();
15897
15898 // Delay interchange to when template is completely instantiated.
15899 if (CurContext->isDependentContext())
15900 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15901 NumLoops, AStmt, nullptr, nullptr);
15902
15903 // An invalid expression in the permutation clause is set to nullptr in
15904 // ActOnOpenMPPermutationClause.
15905 if (PermutationClause &&
15906 llvm::is_contained(PermutationClause->getArgsRefs(), nullptr))
15907 return StmtError();
15908
15909 assert(LoopHelpers.size() == NumLoops &&
15910 "Expecting loop iteration space dimensionaly to match number of "
15911 "affected loops");
15912 assert(OriginalInits.size() == NumLoops &&
15913 "Expecting loop iteration space dimensionaly to match number of "
15914 "affected loops");
15915
15916 // Decode the permutation clause.
15917 SmallVector<uint64_t, 2> Permutation;
15918 if (!PermutationClause) {
15919 Permutation = {1, 0};
15920 } else {
15921 ArrayRef<Expr *> PermArgs = PermutationClause->getArgsRefs();
15922 llvm::BitVector Flags(PermArgs.size());
15923 for (Expr *PermArg : PermArgs) {
15924 std::optional<llvm::APSInt> PermCstExpr =
15925 PermArg->getIntegerConstantExpr(Context);
15926 if (!PermCstExpr)
15927 continue;
15928 uint64_t PermInt = PermCstExpr->getZExtValue();
15929 assert(1 <= PermInt && PermInt <= NumLoops &&
15930 "Must be a permutation; diagnostic emitted in "
15931 "ActOnOpenMPPermutationClause");
15932 if (Flags[PermInt - 1]) {
15933 SourceRange ExprRange(PermArg->getBeginLoc(), PermArg->getEndLoc());
15934 Diag(PermArg->getExprLoc(),
15935 diag::err_omp_interchange_permutation_value_repeated)
15936 << PermInt << ExprRange;
15937 continue;
15938 }
15939 Flags[PermInt - 1] = true;
15940
15941 Permutation.push_back(PermInt - 1);
15942 }
15943
15944 if (Permutation.size() != NumLoops)
15945 return StmtError();
15946 }
15947
15948 // Nothing to transform with trivial permutation.
15949 if (NumLoops <= 1 || llvm::all_of(llvm::enumerate(Permutation), [](auto P) {
15950 auto [Idx, Arg] = P;
15951 return Idx == Arg;
15952 }))
15953 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
15954 NumLoops, AStmt, AStmt, nullptr);
15955
15956 // Find the affected loops.
15957 SmallVector<Stmt *> LoopStmts(NumLoops, nullptr);
15958 collectLoopStmts(AStmt, LoopStmts);
15959
15960 // Collect pre-init statements on the order before the permuation.
15961 SmallVector<Stmt *> PreInits;
15962 for (auto I : llvm::seq<int>(NumLoops)) {
15963 OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers[I];
15964
15965 assert(LoopHelper.Counters.size() == 1 &&
15966 "Single-dimensional loop iteration space expected");
15967
15968 addLoopPreInits(Context, LoopHelper, LoopStmts[I], OriginalInits[I],
15969 PreInits);
15970 }
15971
15972 SmallVector<VarDecl *> PermutedIndVars(NumLoops);
15973 CaptureVars CopyTransformer(SemaRef);
15974
15975 // Create the permuted loops from the inside to the outside of the
15976 // interchanged loop nest. Body of the innermost new loop is the original
15977 // innermost body.
15978 Stmt *Inner = Body;
15979 for (auto TargetIdx : llvm::reverse(llvm::seq<int>(NumLoops))) {
15980 // Get the original loop that belongs to this new position.
15981 uint64_t SourceIdx = Permutation[TargetIdx];
15982 OMPLoopBasedDirective::HelperExprs &SourceHelper = LoopHelpers[SourceIdx];
15983 Stmt *SourceLoopStmt = LoopStmts[SourceIdx];
15984 assert(SourceHelper.Counters.size() == 1 &&
15985 "Single-dimensional loop iteration space expected");
15986 auto *OrigCntVar = cast<DeclRefExpr>(SourceHelper.Counters.front());
15987
15988 // Normalized loop counter variable: From 0 to n-1, always an integer type.
15989 DeclRefExpr *IterVarRef = cast<DeclRefExpr>(SourceHelper.IterationVarRef);
15990 QualType IVTy = IterVarRef->getType();
15991 assert(IVTy->isIntegerType() &&
15992 "Expected the logical iteration counter to be an integer");
15993
15994 std::string OrigVarName = OrigCntVar->getNameInfo().getAsString();
15995 SourceLocation OrigVarLoc = IterVarRef->getExprLoc();
15996
15997 // Make a copy of the NumIterations expression for each use: By the AST
15998 // constraints, every expression object in a DeclContext must be unique.
15999 auto MakeNumIterations = [&CopyTransformer, &SourceHelper]() -> Expr * {
16000 return AssertSuccess(
16001 CopyTransformer.TransformExpr(SourceHelper.NumIterations));
16002 };
16003
16004 // Iteration variable for the permuted loop. Reuse the one from
16005 // checkOpenMPLoop which will also be used to update the original loop
16006 // variable.
16007 SmallString<64> PermutedCntName(".permuted_");
16008 PermutedCntName.append({llvm::utostr(TargetIdx), ".iv.", OrigVarName});
16009 auto *PermutedCntDecl = cast<VarDecl>(IterVarRef->getDecl());
16010 PermutedCntDecl->setDeclName(
16011 &SemaRef.PP.getIdentifierTable().get(PermutedCntName));
16012 PermutedIndVars[TargetIdx] = PermutedCntDecl;
16013 auto MakePermutedRef = [this, PermutedCntDecl, IVTy, OrigVarLoc]() {
16014 return buildDeclRefExpr(SemaRef, PermutedCntDecl, IVTy, OrigVarLoc);
16015 };
16016
16017 // For init-statement:
16018 // \code
16019 // auto .permuted_{target}.iv = 0
16020 // \endcode
16021 ExprResult Zero = SemaRef.ActOnIntegerConstant(OrigVarLoc, 0);
16022 if (!Zero.isUsable())
16023 return StmtError();
16024 SemaRef.AddInitializerToDecl(PermutedCntDecl, Zero.get(),
16025 /*DirectInit=*/false);
16026 StmtResult InitStmt = new (Context)
16027 DeclStmt(DeclGroupRef(PermutedCntDecl), OrigCntVar->getBeginLoc(),
16028 OrigCntVar->getEndLoc());
16029 if (!InitStmt.isUsable())
16030 return StmtError();
16031
16032 // For cond-expression:
16033 // \code
16034 // .permuted_{target}.iv < MakeNumIterations()
16035 // \endcode
16036 ExprResult CondExpr =
16037 SemaRef.BuildBinOp(CurScope, SourceHelper.Cond->getExprLoc(), BO_LT,
16038 MakePermutedRef(), MakeNumIterations());
16039 if (!CondExpr.isUsable())
16040 return StmtError();
16041
16042 // For incr-statement:
16043 // \code
16044 // ++.tile.iv
16045 // \endcode
16046 ExprResult IncrStmt = SemaRef.BuildUnaryOp(
16047 CurScope, SourceHelper.Inc->getExprLoc(), UO_PreInc, MakePermutedRef());
16048 if (!IncrStmt.isUsable())
16049 return StmtError();
16050
16051 SmallVector<Stmt *, 4> BodyParts(SourceHelper.Updates.begin(),
16052 SourceHelper.Updates.end());
16053 if (auto *SourceCXXFor = dyn_cast<CXXForRangeStmt>(SourceLoopStmt))
16054 BodyParts.push_back(SourceCXXFor->getLoopVarStmt());
16055 BodyParts.push_back(Inner);
16056 Inner = CompoundStmt::Create(Context, BodyParts, FPOptionsOverride(),
16057 Inner->getBeginLoc(), Inner->getEndLoc());
16058 Inner = new (Context) ForStmt(
16059 Context, InitStmt.get(), CondExpr.get(), nullptr, IncrStmt.get(), Inner,
16060 SourceHelper.Init->getBeginLoc(), SourceHelper.Init->getBeginLoc(),
16061 SourceHelper.Inc->getEndLoc());
16062 }
16063
16064 return OMPInterchangeDirective::Create(Context, StartLoc, EndLoc, Clauses,
16065 NumLoops, AStmt, Inner,
16066 buildPreInits(Context, PreInits));
16067}
16068
16070 Stmt *AStmt,
16071 SourceLocation StartLoc,
16072 SourceLocation EndLoc) {
16073
16074 ASTContext &Context = getASTContext();
16075 DeclContext *CurrContext = SemaRef.CurContext;
16076 Scope *CurScope = SemaRef.getCurScope();
16077 CaptureVars CopyTransformer(SemaRef);
16078
16079 // Ensure the structured block is not empty
16080 if (!AStmt)
16081 return StmtError();
16082
16083 // Defer transformation in dependent contexts
16084 // The NumLoopNests argument is set to a placeholder 1 (even though
16085 // using looprange fuse could yield up to 3 top level loop nests)
16086 // because a dependent context could prevent determining its true value
16087 if (CurrContext->isDependentContext())
16088 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16089 /* NumLoops */ 1, AStmt, nullptr, nullptr);
16090
16091 // Validate that the potential loop sequence is transformable for fusion
16092 // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops
16093 LoopSequenceAnalysis SeqAnalysis;
16094 if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, SeqAnalysis, Context))
16095 return StmtError();
16096
16097 // SeqAnalysis.LoopSeqSize exists mostly to handle dependent contexts,
16098 // otherwise it must be the same as SeqAnalysis.Loops.size().
16099 assert(SeqAnalysis.LoopSeqSize == SeqAnalysis.Loops.size() &&
16100 "Inconsistent size of the loop sequence and the number of loops "
16101 "found in the sequence");
16102
16103 // Handle clauses, which can be any of the following: [looprange, apply]
16104 const auto *LRC =
16105 OMPExecutableDirective::getSingleClause<OMPLoopRangeClause>(Clauses);
16106
16107 // The clause arguments are invalidated if any error arises
16108 // such as non-constant or non-positive arguments
16109 if (LRC && (!LRC->getFirst() || !LRC->getCount()))
16110 return StmtError();
16111
16112 // Delayed semantic check of LoopRange constraint
16113 // Evaluates the loop range arguments and returns the first and count values
16114 auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count,
16115 uint64_t &FirstVal,
16116 uint64_t &CountVal) {
16117 llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context);
16118 llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context);
16119 FirstVal = FirstInt.getZExtValue();
16120 CountVal = CountInt.getZExtValue();
16121 };
16122
16123 // OpenMP [6.0, Restrictions]
16124 // first + count - 1 must not evaluate to a value greater than the
16125 // loop sequence length of the associated canonical loop sequence.
16126 auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
16127 unsigned NumLoops) -> bool {
16128 return FirstVal + CountVal - 1 <= NumLoops;
16129 };
16130 uint64_t FirstVal = 1, CountVal = 0, LastVal = SeqAnalysis.LoopSeqSize;
16131
16132 // Validates the loop range after evaluating the semantic information
16133 // and ensures that the range is valid for the given loop sequence size.
16134 // Expressions are evaluated at compile time to obtain constant values.
16135 if (LRC) {
16136 EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
16137 CountVal);
16138 if (CountVal == 1)
16139 SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion)
16140 << getOpenMPDirectiveName(OMPD_fuse);
16141
16142 if (!ValidLoopRange(FirstVal, CountVal, SeqAnalysis.LoopSeqSize)) {
16143 SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange)
16144 << getOpenMPDirectiveName(OMPD_fuse) << FirstVal
16145 << (FirstVal + CountVal - 1) << SeqAnalysis.LoopSeqSize;
16146 return StmtError();
16147 }
16148
16149 LastVal = FirstVal + CountVal - 1;
16150 }
16151
16152 // Complete fusion generates a single canonical loop nest
16153 // However looprange clause may generate several loop nests
16154 unsigned NumGeneratedTopLevelLoops =
16155 LRC ? SeqAnalysis.LoopSeqSize - CountVal + 1 : 1;
16156
16157 // Emit a warning for redundant loop fusion when the sequence contains only
16158 // one loop.
16159 if (SeqAnalysis.LoopSeqSize == 1)
16160 SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion)
16161 << getOpenMPDirectiveName(OMPD_fuse);
16162
16163 // Select the type with the largest bit width among all induction variables
16164 QualType IVType =
16165 SeqAnalysis.Loops[FirstVal - 1].HelperExprs.IterationVarRef->getType();
16166 for (unsigned I : llvm::seq<unsigned>(FirstVal, LastVal)) {
16167 QualType CurrentIVType =
16168 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef->getType();
16169 if (Context.getTypeSize(CurrentIVType) > Context.getTypeSize(IVType)) {
16170 IVType = CurrentIVType;
16171 }
16172 }
16173 uint64_t IVBitWidth = Context.getIntWidth(IVType);
16174
16175 // Create pre-init declarations for all loops lower bounds, upper bounds,
16176 // strides and num-iterations for every top level loop in the fusion
16177 SmallVector<VarDecl *, 4> LBVarDecls;
16178 SmallVector<VarDecl *, 4> STVarDecls;
16179 SmallVector<VarDecl *, 4> NIVarDecls;
16180 SmallVector<VarDecl *, 4> UBVarDecls;
16181 SmallVector<VarDecl *, 4> IVVarDecls;
16182
16183 // Helper lambda to create variables for bounds, strides, and other
16184 // expressions. Generates both the variable declaration and the corresponding
16185 // initialization statement.
16186 auto CreateHelperVarAndStmt =
16187 [&, &SemaRef = SemaRef](Expr *ExprToCopy, const std::string &BaseName,
16188 unsigned I, bool NeedsNewVD = false) {
16189 Expr *TransformedExpr =
16190 AssertSuccess(CopyTransformer.TransformExpr(ExprToCopy));
16191 if (!TransformedExpr)
16192 return std::pair<VarDecl *, StmtResult>(nullptr, StmtError());
16193
16194 auto Name = (Twine(".omp.") + BaseName + std::to_string(I)).str();
16195
16196 VarDecl *VD;
16197 if (NeedsNewVD) {
16198 VD = buildVarDecl(SemaRef, SourceLocation(), IVType, Name);
16199 SemaRef.AddInitializerToDecl(VD, TransformedExpr, false);
16200 } else {
16201 // Create a unique variable name
16202 DeclRefExpr *DRE = cast<DeclRefExpr>(TransformedExpr);
16203 VD = cast<VarDecl>(DRE->getDecl());
16204 VD->setDeclName(&SemaRef.PP.getIdentifierTable().get(Name));
16205 }
16206 // Create the corresponding declaration statement
16207 StmtResult DeclStmt = new (Context) class DeclStmt(
16209 return std::make_pair(VD, DeclStmt);
16210 };
16211
16212 // PreInits hold a sequence of variable declarations that must be executed
16213 // before the fused loop begins. These include bounds, strides, and other
16214 // helper variables required for the transformation. Other loop transforms
16215 // also contain their own preinits
16216 SmallVector<Stmt *> PreInits;
16217
16218 // Update the general preinits using the preinits generated by loop sequence
16219 // generating loop transformations. These preinits differ slightly from
16220 // single-loop transformation preinits, as they can be detached from a
16221 // specific loop inside multiple generated loop nests. This happens
16222 // because certain helper variables, like '.omp.fuse.max', are introduced to
16223 // handle fused iteration spaces and may not be directly tied to a single
16224 // original loop. The preinit structure must ensure that hidden variables
16225 // like '.omp.fuse.max' are still properly handled.
16226 // Transformations that apply this concept: Loopranged Fuse, Split
16227 llvm::append_range(PreInits, SeqAnalysis.LoopSequencePreInits);
16228
16229 // Process each single loop to generate and collect declarations
16230 // and statements for all helper expressions related to
16231 // particular single loop nests
16232
16233 // Also In the case of the fused loops, we keep track of their original
16234 // inits by appending them to their preinits statement, and in the case of
16235 // transformations, also append their preinits (which contain the original
16236 // loop initialization statement or other statements)
16237
16238 // Firstly we need to set TransformIndex to match the begining of the
16239 // looprange section
16240 unsigned int TransformIndex = 0;
16241 for (unsigned I : llvm::seq<unsigned>(FirstVal - 1)) {
16242 if (SeqAnalysis.Loops[I].isLoopTransformation())
16243 ++TransformIndex;
16244 }
16245
16246 for (unsigned int I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16247 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16248 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16249 SeqAnalysis.Loops[I].TheForStmt,
16250 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16251 } else if (SeqAnalysis.Loops[I].isLoopTransformation()) {
16252 // For transformed loops, insert both pre-inits and original inits.
16253 // Order matters: pre-inits may define variables used in the original
16254 // inits such as upper bounds...
16255 SmallVector<Stmt *> &TransformPreInit =
16256 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16257 llvm::append_range(PreInits, TransformPreInit);
16258
16259 addLoopPreInits(Context, SeqAnalysis.Loops[I].HelperExprs,
16260 SeqAnalysis.Loops[I].TheForStmt,
16261 SeqAnalysis.Loops[I].OriginalInits, PreInits);
16262 }
16263 auto [UBVD, UBDStmt] =
16264 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.UB, "ub", J);
16265 auto [LBVD, LBDStmt] =
16266 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.LB, "lb", J);
16267 auto [STVD, STDStmt] =
16268 CreateHelperVarAndStmt(SeqAnalysis.Loops[I].HelperExprs.ST, "st", J);
16269 auto [NIVD, NIDStmt] = CreateHelperVarAndStmt(
16270 SeqAnalysis.Loops[I].HelperExprs.NumIterations, "ni", J, true);
16271 auto [IVVD, IVDStmt] = CreateHelperVarAndStmt(
16272 SeqAnalysis.Loops[I].HelperExprs.IterationVarRef, "iv", J);
16273
16274 assert(LBVD && STVD && NIVD && IVVD &&
16275 "OpenMP Fuse Helper variables creation failed");
16276
16277 UBVarDecls.push_back(UBVD);
16278 LBVarDecls.push_back(LBVD);
16279 STVarDecls.push_back(STVD);
16280 NIVarDecls.push_back(NIVD);
16281 IVVarDecls.push_back(IVVD);
16282
16283 PreInits.push_back(LBDStmt.get());
16284 PreInits.push_back(STDStmt.get());
16285 PreInits.push_back(NIDStmt.get());
16286 PreInits.push_back(IVDStmt.get());
16287 }
16288
16289 auto MakeVarDeclRef = [&SemaRef = this->SemaRef](VarDecl *VD) {
16290 return buildDeclRefExpr(SemaRef, VD, VD->getType(), VD->getLocation(),
16291 false);
16292 };
16293
16294 // Following up the creation of the final fused loop will be performed
16295 // which has the following shape (considering the selected loops):
16296 //
16297 // for (fuse.index = 0; fuse.index < max(ni0, ni1..., nik); ++fuse.index) {
16298 // if (fuse.index < ni0){
16299 // iv0 = lb0 + st0 * fuse.index;
16300 // original.index0 = iv0
16301 // body(0);
16302 // }
16303 // if (fuse.index < ni1){
16304 // iv1 = lb1 + st1 * fuse.index;
16305 // original.index1 = iv1
16306 // body(1);
16307 // }
16308 //
16309 // ...
16310 //
16311 // if (fuse.index < nik){
16312 // ivk = lbk + stk * fuse.index;
16313 // original.indexk = ivk
16314 // body(k); Expr *InitVal = IntegerLiteral::Create(Context,
16315 // llvm::APInt(IVWidth, 0),
16316 // }
16317
16318 // 1. Create the initialized fuse index
16319 StringRef IndexName = ".omp.fuse.index";
16320 Expr *InitVal = IntegerLiteral::Create(Context, llvm::APInt(IVBitWidth, 0),
16321 IVType, SourceLocation());
16322 VarDecl *IndexDecl =
16323 buildVarDecl(SemaRef, {}, IVType, IndexName, nullptr, nullptr);
16324 SemaRef.AddInitializerToDecl(IndexDecl, InitVal, false);
16325 StmtResult InitStmt = new (Context)
16327
16328 if (!InitStmt.isUsable())
16329 return StmtError();
16330
16331 auto MakeIVRef = [&SemaRef = this->SemaRef, IndexDecl, IVType,
16332 Loc = InitVal->getExprLoc()]() {
16333 return buildDeclRefExpr(SemaRef, IndexDecl, IVType, Loc, false);
16334 };
16335
16336 // 2. Iteratively compute the max number of logical iterations Max(NI_1, NI_2,
16337 // ..., NI_k)
16338 //
16339 // This loop accumulates the maximum value across multiple expressions,
16340 // ensuring each step constructs a unique AST node for correctness. By using
16341 // intermediate temporary variables and conditional operators, we maintain
16342 // distinct nodes and avoid duplicating subtrees, For instance, max(a,b,c):
16343 // omp.temp0 = max(a, b)
16344 // omp.temp1 = max(omp.temp0, c)
16345 // omp.fuse.max = max(omp.temp1, omp.temp0)
16346
16347 ExprResult MaxExpr;
16348 // I is the range of loops in the sequence that we fuse.
16349 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16350 DeclRefExpr *NIRef = MakeVarDeclRef(NIVarDecls[J]);
16351 QualType NITy = NIRef->getType();
16352
16353 if (MaxExpr.isUnset()) {
16354 // Initialize MaxExpr with the first NI expression
16355 MaxExpr = NIRef;
16356 } else {
16357 // Create a new acummulator variable t_i = MaxExpr
16358 std::string TempName = (Twine(".omp.temp.") + Twine(J)).str();
16359 VarDecl *TempDecl =
16360 buildVarDecl(SemaRef, {}, NITy, TempName, nullptr, nullptr);
16361 TempDecl->setInit(MaxExpr.get());
16362 DeclRefExpr *TempRef =
16363 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16364 DeclRefExpr *TempRef2 =
16365 buildDeclRefExpr(SemaRef, TempDecl, NITy, SourceLocation(), false);
16366 // Add a DeclStmt to PreInits to ensure the variable is declared.
16367 StmtResult TempStmt = new (Context)
16369
16370 if (!TempStmt.isUsable())
16371 return StmtError();
16372 PreInits.push_back(TempStmt.get());
16373
16374 // Build MaxExpr <-(MaxExpr > NIRef ? MaxExpr : NIRef)
16376 SemaRef.BuildBinOp(nullptr, SourceLocation(), BO_GT, TempRef, NIRef);
16377 // Handle any errors in Comparison creation
16378 if (!Comparison.isUsable())
16379 return StmtError();
16380
16381 DeclRefExpr *NIRef2 = MakeVarDeclRef(NIVarDecls[J]);
16382 // Update MaxExpr using a conditional expression to hold the max value
16383 MaxExpr = new (Context) ConditionalOperator(
16384 Comparison.get(), SourceLocation(), TempRef2, SourceLocation(),
16385 NIRef2->getExprStmt(), NITy, VK_LValue, OK_Ordinary);
16386
16387 if (!MaxExpr.isUsable())
16388 return StmtError();
16389 }
16390 }
16391 if (!MaxExpr.isUsable())
16392 return StmtError();
16393
16394 // 3. Declare the max variable
16395 const std::string MaxName = Twine(".omp.fuse.max").str();
16396 VarDecl *MaxDecl =
16397 buildVarDecl(SemaRef, {}, IVType, MaxName, nullptr, nullptr);
16398 MaxDecl->setInit(MaxExpr.get());
16399 DeclRefExpr *MaxRef = buildDeclRefExpr(SemaRef, MaxDecl, IVType, {}, false);
16400 StmtResult MaxStmt = new (Context)
16402
16403 if (MaxStmt.isInvalid())
16404 return StmtError();
16405 PreInits.push_back(MaxStmt.get());
16406
16407 // 4. Create condition Expr: index < n_max
16408 ExprResult CondExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT,
16409 MakeIVRef(), MaxRef);
16410 if (!CondExpr.isUsable())
16411 return StmtError();
16412
16413 // 5. Increment Expr: ++index
16414 ExprResult IncrExpr =
16415 SemaRef.BuildUnaryOp(CurScope, SourceLocation(), UO_PreInc, MakeIVRef());
16416 if (!IncrExpr.isUsable())
16417 return StmtError();
16418
16419 // 6. Build the Fused Loop Body
16420 // The final fused loop iterates over the maximum logical range. Inside the
16421 // loop, each original loop's index is calculated dynamically, and its body
16422 // is executed conditionally.
16423 //
16424 // Each sub-loop's body is guarded by a conditional statement to ensure
16425 // it executes only within its logical iteration range:
16426 //
16427 // if (fuse.index < ni_k){
16428 // iv_k = lb_k + st_k * fuse.index;
16429 // original.index = iv_k
16430 // body(k);
16431 // }
16432
16433 CompoundStmt *FusedBody = nullptr;
16434 SmallVector<Stmt *, 4> FusedBodyStmts;
16435 for (unsigned I = FirstVal - 1, J = 0; I < LastVal; ++I, ++J) {
16436 // Assingment of the original sub-loop index to compute the logical index
16437 // IV_k = LB_k + omp.fuse.index * ST_k
16438 ExprResult IdxExpr =
16439 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Mul,
16440 MakeVarDeclRef(STVarDecls[J]), MakeIVRef());
16441 if (!IdxExpr.isUsable())
16442 return StmtError();
16443 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Add,
16444 MakeVarDeclRef(LBVarDecls[J]), IdxExpr.get());
16445
16446 if (!IdxExpr.isUsable())
16447 return StmtError();
16448 IdxExpr = SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_Assign,
16449 MakeVarDeclRef(IVVarDecls[J]), IdxExpr.get());
16450 if (!IdxExpr.isUsable())
16451 return StmtError();
16452
16453 // Update the original i_k = IV_k
16454 SmallVector<Stmt *, 4> BodyStmts;
16455 BodyStmts.push_back(IdxExpr.get());
16456 llvm::append_range(BodyStmts, SeqAnalysis.Loops[I].HelperExprs.Updates);
16457
16458 // If the loop is a CXXForRangeStmt then the iterator variable is needed
16459 if (auto *SourceCXXFor =
16460 dyn_cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt))
16461 BodyStmts.push_back(SourceCXXFor->getLoopVarStmt());
16462
16463 Stmt *Body =
16464 (isa<ForStmt>(SeqAnalysis.Loops[I].TheForStmt))
16465 ? cast<ForStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody()
16466 : cast<CXXForRangeStmt>(SeqAnalysis.Loops[I].TheForStmt)->getBody();
16467 BodyStmts.push_back(Body);
16468
16469 CompoundStmt *CombinedBody =
16470 CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
16473 SemaRef.BuildBinOp(CurScope, SourceLocation(), BO_LT, MakeIVRef(),
16474 MakeVarDeclRef(NIVarDecls[J]));
16475
16476 if (!Condition.isUsable())
16477 return StmtError();
16478
16479 IfStmt *IfStatement = IfStmt::Create(
16480 Context, SourceLocation(), IfStatementKind::Ordinary, nullptr, nullptr,
16481 Condition.get(), SourceLocation(), SourceLocation(), CombinedBody,
16482 SourceLocation(), nullptr);
16483
16484 FusedBodyStmts.push_back(IfStatement);
16485 }
16486 FusedBody = CompoundStmt::Create(Context, FusedBodyStmts, FPOptionsOverride(),
16488
16489 // 7. Construct the final fused loop
16490 ForStmt *FusedForStmt = new (Context)
16491 ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr, IncrExpr.get(),
16492 FusedBody, InitStmt.get()->getBeginLoc(), SourceLocation(),
16493 IncrExpr.get()->getEndLoc());
16494
16495 // In the case of looprange, the result of fuse won't simply
16496 // be a single loop (ForStmt), but rather a loop sequence
16497 // (CompoundStmt) of 3 parts: the pre-fusion loops, the fused loop
16498 // and the post-fusion loops, preserving its original order.
16499 //
16500 // Note: If looprange clause produces a single fused loop nest then
16501 // this compound statement wrapper is unnecessary (Therefore this
16502 // treatment is skipped)
16503
16504 Stmt *FusionStmt = FusedForStmt;
16505 if (LRC && CountVal != SeqAnalysis.LoopSeqSize) {
16506 SmallVector<Stmt *, 4> FinalLoops;
16507
16508 // Reset the transform index
16509 TransformIndex = 0;
16510
16511 // Collect all non-fused loops before and after the fused region.
16512 // Pre-fusion and post-fusion loops are inserted in order exploiting their
16513 // symmetry, along with their corresponding transformation pre-inits if
16514 // needed. The fused loop is added between the two regions.
16515 for (unsigned I : llvm::seq<unsigned>(SeqAnalysis.LoopSeqSize)) {
16516 if (I >= FirstVal - 1 && I < FirstVal + CountVal - 1) {
16517 // Update the Transformation counter to skip already treated
16518 // loop transformations
16519 if (!SeqAnalysis.Loops[I].isLoopTransformation())
16520 ++TransformIndex;
16521 continue;
16522 }
16523
16524 // No need to handle:
16525 // Regular loops: they are kept intact as-is.
16526 // Loop-sequence-generating transformations: already handled earlier.
16527 // Only TransformSingleLoop requires inserting pre-inits here
16528 if (SeqAnalysis.Loops[I].isRegularLoop()) {
16529 const auto &TransformPreInit =
16530 SeqAnalysis.Loops[TransformIndex++].TransformsPreInits;
16531 if (!TransformPreInit.empty())
16532 llvm::append_range(PreInits, TransformPreInit);
16533 }
16534
16535 FinalLoops.push_back(SeqAnalysis.Loops[I].TheForStmt);
16536 }
16537
16538 FinalLoops.insert(FinalLoops.begin() + (FirstVal - 1), FusedForStmt);
16539 FusionStmt = CompoundStmt::Create(Context, FinalLoops, FPOptionsOverride(),
16541 }
16542 return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses,
16543 NumGeneratedTopLevelLoops, AStmt, FusionStmt,
16544 buildPreInits(Context, PreInits));
16545}
16546
16548 Expr *Expr,
16549 SourceLocation StartLoc,
16550 SourceLocation LParenLoc,
16551 SourceLocation EndLoc) {
16552 OMPClause *Res = nullptr;
16553 switch (Kind) {
16554 case OMPC_final:
16555 Res = ActOnOpenMPFinalClause(Expr, StartLoc, LParenLoc, EndLoc);
16556 break;
16557 case OMPC_safelen:
16558 Res = ActOnOpenMPSafelenClause(Expr, StartLoc, LParenLoc, EndLoc);
16559 break;
16560 case OMPC_simdlen:
16561 Res = ActOnOpenMPSimdlenClause(Expr, StartLoc, LParenLoc, EndLoc);
16562 break;
16563 case OMPC_allocator:
16564 Res = ActOnOpenMPAllocatorClause(Expr, StartLoc, LParenLoc, EndLoc);
16565 break;
16566 case OMPC_collapse:
16567 Res = ActOnOpenMPCollapseClause(Expr, StartLoc, LParenLoc, EndLoc);
16568 break;
16569 case OMPC_ordered:
16570 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc, LParenLoc, Expr);
16571 break;
16572 case OMPC_nowait:
16573 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc, LParenLoc, Expr);
16574 break;
16575 case OMPC_priority:
16576 Res = ActOnOpenMPPriorityClause(Expr, StartLoc, LParenLoc, EndLoc);
16577 break;
16578 case OMPC_hint:
16579 Res = ActOnOpenMPHintClause(Expr, StartLoc, LParenLoc, EndLoc);
16580 break;
16581 case OMPC_depobj:
16582 Res = ActOnOpenMPDepobjClause(Expr, StartLoc, LParenLoc, EndLoc);
16583 break;
16584 case OMPC_detach:
16585 Res = ActOnOpenMPDetachClause(Expr, StartLoc, LParenLoc, EndLoc);
16586 break;
16587 case OMPC_novariants:
16588 Res = ActOnOpenMPNovariantsClause(Expr, StartLoc, LParenLoc, EndLoc);
16589 break;
16590 case OMPC_nocontext:
16591 Res = ActOnOpenMPNocontextClause(Expr, StartLoc, LParenLoc, EndLoc);
16592 break;
16593 case OMPC_filter:
16594 Res = ActOnOpenMPFilterClause(Expr, StartLoc, LParenLoc, EndLoc);
16595 break;
16596 case OMPC_partial:
16597 Res = ActOnOpenMPPartialClause(Expr, StartLoc, LParenLoc, EndLoc);
16598 break;
16599 case OMPC_message:
16600 Res = ActOnOpenMPMessageClause(Expr, StartLoc, LParenLoc, EndLoc);
16601 break;
16602 case OMPC_align:
16603 Res = ActOnOpenMPAlignClause(Expr, StartLoc, LParenLoc, EndLoc);
16604 break;
16605 case OMPC_ompx_dyn_cgroup_mem:
16606 Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
16607 break;
16608 case OMPC_holds:
16609 Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
16610 break;
16611 case OMPC_transparent:
16612 Res = ActOnOpenMPTransparentClause(Expr, StartLoc, LParenLoc, EndLoc);
16613 break;
16614 case OMPC_dyn_groupprivate:
16615 case OMPC_grainsize:
16616 case OMPC_num_tasks:
16617 case OMPC_num_threads:
16618 case OMPC_device:
16619 case OMPC_if:
16620 case OMPC_default:
16621 case OMPC_proc_bind:
16622 case OMPC_schedule:
16623 case OMPC_private:
16624 case OMPC_firstprivate:
16625 case OMPC_lastprivate:
16626 case OMPC_shared:
16627 case OMPC_reduction:
16628 case OMPC_task_reduction:
16629 case OMPC_in_reduction:
16630 case OMPC_linear:
16631 case OMPC_aligned:
16632 case OMPC_copyin:
16633 case OMPC_copyprivate:
16634 case OMPC_untied:
16635 case OMPC_mergeable:
16636 case OMPC_threadprivate:
16637 case OMPC_groupprivate:
16638 case OMPC_sizes:
16639 case OMPC_allocate:
16640 case OMPC_flush:
16641 case OMPC_read:
16642 case OMPC_write:
16643 case OMPC_update:
16644 case OMPC_capture:
16645 case OMPC_compare:
16646 case OMPC_seq_cst:
16647 case OMPC_acq_rel:
16648 case OMPC_acquire:
16649 case OMPC_release:
16650 case OMPC_relaxed:
16651 case OMPC_depend:
16652 case OMPC_threads:
16653 case OMPC_simd:
16654 case OMPC_map:
16655 case OMPC_nogroup:
16656 case OMPC_dist_schedule:
16657 case OMPC_defaultmap:
16658 case OMPC_unknown:
16659 case OMPC_uniform:
16660 case OMPC_to:
16661 case OMPC_from:
16662 case OMPC_use_device_ptr:
16663 case OMPC_use_device_addr:
16664 case OMPC_is_device_ptr:
16665 case OMPC_unified_address:
16666 case OMPC_unified_shared_memory:
16667 case OMPC_reverse_offload:
16668 case OMPC_dynamic_allocators:
16669 case OMPC_atomic_default_mem_order:
16670 case OMPC_self_maps:
16671 case OMPC_device_type:
16672 case OMPC_match:
16673 case OMPC_nontemporal:
16674 case OMPC_order:
16675 case OMPC_at:
16676 case OMPC_severity:
16677 case OMPC_destroy:
16678 case OMPC_inclusive:
16679 case OMPC_exclusive:
16680 case OMPC_uses_allocators:
16681 case OMPC_affinity:
16682 case OMPC_when:
16683 case OMPC_bind:
16684 case OMPC_num_teams:
16685 case OMPC_thread_limit:
16686 default:
16687 llvm_unreachable("Clause is not allowed.");
16688 }
16689 return Res;
16690}
16691
16692// An OpenMP directive such as 'target parallel' has two captured regions:
16693// for the 'target' and 'parallel' respectively. This function returns
16694// the region in which to capture expressions associated with a clause.
16695// A return value of OMPD_unknown signifies that the expression should not
16696// be captured.
16698 OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion,
16699 OpenMPDirectiveKind NameModifier = OMPD_unknown) {
16700 assert(isAllowedClauseForDirective(DKind, CKind, OpenMPVersion) &&
16701 "Invalid directive with CKind-clause");
16702
16703 // Invalid modifier will be diagnosed separately, just return OMPD_unknown.
16704 if (NameModifier != OMPD_unknown &&
16705 !isAllowedClauseForDirective(NameModifier, CKind, OpenMPVersion))
16706 return OMPD_unknown;
16707
16708 ArrayRef<OpenMPDirectiveKind> Leafs = getLeafConstructsOrSelf(DKind);
16709
16710 // [5.2:341:24-30]
16711 // If the clauses have expressions on them, such as for various clauses where
16712 // the argument of the clause is an expression, or lower-bound, length, or
16713 // stride expressions inside array sections (or subscript and stride
16714 // expressions in subscript-triplet for Fortran), or linear-step or alignment
16715 // expressions, the expressions are evaluated immediately before the construct
16716 // to which the clause has been split or duplicated per the above rules
16717 // (therefore inside of the outer leaf constructs). However, the expressions
16718 // inside the num_teams and thread_limit clauses are always evaluated before
16719 // the outermost leaf construct.
16720
16721 // Process special cases first.
16722 switch (CKind) {
16723 case OMPC_if:
16724 switch (DKind) {
16725 case OMPD_teams_loop:
16726 case OMPD_target_teams_loop:
16727 // For [target] teams loop, assume capture region is 'teams' so it's
16728 // available for codegen later to use if/when necessary.
16729 return OMPD_teams;
16730 case OMPD_target_update:
16731 case OMPD_target_enter_data:
16732 case OMPD_target_exit_data:
16733 return OMPD_task;
16734 default:
16735 break;
16736 }
16737 break;
16738 case OMPC_num_teams:
16739 case OMPC_thread_limit:
16740 case OMPC_ompx_dyn_cgroup_mem:
16741 case OMPC_dyn_groupprivate:
16742 // TODO: This may need to consider teams too.
16743 if (Leafs[0] == OMPD_target)
16744 return OMPD_target;
16745 break;
16746 case OMPC_device:
16747 if (Leafs[0] == OMPD_target ||
16748 llvm::is_contained({OMPD_dispatch, OMPD_target_update,
16749 OMPD_target_enter_data, OMPD_target_exit_data},
16750 DKind))
16751 return OMPD_task;
16752 break;
16753 case OMPC_novariants:
16754 case OMPC_nocontext:
16755 if (DKind == OMPD_dispatch)
16756 return OMPD_task;
16757 break;
16758 case OMPC_when:
16759 if (DKind == OMPD_metadirective)
16760 return OMPD_metadirective;
16761 break;
16762 case OMPC_filter:
16763 return OMPD_unknown;
16764 default:
16765 break;
16766 }
16767
16768 // If none of the special cases above applied, and DKind is a capturing
16769 // directive, find the innermost enclosing leaf construct that allows the
16770 // clause, and returns the corresponding capture region.
16771
16772 auto GetEnclosingRegion = [&](int EndIdx, OpenMPClauseKind Clause) {
16773 // Find the index in "Leafs" of the last leaf that allows the given
16774 // clause. The search will only include indexes [0, EndIdx).
16775 // EndIdx may be set to the index of the NameModifier, if present.
16776 int InnermostIdx = [&]() {
16777 for (int I = EndIdx - 1; I >= 0; --I) {
16778 if (isAllowedClauseForDirective(Leafs[I], Clause, OpenMPVersion))
16779 return I;
16780 }
16781 return -1;
16782 }();
16783
16784 // Find the nearest enclosing capture region.
16786 for (int I = InnermostIdx - 1; I >= 0; --I) {
16787 if (!isOpenMPCapturingDirective(Leafs[I]))
16788 continue;
16789 Regions.clear();
16790 getOpenMPCaptureRegions(Regions, Leafs[I]);
16791 if (Regions[0] != OMPD_unknown)
16792 return Regions.back();
16793 }
16794 return OMPD_unknown;
16795 };
16796
16797 if (isOpenMPCapturingDirective(DKind)) {
16798 auto GetLeafIndex = [&](OpenMPDirectiveKind Dir) {
16799 for (int I = 0, E = Leafs.size(); I != E; ++I) {
16800 if (Leafs[I] == Dir)
16801 return I + 1;
16802 }
16803 return 0;
16804 };
16805
16806 int End = NameModifier == OMPD_unknown ? Leafs.size()
16807 : GetLeafIndex(NameModifier);
16808 return GetEnclosingRegion(End, CKind);
16809 }
16810
16811 return OMPD_unknown;
16812}
16813
16815 OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc,
16816 SourceLocation LParenLoc, SourceLocation NameModifierLoc,
16817 SourceLocation ColonLoc, SourceLocation EndLoc) {
16818 Expr *ValExpr = Condition;
16819 Stmt *HelperValStmt = nullptr;
16820 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16821 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16822 !Condition->isInstantiationDependent() &&
16823 !Condition->containsUnexpandedParameterPack()) {
16824 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16825 if (Val.isInvalid())
16826 return nullptr;
16827
16828 ValExpr = Val.get();
16829
16830 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16831 CaptureRegion = getOpenMPCaptureRegionForClause(
16832 DKind, OMPC_if, getLangOpts().OpenMP, NameModifier);
16833 if (CaptureRegion != OMPD_unknown &&
16834 !SemaRef.CurContext->isDependentContext()) {
16835 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16836 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16837 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16838 HelperValStmt = buildPreInits(getASTContext(), Captures);
16839 }
16840 }
16841
16842 return new (getASTContext())
16843 OMPIfClause(NameModifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
16844 LParenLoc, NameModifierLoc, ColonLoc, EndLoc);
16845}
16846
16848 SourceLocation StartLoc,
16849 SourceLocation LParenLoc,
16850 SourceLocation EndLoc) {
16851 Expr *ValExpr = Condition;
16852 Stmt *HelperValStmt = nullptr;
16853 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
16854 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
16855 !Condition->isInstantiationDependent() &&
16856 !Condition->containsUnexpandedParameterPack()) {
16857 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
16858 if (Val.isInvalid())
16859 return nullptr;
16860
16861 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
16862
16863 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
16864 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_final,
16865 getLangOpts().OpenMP);
16866 if (CaptureRegion != OMPD_unknown &&
16867 !SemaRef.CurContext->isDependentContext()) {
16868 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16869 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16870 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16871 HelperValStmt = buildPreInits(getASTContext(), Captures);
16872 }
16873 }
16874
16875 return new (getASTContext()) OMPFinalClause(
16876 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
16877}
16878
16881 Expr *Op) {
16882 if (!Op)
16883 return ExprError();
16884
16885 class IntConvertDiagnoser : public Sema::ICEConvertDiagnoser {
16886 public:
16887 IntConvertDiagnoser()
16888 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, false, true) {}
16889 SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc,
16890 QualType T) override {
16891 return S.Diag(Loc, diag::err_omp_not_integral) << T;
16892 }
16893 SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc,
16894 QualType T) override {
16895 return S.Diag(Loc, diag::err_omp_incomplete_type) << T;
16896 }
16897 SemaDiagnosticBuilder diagnoseExplicitConv(Sema &S, SourceLocation Loc,
16898 QualType T,
16899 QualType ConvTy) override {
16900 return S.Diag(Loc, diag::err_omp_explicit_conversion) << T << ConvTy;
16901 }
16902 SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv,
16903 QualType ConvTy) override {
16904 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16905 << ConvTy->isEnumeralType() << ConvTy;
16906 }
16907 SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc,
16908 QualType T) override {
16909 return S.Diag(Loc, diag::err_omp_ambiguous_conversion) << T;
16910 }
16911 SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv,
16912 QualType ConvTy) override {
16913 return S.Diag(Conv->getLocation(), diag::note_omp_conversion_here)
16914 << ConvTy->isEnumeralType() << ConvTy;
16915 }
16916 SemaDiagnosticBuilder diagnoseConversion(Sema &, SourceLocation, QualType,
16917 QualType) override {
16918 llvm_unreachable("conversion functions are permitted");
16919 }
16920 } ConvertDiagnoser;
16921 return SemaRef.PerformContextualImplicitConversion(Loc, Op, ConvertDiagnoser);
16922}
16923
16924static bool
16926 bool StrictlyPositive, bool BuildCapture = false,
16927 OpenMPDirectiveKind DKind = OMPD_unknown,
16928 OpenMPDirectiveKind *CaptureRegion = nullptr,
16929 Stmt **HelperValStmt = nullptr) {
16930 if (!ValExpr->isTypeDependent() && !ValExpr->isValueDependent() &&
16931 !ValExpr->isInstantiationDependent()) {
16932 SourceLocation Loc = ValExpr->getExprLoc();
16934 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(Loc, ValExpr);
16935 if (Value.isInvalid())
16936 return false;
16937
16938 ValExpr = Value.get();
16939 // The expression must evaluate to a non-negative integer value.
16940 if (std::optional<llvm::APSInt> Result =
16941 ValExpr->getIntegerConstantExpr(SemaRef.Context)) {
16942 if (Result->isSigned() &&
16943 !((!StrictlyPositive && Result->isNonNegative()) ||
16944 (StrictlyPositive && Result->isStrictlyPositive()))) {
16945 SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause)
16946 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
16947 << ValExpr->getSourceRange();
16948 return false;
16949 }
16950 }
16951 if (!BuildCapture)
16952 return true;
16953 *CaptureRegion =
16954 getOpenMPCaptureRegionForClause(DKind, CKind, SemaRef.LangOpts.OpenMP);
16955 if (*CaptureRegion != OMPD_unknown &&
16956 !SemaRef.CurContext->isDependentContext()) {
16957 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
16958 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
16959 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
16960 *HelperValStmt = buildPreInits(SemaRef.Context, Captures);
16961 }
16962 }
16963 return true;
16964}
16965
16966static std::string getListOfPossibleValues(OpenMPClauseKind K, unsigned First,
16967 unsigned Last,
16968 ArrayRef<unsigned> Exclude = {}) {
16969 SmallString<256> Buffer;
16970 llvm::raw_svector_ostream Out(Buffer);
16971 unsigned Skipped = Exclude.size();
16972 for (unsigned I = First; I < Last; ++I) {
16973 if (llvm::is_contained(Exclude, I)) {
16974 --Skipped;
16975 continue;
16976 }
16977 Out << "'" << getOpenMPSimpleClauseTypeName(K, I) << "'";
16978 if (I + Skipped + 2 == Last)
16979 Out << " or ";
16980 else if (I + Skipped + 1 != Last)
16981 Out << ", ";
16982 }
16983 return std::string(Out.str());
16984}
16985
16987 OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads,
16988 SourceLocation StartLoc, SourceLocation LParenLoc,
16989 SourceLocation ModifierLoc, SourceLocation EndLoc) {
16990 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 60) &&
16991 "Unexpected num_threads modifier in OpenMP < 60.");
16992
16993 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTHREADS_unknown) {
16994 std::string Values = getListOfPossibleValues(OMPC_num_threads, /*First=*/0,
16996 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
16997 << Values << getOpenMPClauseNameForDiag(OMPC_num_threads);
16998 return nullptr;
16999 }
17000
17001 Expr *ValExpr = NumThreads;
17002 Stmt *HelperValStmt = nullptr;
17003
17004 // OpenMP [2.5, Restrictions]
17005 // The num_threads expression must evaluate to a positive integer value.
17006 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_threads,
17007 /*StrictlyPositive=*/true))
17008 return nullptr;
17009
17010 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17012 DKind, OMPC_num_threads, getLangOpts().OpenMP);
17013 if (CaptureRegion != OMPD_unknown &&
17014 !SemaRef.CurContext->isDependentContext()) {
17015 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
17016 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17017 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
17018 HelperValStmt = buildPreInits(getASTContext(), Captures);
17019 }
17020
17021 return new (getASTContext())
17022 OMPNumThreadsClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
17023 StartLoc, LParenLoc, ModifierLoc, EndLoc);
17024}
17025
17027 Expr *E, OpenMPClauseKind CKind, bool StrictlyPositive,
17028 bool SuppressExprDiags) {
17029 if (!E)
17030 return ExprError();
17031 if (E->isValueDependent() || E->isTypeDependent() ||
17033 return E;
17034
17035 llvm::APSInt Result;
17036 ExprResult ICE;
17037 if (SuppressExprDiags) {
17038 // Use a custom diagnoser that suppresses 'note' diagnostics about the
17039 // expression.
17040 struct SuppressedDiagnoser : public Sema::VerifyICEDiagnoser {
17041 SuppressedDiagnoser() : VerifyICEDiagnoser(/*Suppress=*/true) {}
17043 diagnoseNotICE(Sema &S, SourceLocation Loc) override {
17044 llvm_unreachable("Diagnostic suppressed");
17045 }
17046 } Diagnoser;
17047 ICE = SemaRef.VerifyIntegerConstantExpression(E, &Result, Diagnoser,
17049 } else {
17050 ICE =
17051 SemaRef.VerifyIntegerConstantExpression(E, &Result,
17052 /*FIXME*/ AllowFoldKind::Allow);
17053 }
17054 if (ICE.isInvalid())
17055 return ExprError();
17056
17057 if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
17058 (!StrictlyPositive && !Result.isNonNegative())) {
17059 Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
17060 << getOpenMPClauseNameForDiag(CKind) << (StrictlyPositive ? 1 : 0)
17061 << E->getSourceRange();
17062 return ExprError();
17063 }
17064 if ((CKind == OMPC_aligned || CKind == OMPC_align ||
17065 CKind == OMPC_allocate) &&
17066 !Result.isPowerOf2()) {
17067 Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
17068 << E->getSourceRange();
17069 return ExprError();
17070 }
17071
17072 if (!Result.isRepresentableByInt64()) {
17073 Diag(E->getExprLoc(), diag::err_omp_large_expression_in_clause)
17075 return ExprError();
17076 }
17077
17078 if (CKind == OMPC_collapse && DSAStack->getAssociatedLoops() == 1)
17079 DSAStack->setAssociatedLoops(Result.getExtValue());
17080 else if (CKind == OMPC_ordered)
17081 DSAStack->setAssociatedLoops(Result.getExtValue());
17082 return ICE;
17083}
17084
17085void SemaOpenMP::setOpenMPDeviceNum(int Num) { DeviceNum = Num; }
17086
17087void SemaOpenMP::setOpenMPDeviceNumID(StringRef ID) { DeviceNumID = ID; }
17088
17089int SemaOpenMP::getOpenMPDeviceNum() const { return DeviceNum; }
17090
17092 llvm::APSInt Result;
17093 Expr::EvalResult EvalResult;
17094 // Evaluate the expression to an integer value
17095 if (!DeviceNumExpr->isValueDependent() &&
17096 DeviceNumExpr->EvaluateAsInt(EvalResult, SemaRef.Context)) {
17097 // The device expression must evaluate to a non-negative integer value.
17098 Result = EvalResult.Val.getInt();
17099 if (Result.isNonNegative()) {
17100 setOpenMPDeviceNum(Result.getZExtValue());
17101 } else {
17102 Diag(DeviceNumExpr->getExprLoc(),
17103 diag::err_omp_negative_expression_in_clause)
17104 << "device_num" << 0 << DeviceNumExpr->getSourceRange();
17105 }
17106 } else if (auto *DeclRef = dyn_cast<DeclRefExpr>(DeviceNumExpr)) {
17107 // Check if the expression is an identifier
17108 IdentifierInfo *IdInfo = DeclRef->getDecl()->getIdentifier();
17109 if (IdInfo) {
17110 setOpenMPDeviceNumID(IdInfo->getName());
17111 }
17112 } else {
17113 Diag(DeviceNumExpr->getExprLoc(), diag::err_expected_expression);
17114 }
17115}
17116
17118 SourceLocation StartLoc,
17119 SourceLocation LParenLoc,
17120 SourceLocation EndLoc) {
17121 // OpenMP [2.8.1, simd construct, Description]
17122 // The parameter of the safelen clause must be a constant
17123 // positive integer expression.
17124 ExprResult Safelen = VerifyPositiveIntegerConstantInClause(Len, OMPC_safelen);
17125 if (Safelen.isInvalid())
17126 return nullptr;
17127 return new (getASTContext())
17128 OMPSafelenClause(Safelen.get(), StartLoc, LParenLoc, EndLoc);
17129}
17130
17132 SourceLocation StartLoc,
17133 SourceLocation LParenLoc,
17134 SourceLocation EndLoc) {
17135 // OpenMP [2.8.1, simd construct, Description]
17136 // The parameter of the simdlen clause must be a constant
17137 // positive integer expression.
17138 ExprResult Simdlen = VerifyPositiveIntegerConstantInClause(Len, OMPC_simdlen);
17139 if (Simdlen.isInvalid())
17140 return nullptr;
17141 return new (getASTContext())
17142 OMPSimdlenClause(Simdlen.get(), StartLoc, LParenLoc, EndLoc);
17143}
17144
17145/// Tries to find omp_allocator_handle_t type.
17147 DSAStackTy *Stack) {
17148 if (!Stack->getOMPAllocatorHandleT().isNull())
17149 return true;
17150
17151 // Set the allocator handle type.
17152 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_allocator_handle_t");
17153 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
17154 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
17155 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17156 << "omp_allocator_handle_t";
17157 return false;
17158 }
17159 QualType AllocatorHandleEnumTy = PT.get();
17160 AllocatorHandleEnumTy.addConst();
17161 Stack->setOMPAllocatorHandleT(AllocatorHandleEnumTy);
17162
17163 // Fill the predefined allocator map.
17164 bool ErrorFound = false;
17165 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
17166 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
17167 StringRef Allocator =
17168 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
17169 DeclarationName AllocatorName = &S.getASTContext().Idents.get(Allocator);
17170 auto *VD = dyn_cast_or_null<ValueDecl>(
17171 S.LookupSingleName(S.TUScope, AllocatorName, Loc, Sema::LookupAnyName));
17172 if (!VD) {
17173 ErrorFound = true;
17174 break;
17175 }
17176 QualType AllocatorType =
17178 ExprResult Res = S.BuildDeclRefExpr(VD, AllocatorType, VK_LValue, Loc);
17179 if (!Res.isUsable()) {
17180 ErrorFound = true;
17181 break;
17182 }
17183 Res = S.PerformImplicitConversion(Res.get(), AllocatorHandleEnumTy,
17185 /*AllowExplicit=*/true);
17186 if (!Res.isUsable()) {
17187 ErrorFound = true;
17188 break;
17189 }
17190 Stack->setAllocator(AllocatorKind, Res.get());
17191 }
17192 if (ErrorFound) {
17193 S.Diag(Loc, diag::err_omp_implied_type_not_found)
17194 << "omp_allocator_handle_t";
17195 return false;
17196 }
17197
17198 return true;
17199}
17200
17202 SourceLocation StartLoc,
17203 SourceLocation LParenLoc,
17204 SourceLocation EndLoc) {
17205 // OpenMP [2.11.3, allocate Directive, Description]
17206 // allocator is an expression of omp_allocator_handle_t type.
17208 return nullptr;
17209
17210 ExprResult Allocator = SemaRef.DefaultLvalueConversion(A);
17211 if (Allocator.isInvalid())
17212 return nullptr;
17213 Allocator = SemaRef.PerformImplicitConversion(
17214 Allocator.get(), DSAStack->getOMPAllocatorHandleT(),
17216 /*AllowExplicit=*/true);
17217 if (Allocator.isInvalid())
17218 return nullptr;
17219 return new (getASTContext())
17220 OMPAllocatorClause(Allocator.get(), StartLoc, LParenLoc, EndLoc);
17221}
17222
17224 SourceLocation StartLoc,
17225 SourceLocation LParenLoc,
17226 SourceLocation EndLoc) {
17227 // OpenMP [2.7.1, loop construct, Description]
17228 // OpenMP [2.8.1, simd construct, Description]
17229 // OpenMP [2.9.6, distribute construct, Description]
17230 // The parameter of the collapse clause must be a constant
17231 // positive integer expression.
17232 ExprResult NumForLoopsResult =
17233 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_collapse);
17234 if (NumForLoopsResult.isInvalid())
17235 return nullptr;
17236 return new (getASTContext())
17237 OMPCollapseClause(NumForLoopsResult.get(), StartLoc, LParenLoc, EndLoc);
17238}
17239
17241 SourceLocation EndLoc,
17242 SourceLocation LParenLoc,
17243 Expr *NumForLoops) {
17244 // OpenMP [2.7.1, loop construct, Description]
17245 // OpenMP [2.8.1, simd construct, Description]
17246 // OpenMP [2.9.6, distribute construct, Description]
17247 // The parameter of the ordered clause must be a constant
17248 // positive integer expression if any.
17249 if (NumForLoops && LParenLoc.isValid()) {
17250 ExprResult NumForLoopsResult =
17251 VerifyPositiveIntegerConstantInClause(NumForLoops, OMPC_ordered);
17252 if (NumForLoopsResult.isInvalid())
17253 return nullptr;
17254 NumForLoops = NumForLoopsResult.get();
17255 } else {
17256 NumForLoops = nullptr;
17257 }
17258 auto *Clause =
17259 OMPOrderedClause::Create(getASTContext(), NumForLoops,
17260 NumForLoops ? DSAStack->getAssociatedLoops() : 0,
17261 StartLoc, LParenLoc, EndLoc);
17262 DSAStack->setOrderedRegion(/*IsOrdered=*/true, NumForLoops, Clause);
17263 return Clause;
17264}
17265
17267 OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc,
17268 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17269 OMPClause *Res = nullptr;
17270 switch (Kind) {
17271 case OMPC_proc_bind:
17272 Res = ActOnOpenMPProcBindClause(static_cast<ProcBindKind>(Argument),
17273 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17274 break;
17275 case OMPC_atomic_default_mem_order:
17277 static_cast<OpenMPAtomicDefaultMemOrderClauseKind>(Argument),
17278 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17279 break;
17280 case OMPC_fail:
17281 Res = ActOnOpenMPFailClause(static_cast<OpenMPClauseKind>(Argument),
17282 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17283 break;
17284 case OMPC_update:
17285 Res = ActOnOpenMPUpdateClause(static_cast<OpenMPDependClauseKind>(Argument),
17286 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17287 break;
17288 case OMPC_bind:
17289 Res = ActOnOpenMPBindClause(static_cast<OpenMPBindClauseKind>(Argument),
17290 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17291 break;
17292 case OMPC_at:
17293 Res = ActOnOpenMPAtClause(static_cast<OpenMPAtClauseKind>(Argument),
17294 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17295 break;
17296 case OMPC_severity:
17298 static_cast<OpenMPSeverityClauseKind>(Argument), ArgumentLoc, StartLoc,
17299 LParenLoc, EndLoc);
17300 break;
17301 case OMPC_threadset:
17302 Res = ActOnOpenMPThreadsetClause(static_cast<OpenMPThreadsetKind>(Argument),
17303 ArgumentLoc, StartLoc, LParenLoc, EndLoc);
17304 break;
17305 case OMPC_if:
17306 case OMPC_final:
17307 case OMPC_num_threads:
17308 case OMPC_safelen:
17309 case OMPC_simdlen:
17310 case OMPC_sizes:
17311 case OMPC_allocator:
17312 case OMPC_collapse:
17313 case OMPC_schedule:
17314 case OMPC_private:
17315 case OMPC_firstprivate:
17316 case OMPC_lastprivate:
17317 case OMPC_shared:
17318 case OMPC_reduction:
17319 case OMPC_task_reduction:
17320 case OMPC_in_reduction:
17321 case OMPC_linear:
17322 case OMPC_aligned:
17323 case OMPC_copyin:
17324 case OMPC_copyprivate:
17325 case OMPC_ordered:
17326 case OMPC_nowait:
17327 case OMPC_untied:
17328 case OMPC_mergeable:
17329 case OMPC_threadprivate:
17330 case OMPC_groupprivate:
17331 case OMPC_allocate:
17332 case OMPC_flush:
17333 case OMPC_depobj:
17334 case OMPC_read:
17335 case OMPC_write:
17336 case OMPC_capture:
17337 case OMPC_compare:
17338 case OMPC_seq_cst:
17339 case OMPC_acq_rel:
17340 case OMPC_acquire:
17341 case OMPC_release:
17342 case OMPC_relaxed:
17343 case OMPC_depend:
17344 case OMPC_device:
17345 case OMPC_threads:
17346 case OMPC_simd:
17347 case OMPC_map:
17348 case OMPC_num_teams:
17349 case OMPC_thread_limit:
17350 case OMPC_priority:
17351 case OMPC_grainsize:
17352 case OMPC_nogroup:
17353 case OMPC_num_tasks:
17354 case OMPC_hint:
17355 case OMPC_dist_schedule:
17356 case OMPC_default:
17357 case OMPC_defaultmap:
17358 case OMPC_unknown:
17359 case OMPC_uniform:
17360 case OMPC_to:
17361 case OMPC_from:
17362 case OMPC_use_device_ptr:
17363 case OMPC_use_device_addr:
17364 case OMPC_is_device_ptr:
17365 case OMPC_has_device_addr:
17366 case OMPC_unified_address:
17367 case OMPC_unified_shared_memory:
17368 case OMPC_reverse_offload:
17369 case OMPC_dynamic_allocators:
17370 case OMPC_self_maps:
17371 case OMPC_device_type:
17372 case OMPC_match:
17373 case OMPC_nontemporal:
17374 case OMPC_destroy:
17375 case OMPC_novariants:
17376 case OMPC_nocontext:
17377 case OMPC_detach:
17378 case OMPC_inclusive:
17379 case OMPC_exclusive:
17380 case OMPC_uses_allocators:
17381 case OMPC_affinity:
17382 case OMPC_when:
17383 case OMPC_message:
17384 default:
17385 llvm_unreachable("Clause is not allowed.");
17386 }
17387 return Res;
17388}
17389
17391 llvm::omp::DefaultKind M, SourceLocation MLoc,
17393 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17394 if (M == OMP_DEFAULT_unknown) {
17395 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17396 << getListOfPossibleValues(OMPC_default, /*First=*/0,
17397 /*Last=*/unsigned(OMP_DEFAULT_unknown))
17398 << getOpenMPClauseNameForDiag(OMPC_default);
17399 return nullptr;
17400 }
17401 if (VCKind == OMPC_DEFAULT_VC_unknown) {
17402 Diag(VCKindLoc, diag::err_omp_default_vc)
17403 << getOpenMPSimpleClauseTypeName(OMPC_default, unsigned(M));
17404 return nullptr;
17405 }
17406
17407 bool IsTargetDefault =
17408 getLangOpts().OpenMP >= 60 &&
17409 isOpenMPTargetExecutionDirective(DSAStack->getCurrentDirective());
17410
17411 // OpenMP 6.0, page 224, lines 3-4 default Clause, Semantics
17412 // If data-sharing-attribute is shared then the clause has no effect
17413 // on a target construct;
17414 if (IsTargetDefault && M == OMP_DEFAULT_shared)
17415 return nullptr;
17416
17417 auto SetDefaultClauseAttrs = [&](llvm::omp::DefaultKind M,
17420 OpenMPDefaultmapClauseKind DefMapKind;
17421 // default data-sharing-attribute
17422 switch (M) {
17423 case OMP_DEFAULT_none:
17424 if (IsTargetDefault)
17425 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_none;
17426 else
17427 DSAStack->setDefaultDSANone(MLoc);
17428 break;
17429 case OMP_DEFAULT_firstprivate:
17430 if (IsTargetDefault)
17431 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_firstprivate;
17432 else
17433 DSAStack->setDefaultDSAFirstPrivate(MLoc);
17434 break;
17435 case OMP_DEFAULT_private:
17436 if (IsTargetDefault)
17437 DefMapMod = OMPC_DEFAULTMAP_MODIFIER_private;
17438 else
17439 DSAStack->setDefaultDSAPrivate(MLoc);
17440 break;
17441 case OMP_DEFAULT_shared:
17442 assert(!IsTargetDefault && "DSA shared invalid with target directive");
17443 DSAStack->setDefaultDSAShared(MLoc);
17444 break;
17445 default:
17446 llvm_unreachable("unexpected DSA in OpenMP default clause");
17447 }
17448 // default variable-category
17449 switch (VCKind) {
17450 case OMPC_DEFAULT_VC_aggregate:
17451 if (IsTargetDefault)
17452 DefMapKind = OMPC_DEFAULTMAP_aggregate;
17453 else
17454 DSAStack->setDefaultDSAVCAggregate(VCKindLoc);
17455 break;
17456 case OMPC_DEFAULT_VC_pointer:
17457 if (IsTargetDefault)
17458 DefMapKind = OMPC_DEFAULTMAP_pointer;
17459 else
17460 DSAStack->setDefaultDSAVCPointer(VCKindLoc);
17461 break;
17462 case OMPC_DEFAULT_VC_scalar:
17463 if (IsTargetDefault)
17464 DefMapKind = OMPC_DEFAULTMAP_scalar;
17465 else
17466 DSAStack->setDefaultDSAVCScalar(VCKindLoc);
17467 break;
17468 case OMPC_DEFAULT_VC_all:
17469 if (IsTargetDefault)
17470 DefMapKind = OMPC_DEFAULTMAP_all;
17471 else
17472 DSAStack->setDefaultDSAVCAll(VCKindLoc);
17473 break;
17474 default:
17475 llvm_unreachable("unexpected variable category in OpenMP default clause");
17476 }
17477 // OpenMP 6.0, page 224, lines 4-5 default Clause, Semantics
17478 // otherwise, its effect on a target construct is equivalent to
17479 // specifying the defaultmap clause with the same data-sharing-attribute
17480 // and variable-category.
17481 //
17482 // If earlier than OpenMP 6.0, or not a target directive, the default DSA
17483 // is/was set as before.
17484 if (IsTargetDefault) {
17485 if (DefMapKind == OMPC_DEFAULTMAP_all) {
17486 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_aggregate, MLoc);
17487 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_scalar, MLoc);
17488 DSAStack->setDefaultDMAAttr(DefMapMod, OMPC_DEFAULTMAP_pointer, MLoc);
17489 } else {
17490 DSAStack->setDefaultDMAAttr(DefMapMod, DefMapKind, MLoc);
17491 }
17492 }
17493 };
17494
17495 SetDefaultClauseAttrs(M, VCKind);
17496 return new (getASTContext())
17497 OMPDefaultClause(M, MLoc, VCKind, VCKindLoc, StartLoc, LParenLoc, EndLoc);
17498}
17499
17501 SourceLocation KindLoc,
17502 SourceLocation StartLoc,
17503 SourceLocation LParenLoc,
17504 SourceLocation EndLoc) {
17505 if (Kind == OMPC_THREADSET_unknown) {
17506 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17507 << getListOfPossibleValues(OMPC_threadset, /*First=*/0,
17508 /*Last=*/unsigned(OMPC_THREADSET_unknown))
17509 << getOpenMPClauseName(OMPC_threadset);
17510 return nullptr;
17511 }
17512
17513 return new (getASTContext())
17514 OMPThreadsetClause(Kind, KindLoc, StartLoc, LParenLoc, EndLoc);
17515}
17516
17518 Expr *ImpexTypeArg,
17519 SourceLocation StartLoc,
17520 SourceLocation LParenLoc,
17521 SourceLocation EndLoc) {
17522 ExprResult ER = SemaRef.DefaultLvalueConversion(ImpexTypeArg);
17523 if (ER.isInvalid())
17524 return nullptr;
17525
17526 return new (Ctx) OMPTransparentClause(ER.get(), StartLoc, LParenLoc, EndLoc);
17527}
17528
17530 SourceLocation StartLoc,
17531 SourceLocation LParenLoc,
17532 SourceLocation EndLoc) {
17533 if (!ImpexTypeArg) {
17534 return new (getASTContext())
17535 OMPTransparentClause(ImpexTypeArg, StartLoc, LParenLoc, EndLoc);
17536 }
17537 QualType Ty = ImpexTypeArg->getType();
17538
17539 if (const auto *TT = Ty->getAs<TypedefType>()) {
17540 const TypedefNameDecl *TypedefDecl = TT->getDecl();
17541 llvm::StringRef TypedefName = TypedefDecl->getName();
17542 IdentifierInfo &II = SemaRef.PP.getIdentifierTable().get(TypedefName);
17543 ParsedType ImpexTy =
17544 SemaRef.getTypeName(II, StartLoc, SemaRef.getCurScope());
17545 if (!ImpexTy.getAsOpaquePtr() || ImpexTy.get().isNull()) {
17546 SemaRef.Diag(StartLoc, diag::err_omp_implied_type_not_found)
17547 << TypedefName;
17548 return nullptr;
17549 }
17550 return createTransparentClause(SemaRef, getASTContext(), ImpexTypeArg,
17551 StartLoc, LParenLoc, EndLoc);
17552 }
17553
17554 if (Ty->isEnumeralType())
17555 return createTransparentClause(SemaRef, getASTContext(), ImpexTypeArg,
17556 StartLoc, LParenLoc, EndLoc);
17557
17558 if (Ty->isIntegerType()) {
17559 if (isNonNegativeIntegerValue(ImpexTypeArg, SemaRef, OMPC_transparent,
17560 /*StrictlyPositive=*/false)) {
17562 SemaRef.OpenMP().PerformOpenMPImplicitIntegerConversion(StartLoc,
17563 ImpexTypeArg);
17564 if (std::optional<llvm::APSInt> Result =
17565 Value.get()->getIntegerConstantExpr(SemaRef.Context)) {
17566 if (Result->isNegative() ||
17567 Result >
17568 static_cast<int64_t>(SemaOpenMP::OpenMPImpexType::OMP_Export))
17569 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_value);
17570 }
17571 return createTransparentClause(SemaRef, getASTContext(), ImpexTypeArg,
17572 StartLoc, LParenLoc, EndLoc);
17573 }
17574 }
17575 SemaRef.Diag(StartLoc, diag::err_omp_transparent_invalid_type) << Ty;
17576 return nullptr;
17577}
17578
17580 SourceLocation KindKwLoc,
17581 SourceLocation StartLoc,
17582 SourceLocation LParenLoc,
17583 SourceLocation EndLoc) {
17584 if (Kind == OMP_PROC_BIND_unknown) {
17585 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17586 << getListOfPossibleValues(OMPC_proc_bind,
17587 /*First=*/unsigned(OMP_PROC_BIND_master),
17588 /*Last=*/
17589 unsigned(getLangOpts().OpenMP > 50
17590 ? OMP_PROC_BIND_primary
17591 : OMP_PROC_BIND_spread) +
17592 1)
17593 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17594 return nullptr;
17595 }
17596 if (Kind == OMP_PROC_BIND_primary && getLangOpts().OpenMP < 51)
17597 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17598 << getListOfPossibleValues(OMPC_proc_bind,
17599 /*First=*/unsigned(OMP_PROC_BIND_master),
17600 /*Last=*/
17601 unsigned(OMP_PROC_BIND_spread) + 1)
17602 << getOpenMPClauseNameForDiag(OMPC_proc_bind);
17603 return new (getASTContext())
17604 OMPProcBindClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17605}
17606
17609 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc) {
17611 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17613 OMPC_atomic_default_mem_order, /*First=*/0,
17615 << getOpenMPClauseNameForDiag(OMPC_atomic_default_mem_order);
17616 return nullptr;
17617 }
17618 return new (getASTContext()) OMPAtomicDefaultMemOrderClause(
17619 Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17620}
17621
17623 SourceLocation KindKwLoc,
17624 SourceLocation StartLoc,
17625 SourceLocation LParenLoc,
17626 SourceLocation EndLoc) {
17627 if (Kind == OMPC_AT_unknown) {
17628 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17629 << getListOfPossibleValues(OMPC_at, /*First=*/0,
17630 /*Last=*/OMPC_AT_unknown)
17631 << getOpenMPClauseNameForDiag(OMPC_at);
17632 return nullptr;
17633 }
17634 return new (getASTContext())
17635 OMPAtClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17636}
17637
17639 SourceLocation KindKwLoc,
17640 SourceLocation StartLoc,
17641 SourceLocation LParenLoc,
17642 SourceLocation EndLoc) {
17643 if (Kind == OMPC_SEVERITY_unknown) {
17644 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17645 << getListOfPossibleValues(OMPC_severity, /*First=*/0,
17646 /*Last=*/OMPC_SEVERITY_unknown)
17647 << getOpenMPClauseNameForDiag(OMPC_severity);
17648 return nullptr;
17649 }
17650 return new (getASTContext())
17651 OMPSeverityClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
17652}
17653
17655 SourceLocation StartLoc,
17656 SourceLocation LParenLoc,
17657 SourceLocation EndLoc) {
17658 assert(ME && "NULL expr in Message clause");
17659 QualType Type = ME->getType();
17660 if ((!Type->isPointerType() && !Type->isArrayType()) ||
17662 Diag(ME->getBeginLoc(), diag::warn_clause_expected_string)
17663 << getOpenMPClauseNameForDiag(OMPC_message) << 0;
17664 return nullptr;
17665 }
17666
17667 Stmt *HelperValStmt = nullptr;
17668
17669 // Depending on whether this clause appears in an executable context or not,
17670 // we may or may not build a capture.
17671 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
17672 OpenMPDirectiveKind CaptureRegion =
17673 DKind == OMPD_unknown ? OMPD_unknown
17675 DKind, OMPC_message, getLangOpts().OpenMP);
17676 if (CaptureRegion != OMPD_unknown &&
17677 !SemaRef.CurContext->isDependentContext()) {
17678 ME = SemaRef.MakeFullExpr(ME).get();
17679 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
17680 ME = tryBuildCapture(SemaRef, ME, Captures).get();
17681 HelperValStmt = buildPreInits(getASTContext(), Captures);
17682 }
17683
17684 // Convert array type to pointer type if needed.
17685 ME = SemaRef.DefaultFunctionArrayLvalueConversion(ME).get();
17686
17687 return new (getASTContext()) OMPMessageClause(
17688 ME, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
17689}
17690
17693 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
17694 SourceLocation KindLoc, SourceLocation EndLoc) {
17695 if (Kind != OMPC_ORDER_concurrent ||
17696 (getLangOpts().OpenMP < 51 && MLoc.isValid())) {
17697 // Kind should be concurrent,
17698 // Modifiers introduced in OpenMP 5.1
17699 static_assert(OMPC_ORDER_unknown > 0,
17700 "OMPC_ORDER_unknown not greater than 0");
17701
17702 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
17703 << getListOfPossibleValues(OMPC_order,
17704 /*First=*/0,
17705 /*Last=*/OMPC_ORDER_unknown)
17706 << getOpenMPClauseNameForDiag(OMPC_order);
17707 return nullptr;
17708 }
17709 if (getLangOpts().OpenMP >= 51 && Modifier == OMPC_ORDER_MODIFIER_unknown &&
17710 MLoc.isValid()) {
17711 Diag(MLoc, diag::err_omp_unexpected_clause_value)
17712 << getListOfPossibleValues(OMPC_order,
17713 /*First=*/OMPC_ORDER_MODIFIER_unknown + 1,
17714 /*Last=*/OMPC_ORDER_MODIFIER_last)
17715 << getOpenMPClauseNameForDiag(OMPC_order);
17716 } else if (getLangOpts().OpenMP >= 50) {
17717 DSAStack->setRegionHasOrderConcurrent(/*HasOrderConcurrent=*/true);
17718 if (DSAStack->getCurScope()) {
17719 // mark the current scope with 'order' flag
17720 unsigned existingFlags = DSAStack->getCurScope()->getFlags();
17721 DSAStack->getCurScope()->setFlags(existingFlags |
17723 }
17724 }
17725 return new (getASTContext()) OMPOrderClause(
17726 Kind, KindLoc, StartLoc, LParenLoc, EndLoc, Modifier, MLoc);
17727}
17728
17730 SourceLocation KindKwLoc,
17731 SourceLocation StartLoc,
17732 SourceLocation LParenLoc,
17733 SourceLocation EndLoc) {
17734 if (Kind == OMPC_DEPEND_unknown || Kind == OMPC_DEPEND_source ||
17735 Kind == OMPC_DEPEND_sink || Kind == OMPC_DEPEND_depobj) {
17736 SmallVector<unsigned> Except = {
17737 OMPC_DEPEND_source, OMPC_DEPEND_sink, OMPC_DEPEND_depobj,
17738 OMPC_DEPEND_outallmemory, OMPC_DEPEND_inoutallmemory};
17739 if (getLangOpts().OpenMP < 51)
17740 Except.push_back(OMPC_DEPEND_inoutset);
17741 Diag(KindKwLoc, diag::err_omp_unexpected_clause_value)
17742 << getListOfPossibleValues(OMPC_depend, /*First=*/0,
17743 /*Last=*/OMPC_DEPEND_unknown, Except)
17744 << getOpenMPClauseNameForDiag(OMPC_update);
17745 return nullptr;
17746 }
17747 return OMPUpdateClause::Create(getASTContext(), StartLoc, LParenLoc,
17748 KindKwLoc, Kind, EndLoc);
17749}
17750
17752 SourceLocation StartLoc,
17753 SourceLocation LParenLoc,
17754 SourceLocation EndLoc) {
17755 SmallVector<Expr *> SanitizedSizeExprs(SizeExprs);
17756
17757 for (Expr *&SizeExpr : SanitizedSizeExprs) {
17758 // Skip if already sanitized, e.g. during a partial template instantiation.
17759 if (!SizeExpr)
17760 continue;
17761
17762 bool IsValid = isNonNegativeIntegerValue(SizeExpr, SemaRef, OMPC_sizes,
17763 /*StrictlyPositive=*/true);
17764
17765 // isNonNegativeIntegerValue returns true for non-integral types (but still
17766 // emits error diagnostic), so check for the expected type explicitly.
17767 QualType SizeTy = SizeExpr->getType();
17768 if (!SizeTy->isIntegerType())
17769 IsValid = false;
17770
17771 // Handling in templates is tricky. There are four possibilities to
17772 // consider:
17773 //
17774 // 1a. The expression is valid and we are in a instantiated template or not
17775 // in a template:
17776 // Pass valid expression to be further analysed later in Sema.
17777 // 1b. The expression is valid and we are in a template (including partial
17778 // instantiation):
17779 // isNonNegativeIntegerValue skipped any checks so there is no
17780 // guarantee it will be correct after instantiation.
17781 // ActOnOpenMPSizesClause will be called again at instantiation when
17782 // it is not in a dependent context anymore. This may cause warnings
17783 // to be emitted multiple times.
17784 // 2a. The expression is invalid and we are in an instantiated template or
17785 // not in a template:
17786 // Invalidate the expression with a clearly wrong value (nullptr) so
17787 // later in Sema we do not have to do the same validity analysis again
17788 // or crash from unexpected data. Error diagnostics have already been
17789 // emitted.
17790 // 2b. The expression is invalid and we are in a template (including partial
17791 // instantiation):
17792 // Pass the invalid expression as-is, template instantiation may
17793 // replace unexpected types/values with valid ones. The directives
17794 // with this clause must not try to use these expressions in dependent
17795 // contexts, but delay analysis until full instantiation.
17796 if (!SizeExpr->isInstantiationDependent() && !IsValid)
17797 SizeExpr = nullptr;
17798 }
17799
17800 return OMPSizesClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17801 SanitizedSizeExprs);
17802}
17803
17805 SourceLocation StartLoc,
17806 SourceLocation LParenLoc,
17807 SourceLocation EndLoc) {
17808 size_t NumLoops = PermExprs.size();
17809 SmallVector<Expr *> SanitizedPermExprs;
17810 llvm::append_range(SanitizedPermExprs, PermExprs);
17811
17812 for (Expr *&PermExpr : SanitizedPermExprs) {
17813 // Skip if template-dependent or already sanitized, e.g. during a partial
17814 // template instantiation.
17815 if (!PermExpr || PermExpr->isInstantiationDependent())
17816 continue;
17817
17818 llvm::APSInt PermVal;
17819 ExprResult PermEvalExpr = SemaRef.VerifyIntegerConstantExpression(
17820 PermExpr, &PermVal, AllowFoldKind::Allow);
17821 bool IsValid = PermEvalExpr.isUsable();
17822 if (IsValid)
17823 PermExpr = PermEvalExpr.get();
17824
17825 if (IsValid && (PermVal < 1 || NumLoops < PermVal)) {
17826 SourceRange ExprRange(PermEvalExpr.get()->getBeginLoc(),
17827 PermEvalExpr.get()->getEndLoc());
17828 Diag(PermEvalExpr.get()->getExprLoc(),
17829 diag::err_omp_interchange_permutation_value_range)
17830 << NumLoops << ExprRange;
17831 IsValid = false;
17832 }
17833
17834 if (!PermExpr->isInstantiationDependent() && !IsValid)
17835 PermExpr = nullptr;
17836 }
17837
17838 return OMPPermutationClause::Create(getASTContext(), StartLoc, LParenLoc,
17839 EndLoc, SanitizedPermExprs);
17840}
17841
17843 SourceLocation EndLoc) {
17844 return OMPFullClause::Create(getASTContext(), StartLoc, EndLoc);
17845}
17846
17848 SourceLocation StartLoc,
17849 SourceLocation LParenLoc,
17850 SourceLocation EndLoc) {
17851 if (FactorExpr) {
17852 // If an argument is specified, it must be a constant (or an unevaluated
17853 // template expression).
17855 FactorExpr, OMPC_partial, /*StrictlyPositive=*/true);
17856 if (FactorResult.isInvalid())
17857 return nullptr;
17858 FactorExpr = FactorResult.get();
17859 }
17860
17861 return OMPPartialClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
17862 FactorExpr);
17863}
17864
17866 Expr *First, Expr *Count, SourceLocation StartLoc, SourceLocation LParenLoc,
17867 SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc) {
17868
17869 // OpenMP [6.0, Restrictions]
17870 // First and Count must be integer expressions with positive value
17871 ExprResult FirstVal =
17873 if (FirstVal.isInvalid())
17874 First = nullptr;
17875
17876 ExprResult CountVal =
17877 VerifyPositiveIntegerConstantInClause(Count, OMPC_looprange);
17878 if (CountVal.isInvalid())
17879 Count = nullptr;
17880
17881 // OpenMP [6.0, Restrictions]
17882 // first + count - 1 must not evaluate to a value greater than the
17883 // loop sequence length of the associated canonical loop sequence.
17884 // This check must be performed afterwards due to the delayed
17885 // parsing and computation of the associated loop sequence
17886 return OMPLoopRangeClause::Create(getASTContext(), StartLoc, LParenLoc,
17887 FirstLoc, CountLoc, EndLoc, First, Count);
17888}
17889
17891 SourceLocation LParenLoc,
17892 SourceLocation EndLoc) {
17893 ExprResult AlignVal;
17894 AlignVal = VerifyPositiveIntegerConstantInClause(A, OMPC_align);
17895 if (AlignVal.isInvalid())
17896 return nullptr;
17897 return OMPAlignClause::Create(getASTContext(), AlignVal.get(), StartLoc,
17898 LParenLoc, EndLoc);
17899}
17900
17903 SourceLocation StartLoc, SourceLocation LParenLoc,
17904 ArrayRef<SourceLocation> ArgumentLoc, SourceLocation DelimLoc,
17905 SourceLocation EndLoc) {
17906 OMPClause *Res = nullptr;
17907 switch (Kind) {
17908 case OMPC_schedule: {
17909 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
17910 assert(Argument.size() == NumberOfElements &&
17911 ArgumentLoc.size() == NumberOfElements);
17913 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier1]),
17914 static_cast<OpenMPScheduleClauseModifier>(Argument[Modifier2]),
17915 static_cast<OpenMPScheduleClauseKind>(Argument[ScheduleKind]), Expr,
17916 StartLoc, LParenLoc, ArgumentLoc[Modifier1], ArgumentLoc[Modifier2],
17917 ArgumentLoc[ScheduleKind], DelimLoc, EndLoc);
17918 break;
17919 }
17920 case OMPC_if:
17921 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17922 Res = ActOnOpenMPIfClause(static_cast<OpenMPDirectiveKind>(Argument.back()),
17923 Expr, StartLoc, LParenLoc, ArgumentLoc.back(),
17924 DelimLoc, EndLoc);
17925 break;
17926 case OMPC_dist_schedule:
17928 static_cast<OpenMPDistScheduleClauseKind>(Argument.back()), Expr,
17929 StartLoc, LParenLoc, ArgumentLoc.back(), DelimLoc, EndLoc);
17930 break;
17931 case OMPC_default:
17932 enum { DefaultModifier, DefaultVarCategory };
17934 static_cast<llvm::omp::DefaultKind>(Argument[DefaultModifier]),
17935 ArgumentLoc[DefaultModifier],
17937 Argument[DefaultVarCategory]),
17938 ArgumentLoc[DefaultVarCategory], StartLoc, LParenLoc, EndLoc);
17939 break;
17940 case OMPC_defaultmap:
17941 enum { Modifier, DefaultmapKind };
17943 static_cast<OpenMPDefaultmapClauseModifier>(Argument[Modifier]),
17944 static_cast<OpenMPDefaultmapClauseKind>(Argument[DefaultmapKind]),
17945 StartLoc, LParenLoc, ArgumentLoc[Modifier], ArgumentLoc[DefaultmapKind],
17946 EndLoc);
17947 break;
17948 case OMPC_order:
17949 enum { OrderModifier, OrderKind };
17951 static_cast<OpenMPOrderClauseModifier>(Argument[OrderModifier]),
17952 static_cast<OpenMPOrderClauseKind>(Argument[OrderKind]), StartLoc,
17953 LParenLoc, ArgumentLoc[OrderModifier], ArgumentLoc[OrderKind], EndLoc);
17954 break;
17955 case OMPC_device:
17956 assert(Argument.size() == 1 && ArgumentLoc.size() == 1);
17958 static_cast<OpenMPDeviceClauseModifier>(Argument.back()), Expr,
17959 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17960 break;
17961 case OMPC_grainsize:
17962 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17963 "Modifier for grainsize clause and its location are expected.");
17965 static_cast<OpenMPGrainsizeClauseModifier>(Argument.back()), Expr,
17966 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17967 break;
17968 case OMPC_num_tasks:
17969 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17970 "Modifier for num_tasks clause and its location are expected.");
17972 static_cast<OpenMPNumTasksClauseModifier>(Argument.back()), Expr,
17973 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17974 break;
17975 case OMPC_dyn_groupprivate: {
17976 enum { Modifier1, Modifier2, NumberOfElements };
17977 assert(Argument.size() == NumberOfElements &&
17978 ArgumentLoc.size() == NumberOfElements &&
17979 "Modifiers for dyn_groupprivate clause and their locations are "
17980 "expected.");
17982 static_cast<OpenMPDynGroupprivateClauseModifier>(Argument[Modifier1]),
17984 Argument[Modifier2]),
17985 Expr, StartLoc, LParenLoc, ArgumentLoc[Modifier1],
17986 ArgumentLoc[Modifier2], EndLoc);
17987 break;
17988 }
17989 case OMPC_num_threads:
17990 assert(Argument.size() == 1 && ArgumentLoc.size() == 1 &&
17991 "Modifier for num_threads clause and its location are expected.");
17993 static_cast<OpenMPNumThreadsClauseModifier>(Argument.back()), Expr,
17994 StartLoc, LParenLoc, ArgumentLoc.back(), EndLoc);
17995 break;
17996 case OMPC_final:
17997 case OMPC_safelen:
17998 case OMPC_simdlen:
17999 case OMPC_sizes:
18000 case OMPC_allocator:
18001 case OMPC_collapse:
18002 case OMPC_proc_bind:
18003 case OMPC_private:
18004 case OMPC_firstprivate:
18005 case OMPC_lastprivate:
18006 case OMPC_shared:
18007 case OMPC_reduction:
18008 case OMPC_task_reduction:
18009 case OMPC_in_reduction:
18010 case OMPC_linear:
18011 case OMPC_aligned:
18012 case OMPC_copyin:
18013 case OMPC_copyprivate:
18014 case OMPC_ordered:
18015 case OMPC_nowait:
18016 case OMPC_untied:
18017 case OMPC_mergeable:
18018 case OMPC_threadprivate:
18019 case OMPC_groupprivate:
18020 case OMPC_allocate:
18021 case OMPC_flush:
18022 case OMPC_depobj:
18023 case OMPC_read:
18024 case OMPC_write:
18025 case OMPC_update:
18026 case OMPC_capture:
18027 case OMPC_compare:
18028 case OMPC_seq_cst:
18029 case OMPC_acq_rel:
18030 case OMPC_acquire:
18031 case OMPC_release:
18032 case OMPC_relaxed:
18033 case OMPC_depend:
18034 case OMPC_threads:
18035 case OMPC_simd:
18036 case OMPC_map:
18037 case OMPC_num_teams:
18038 case OMPC_thread_limit:
18039 case OMPC_priority:
18040 case OMPC_nogroup:
18041 case OMPC_hint:
18042 case OMPC_unknown:
18043 case OMPC_uniform:
18044 case OMPC_to:
18045 case OMPC_from:
18046 case OMPC_use_device_ptr:
18047 case OMPC_use_device_addr:
18048 case OMPC_is_device_ptr:
18049 case OMPC_has_device_addr:
18050 case OMPC_unified_address:
18051 case OMPC_unified_shared_memory:
18052 case OMPC_reverse_offload:
18053 case OMPC_dynamic_allocators:
18054 case OMPC_atomic_default_mem_order:
18055 case OMPC_self_maps:
18056 case OMPC_device_type:
18057 case OMPC_match:
18058 case OMPC_nontemporal:
18059 case OMPC_at:
18060 case OMPC_severity:
18061 case OMPC_message:
18062 case OMPC_destroy:
18063 case OMPC_novariants:
18064 case OMPC_nocontext:
18065 case OMPC_detach:
18066 case OMPC_inclusive:
18067 case OMPC_exclusive:
18068 case OMPC_uses_allocators:
18069 case OMPC_affinity:
18070 case OMPC_when:
18071 case OMPC_bind:
18072 default:
18073 llvm_unreachable("Clause is not allowed.");
18074 }
18075 return Res;
18076}
18077
18080 SourceLocation M1Loc, SourceLocation M2Loc) {
18081 if (M1 == OMPC_SCHEDULE_MODIFIER_unknown && M1Loc.isValid()) {
18082 SmallVector<unsigned, 2> Excluded;
18084 Excluded.push_back(M2);
18085 if (M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic)
18086 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_monotonic);
18087 if (M2 == OMPC_SCHEDULE_MODIFIER_monotonic)
18088 Excluded.push_back(OMPC_SCHEDULE_MODIFIER_nonmonotonic);
18089 S.Diag(M1Loc, diag::err_omp_unexpected_clause_value)
18090 << getListOfPossibleValues(OMPC_schedule,
18091 /*First=*/OMPC_SCHEDULE_MODIFIER_unknown + 1,
18093 Excluded)
18094 << getOpenMPClauseNameForDiag(OMPC_schedule);
18095 return true;
18096 }
18097 return false;
18098}
18099
18102 OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
18103 SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc,
18104 SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc) {
18105 if (checkScheduleModifiers(SemaRef, M1, M2, M1Loc, M2Loc) ||
18106 checkScheduleModifiers(SemaRef, M2, M1, M2Loc, M1Loc))
18107 return nullptr;
18108 // OpenMP, 2.7.1, Loop Construct, Restrictions
18109 // Either the monotonic modifier or the nonmonotonic modifier can be specified
18110 // but not both.
18111 if ((M1 == M2 && M1 != OMPC_SCHEDULE_MODIFIER_unknown) ||
18112 (M1 == OMPC_SCHEDULE_MODIFIER_monotonic &&
18113 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) ||
18114 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic &&
18115 M2 == OMPC_SCHEDULE_MODIFIER_monotonic)) {
18116 Diag(M2Loc, diag::err_omp_unexpected_schedule_modifier)
18117 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M2)
18118 << getOpenMPSimpleClauseTypeName(OMPC_schedule, M1);
18119 return nullptr;
18120 }
18121 if (Kind == OMPC_SCHEDULE_unknown) {
18122 std::string Values;
18123 if (M1Loc.isInvalid() && M2Loc.isInvalid()) {
18124 unsigned Exclude[] = {OMPC_SCHEDULE_unknown};
18125 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
18127 Exclude);
18128 } else {
18129 Values = getListOfPossibleValues(OMPC_schedule, /*First=*/0,
18130 /*Last=*/OMPC_SCHEDULE_unknown);
18131 }
18132 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
18133 << Values << getOpenMPClauseNameForDiag(OMPC_schedule);
18134 return nullptr;
18135 }
18136 // OpenMP, 2.7.1, Loop Construct, Restrictions
18137 // The nonmonotonic modifier can only be specified with schedule(dynamic) or
18138 // schedule(guided).
18139 // OpenMP 5.0 does not have this restriction.
18140 if (getLangOpts().OpenMP < 50 &&
18141 (M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ||
18142 M2 == OMPC_SCHEDULE_MODIFIER_nonmonotonic) &&
18143 Kind != OMPC_SCHEDULE_dynamic && Kind != OMPC_SCHEDULE_guided) {
18144 Diag(M1 == OMPC_SCHEDULE_MODIFIER_nonmonotonic ? M1Loc : M2Loc,
18145 diag::err_omp_schedule_nonmonotonic_static);
18146 return nullptr;
18147 }
18148 Expr *ValExpr = ChunkSize;
18149 Stmt *HelperValStmt = nullptr;
18150 if (ChunkSize) {
18151 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
18152 !ChunkSize->isInstantiationDependent() &&
18153 !ChunkSize->containsUnexpandedParameterPack()) {
18154 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
18155 ExprResult Val =
18156 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
18157 if (Val.isInvalid())
18158 return nullptr;
18159
18160 ValExpr = Val.get();
18161
18162 // OpenMP [2.7.1, Restrictions]
18163 // chunk_size must be a loop invariant integer expression with a positive
18164 // value.
18165 if (std::optional<llvm::APSInt> Result =
18167 if (Result->isSigned() && !Result->isStrictlyPositive()) {
18168 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
18169 << "schedule" << 1 << ChunkSize->getSourceRange();
18170 return nullptr;
18171 }
18173 DSAStack->getCurrentDirective(), OMPC_schedule,
18174 getLangOpts().OpenMP) != OMPD_unknown &&
18175 !SemaRef.CurContext->isDependentContext()) {
18176 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18177 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18178 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18179 HelperValStmt = buildPreInits(getASTContext(), Captures);
18180 }
18181 }
18182 }
18183
18184 return new (getASTContext())
18185 OMPScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc, Kind,
18186 ValExpr, HelperValStmt, M1, M1Loc, M2, M2Loc);
18187}
18188
18190 SourceLocation StartLoc,
18191 SourceLocation EndLoc) {
18192 OMPClause *Res = nullptr;
18193 switch (Kind) {
18194 case OMPC_ordered:
18195 Res = ActOnOpenMPOrderedClause(StartLoc, EndLoc);
18196 break;
18197 case OMPC_nowait:
18198 Res = ActOnOpenMPNowaitClause(StartLoc, EndLoc,
18199 /*LParenLoc=*/SourceLocation(),
18200 /*Condition=*/nullptr);
18201 break;
18202 case OMPC_untied:
18203 Res = ActOnOpenMPUntiedClause(StartLoc, EndLoc);
18204 break;
18205 case OMPC_mergeable:
18206 Res = ActOnOpenMPMergeableClause(StartLoc, EndLoc);
18207 break;
18208 case OMPC_read:
18209 Res = ActOnOpenMPReadClause(StartLoc, EndLoc);
18210 break;
18211 case OMPC_write:
18212 Res = ActOnOpenMPWriteClause(StartLoc, EndLoc);
18213 break;
18214 case OMPC_update:
18215 Res = ActOnOpenMPUpdateClause(StartLoc, EndLoc);
18216 break;
18217 case OMPC_capture:
18218 Res = ActOnOpenMPCaptureClause(StartLoc, EndLoc);
18219 break;
18220 case OMPC_compare:
18221 Res = ActOnOpenMPCompareClause(StartLoc, EndLoc);
18222 break;
18223 case OMPC_fail:
18224 Res = ActOnOpenMPFailClause(StartLoc, EndLoc);
18225 break;
18226 case OMPC_seq_cst:
18227 Res = ActOnOpenMPSeqCstClause(StartLoc, EndLoc);
18228 break;
18229 case OMPC_acq_rel:
18230 Res = ActOnOpenMPAcqRelClause(StartLoc, EndLoc);
18231 break;
18232 case OMPC_acquire:
18233 Res = ActOnOpenMPAcquireClause(StartLoc, EndLoc);
18234 break;
18235 case OMPC_release:
18236 Res = ActOnOpenMPReleaseClause(StartLoc, EndLoc);
18237 break;
18238 case OMPC_relaxed:
18239 Res = ActOnOpenMPRelaxedClause(StartLoc, EndLoc);
18240 break;
18241 case OMPC_weak:
18242 Res = ActOnOpenMPWeakClause(StartLoc, EndLoc);
18243 break;
18244 case OMPC_threads:
18245 Res = ActOnOpenMPThreadsClause(StartLoc, EndLoc);
18246 break;
18247 case OMPC_simd:
18248 Res = ActOnOpenMPSIMDClause(StartLoc, EndLoc);
18249 break;
18250 case OMPC_nogroup:
18251 Res = ActOnOpenMPNogroupClause(StartLoc, EndLoc);
18252 break;
18253 case OMPC_unified_address:
18254 Res = ActOnOpenMPUnifiedAddressClause(StartLoc, EndLoc);
18255 break;
18256 case OMPC_unified_shared_memory:
18257 Res = ActOnOpenMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18258 break;
18259 case OMPC_reverse_offload:
18260 Res = ActOnOpenMPReverseOffloadClause(StartLoc, EndLoc);
18261 break;
18262 case OMPC_dynamic_allocators:
18263 Res = ActOnOpenMPDynamicAllocatorsClause(StartLoc, EndLoc);
18264 break;
18265 case OMPC_self_maps:
18266 Res = ActOnOpenMPSelfMapsClause(StartLoc, EndLoc);
18267 break;
18268 case OMPC_destroy:
18269 Res = ActOnOpenMPDestroyClause(/*InteropVar=*/nullptr, StartLoc,
18270 /*LParenLoc=*/SourceLocation(),
18271 /*VarLoc=*/SourceLocation(), EndLoc);
18272 break;
18273 case OMPC_full:
18274 Res = ActOnOpenMPFullClause(StartLoc, EndLoc);
18275 break;
18276 case OMPC_partial:
18277 Res = ActOnOpenMPPartialClause(nullptr, StartLoc, /*LParenLoc=*/{}, EndLoc);
18278 break;
18279 case OMPC_ompx_bare:
18280 Res = ActOnOpenMPXBareClause(StartLoc, EndLoc);
18281 break;
18282 case OMPC_if:
18283 case OMPC_final:
18284 case OMPC_num_threads:
18285 case OMPC_safelen:
18286 case OMPC_simdlen:
18287 case OMPC_sizes:
18288 case OMPC_allocator:
18289 case OMPC_collapse:
18290 case OMPC_schedule:
18291 case OMPC_private:
18292 case OMPC_firstprivate:
18293 case OMPC_lastprivate:
18294 case OMPC_shared:
18295 case OMPC_reduction:
18296 case OMPC_task_reduction:
18297 case OMPC_in_reduction:
18298 case OMPC_linear:
18299 case OMPC_aligned:
18300 case OMPC_copyin:
18301 case OMPC_copyprivate:
18302 case OMPC_default:
18303 case OMPC_proc_bind:
18304 case OMPC_threadprivate:
18305 case OMPC_groupprivate:
18306 case OMPC_allocate:
18307 case OMPC_flush:
18308 case OMPC_depobj:
18309 case OMPC_depend:
18310 case OMPC_device:
18311 case OMPC_map:
18312 case OMPC_num_teams:
18313 case OMPC_thread_limit:
18314 case OMPC_priority:
18315 case OMPC_grainsize:
18316 case OMPC_num_tasks:
18317 case OMPC_hint:
18318 case OMPC_dist_schedule:
18319 case OMPC_defaultmap:
18320 case OMPC_unknown:
18321 case OMPC_uniform:
18322 case OMPC_to:
18323 case OMPC_from:
18324 case OMPC_use_device_ptr:
18325 case OMPC_use_device_addr:
18326 case OMPC_is_device_ptr:
18327 case OMPC_has_device_addr:
18328 case OMPC_atomic_default_mem_order:
18329 case OMPC_device_type:
18330 case OMPC_match:
18331 case OMPC_nontemporal:
18332 case OMPC_order:
18333 case OMPC_at:
18334 case OMPC_severity:
18335 case OMPC_message:
18336 case OMPC_novariants:
18337 case OMPC_nocontext:
18338 case OMPC_detach:
18339 case OMPC_inclusive:
18340 case OMPC_exclusive:
18341 case OMPC_uses_allocators:
18342 case OMPC_affinity:
18343 case OMPC_when:
18344 case OMPC_ompx_dyn_cgroup_mem:
18345 case OMPC_dyn_groupprivate:
18346 default:
18347 llvm_unreachable("Clause is not allowed.");
18348 }
18349 return Res;
18350}
18351
18353 SourceLocation EndLoc,
18354 SourceLocation LParenLoc,
18355 Expr *Condition) {
18356 Expr *ValExpr = Condition;
18357 if (Condition && LParenLoc.isValid()) {
18358 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18359 !Condition->isInstantiationDependent() &&
18360 !Condition->containsUnexpandedParameterPack()) {
18361 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18362 if (Val.isInvalid())
18363 return nullptr;
18364
18365 ValExpr = Val.get();
18366 }
18367 }
18368 DSAStack->setNowaitRegion();
18369 return new (getASTContext())
18370 OMPNowaitClause(ValExpr, StartLoc, LParenLoc, EndLoc);
18371}
18372
18374 SourceLocation EndLoc) {
18375 DSAStack->setUntiedRegion();
18376 return new (getASTContext()) OMPUntiedClause(StartLoc, EndLoc);
18377}
18378
18380 SourceLocation EndLoc) {
18381 return new (getASTContext()) OMPMergeableClause(StartLoc, EndLoc);
18382}
18383
18385 SourceLocation EndLoc) {
18386 return new (getASTContext()) OMPReadClause(StartLoc, EndLoc);
18387}
18388
18390 SourceLocation EndLoc) {
18391 return new (getASTContext()) OMPWriteClause(StartLoc, EndLoc);
18392}
18393
18395 SourceLocation EndLoc) {
18396 return OMPUpdateClause::Create(getASTContext(), StartLoc, EndLoc);
18397}
18398
18400 SourceLocation EndLoc) {
18401 return new (getASTContext()) OMPCaptureClause(StartLoc, EndLoc);
18402}
18403
18405 SourceLocation EndLoc) {
18406 return new (getASTContext()) OMPCompareClause(StartLoc, EndLoc);
18407}
18408
18410 SourceLocation EndLoc) {
18411 return new (getASTContext()) OMPFailClause(StartLoc, EndLoc);
18412}
18413
18415 SourceLocation KindLoc,
18416 SourceLocation StartLoc,
18417 SourceLocation LParenLoc,
18418 SourceLocation EndLoc) {
18419
18421 Diag(KindLoc, diag::err_omp_atomic_fail_wrong_or_no_clauses);
18422 return nullptr;
18423 }
18424 return new (getASTContext())
18425 OMPFailClause(Parameter, KindLoc, StartLoc, LParenLoc, EndLoc);
18426}
18427
18429 SourceLocation EndLoc) {
18430 return new (getASTContext()) OMPSeqCstClause(StartLoc, EndLoc);
18431}
18432
18434 SourceLocation EndLoc) {
18435 return new (getASTContext()) OMPAcqRelClause(StartLoc, EndLoc);
18436}
18437
18439 SourceLocation EndLoc) {
18440 return new (getASTContext()) OMPAcquireClause(StartLoc, EndLoc);
18441}
18442
18444 SourceLocation EndLoc) {
18445 return new (getASTContext()) OMPReleaseClause(StartLoc, EndLoc);
18446}
18447
18449 SourceLocation EndLoc) {
18450 return new (getASTContext()) OMPRelaxedClause(StartLoc, EndLoc);
18451}
18452
18454 SourceLocation EndLoc) {
18455 return new (getASTContext()) OMPWeakClause(StartLoc, EndLoc);
18456}
18457
18459 SourceLocation EndLoc) {
18460 return new (getASTContext()) OMPThreadsClause(StartLoc, EndLoc);
18461}
18462
18464 SourceLocation EndLoc) {
18465 return new (getASTContext()) OMPSIMDClause(StartLoc, EndLoc);
18466}
18467
18469 SourceLocation EndLoc) {
18470 return new (getASTContext()) OMPNogroupClause(StartLoc, EndLoc);
18471}
18472
18474 SourceLocation EndLoc) {
18475 return new (getASTContext()) OMPUnifiedAddressClause(StartLoc, EndLoc);
18476}
18477
18478OMPClause *
18480 SourceLocation EndLoc) {
18481 return new (getASTContext()) OMPUnifiedSharedMemoryClause(StartLoc, EndLoc);
18482}
18483
18485 SourceLocation EndLoc) {
18486 return new (getASTContext()) OMPReverseOffloadClause(StartLoc, EndLoc);
18487}
18488
18489OMPClause *
18491 SourceLocation EndLoc) {
18492 return new (getASTContext()) OMPDynamicAllocatorsClause(StartLoc, EndLoc);
18493}
18494
18496 SourceLocation EndLoc) {
18497 return new (getASTContext()) OMPSelfMapsClause(StartLoc, EndLoc);
18498}
18499
18502 SourceLocation StartLoc,
18503 SourceLocation EndLoc) {
18504
18505 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18506 // At least one action-clause must appear on a directive.
18507 if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
18508 unsigned OMPVersion = getLangOpts().OpenMP;
18509 StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
18510 Diag(StartLoc, diag::err_omp_no_clause_for_directive)
18511 << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
18512 return StmtError();
18513 }
18514
18515 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18516 // A depend clause can only appear on the directive if a targetsync
18517 // interop-type is present or the interop-var was initialized with
18518 // the targetsync interop-type.
18519
18520 // If there is any 'init' clause diagnose if there is no 'init' clause with
18521 // interop-type of 'targetsync'. Cases involving other directives cannot be
18522 // diagnosed.
18523 const OMPDependClause *DependClause = nullptr;
18524 bool HasInitClause = false;
18525 bool IsTargetSync = false;
18526 for (const OMPClause *C : Clauses) {
18527 if (IsTargetSync)
18528 break;
18529 if (const auto *InitClause = dyn_cast<OMPInitClause>(C)) {
18530 HasInitClause = true;
18531 if (InitClause->getIsTargetSync())
18532 IsTargetSync = true;
18533 } else if (const auto *DC = dyn_cast<OMPDependClause>(C)) {
18534 DependClause = DC;
18535 }
18536 }
18537 if (DependClause && HasInitClause && !IsTargetSync) {
18538 Diag(DependClause->getBeginLoc(), diag::err_omp_interop_bad_depend_clause);
18539 return StmtError();
18540 }
18541
18542 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18543 // Each interop-var may be specified for at most one action-clause of each
18544 // interop construct.
18546 for (OMPClause *C : Clauses) {
18547 OpenMPClauseKind ClauseKind = C->getClauseKind();
18548 std::pair<ValueDecl *, bool> DeclResult;
18549 SourceLocation ELoc;
18550 SourceRange ERange;
18551
18552 if (ClauseKind == OMPC_init) {
18553 auto *E = cast<OMPInitClause>(C)->getInteropVar();
18554 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18555 } else if (ClauseKind == OMPC_use) {
18556 auto *E = cast<OMPUseClause>(C)->getInteropVar();
18557 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18558 } else if (ClauseKind == OMPC_destroy) {
18559 auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
18560 DeclResult = getPrivateItem(SemaRef, E, ELoc, ERange);
18561 }
18562
18563 if (DeclResult.first) {
18564 if (!InteropVars.insert(DeclResult.first).second) {
18565 Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
18566 << DeclResult.first;
18567 return StmtError();
18568 }
18569 }
18570 }
18571
18572 return OMPInteropDirective::Create(getASTContext(), StartLoc, EndLoc,
18573 Clauses);
18574}
18575
18576static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
18577 SourceLocation VarLoc,
18578 OpenMPClauseKind Kind) {
18579 SourceLocation ELoc;
18580 SourceRange ERange;
18581 Expr *RefExpr = InteropVarExpr;
18582 auto Res = getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
18583 /*AllowArraySection=*/false,
18584 /*AllowAssumedSizeArray=*/false,
18585 /*DiagType=*/"omp_interop_t");
18586
18587 if (Res.second) {
18588 // It will be analyzed later.
18589 return true;
18590 }
18591
18592 if (!Res.first)
18593 return false;
18594
18595 // Interop variable should be of type omp_interop_t.
18596 bool HasError = false;
18597 QualType InteropType;
18598 LookupResult Result(SemaRef, &SemaRef.Context.Idents.get("omp_interop_t"),
18599 VarLoc, Sema::LookupOrdinaryName);
18600 if (SemaRef.LookupName(Result, SemaRef.getCurScope())) {
18601 NamedDecl *ND = Result.getFoundDecl();
18602 if (const auto *TD = dyn_cast<TypeDecl>(ND)) {
18603 InteropType = QualType(TD->getTypeForDecl(), 0);
18604 } else {
18605 HasError = true;
18606 }
18607 } else {
18608 HasError = true;
18609 }
18610
18611 if (HasError) {
18612 SemaRef.Diag(VarLoc, diag::err_omp_implied_type_not_found)
18613 << "omp_interop_t";
18614 return false;
18615 }
18616
18617 QualType VarType = InteropVarExpr->getType().getUnqualifiedType();
18618 if (!SemaRef.Context.hasSameType(InteropType, VarType)) {
18619 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_wrong_type);
18620 return false;
18621 }
18622
18623 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
18624 // The interop-var passed to init or destroy must be non-const.
18625 if ((Kind == OMPC_init || Kind == OMPC_destroy) &&
18626 isConstNotMutableType(SemaRef, InteropVarExpr->getType())) {
18627 SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected)
18628 << /*non-const*/ 1;
18629 return false;
18630 }
18631 return true;
18632}
18633
18635 Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc,
18636 SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc) {
18637
18638 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_init))
18639 return nullptr;
18640
18641 // Check prefer_type values. These foreign-runtime-id values are either
18642 // string literals or constant integral expressions.
18643 for (const Expr *E : InteropInfo.PreferTypes) {
18644 if (E->isValueDependent() || E->isTypeDependent() ||
18646 continue;
18648 continue;
18649 if (isa<StringLiteral>(E))
18650 continue;
18651 Diag(E->getExprLoc(), diag::err_omp_interop_prefer_type);
18652 return nullptr;
18653 }
18654
18655 return OMPInitClause::Create(getASTContext(), InteropVar, InteropInfo,
18656 StartLoc, LParenLoc, VarLoc, EndLoc);
18657}
18658
18660 SourceLocation StartLoc,
18661 SourceLocation LParenLoc,
18662 SourceLocation VarLoc,
18663 SourceLocation EndLoc) {
18664
18665 if (!isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_use))
18666 return nullptr;
18667
18668 return new (getASTContext())
18669 OMPUseClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18670}
18671
18673 SourceLocation StartLoc,
18674 SourceLocation LParenLoc,
18675 SourceLocation VarLoc,
18676 SourceLocation EndLoc) {
18677 if (!InteropVar && getLangOpts().OpenMP >= 52 &&
18678 DSAStack->getCurrentDirective() == OMPD_depobj) {
18679 unsigned OMPVersion = getLangOpts().OpenMP;
18680 Diag(StartLoc, diag::err_omp_expected_clause_argument)
18681 << getOpenMPClauseNameForDiag(OMPC_destroy)
18682 << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
18683 return nullptr;
18684 }
18685 if (InteropVar &&
18686 !isValidInteropVariable(SemaRef, InteropVar, VarLoc, OMPC_destroy))
18687 return nullptr;
18688
18689 return new (getASTContext())
18690 OMPDestroyClause(InteropVar, StartLoc, LParenLoc, VarLoc, EndLoc);
18691}
18692
18694 SourceLocation StartLoc,
18695 SourceLocation LParenLoc,
18696 SourceLocation EndLoc) {
18697 Expr *ValExpr = Condition;
18698 Stmt *HelperValStmt = nullptr;
18699 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18700 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18701 !Condition->isInstantiationDependent() &&
18702 !Condition->containsUnexpandedParameterPack()) {
18703 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18704 if (Val.isInvalid())
18705 return nullptr;
18706
18707 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18708
18709 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18710 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_novariants,
18711 getLangOpts().OpenMP);
18712 if (CaptureRegion != OMPD_unknown &&
18713 !SemaRef.CurContext->isDependentContext()) {
18714 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18715 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18716 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18717 HelperValStmt = buildPreInits(getASTContext(), Captures);
18718 }
18719 }
18720
18721 return new (getASTContext()) OMPNovariantsClause(
18722 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18723}
18724
18726 SourceLocation StartLoc,
18727 SourceLocation LParenLoc,
18728 SourceLocation EndLoc) {
18729 Expr *ValExpr = Condition;
18730 Stmt *HelperValStmt = nullptr;
18731 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
18732 if (!Condition->isValueDependent() && !Condition->isTypeDependent() &&
18733 !Condition->isInstantiationDependent() &&
18734 !Condition->containsUnexpandedParameterPack()) {
18735 ExprResult Val = SemaRef.CheckBooleanCondition(StartLoc, Condition);
18736 if (Val.isInvalid())
18737 return nullptr;
18738
18739 ValExpr = SemaRef.MakeFullExpr(Val.get()).get();
18740
18741 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18742 CaptureRegion = getOpenMPCaptureRegionForClause(DKind, OMPC_nocontext,
18743 getLangOpts().OpenMP);
18744 if (CaptureRegion != OMPD_unknown &&
18745 !SemaRef.CurContext->isDependentContext()) {
18746 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18747 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18748 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18749 HelperValStmt = buildPreInits(getASTContext(), Captures);
18750 }
18751 }
18752
18753 return new (getASTContext()) OMPNocontextClause(
18754 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18755}
18756
18758 SourceLocation StartLoc,
18759 SourceLocation LParenLoc,
18760 SourceLocation EndLoc) {
18761 Expr *ValExpr = ThreadID;
18762 Stmt *HelperValStmt = nullptr;
18763
18764 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
18765 OpenMPDirectiveKind CaptureRegion =
18766 getOpenMPCaptureRegionForClause(DKind, OMPC_filter, getLangOpts().OpenMP);
18767 if (CaptureRegion != OMPD_unknown &&
18768 !SemaRef.CurContext->isDependentContext()) {
18769 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
18770 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
18771 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
18772 HelperValStmt = buildPreInits(getASTContext(), Captures);
18773 }
18774
18775 return new (getASTContext()) OMPFilterClause(
18776 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
18777}
18778
18780 ArrayRef<Expr *> VarList,
18781 const OMPVarListLocTy &Locs,
18783 SourceLocation StartLoc = Locs.StartLoc;
18784 SourceLocation LParenLoc = Locs.LParenLoc;
18785 SourceLocation EndLoc = Locs.EndLoc;
18786 OMPClause *Res = nullptr;
18787 int ExtraModifier = Data.ExtraModifier;
18788 int OriginalSharingModifier = Data.OriginalSharingModifier;
18789 SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
18790 SourceLocation ColonLoc = Data.ColonLoc;
18791 switch (Kind) {
18792 case OMPC_private:
18793 Res = ActOnOpenMPPrivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18794 break;
18795 case OMPC_firstprivate:
18796 Res = ActOnOpenMPFirstprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18797 break;
18798 case OMPC_lastprivate:
18799 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LASTPRIVATE_unknown &&
18800 "Unexpected lastprivate modifier.");
18802 VarList, static_cast<OpenMPLastprivateModifier>(ExtraModifier),
18803 ExtraModifierLoc, ColonLoc, StartLoc, LParenLoc, EndLoc);
18804 break;
18805 case OMPC_shared:
18806 Res = ActOnOpenMPSharedClause(VarList, StartLoc, LParenLoc, EndLoc);
18807 break;
18808 case OMPC_reduction:
18809 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
18810 "Unexpected lastprivate modifier.");
18812 VarList,
18814 ExtraModifier, OriginalSharingModifier),
18815 StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
18816 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18817 break;
18818 case OMPC_task_reduction:
18820 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18821 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18822 break;
18823 case OMPC_in_reduction:
18825 VarList, StartLoc, LParenLoc, ColonLoc, EndLoc,
18826 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
18827 break;
18828 case OMPC_linear:
18829 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
18830 "Unexpected linear modifier.");
18832 VarList, Data.DepModOrTailExpr, StartLoc, LParenLoc,
18833 static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
18834 ColonLoc, Data.StepModifierLoc, EndLoc);
18835 break;
18836 case OMPC_aligned:
18837 Res = ActOnOpenMPAlignedClause(VarList, Data.DepModOrTailExpr, StartLoc,
18838 LParenLoc, ColonLoc, EndLoc);
18839 break;
18840 case OMPC_copyin:
18841 Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
18842 break;
18843 case OMPC_copyprivate:
18844 Res = ActOnOpenMPCopyprivateClause(VarList, StartLoc, LParenLoc, EndLoc);
18845 break;
18846 case OMPC_flush:
18847 Res = ActOnOpenMPFlushClause(VarList, StartLoc, LParenLoc, EndLoc);
18848 break;
18849 case OMPC_depend:
18850 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
18851 "Unexpected depend modifier.");
18853 {static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
18854 ColonLoc, Data.OmpAllMemoryLoc},
18855 Data.DepModOrTailExpr, VarList, StartLoc, LParenLoc, EndLoc);
18856 break;
18857 case OMPC_map:
18858 assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
18859 "Unexpected map modifier.");
18861 Data.IteratorExpr, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
18862 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
18863 static_cast<OpenMPMapClauseKind>(ExtraModifier), Data.IsMapTypeImplicit,
18864 ExtraModifierLoc, ColonLoc, VarList, Locs);
18865 break;
18866 case OMPC_to:
18867 Res = ActOnOpenMPToClause(
18868 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18869 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18870 VarList, Locs);
18871 break;
18872 case OMPC_from:
18874 Data.MotionModifiers, Data.MotionModifiersLoc, Data.IteratorExpr,
18875 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, ColonLoc,
18876 VarList, Locs);
18877 break;
18878 case OMPC_use_device_ptr:
18879 assert(0 <= Data.ExtraModifier &&
18880 Data.ExtraModifier <= OMPC_USE_DEVICE_PTR_FALLBACK_unknown &&
18881 "Unexpected use_device_ptr fallback modifier.");
18883 VarList, Locs,
18884 static_cast<OpenMPUseDevicePtrFallbackModifier>(Data.ExtraModifier),
18885 Data.ExtraModifierLoc);
18886 break;
18887 case OMPC_use_device_addr:
18888 Res = ActOnOpenMPUseDeviceAddrClause(VarList, Locs);
18889 break;
18890 case OMPC_is_device_ptr:
18891 Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
18892 break;
18893 case OMPC_has_device_addr:
18894 Res = ActOnOpenMPHasDeviceAddrClause(VarList, Locs);
18895 break;
18896 case OMPC_allocate: {
18899 SourceLocation Modifier1Loc, Modifier2Loc;
18900 if (!Data.AllocClauseModifiers.empty()) {
18901 assert(Data.AllocClauseModifiers.size() <= 2 &&
18902 "More allocate modifiers than expected");
18903 Modifier1 = Data.AllocClauseModifiers[0];
18904 Modifier1Loc = Data.AllocClauseModifiersLoc[0];
18905 if (Data.AllocClauseModifiers.size() == 2) {
18906 Modifier2 = Data.AllocClauseModifiers[1];
18907 Modifier2Loc = Data.AllocClauseModifiersLoc[1];
18908 }
18909 }
18911 Data.DepModOrTailExpr, Data.AllocateAlignment, Modifier1, Modifier1Loc,
18912 Modifier2, Modifier2Loc, VarList, StartLoc, LParenLoc, ColonLoc,
18913 EndLoc);
18914 break;
18915 }
18916 case OMPC_nontemporal:
18917 Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
18918 break;
18919 case OMPC_inclusive:
18920 Res = ActOnOpenMPInclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18921 break;
18922 case OMPC_exclusive:
18923 Res = ActOnOpenMPExclusiveClause(VarList, StartLoc, LParenLoc, EndLoc);
18924 break;
18925 case OMPC_affinity:
18926 Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
18927 Data.DepModOrTailExpr, VarList);
18928 break;
18929 case OMPC_doacross:
18931 static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
18932 ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
18933 break;
18934 case OMPC_num_teams:
18935 Res = ActOnOpenMPNumTeamsClause(VarList, StartLoc, LParenLoc, EndLoc);
18936 break;
18937 case OMPC_thread_limit:
18938 Res = ActOnOpenMPThreadLimitClause(VarList, StartLoc, LParenLoc, EndLoc);
18939 break;
18940 case OMPC_if:
18941 case OMPC_depobj:
18942 case OMPC_final:
18943 case OMPC_num_threads:
18944 case OMPC_safelen:
18945 case OMPC_simdlen:
18946 case OMPC_sizes:
18947 case OMPC_allocator:
18948 case OMPC_collapse:
18949 case OMPC_default:
18950 case OMPC_proc_bind:
18951 case OMPC_schedule:
18952 case OMPC_ordered:
18953 case OMPC_nowait:
18954 case OMPC_untied:
18955 case OMPC_mergeable:
18956 case OMPC_threadprivate:
18957 case OMPC_groupprivate:
18958 case OMPC_read:
18959 case OMPC_write:
18960 case OMPC_update:
18961 case OMPC_capture:
18962 case OMPC_compare:
18963 case OMPC_seq_cst:
18964 case OMPC_acq_rel:
18965 case OMPC_acquire:
18966 case OMPC_release:
18967 case OMPC_relaxed:
18968 case OMPC_device:
18969 case OMPC_threads:
18970 case OMPC_simd:
18971 case OMPC_priority:
18972 case OMPC_grainsize:
18973 case OMPC_nogroup:
18974 case OMPC_num_tasks:
18975 case OMPC_hint:
18976 case OMPC_dist_schedule:
18977 case OMPC_defaultmap:
18978 case OMPC_unknown:
18979 case OMPC_uniform:
18980 case OMPC_unified_address:
18981 case OMPC_unified_shared_memory:
18982 case OMPC_reverse_offload:
18983 case OMPC_dynamic_allocators:
18984 case OMPC_atomic_default_mem_order:
18985 case OMPC_self_maps:
18986 case OMPC_device_type:
18987 case OMPC_match:
18988 case OMPC_order:
18989 case OMPC_at:
18990 case OMPC_severity:
18991 case OMPC_message:
18992 case OMPC_destroy:
18993 case OMPC_novariants:
18994 case OMPC_nocontext:
18995 case OMPC_detach:
18996 case OMPC_uses_allocators:
18997 case OMPC_when:
18998 case OMPC_bind:
18999 default:
19000 llvm_unreachable("Clause is not allowed.");
19001 }
19002 return Res;
19003}
19004
19006 ExprObjectKind OK,
19007 SourceLocation Loc) {
19008 ExprResult Res = SemaRef.BuildDeclRefExpr(
19009 Capture, Capture->getType().getNonReferenceType(), VK_LValue, Loc);
19010 if (!Res.isUsable())
19011 return ExprError();
19012 if (OK == OK_Ordinary && !getLangOpts().CPlusPlus) {
19013 Res = SemaRef.CreateBuiltinUnaryOp(Loc, UO_Deref, Res.get());
19014 if (!Res.isUsable())
19015 return ExprError();
19016 }
19017 if (VK != VK_LValue && Res.get()->isGLValue()) {
19018 Res = SemaRef.DefaultLvalueConversion(Res.get());
19019 if (!Res.isUsable())
19020 return ExprError();
19021 }
19022 return Res;
19023}
19024
19026 SourceLocation StartLoc,
19027 SourceLocation LParenLoc,
19028 SourceLocation EndLoc) {
19030 SmallVector<Expr *, 8> PrivateCopies;
19031 unsigned OMPVersion = getLangOpts().OpenMP;
19032 bool IsImplicitClause =
19033 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19034 for (Expr *RefExpr : VarList) {
19035 assert(RefExpr && "NULL expr in OpenMP private clause.");
19036 SourceLocation ELoc;
19037 SourceRange ERange;
19038 Expr *SimpleRefExpr = RefExpr;
19039 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19040 if (Res.second) {
19041 // It will be analyzed later.
19042 Vars.push_back(RefExpr);
19043 PrivateCopies.push_back(nullptr);
19044 }
19045 ValueDecl *D = Res.first;
19046 if (!D)
19047 continue;
19048
19049 QualType Type = D->getType();
19050 auto *VD = dyn_cast<VarDecl>(D);
19051
19052 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19053 // A variable that appears in a private clause must not have an incomplete
19054 // type or a reference type.
19055 if (SemaRef.RequireCompleteType(ELoc, Type,
19056 diag::err_omp_private_incomplete_type))
19057 continue;
19058 Type = Type.getNonReferenceType();
19059
19060 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19061 // A variable that is privatized must not have a const-qualified type
19062 // unless it is of class type with a mutable member. This restriction does
19063 // not apply to the firstprivate clause.
19064 //
19065 // OpenMP 3.1 [2.9.3.3, private clause, Restrictions]
19066 // A variable that appears in a private clause must not have a
19067 // const-qualified type unless it is of class type with a mutable member.
19068 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_private, ELoc))
19069 continue;
19070
19071 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19072 // in a Construct]
19073 // Variables with the predetermined data-sharing attributes may not be
19074 // listed in data-sharing attributes clauses, except for the cases
19075 // listed below. For these exceptions only, listing a predetermined
19076 // variable in a data-sharing attribute clause is allowed and overrides
19077 // the variable's predetermined data-sharing attributes.
19078 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19079 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) {
19080 Diag(ELoc, diag::err_omp_wrong_dsa)
19081 << getOpenMPClauseNameForDiag(DVar.CKind)
19082 << getOpenMPClauseNameForDiag(OMPC_private);
19084 continue;
19085 }
19086
19087 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19088 // Variably modified types are not supported for tasks.
19090 isOpenMPTaskingDirective(CurrDir)) {
19091 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19092 << getOpenMPClauseNameForDiag(OMPC_private) << Type
19093 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19094 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19096 Diag(D->getLocation(),
19097 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19098 << D;
19099 continue;
19100 }
19101
19102 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19103 // A list item cannot appear in both a map clause and a data-sharing
19104 // attribute clause on the same construct
19105 //
19106 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19107 // A list item cannot appear in both a map clause and a data-sharing
19108 // attribute clause on the same construct unless the construct is a
19109 // combined construct.
19110 if ((getLangOpts().OpenMP <= 45 &&
19112 CurrDir == OMPD_target) {
19113 OpenMPClauseKind ConflictKind;
19114 if (DSAStack->checkMappableExprComponentListsForDecl(
19115 VD, /*CurrentRegionOnly=*/true,
19117 OpenMPClauseKind WhereFoundClauseKind) -> bool {
19118 ConflictKind = WhereFoundClauseKind;
19119 return true;
19120 })) {
19121 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19122 << getOpenMPClauseNameForDiag(OMPC_private)
19123 << getOpenMPClauseNameForDiag(ConflictKind)
19124 << getOpenMPDirectiveName(CurrDir, OMPVersion);
19126 continue;
19127 }
19128 }
19129
19130 // OpenMP [2.9.3.3, Restrictions, C/C++, p.1]
19131 // A variable of class type (or array thereof) that appears in a private
19132 // clause requires an accessible, unambiguous default constructor for the
19133 // class type.
19134 // Generate helper private variable and initialize it with the default
19135 // value. The address of the original variable is replaced by the address of
19136 // the new private variable in CodeGen. This new variable is not added to
19137 // IdResolver, so the code in the OpenMP region uses original variable for
19138 // proper diagnostics.
19139 Type = Type.getUnqualifiedType();
19140 VarDecl *VDPrivate =
19141 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19142 D->hasAttrs() ? &D->getAttrs() : nullptr,
19143 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19144 SemaRef.ActOnUninitializedDecl(VDPrivate);
19145 if (VDPrivate->isInvalidDecl())
19146 continue;
19147 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19148 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
19149
19150 DeclRefExpr *Ref = nullptr;
19151 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19152 auto *FD = dyn_cast<FieldDecl>(D);
19153 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19154 if (VD)
19156 RefExpr->getExprLoc());
19157 else
19158 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19159 }
19160 if (!IsImplicitClause)
19161 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_private, Ref);
19162 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19163 ? RefExpr->IgnoreParens()
19164 : Ref);
19165 PrivateCopies.push_back(VDPrivateRefExpr);
19166 }
19167
19168 if (Vars.empty())
19169 return nullptr;
19170
19171 return OMPPrivateClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19172 Vars, PrivateCopies);
19173}
19174
19176 SourceLocation StartLoc,
19177 SourceLocation LParenLoc,
19178 SourceLocation EndLoc) {
19180 SmallVector<Expr *, 8> PrivateCopies;
19182 SmallVector<Decl *, 4> ExprCaptures;
19183 bool IsImplicitClause =
19184 StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
19185 SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
19186 unsigned OMPVersion = getLangOpts().OpenMP;
19187
19188 for (Expr *RefExpr : VarList) {
19189 assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
19190 SourceLocation ELoc;
19191 SourceRange ERange;
19192 Expr *SimpleRefExpr = RefExpr;
19193 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19194 if (Res.second) {
19195 // It will be analyzed later.
19196 Vars.push_back(RefExpr);
19197 PrivateCopies.push_back(nullptr);
19198 Inits.push_back(nullptr);
19199 }
19200 ValueDecl *D = Res.first;
19201 if (!D)
19202 continue;
19203
19204 ELoc = IsImplicitClause ? ImplicitClauseLoc : ELoc;
19205 QualType Type = D->getType();
19206 auto *VD = dyn_cast<VarDecl>(D);
19207
19208 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
19209 // A variable that appears in a private clause must not have an incomplete
19210 // type or a reference type.
19211 if (SemaRef.RequireCompleteType(ELoc, Type,
19212 diag::err_omp_firstprivate_incomplete_type))
19213 continue;
19214 Type = Type.getNonReferenceType();
19215
19216 // OpenMP [2.9.3.4, Restrictions, C/C++, p.1]
19217 // A variable of class type (or array thereof) that appears in a private
19218 // clause requires an accessible, unambiguous copy constructor for the
19219 // class type.
19220 QualType ElemType =
19222
19223 // If an implicit firstprivate variable found it was checked already.
19224 DSAStackTy::DSAVarData TopDVar;
19225 if (!IsImplicitClause) {
19226 DSAStackTy::DSAVarData DVar =
19227 DSAStack->getTopDSA(D, /*FromParent=*/false);
19228 TopDVar = DVar;
19229 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19230 bool IsConstant = ElemType.isConstant(getASTContext());
19231 // OpenMP [2.4.13, Data-sharing Attribute Clauses]
19232 // A list item that specifies a given variable may not appear in more
19233 // than one clause on the same directive, except that a variable may be
19234 // specified in both firstprivate and lastprivate clauses.
19235 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19236 // A list item may appear in a firstprivate or lastprivate clause but not
19237 // both.
19238 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
19239 (isOpenMPDistributeDirective(CurrDir) ||
19240 DVar.CKind != OMPC_lastprivate) &&
19241 DVar.RefExpr) {
19242 Diag(ELoc, diag::err_omp_wrong_dsa)
19243 << getOpenMPClauseNameForDiag(DVar.CKind)
19244 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19246 continue;
19247 }
19248
19249 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19250 // in a Construct]
19251 // Variables with the predetermined data-sharing attributes may not be
19252 // listed in data-sharing attributes clauses, except for the cases
19253 // listed below. For these exceptions only, listing a predetermined
19254 // variable in a data-sharing attribute clause is allowed and overrides
19255 // the variable's predetermined data-sharing attributes.
19256 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19257 // in a Construct, C/C++, p.2]
19258 // Variables with const-qualified type having no mutable member may be
19259 // listed in a firstprivate clause, even if they are static data members.
19260 if (!(IsConstant || (VD && VD->isStaticDataMember())) && !DVar.RefExpr &&
19261 DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared) {
19262 Diag(ELoc, diag::err_omp_wrong_dsa)
19263 << getOpenMPClauseNameForDiag(DVar.CKind)
19264 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
19266 continue;
19267 }
19268
19269 // OpenMP [2.9.3.4, Restrictions, p.2]
19270 // A list item that is private within a parallel region must not appear
19271 // in a firstprivate clause on a worksharing construct if any of the
19272 // worksharing regions arising from the worksharing construct ever bind
19273 // to any of the parallel regions arising from the parallel construct.
19274 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19275 // A list item that is private within a teams region must not appear in a
19276 // firstprivate clause on a distribute construct if any of the distribute
19277 // regions arising from the distribute construct ever bind to any of the
19278 // teams regions arising from the teams construct.
19279 // OpenMP 4.5 [2.15.3.4, Restrictions, p.3]
19280 // A list item that appears in a reduction clause of a teams construct
19281 // must not appear in a firstprivate clause on a distribute construct if
19282 // any of the distribute regions arising from the distribute construct
19283 // ever bind to any of the teams regions arising from the teams construct.
19284 if ((isOpenMPWorksharingDirective(CurrDir) ||
19285 isOpenMPDistributeDirective(CurrDir)) &&
19286 !isOpenMPParallelDirective(CurrDir) &&
19287 !isOpenMPTeamsDirective(CurrDir)) {
19288 DVar = DSAStack->getImplicitDSA(D, true);
19289 if (DVar.CKind != OMPC_shared &&
19290 (isOpenMPParallelDirective(DVar.DKind) ||
19291 isOpenMPTeamsDirective(DVar.DKind) ||
19292 DVar.DKind == OMPD_unknown)) {
19293 Diag(ELoc, diag::err_omp_required_access)
19294 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19295 << getOpenMPClauseNameForDiag(OMPC_shared);
19297 continue;
19298 }
19299 }
19300 // OpenMP [2.9.3.4, Restrictions, p.3]
19301 // A list item that appears in a reduction clause of a parallel construct
19302 // must not appear in a firstprivate clause on a worksharing or task
19303 // construct if any of the worksharing or task regions arising from the
19304 // worksharing or task construct ever bind to any of the parallel regions
19305 // arising from the parallel construct.
19306 // OpenMP [2.9.3.4, Restrictions, p.4]
19307 // A list item that appears in a reduction clause in worksharing
19308 // construct must not appear in a firstprivate clause in a task construct
19309 // encountered during execution of any of the worksharing regions arising
19310 // from the worksharing construct.
19311 if (isOpenMPTaskingDirective(CurrDir)) {
19312 DVar = DSAStack->hasInnermostDSA(
19313 D,
19314 [](OpenMPClauseKind C, bool AppliedToPointee) {
19315 return C == OMPC_reduction && !AppliedToPointee;
19316 },
19317 [](OpenMPDirectiveKind K) {
19318 return isOpenMPParallelDirective(K) ||
19321 },
19322 /*FromParent=*/true);
19323 if (DVar.CKind == OMPC_reduction &&
19324 (isOpenMPParallelDirective(DVar.DKind) ||
19325 isOpenMPWorksharingDirective(DVar.DKind) ||
19326 isOpenMPTeamsDirective(DVar.DKind))) {
19327 Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
19328 << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
19330 continue;
19331 }
19332 }
19333
19334 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
19335 // A list item cannot appear in both a map clause and a data-sharing
19336 // attribute clause on the same construct
19337 //
19338 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
19339 // A list item cannot appear in both a map clause and a data-sharing
19340 // attribute clause on the same construct unless the construct is a
19341 // combined construct.
19342 if ((getLangOpts().OpenMP <= 45 &&
19344 CurrDir == OMPD_target) {
19345 OpenMPClauseKind ConflictKind;
19346 if (DSAStack->checkMappableExprComponentListsForDecl(
19347 VD, /*CurrentRegionOnly=*/true,
19348 [&ConflictKind](
19350 OpenMPClauseKind WhereFoundClauseKind) {
19351 ConflictKind = WhereFoundClauseKind;
19352 return true;
19353 })) {
19354 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
19355 << getOpenMPClauseNameForDiag(OMPC_firstprivate)
19356 << getOpenMPClauseNameForDiag(ConflictKind)
19357 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19358 OMPVersion);
19360 continue;
19361 }
19362 }
19363 }
19364
19365 // Variably modified types are not supported for tasks.
19367 isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
19368 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
19369 << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
19370 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
19371 OMPVersion);
19372 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19374 Diag(D->getLocation(),
19375 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19376 << D;
19377 continue;
19378 }
19379
19380 Type = Type.getUnqualifiedType();
19381 VarDecl *VDPrivate =
19382 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
19383 D->hasAttrs() ? &D->getAttrs() : nullptr,
19384 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
19385 // Generate helper private variable and initialize it with the value of the
19386 // original variable. The address of the original variable is replaced by
19387 // the address of the new private variable in the CodeGen. This new variable
19388 // is not added to IdResolver, so the code in the OpenMP region uses
19389 // original variable for proper diagnostics and variable capturing.
19390 Expr *VDInitRefExpr = nullptr;
19391 // For arrays generate initializer for single element and replace it by the
19392 // original array element in CodeGen.
19393 if (Type->isArrayType()) {
19394 VarDecl *VDInit =
19395 buildVarDecl(SemaRef, RefExpr->getExprLoc(), ElemType, D->getName());
19396 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, ElemType, ELoc);
19397 Expr *Init = SemaRef.DefaultLvalueConversion(VDInitRefExpr).get();
19398 ElemType = ElemType.getUnqualifiedType();
19399 VarDecl *VDInitTemp = buildVarDecl(SemaRef, RefExpr->getExprLoc(),
19400 ElemType, ".firstprivate.temp");
19401 InitializedEntity Entity =
19404
19405 InitializationSequence InitSeq(SemaRef, Entity, Kind, Init);
19406 ExprResult Result = InitSeq.Perform(SemaRef, Entity, Kind, Init);
19407 if (Result.isInvalid())
19408 VDPrivate->setInvalidDecl();
19409 else
19410 VDPrivate->setInit(Result.getAs<Expr>());
19411 // Remove temp variable declaration.
19412 getASTContext().Deallocate(VDInitTemp);
19413 } else {
19414 VarDecl *VDInit = buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type,
19415 ".firstprivate.temp");
19416 VDInitRefExpr = buildDeclRefExpr(SemaRef, VDInit, RefExpr->getType(),
19417 RefExpr->getExprLoc());
19418 SemaRef.AddInitializerToDecl(
19419 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
19420 /*DirectInit=*/false);
19421 }
19422 if (VDPrivate->isInvalidDecl()) {
19423 if (IsImplicitClause) {
19424 Diag(RefExpr->getExprLoc(),
19425 diag::note_omp_task_predetermined_firstprivate_here);
19426 }
19427 continue;
19428 }
19429 SemaRef.CurContext->addDecl(VDPrivate);
19430 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
19431 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(),
19432 RefExpr->getExprLoc());
19433 DeclRefExpr *Ref = nullptr;
19434 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19435 if (TopDVar.CKind == OMPC_lastprivate) {
19436 Ref = TopDVar.PrivateCopy;
19437 } else {
19438 auto *FD = dyn_cast<FieldDecl>(D);
19439 VarDecl *VD = FD ? DSAStack->getImplicitFDCapExprDecl(FD) : nullptr;
19440 if (VD)
19441 Ref =
19443 RefExpr->getExprLoc());
19444 else
19445 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19446 if (VD || !isOpenMPCapturedDecl(D))
19447 ExprCaptures.push_back(Ref->getDecl());
19448 }
19449 }
19450 if (!IsImplicitClause)
19451 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
19452 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19453 ? RefExpr->IgnoreParens()
19454 : Ref);
19455 PrivateCopies.push_back(VDPrivateRefExpr);
19456 Inits.push_back(VDInitRefExpr);
19457 }
19458
19459 if (Vars.empty())
19460 return nullptr;
19461
19462 return OMPFirstprivateClause::Create(
19463 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, PrivateCopies, Inits,
19464 buildPreInits(getASTContext(), ExprCaptures));
19465}
19466
19469 SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc,
19470 SourceLocation LParenLoc, SourceLocation EndLoc) {
19471 if (LPKind == OMPC_LASTPRIVATE_unknown && LPKindLoc.isValid()) {
19472 assert(ColonLoc.isValid() && "Colon location must be valid.");
19473 Diag(LPKindLoc, diag::err_omp_unexpected_clause_value)
19474 << getListOfPossibleValues(OMPC_lastprivate, /*First=*/0,
19475 /*Last=*/OMPC_LASTPRIVATE_unknown)
19476 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19477 return nullptr;
19478 }
19479
19481 SmallVector<Expr *, 8> SrcExprs;
19482 SmallVector<Expr *, 8> DstExprs;
19483 SmallVector<Expr *, 8> AssignmentOps;
19484 SmallVector<Decl *, 4> ExprCaptures;
19485 SmallVector<Expr *, 4> ExprPostUpdates;
19486 for (Expr *RefExpr : VarList) {
19487 assert(RefExpr && "NULL expr in OpenMP lastprivate clause.");
19488 SourceLocation ELoc;
19489 SourceRange ERange;
19490 Expr *SimpleRefExpr = RefExpr;
19491 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19492 if (Res.second) {
19493 // It will be analyzed later.
19494 Vars.push_back(RefExpr);
19495 SrcExprs.push_back(nullptr);
19496 DstExprs.push_back(nullptr);
19497 AssignmentOps.push_back(nullptr);
19498 }
19499 ValueDecl *D = Res.first;
19500 if (!D)
19501 continue;
19502
19503 QualType Type = D->getType();
19504 auto *VD = dyn_cast<VarDecl>(D);
19505
19506 // OpenMP [2.14.3.5, Restrictions, C/C++, p.2]
19507 // A variable that appears in a lastprivate clause must not have an
19508 // incomplete type or a reference type.
19509 if (SemaRef.RequireCompleteType(ELoc, Type,
19510 diag::err_omp_lastprivate_incomplete_type))
19511 continue;
19512 Type = Type.getNonReferenceType();
19513
19514 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
19515 // A variable that is privatized must not have a const-qualified type
19516 // unless it is of class type with a mutable member. This restriction does
19517 // not apply to the firstprivate clause.
19518 //
19519 // OpenMP 3.1 [2.9.3.5, lastprivate clause, Restrictions]
19520 // A variable that appears in a lastprivate clause must not have a
19521 // const-qualified type unless it is of class type with a mutable member.
19522 if (rejectConstNotMutableType(SemaRef, D, Type, OMPC_lastprivate, ELoc))
19523 continue;
19524
19525 // OpenMP 5.0 [2.19.4.5 lastprivate Clause, Restrictions]
19526 // A list item that appears in a lastprivate clause with the conditional
19527 // modifier must be a scalar variable.
19528 if (LPKind == OMPC_LASTPRIVATE_conditional && !Type->isScalarType()) {
19529 Diag(ELoc, diag::err_omp_lastprivate_conditional_non_scalar);
19530 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
19532 Diag(D->getLocation(),
19533 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
19534 << D;
19535 continue;
19536 }
19537
19538 OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective();
19539 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
19540 // in a Construct]
19541 // Variables with the predetermined data-sharing attributes may not be
19542 // listed in data-sharing attributes clauses, except for the cases
19543 // listed below.
19544 // OpenMP 4.5 [2.10.8, Distribute Construct, p.3]
19545 // A list item may appear in a firstprivate or lastprivate clause but not
19546 // both.
19547 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19548 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate &&
19549 (isOpenMPDistributeDirective(CurrDir) ||
19550 DVar.CKind != OMPC_firstprivate) &&
19551 (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) {
19552 Diag(ELoc, diag::err_omp_wrong_dsa)
19553 << getOpenMPClauseNameForDiag(DVar.CKind)
19554 << getOpenMPClauseNameForDiag(OMPC_lastprivate);
19556 continue;
19557 }
19558
19559 // OpenMP [2.14.3.5, Restrictions, p.2]
19560 // A list item that is private within a parallel region, or that appears in
19561 // the reduction clause of a parallel construct, must not appear in a
19562 // lastprivate clause on a worksharing construct if any of the corresponding
19563 // worksharing regions ever binds to any of the corresponding parallel
19564 // regions.
19565 DSAStackTy::DSAVarData TopDVar = DVar;
19566 if (isOpenMPWorksharingDirective(CurrDir) &&
19567 !isOpenMPParallelDirective(CurrDir) &&
19568 !isOpenMPTeamsDirective(CurrDir)) {
19569 DVar = DSAStack->getImplicitDSA(D, true);
19570 if (DVar.CKind != OMPC_shared) {
19571 Diag(ELoc, diag::err_omp_required_access)
19572 << getOpenMPClauseNameForDiag(OMPC_lastprivate)
19573 << getOpenMPClauseNameForDiag(OMPC_shared);
19575 continue;
19576 }
19577 }
19578
19579 // OpenMP [2.14.3.5, Restrictions, C++, p.1,2]
19580 // A variable of class type (or array thereof) that appears in a
19581 // lastprivate clause requires an accessible, unambiguous default
19582 // constructor for the class type, unless the list item is also specified
19583 // in a firstprivate clause.
19584 // A variable of class type (or array thereof) that appears in a
19585 // lastprivate clause requires an accessible, unambiguous copy assignment
19586 // operator for the class type.
19588 VarDecl *SrcVD = buildVarDecl(SemaRef, ERange.getBegin(),
19589 Type.getUnqualifiedType(), ".lastprivate.src",
19590 D->hasAttrs() ? &D->getAttrs() : nullptr);
19591 DeclRefExpr *PseudoSrcExpr =
19592 buildDeclRefExpr(SemaRef, SrcVD, Type.getUnqualifiedType(), ELoc);
19593 VarDecl *DstVD =
19594 buildVarDecl(SemaRef, ERange.getBegin(), Type, ".lastprivate.dst",
19595 D->hasAttrs() ? &D->getAttrs() : nullptr);
19596 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
19597 // For arrays generate assignment operation for single element and replace
19598 // it by the original array element in CodeGen.
19599 ExprResult AssignmentOp = SemaRef.BuildBinOp(/*S=*/nullptr, ELoc, BO_Assign,
19600 PseudoDstExpr, PseudoSrcExpr);
19601 if (AssignmentOp.isInvalid())
19602 continue;
19603 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
19604 /*DiscardedValue=*/false);
19605 if (AssignmentOp.isInvalid())
19606 continue;
19607
19608 DeclRefExpr *Ref = nullptr;
19609 if (!VD && !SemaRef.CurContext->isDependentContext()) {
19610 if (TopDVar.CKind == OMPC_firstprivate) {
19611 Ref = TopDVar.PrivateCopy;
19612 } else {
19613 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
19614 if (!isOpenMPCapturedDecl(D))
19615 ExprCaptures.push_back(Ref->getDecl());
19616 }
19617 if ((TopDVar.CKind == OMPC_firstprivate && !TopDVar.PrivateCopy) ||
19618 (!isOpenMPCapturedDecl(D) &&
19619 Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>())) {
19620 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
19621 if (!RefRes.isUsable())
19622 continue;
19623 ExprResult PostUpdateRes =
19624 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
19625 SimpleRefExpr, RefRes.get());
19626 if (!PostUpdateRes.isUsable())
19627 continue;
19628 ExprPostUpdates.push_back(
19629 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
19630 }
19631 }
19632 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_lastprivate, Ref);
19633 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
19634 ? RefExpr->IgnoreParens()
19635 : Ref);
19636 SrcExprs.push_back(PseudoSrcExpr);
19637 DstExprs.push_back(PseudoDstExpr);
19638 AssignmentOps.push_back(AssignmentOp.get());
19639 }
19640
19641 if (Vars.empty())
19642 return nullptr;
19643
19644 return OMPLastprivateClause::Create(
19645 getASTContext(), StartLoc, LParenLoc, EndLoc, Vars, SrcExprs, DstExprs,
19646 AssignmentOps, LPKind, LPKindLoc, ColonLoc,
19647 buildPreInits(getASTContext(), ExprCaptures),
19648 buildPostUpdate(SemaRef, ExprPostUpdates));
19649}
19650
19652 SourceLocation StartLoc,
19653 SourceLocation LParenLoc,
19654 SourceLocation EndLoc) {
19656 for (Expr *RefExpr : VarList) {
19657 assert(RefExpr && "NULL expr in OpenMP shared clause.");
19658 SourceLocation ELoc;
19659 SourceRange ERange;
19660 Expr *SimpleRefExpr = RefExpr;
19661 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
19662 if (Res.second) {
19663 // It will be analyzed later.
19664 Vars.push_back(RefExpr);
19665 }
19666 ValueDecl *D = Res.first;
19667 if (!D)
19668 continue;
19669
19670 auto *VD = dyn_cast<VarDecl>(D);
19671 // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
19672 // in a Construct]
19673 // Variables with the predetermined data-sharing attributes may not be
19674 // listed in data-sharing attributes clauses, except for the cases
19675 // listed below. For these exceptions only, listing a predetermined
19676 // variable in a data-sharing attribute clause is allowed and overrides
19677 // the variable's predetermined data-sharing attributes.
19678 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
19679 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared &&
19680 DVar.RefExpr) {
19681 Diag(ELoc, diag::err_omp_wrong_dsa)
19682 << getOpenMPClauseNameForDiag(DVar.CKind)
19683 << getOpenMPClauseNameForDiag(OMPC_shared);
19685 continue;
19686 }
19687
19688 DeclRefExpr *Ref = nullptr;
19689 if (!VD && isOpenMPCapturedDecl(D) &&
19690 !SemaRef.CurContext->isDependentContext())
19691 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
19692 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_shared, Ref);
19693 Vars.push_back((VD || !Ref || SemaRef.CurContext->isDependentContext())
19694 ? RefExpr->IgnoreParens()
19695 : Ref);
19696 }
19697
19698 if (Vars.empty())
19699 return nullptr;
19700
19701 return OMPSharedClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
19702 Vars);
19703}
19704
19705namespace {
19706class DSARefChecker : public StmtVisitor<DSARefChecker, bool> {
19707 DSAStackTy *Stack;
19708
19709public:
19710 bool VisitDeclRefExpr(DeclRefExpr *E) {
19711 if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
19712 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, /*FromParent=*/false);
19713 if (DVar.CKind == OMPC_shared && !DVar.RefExpr)
19714 return false;
19715 if (DVar.CKind != OMPC_unknown)
19716 return true;
19717 DSAStackTy::DSAVarData DVarPrivate = Stack->hasDSA(
19718 VD,
19719 [](OpenMPClauseKind C, bool AppliedToPointee, bool) {
19720 return isOpenMPPrivate(C) && !AppliedToPointee;
19721 },
19722 [](OpenMPDirectiveKind) { return true; },
19723 /*FromParent=*/true);
19724 return DVarPrivate.CKind != OMPC_unknown;
19725 }
19726 return false;
19727 }
19728 bool VisitStmt(Stmt *S) {
19729 for (Stmt *Child : S->children()) {
19730 if (Child && Visit(Child))
19731 return true;
19732 }
19733 return false;
19734 }
19735 explicit DSARefChecker(DSAStackTy *S) : Stack(S) {}
19736};
19737} // namespace
19738
19739namespace {
19740// Transform MemberExpression for specified FieldDecl of current class to
19741// DeclRefExpr to specified OMPCapturedExprDecl.
19742class TransformExprToCaptures : public TreeTransform<TransformExprToCaptures> {
19743 typedef TreeTransform<TransformExprToCaptures> BaseTransform;
19744 ValueDecl *Field = nullptr;
19745 DeclRefExpr *CapturedExpr = nullptr;
19746
19747public:
19748 TransformExprToCaptures(Sema &SemaRef, ValueDecl *FieldDecl)
19749 : BaseTransform(SemaRef), Field(FieldDecl), CapturedExpr(nullptr) {}
19750
19751 ExprResult TransformMemberExpr(MemberExpr *E) {
19753 E->getMemberDecl() == Field) {
19754 CapturedExpr = buildCapture(SemaRef, Field, E, /*WithInit=*/false);
19755 return CapturedExpr;
19756 }
19757 return BaseTransform::TransformMemberExpr(E);
19758 }
19759 DeclRefExpr *getCapturedExpr() { return CapturedExpr; }
19760};
19761} // namespace
19762
19763template <typename T, typename U>
19765 SmallVectorImpl<U> &Lookups, const llvm::function_ref<T(ValueDecl *)> Gen) {
19766 for (U &Set : Lookups) {
19767 for (auto *D : Set) {
19768 if (T Res = Gen(cast<ValueDecl>(D)))
19769 return Res;
19770 }
19771 }
19772 return T();
19773}
19774
19776 assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
19777
19778 for (auto *RD : D->redecls()) {
19779 // Don't bother with extra checks if we already know this one isn't visible.
19780 if (RD == D)
19781 continue;
19782
19783 auto ND = cast<NamedDecl>(RD);
19784 if (LookupResult::isVisible(SemaRef, ND))
19785 return ND;
19786 }
19787
19788 return nullptr;
19789}
19790
19791static void
19793 SourceLocation Loc, QualType Ty,
19795 // Find all of the associated namespaces and classes based on the
19796 // arguments we have.
19797 Sema::AssociatedNamespaceSet AssociatedNamespaces;
19798 Sema::AssociatedClassSet AssociatedClasses;
19799 OpaqueValueExpr OVE(Loc, Ty, VK_LValue);
19800 SemaRef.FindAssociatedClassesAndNamespaces(Loc, &OVE, AssociatedNamespaces,
19801 AssociatedClasses);
19802
19803 // C++ [basic.lookup.argdep]p3:
19804 // Let X be the lookup set produced by unqualified lookup (3.4.1)
19805 // and let Y be the lookup set produced by argument dependent
19806 // lookup (defined as follows). If X contains [...] then Y is
19807 // empty. Otherwise Y is the set of declarations found in the
19808 // namespaces associated with the argument types as described
19809 // below. The set of declarations found by the lookup of the name
19810 // is the union of X and Y.
19811 //
19812 // Here, we compute Y and add its members to the overloaded
19813 // candidate set.
19814 for (auto *NS : AssociatedNamespaces) {
19815 // When considering an associated namespace, the lookup is the
19816 // same as the lookup performed when the associated namespace is
19817 // used as a qualifier (3.4.3.2) except that:
19818 //
19819 // -- Any using-directives in the associated namespace are
19820 // ignored.
19821 //
19822 // -- Any namespace-scope friend functions declared in
19823 // associated classes are visible within their respective
19824 // namespaces even if they are not visible during an ordinary
19825 // lookup (11.4).
19826 DeclContext::lookup_result R = NS->lookup(Id.getName());
19827 for (auto *D : R) {
19828 auto *Underlying = D;
19829 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19830 Underlying = USD->getTargetDecl();
19831
19832 if (!isa<OMPDeclareReductionDecl>(Underlying) &&
19833 !isa<OMPDeclareMapperDecl>(Underlying))
19834 continue;
19835
19836 if (!SemaRef.isVisible(D)) {
19837 D = findAcceptableDecl(SemaRef, D);
19838 if (!D)
19839 continue;
19840 if (auto *USD = dyn_cast<UsingShadowDecl>(D))
19841 Underlying = USD->getTargetDecl();
19842 }
19843 Lookups.emplace_back();
19844 Lookups.back().addDecl(Underlying);
19845 }
19846 }
19847}
19848
19849static ExprResult
19851 Scope *S, CXXScopeSpec &ReductionIdScopeSpec,
19852 const DeclarationNameInfo &ReductionId, QualType Ty,
19853 CXXCastPath &BasePath, Expr *UnresolvedReduction) {
19854 if (ReductionIdScopeSpec.isInvalid())
19855 return ExprError();
19856 SmallVector<UnresolvedSet<8>, 4> Lookups;
19857 if (S) {
19858 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19859 Lookup.suppressDiagnostics();
19860 while (S && SemaRef.LookupParsedName(Lookup, S, &ReductionIdScopeSpec,
19861 /*ObjectType=*/QualType())) {
19862 NamedDecl *D = Lookup.getRepresentativeDecl();
19863 do {
19864 S = S->getParent();
19865 } while (S && !S->isDeclScope(D));
19866 if (S)
19867 S = S->getParent();
19868 Lookups.emplace_back();
19869 Lookups.back().append(Lookup.begin(), Lookup.end());
19870 Lookup.clear();
19871 }
19872 } else if (auto *ULE =
19873 cast_or_null<UnresolvedLookupExpr>(UnresolvedReduction)) {
19874 Lookups.push_back(UnresolvedSet<8>());
19875 Decl *PrevD = nullptr;
19876 for (NamedDecl *D : ULE->decls()) {
19877 if (D == PrevD)
19878 Lookups.push_back(UnresolvedSet<8>());
19879 else if (auto *DRD = dyn_cast<OMPDeclareReductionDecl>(D))
19880 Lookups.back().addDecl(DRD);
19881 PrevD = D;
19882 }
19883 }
19884 if (SemaRef.CurContext->isDependentContext() || Ty->isDependentType() ||
19888 return !D->isInvalidDecl() &&
19889 (D->getType()->isDependentType() ||
19890 D->getType()->isInstantiationDependentType() ||
19891 D->getType()->containsUnexpandedParameterPack());
19892 })) {
19893 UnresolvedSet<8> ResSet;
19894 for (const UnresolvedSet<8> &Set : Lookups) {
19895 if (Set.empty())
19896 continue;
19897 ResSet.append(Set.begin(), Set.end());
19898 // The last item marks the end of all declarations at the specified scope.
19899 ResSet.addDecl(Set[Set.size() - 1]);
19900 }
19902 SemaRef.Context, /*NamingClass=*/nullptr,
19903 ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId,
19904 /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false,
19905 /*KnownInstantiationDependent=*/false);
19906 }
19907 // Lookup inside the classes.
19908 // C++ [over.match.oper]p3:
19909 // For a unary operator @ with an operand of a type whose
19910 // cv-unqualified version is T1, and for a binary operator @ with
19911 // a left operand of a type whose cv-unqualified version is T1 and
19912 // a right operand of a type whose cv-unqualified version is T2,
19913 // three sets of candidate functions, designated member
19914 // candidates, non-member candidates and built-in candidates, are
19915 // constructed as follows:
19916 // -- If T1 is a complete class type or a class currently being
19917 // defined, the set of member candidates is the result of the
19918 // qualified lookup of T1::operator@ (13.3.1.1.1); otherwise,
19919 // the set of member candidates is empty.
19920 LookupResult Lookup(SemaRef, ReductionId, Sema::LookupOMPReductionName);
19921 Lookup.suppressDiagnostics();
19922 if (Ty->isRecordType()) {
19923 // Complete the type if it can be completed.
19924 // If the type is neither complete nor being defined, bail out now.
19925 bool IsComplete = SemaRef.isCompleteType(Loc, Ty);
19926 auto *RD = Ty->castAsRecordDecl();
19927 if (IsComplete || RD->isBeingDefined()) {
19928 Lookup.clear();
19929 SemaRef.LookupQualifiedName(Lookup, RD);
19930 if (Lookup.empty()) {
19931 Lookups.emplace_back();
19932 Lookups.back().append(Lookup.begin(), Lookup.end());
19933 }
19934 }
19935 }
19936 // Perform ADL.
19937 if (SemaRef.getLangOpts().CPlusPlus)
19938 argumentDependentLookup(SemaRef, ReductionId, Loc, Ty, Lookups);
19940 Lookups, [&SemaRef, Ty](ValueDecl *D) -> ValueDecl * {
19941 if (!D->isInvalidDecl() &&
19942 SemaRef.Context.hasSameType(D->getType(), Ty))
19943 return D;
19944 return nullptr;
19945 }))
19946 return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(),
19947 VK_LValue, Loc);
19948 if (SemaRef.getLangOpts().CPlusPlus) {
19950 Lookups, [&SemaRef, Ty, Loc](ValueDecl *D) -> ValueDecl * {
19951 if (!D->isInvalidDecl() &&
19952 SemaRef.IsDerivedFrom(Loc, Ty, D->getType()) &&
19954 SemaRef.getASTContext()))
19955 return D;
19956 return nullptr;
19957 })) {
19958 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
19959 /*DetectVirtual=*/false);
19960 if (SemaRef.IsDerivedFrom(Loc, Ty, VD->getType(), Paths)) {
19961 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
19962 VD->getType().getUnqualifiedType()))) {
19963 if (SemaRef.CheckBaseClassAccess(
19964 Loc, VD->getType(), Ty, Paths.front(),
19965 /*DiagID=*/0) != Sema::AR_inaccessible) {
19966 SemaRef.BuildBasePathArray(Paths, BasePath);
19967 return SemaRef.BuildDeclRefExpr(
19968 VD, VD->getType().getNonReferenceType(), VK_LValue, Loc);
19969 }
19970 }
19971 }
19972 }
19973 }
19974 if (ReductionIdScopeSpec.isSet()) {
19975 SemaRef.Diag(Loc, diag::err_omp_not_resolved_reduction_identifier)
19976 << Ty << Range;
19977 return ExprError();
19978 }
19979 return ExprEmpty();
19980}
19981
19982namespace {
19983/// Data for the reduction-based clauses.
19984struct ReductionData {
19985 /// List of original reduction items.
19986 SmallVector<Expr *, 8> Vars;
19987 /// List of private copies of the reduction items.
19988 SmallVector<Expr *, 8> Privates;
19989 /// LHS expressions for the reduction_op expressions.
19990 SmallVector<Expr *, 8> LHSs;
19991 /// RHS expressions for the reduction_op expressions.
19992 SmallVector<Expr *, 8> RHSs;
19993 /// Reduction operation expression.
19994 SmallVector<Expr *, 8> ReductionOps;
19995 /// inscan copy operation expressions.
19996 SmallVector<Expr *, 8> InscanCopyOps;
19997 /// inscan copy temp array expressions for prefix sums.
19998 SmallVector<Expr *, 8> InscanCopyArrayTemps;
19999 /// inscan copy temp array element expressions for prefix sums.
20000 SmallVector<Expr *, 8> InscanCopyArrayElems;
20001 /// Taskgroup descriptors for the corresponding reduction items in
20002 /// in_reduction clauses.
20003 SmallVector<Expr *, 8> TaskgroupDescriptors;
20004 /// List of captures for clause.
20005 SmallVector<Decl *, 4> ExprCaptures;
20006 /// List of postupdate expressions.
20007 SmallVector<Expr *, 4> ExprPostUpdates;
20008 /// Reduction modifier.
20009 unsigned RedModifier = 0;
20010 /// Original modifier.
20011 unsigned OrigSharingModifier = 0;
20012 /// Private Variable Reduction
20013 SmallVector<bool, 8> IsPrivateVarReduction;
20014 ReductionData() = delete;
20015 /// Reserves required memory for the reduction data.
20016 ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
20017 : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
20018 Vars.reserve(Size);
20019 Privates.reserve(Size);
20020 LHSs.reserve(Size);
20021 RHSs.reserve(Size);
20022 ReductionOps.reserve(Size);
20023 IsPrivateVarReduction.reserve(Size);
20024 if (RedModifier == OMPC_REDUCTION_inscan) {
20025 InscanCopyOps.reserve(Size);
20026 InscanCopyArrayTemps.reserve(Size);
20027 InscanCopyArrayElems.reserve(Size);
20028 }
20029 TaskgroupDescriptors.reserve(Size);
20030 ExprCaptures.reserve(Size);
20031 ExprPostUpdates.reserve(Size);
20032 }
20033 /// Stores reduction item and reduction operation only (required for dependent
20034 /// reduction item).
20035 void push(Expr *Item, Expr *ReductionOp) {
20036 Vars.emplace_back(Item);
20037 Privates.emplace_back(nullptr);
20038 LHSs.emplace_back(nullptr);
20039 RHSs.emplace_back(nullptr);
20040 ReductionOps.emplace_back(ReductionOp);
20041 IsPrivateVarReduction.emplace_back(false);
20042 TaskgroupDescriptors.emplace_back(nullptr);
20043 if (RedModifier == OMPC_REDUCTION_inscan) {
20044 InscanCopyOps.push_back(nullptr);
20045 InscanCopyArrayTemps.push_back(nullptr);
20046 InscanCopyArrayElems.push_back(nullptr);
20047 }
20048 }
20049 /// Stores reduction data.
20050 void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
20051 Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
20052 Expr *CopyArrayElem, bool IsPrivate) {
20053 Vars.emplace_back(Item);
20054 Privates.emplace_back(Private);
20055 LHSs.emplace_back(LHS);
20056 RHSs.emplace_back(RHS);
20057 ReductionOps.emplace_back(ReductionOp);
20058 TaskgroupDescriptors.emplace_back(TaskgroupDescriptor);
20059 if (RedModifier == OMPC_REDUCTION_inscan) {
20060 InscanCopyOps.push_back(CopyOp);
20061 InscanCopyArrayTemps.push_back(CopyArrayTemp);
20062 InscanCopyArrayElems.push_back(CopyArrayElem);
20063 } else {
20064 assert(CopyOp == nullptr && CopyArrayTemp == nullptr &&
20065 CopyArrayElem == nullptr &&
20066 "Copy operation must be used for inscan reductions only.");
20067 }
20068 IsPrivateVarReduction.emplace_back(IsPrivate);
20069 }
20070};
20071} // namespace
20072
20074 ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement,
20075 SmallVectorImpl<llvm::APSInt> &ArraySizes) {
20076 const Expr *Length = OASE->getLength();
20077 if (Length == nullptr) {
20078 // For array sections of the form [1:] or [:], we would need to analyze
20079 // the lower bound...
20080 if (OASE->getColonLocFirst().isValid())
20081 return false;
20082
20083 // This is an array subscript which has implicit length 1!
20084 SingleElement = true;
20085 ArraySizes.push_back(llvm::APSInt::get(1));
20086 } else {
20087 Expr::EvalResult Result;
20088 if (!Length->EvaluateAsInt(Result, Context))
20089 return false;
20090
20091 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20092 SingleElement = (ConstantLengthValue.getSExtValue() == 1);
20093 ArraySizes.push_back(ConstantLengthValue);
20094 }
20095
20096 // Get the base of this array section and walk up from there.
20097 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
20098
20099 // We require length = 1 for all array sections except the right-most to
20100 // guarantee that the memory region is contiguous and has no holes in it.
20101 while (const auto *TempOASE = dyn_cast<ArraySectionExpr>(Base)) {
20102 Length = TempOASE->getLength();
20103 if (Length == nullptr) {
20104 // For array sections of the form [1:] or [:], we would need to analyze
20105 // the lower bound...
20106 if (OASE->getColonLocFirst().isValid())
20107 return false;
20108
20109 // This is an array subscript which has implicit length 1!
20110 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20111 ArraySizes.push_back(ConstantOne);
20112 } else {
20113 Expr::EvalResult Result;
20114 if (!Length->EvaluateAsInt(Result, Context))
20115 return false;
20116
20117 llvm::APSInt ConstantLengthValue = Result.Val.getInt();
20118 if (ConstantLengthValue.getSExtValue() != 1)
20119 return false;
20120
20121 ArraySizes.push_back(ConstantLengthValue);
20122 }
20123 Base = TempOASE->getBase()->IgnoreParenImpCasts();
20124 }
20125
20126 // If we have a single element, we don't need to add the implicit lengths.
20127 if (!SingleElement) {
20128 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) {
20129 // Has implicit length 1!
20130 llvm::APSInt ConstantOne = llvm::APSInt::get(1);
20131 ArraySizes.push_back(ConstantOne);
20132 Base = TempASE->getBase()->IgnoreParenImpCasts();
20133 }
20134 }
20135
20136 // This array section can be privatized as a single value or as a constant
20137 // sized array.
20138 return true;
20139}
20140
20141static BinaryOperatorKind
20143 if (BOK == BO_Add)
20144 return BO_AddAssign;
20145 if (BOK == BO_Mul)
20146 return BO_MulAssign;
20147 if (BOK == BO_And)
20148 return BO_AndAssign;
20149 if (BOK == BO_Or)
20150 return BO_OrAssign;
20151 if (BOK == BO_Xor)
20152 return BO_XorAssign;
20153 return BOK;
20154}
20155
20157 Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind,
20158 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20159 SourceLocation ColonLoc, SourceLocation EndLoc,
20160 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20161 ArrayRef<Expr *> UnresolvedReductions, ReductionData &RD) {
20162 DeclarationName DN = ReductionId.getName();
20164 BinaryOperatorKind BOK = BO_Comma;
20165
20166 ASTContext &Context = S.Context;
20167 // OpenMP [2.14.3.6, reduction clause]
20168 // C
20169 // reduction-identifier is either an identifier or one of the following
20170 // operators: +, -, *, &, |, ^, && and ||
20171 // C++
20172 // reduction-identifier is either an id-expression or one of the following
20173 // operators: +, -, *, &, |, ^, && and ||
20174 switch (OOK) {
20175 case OO_Plus:
20176 BOK = BO_Add;
20177 break;
20178 case OO_Minus:
20179 // Minus(-) operator is not supported in TR11 (OpenMP 6.0). Setting BOK to
20180 // BO_Comma will automatically diagnose it for OpenMP > 52 as not allowed
20181 // reduction identifier.
20182 if (S.LangOpts.OpenMP > 52)
20183 BOK = BO_Comma;
20184 else
20185 BOK = BO_Add;
20186 break;
20187 case OO_Star:
20188 BOK = BO_Mul;
20189 break;
20190 case OO_Amp:
20191 BOK = BO_And;
20192 break;
20193 case OO_Pipe:
20194 BOK = BO_Or;
20195 break;
20196 case OO_Caret:
20197 BOK = BO_Xor;
20198 break;
20199 case OO_AmpAmp:
20200 BOK = BO_LAnd;
20201 break;
20202 case OO_PipePipe:
20203 BOK = BO_LOr;
20204 break;
20205 case OO_New:
20206 case OO_Delete:
20207 case OO_Array_New:
20208 case OO_Array_Delete:
20209 case OO_Slash:
20210 case OO_Percent:
20211 case OO_Tilde:
20212 case OO_Exclaim:
20213 case OO_Equal:
20214 case OO_Less:
20215 case OO_Greater:
20216 case OO_LessEqual:
20217 case OO_GreaterEqual:
20218 case OO_PlusEqual:
20219 case OO_MinusEqual:
20220 case OO_StarEqual:
20221 case OO_SlashEqual:
20222 case OO_PercentEqual:
20223 case OO_CaretEqual:
20224 case OO_AmpEqual:
20225 case OO_PipeEqual:
20226 case OO_LessLess:
20227 case OO_GreaterGreater:
20228 case OO_LessLessEqual:
20229 case OO_GreaterGreaterEqual:
20230 case OO_EqualEqual:
20231 case OO_ExclaimEqual:
20232 case OO_Spaceship:
20233 case OO_PlusPlus:
20234 case OO_MinusMinus:
20235 case OO_Comma:
20236 case OO_ArrowStar:
20237 case OO_Arrow:
20238 case OO_Call:
20239 case OO_Subscript:
20240 case OO_Conditional:
20241 case OO_Coawait:
20243 llvm_unreachable("Unexpected reduction identifier");
20244 case OO_None:
20245 if (IdentifierInfo *II = DN.getAsIdentifierInfo()) {
20246 if (II->isStr("max"))
20247 BOK = BO_GT;
20248 else if (II->isStr("min"))
20249 BOK = BO_LT;
20250 }
20251 break;
20252 }
20253
20254 // OpenMP 5.2, 5.5.5 (see page 627, line 18) reduction Clause, Restrictions
20255 // A reduction clause with the minus (-) operator was deprecated
20256 if (OOK == OO_Minus && S.LangOpts.OpenMP == 52)
20257 S.Diag(ReductionId.getLoc(), diag::warn_omp_minus_in_reduction_deprecated);
20258
20259 SourceRange ReductionIdRange;
20260 if (ReductionIdScopeSpec.isValid())
20261 ReductionIdRange.setBegin(ReductionIdScopeSpec.getBeginLoc());
20262 else
20263 ReductionIdRange.setBegin(ReductionId.getBeginLoc());
20264 ReductionIdRange.setEnd(ReductionId.getEndLoc());
20265
20266 auto IR = UnresolvedReductions.begin(), ER = UnresolvedReductions.end();
20267 bool FirstIter = true;
20268 for (Expr *RefExpr : VarList) {
20269 assert(RefExpr && "nullptr expr in OpenMP reduction clause.");
20270 // OpenMP [2.1, C/C++]
20271 // A list item is a variable or array section, subject to the restrictions
20272 // specified in Section 2.4 on page 42 and in each of the sections
20273 // describing clauses and directives for which a list appears.
20274 // OpenMP [2.14.3.3, Restrictions, p.1]
20275 // A variable that is part of another variable (as an array or
20276 // structure element) cannot appear in a private clause.
20277 if (!FirstIter && IR != ER)
20278 ++IR;
20279 FirstIter = false;
20280 SourceLocation ELoc;
20281 SourceRange ERange;
20282 bool IsPrivate = false;
20283 Expr *SimpleRefExpr = RefExpr;
20284 auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
20285 /*AllowArraySection=*/true);
20286 if (Res.second) {
20287 // Try to find 'declare reduction' corresponding construct before using
20288 // builtin/overloaded operators.
20289 QualType Type = Context.DependentTy;
20290 CXXCastPath BasePath;
20291 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20292 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20293 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20294 Expr *ReductionOp = nullptr;
20295 if (S.CurContext->isDependentContext() &&
20296 (DeclareReductionRef.isUnset() ||
20297 isa<UnresolvedLookupExpr>(DeclareReductionRef.get())))
20298 ReductionOp = DeclareReductionRef.get();
20299 // It will be analyzed later.
20300 RD.push(RefExpr, ReductionOp);
20301 }
20302 ValueDecl *D = Res.first;
20303 if (!D)
20304 continue;
20305
20306 Expr *TaskgroupDescriptor = nullptr;
20307 QualType Type;
20308 auto *ASE = dyn_cast<ArraySubscriptExpr>(RefExpr->IgnoreParens());
20309 auto *OASE = dyn_cast<ArraySectionExpr>(RefExpr->IgnoreParens());
20310 if (ASE) {
20311 Type = ASE->getType().getNonReferenceType();
20312 } else if (OASE) {
20313 QualType BaseType =
20315 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
20316 Type = ATy->getElementType();
20317 else
20318 Type = BaseType->getPointeeType();
20319 Type = Type.getNonReferenceType();
20320 } else {
20321 Type = Context.getBaseElementType(D->getType().getNonReferenceType());
20322 }
20323 auto *VD = dyn_cast<VarDecl>(D);
20324
20325 // OpenMP [2.9.3.3, Restrictions, C/C++, p.3]
20326 // A variable that appears in a private clause must not have an incomplete
20327 // type or a reference type.
20328 if (S.RequireCompleteType(ELoc, D->getType(),
20329 diag::err_omp_reduction_incomplete_type))
20330 continue;
20331 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20332 // A list item that appears in a reduction clause must not be
20333 // const-qualified.
20334 if (rejectConstNotMutableType(S, D, Type, ClauseKind, ELoc,
20335 /*AcceptIfMutable=*/false, ASE || OASE))
20336 continue;
20337
20338 OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
20339 // OpenMP [2.9.3.6, Restrictions, C/C++, p.4]
20340 // If a list-item is a reference type then it must bind to the same object
20341 // for all threads of the team.
20342 if (!ASE && !OASE) {
20343 if (VD) {
20344 VarDecl *VDDef = VD->getDefinition();
20345 if (VD->getType()->isReferenceType() && VDDef && VDDef->hasInit()) {
20346 DSARefChecker Check(Stack);
20347 if (Check.Visit(VDDef->getInit())) {
20348 S.Diag(ELoc, diag::err_omp_reduction_ref_type_arg)
20349 << getOpenMPClauseNameForDiag(ClauseKind) << ERange;
20350 S.Diag(VDDef->getLocation(), diag::note_defined_here) << VDDef;
20351 continue;
20352 }
20353 }
20354 }
20355
20356 // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced
20357 // in a Construct]
20358 // Variables with the predetermined data-sharing attributes may not be
20359 // listed in data-sharing attributes clauses, except for the cases
20360 // listed below. For these exceptions only, listing a predetermined
20361 // variable in a data-sharing attribute clause is allowed and overrides
20362 // the variable's predetermined data-sharing attributes.
20363 // OpenMP [2.14.3.6, Restrictions, p.3]
20364 // Any number of reduction clauses can be specified on the directive,
20365 // but a list item can appear only once in the reduction clauses for that
20366 // directive.
20367 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20368 if (DVar.CKind == OMPC_reduction) {
20369 S.Diag(ELoc, diag::err_omp_once_referenced)
20370 << getOpenMPClauseNameForDiag(ClauseKind);
20371 if (DVar.RefExpr)
20372 S.Diag(DVar.RefExpr->getExprLoc(), diag::note_omp_referenced);
20373 continue;
20374 }
20375 if (DVar.CKind != OMPC_unknown) {
20376 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20377 << getOpenMPClauseNameForDiag(DVar.CKind)
20378 << getOpenMPClauseNameForDiag(OMPC_reduction);
20379 reportOriginalDsa(S, Stack, D, DVar);
20380 continue;
20381 }
20382
20383 // OpenMP [2.14.3.6, Restrictions, p.1]
20384 // A list item that appears in a reduction clause of a worksharing
20385 // construct must be shared in the parallel regions to which any of the
20386 // worksharing regions arising from the worksharing construct bind.
20387
20388 if (S.getLangOpts().OpenMP <= 52 &&
20390 !isOpenMPParallelDirective(CurrDir) &&
20391 !isOpenMPTeamsDirective(CurrDir)) {
20392 DVar = Stack->getImplicitDSA(D, true);
20393 if (DVar.CKind != OMPC_shared) {
20394 S.Diag(ELoc, diag::err_omp_required_access)
20395 << getOpenMPClauseNameForDiag(OMPC_reduction)
20396 << getOpenMPClauseNameForDiag(OMPC_shared);
20397 reportOriginalDsa(S, Stack, D, DVar);
20398 continue;
20399 }
20400 } else if (isOpenMPWorksharingDirective(CurrDir) &&
20401 !isOpenMPParallelDirective(CurrDir) &&
20402 !isOpenMPTeamsDirective(CurrDir)) {
20403 // OpenMP 6.0 [ 7.6.10 ]
20404 // Support Reduction over private variables with reduction clause.
20405 // A list item in a reduction clause can now be private in the enclosing
20406 // context. For orphaned constructs it is assumed to be shared unless
20407 // the original(private) modifier appears in the clause.
20408 DVar = Stack->getImplicitDSA(D, true);
20409 // Determine if the variable should be considered private
20410 IsPrivate = DVar.CKind != OMPC_shared;
20411 bool IsOrphaned = false;
20412 OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
20413 IsOrphaned = ParentDir == OMPD_unknown;
20414 if ((IsOrphaned &&
20415 RD.OrigSharingModifier == OMPC_ORIGINAL_SHARING_private))
20416 IsPrivate = true;
20417 }
20418 } else {
20419 // Threadprivates cannot be shared between threads, so dignose if the base
20420 // is a threadprivate variable.
20421 DSAStackTy::DSAVarData DVar = Stack->getTopDSA(D, /*FromParent=*/false);
20422 if (DVar.CKind == OMPC_threadprivate) {
20423 S.Diag(ELoc, diag::err_omp_wrong_dsa)
20424 << getOpenMPClauseNameForDiag(DVar.CKind)
20425 << getOpenMPClauseNameForDiag(OMPC_reduction);
20426 reportOriginalDsa(S, Stack, D, DVar);
20427 continue;
20428 }
20429 }
20430
20431 // Try to find 'declare reduction' corresponding construct before using
20432 // builtin/overloaded operators.
20433 CXXCastPath BasePath;
20434 ExprResult DeclareReductionRef = buildDeclareReductionRef(
20435 S, ELoc, ERange, Stack->getCurScope(), ReductionIdScopeSpec,
20436 ReductionId, Type, BasePath, IR == ER ? nullptr : *IR);
20437 if (DeclareReductionRef.isInvalid())
20438 continue;
20439 if (S.CurContext->isDependentContext() &&
20440 (DeclareReductionRef.isUnset() ||
20441 isa<UnresolvedLookupExpr>(DeclareReductionRef.get()))) {
20442 RD.push(RefExpr, DeclareReductionRef.get());
20443 continue;
20444 }
20445 if (BOK == BO_Comma && DeclareReductionRef.isUnset()) {
20446 // Not allowed reduction identifier is found.
20447 if (S.LangOpts.OpenMP > 52)
20448 S.Diag(ReductionId.getBeginLoc(),
20449 diag::err_omp_unknown_reduction_identifier_since_omp_6_0)
20450 << Type << ReductionIdRange;
20451 else
20452 S.Diag(ReductionId.getBeginLoc(),
20453 diag::err_omp_unknown_reduction_identifier_prior_omp_6_0)
20454 << Type << ReductionIdRange;
20455 continue;
20456 }
20457
20458 // OpenMP [2.14.3.6, reduction clause, Restrictions]
20459 // The type of a list item that appears in a reduction clause must be valid
20460 // for the reduction-identifier. For a max or min reduction in C, the type
20461 // of the list item must be an allowed arithmetic data type: char, int,
20462 // float, double, or _Bool, possibly modified with long, short, signed, or
20463 // unsigned. For a max or min reduction in C++, the type of the list item
20464 // must be an allowed arithmetic data type: char, wchar_t, int, float,
20465 // double, or bool, possibly modified with long, short, signed, or unsigned.
20466 if (DeclareReductionRef.isUnset()) {
20467 if ((BOK == BO_GT || BOK == BO_LT) &&
20468 !(Type->isScalarType() ||
20469 (S.getLangOpts().CPlusPlus && Type->isArithmeticType()))) {
20470 S.Diag(ELoc, diag::err_omp_clause_not_arithmetic_type_arg)
20471 << getOpenMPClauseNameForDiag(ClauseKind)
20472 << S.getLangOpts().CPlusPlus;
20473 if (!ASE && !OASE) {
20474 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20476 S.Diag(D->getLocation(),
20477 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20478 << D;
20479 }
20480 continue;
20481 }
20482 if ((BOK == BO_OrAssign || BOK == BO_AndAssign || BOK == BO_XorAssign) &&
20483 !S.getLangOpts().CPlusPlus && Type->isFloatingType()) {
20484 S.Diag(ELoc, diag::err_omp_clause_floating_type_arg)
20485 << getOpenMPClauseNameForDiag(ClauseKind);
20486 if (!ASE && !OASE) {
20487 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20489 S.Diag(D->getLocation(),
20490 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20491 << D;
20492 }
20493 continue;
20494 }
20495 }
20496
20497 Type = Type.getNonLValueExprType(Context).getUnqualifiedType();
20498 VarDecl *LHSVD = buildVarDecl(S, ELoc, Type, ".reduction.lhs",
20499 D->hasAttrs() ? &D->getAttrs() : nullptr);
20500 VarDecl *RHSVD = buildVarDecl(S, ELoc, Type, D->getName(),
20501 D->hasAttrs() ? &D->getAttrs() : nullptr);
20502 QualType PrivateTy = Type;
20503
20504 // Try if we can determine constant lengths for all array sections and avoid
20505 // the VLA.
20506 bool ConstantLengthOASE = false;
20507 if (OASE) {
20508 bool SingleElement;
20510 ConstantLengthOASE = checkOMPArraySectionConstantForReduction(
20511 Context, OASE, SingleElement, ArraySizes);
20512
20513 // If we don't have a single element, we must emit a constant array type.
20514 if (ConstantLengthOASE && !SingleElement) {
20515 for (llvm::APSInt &Size : ArraySizes)
20516 PrivateTy = Context.getConstantArrayType(PrivateTy, Size, nullptr,
20518 /*IndexTypeQuals=*/0);
20519 }
20520 }
20521
20522 if ((OASE && !ConstantLengthOASE) ||
20523 (!OASE && !ASE &&
20525 if (!Context.getTargetInfo().isVLASupported()) {
20526 if (isOpenMPTargetExecutionDirective(Stack->getCurrentDirective())) {
20527 S.Diag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20528 S.Diag(ELoc, diag::note_vla_unsupported);
20529 continue;
20530 } else {
20531 S.targetDiag(ELoc, diag::err_omp_reduction_vla_unsupported) << !!OASE;
20532 S.targetDiag(ELoc, diag::note_vla_unsupported);
20533 }
20534 }
20535 // For arrays/array sections only:
20536 // Create pseudo array type for private copy. The size for this array will
20537 // be generated during codegen.
20538 // For array subscripts or single variables Private Ty is the same as Type
20539 // (type of the variable or single array element).
20540 PrivateTy = Context.getVariableArrayType(
20541 Type,
20542 new (Context)
20543 OpaqueValueExpr(ELoc, Context.getSizeType(), VK_PRValue),
20544 ArraySizeModifier::Normal, /*IndexTypeQuals=*/0);
20545 } else if (!ASE && !OASE &&
20546 Context.getAsArrayType(D->getType().getNonReferenceType())) {
20547 PrivateTy = D->getType().getNonReferenceType();
20548 }
20549 // Private copy.
20550 VarDecl *PrivateVD =
20551 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20552 D->hasAttrs() ? &D->getAttrs() : nullptr,
20553 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
20554 // Add initializer for private variable.
20555 Expr *Init = nullptr;
20556 DeclRefExpr *LHSDRE = buildDeclRefExpr(S, LHSVD, Type, ELoc);
20557 DeclRefExpr *RHSDRE = buildDeclRefExpr(S, RHSVD, Type, ELoc);
20558 if (DeclareReductionRef.isUsable()) {
20559 auto *DRDRef = DeclareReductionRef.getAs<DeclRefExpr>();
20560 auto *DRD = cast<OMPDeclareReductionDecl>(DRDRef->getDecl());
20561 if (DRD->getInitializer()) {
20562 Init = DRDRef;
20563 RHSVD->setInit(DRDRef);
20565 }
20566 } else {
20567 switch (BOK) {
20568 case BO_Add:
20569 case BO_Xor:
20570 case BO_Or:
20571 case BO_LOr:
20572 // '+', '-', '^', '|', '||' reduction ops - initializer is '0'.
20574 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/0).get();
20575 break;
20576 case BO_Mul:
20577 case BO_LAnd:
20578 if (Type->isScalarType() || Type->isAnyComplexType()) {
20579 // '*' and '&&' reduction ops - initializer is '1'.
20580 Init = S.ActOnIntegerConstant(ELoc, /*Val=*/1).get();
20581 }
20582 break;
20583 case BO_And: {
20584 // '&' reduction op - initializer is '~0'.
20585 QualType OrigType = Type;
20586 if (auto *ComplexTy = OrigType->getAs<ComplexType>())
20587 Type = ComplexTy->getElementType();
20588 if (Type->isRealFloatingType()) {
20589 llvm::APFloat InitValue = llvm::APFloat::getAllOnesValue(
20590 Context.getFloatTypeSemantics(Type));
20591 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20592 Type, ELoc);
20593 } else if (Type->isScalarType()) {
20594 uint64_t Size = Context.getTypeSize(Type);
20595 QualType IntTy = Context.getIntTypeForBitwidth(Size, /*Signed=*/0);
20596 llvm::APInt InitValue = llvm::APInt::getAllOnes(Size);
20597 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20598 }
20599 if (Init && OrigType->isAnyComplexType()) {
20600 // Init = 0xFFFF + 0xFFFFi;
20601 auto *Im = new (Context) ImaginaryLiteral(Init, OrigType);
20602 Init = S.CreateBuiltinBinOp(ELoc, BO_Add, Init, Im).get();
20603 }
20604 Type = OrigType;
20605 break;
20606 }
20607 case BO_LT:
20608 case BO_GT: {
20609 // 'min' reduction op - initializer is 'Largest representable number in
20610 // the reduction list item type'.
20611 // 'max' reduction op - initializer is 'Least representable number in
20612 // the reduction list item type'.
20613 if (Type->isIntegerType() || Type->isPointerType()) {
20614 bool IsSigned = Type->hasSignedIntegerRepresentation();
20615 uint64_t Size = Context.getTypeSize(Type);
20616 QualType IntTy =
20617 Context.getIntTypeForBitwidth(Size, /*Signed=*/IsSigned);
20618 llvm::APInt InitValue =
20619 (BOK != BO_LT) ? IsSigned ? llvm::APInt::getSignedMinValue(Size)
20620 : llvm::APInt::getMinValue(Size)
20621 : IsSigned ? llvm::APInt::getSignedMaxValue(Size)
20622 : llvm::APInt::getMaxValue(Size);
20623 Init = IntegerLiteral::Create(Context, InitValue, IntTy, ELoc);
20624 if (Type->isPointerType()) {
20625 // Cast to pointer type.
20627 ELoc, Context.getTrivialTypeSourceInfo(Type, ELoc), ELoc, Init);
20628 if (CastExpr.isInvalid())
20629 continue;
20630 Init = CastExpr.get();
20631 }
20632 } else if (Type->isRealFloatingType()) {
20633 llvm::APFloat InitValue = llvm::APFloat::getLargest(
20634 Context.getFloatTypeSemantics(Type), BOK != BO_LT);
20635 Init = FloatingLiteral::Create(Context, InitValue, /*isexact=*/true,
20636 Type, ELoc);
20637 }
20638 break;
20639 }
20640 case BO_PtrMemD:
20641 case BO_PtrMemI:
20642 case BO_MulAssign:
20643 case BO_Div:
20644 case BO_Rem:
20645 case BO_Sub:
20646 case BO_Shl:
20647 case BO_Shr:
20648 case BO_LE:
20649 case BO_GE:
20650 case BO_EQ:
20651 case BO_NE:
20652 case BO_Cmp:
20653 case BO_AndAssign:
20654 case BO_XorAssign:
20655 case BO_OrAssign:
20656 case BO_Assign:
20657 case BO_AddAssign:
20658 case BO_SubAssign:
20659 case BO_DivAssign:
20660 case BO_RemAssign:
20661 case BO_ShlAssign:
20662 case BO_ShrAssign:
20663 case BO_Comma:
20664 llvm_unreachable("Unexpected reduction operation");
20665 }
20666 }
20667 if (Init && DeclareReductionRef.isUnset()) {
20668 S.AddInitializerToDecl(RHSVD, Init, /*DirectInit=*/false);
20669 // Store initializer for single element in private copy. Will be used
20670 // during codegen.
20671 PrivateVD->setInit(RHSVD->getInit());
20672 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20673 } else if (!Init) {
20674 S.ActOnUninitializedDecl(RHSVD);
20675 // Store initializer for single element in private copy. Will be used
20676 // during codegen.
20677 PrivateVD->setInit(RHSVD->getInit());
20678 PrivateVD->setInitStyle(RHSVD->getInitStyle());
20679 }
20680 if (RHSVD->isInvalidDecl())
20681 continue;
20682 if (!RHSVD->hasInit() && DeclareReductionRef.isUnset()) {
20683 S.Diag(ELoc, diag::err_omp_reduction_id_not_compatible)
20684 << Type << ReductionIdRange;
20685 bool IsDecl = !VD || VD->isThisDeclarationADefinition(Context) ==
20687 S.Diag(D->getLocation(),
20688 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
20689 << D;
20690 continue;
20691 }
20692 DeclRefExpr *PrivateDRE = buildDeclRefExpr(S, PrivateVD, PrivateTy, ELoc);
20693 ExprResult ReductionOp;
20694 if (DeclareReductionRef.isUsable()) {
20695 QualType RedTy = DeclareReductionRef.get()->getType();
20696 QualType PtrRedTy = Context.getPointerType(RedTy);
20697 ExprResult LHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, LHSDRE);
20698 ExprResult RHS = S.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, RHSDRE);
20699 if (!BasePath.empty()) {
20700 LHS = S.DefaultLvalueConversion(LHS.get());
20701 RHS = S.DefaultLvalueConversion(RHS.get());
20703 Context, PtrRedTy, CK_UncheckedDerivedToBase, LHS.get(), &BasePath,
20704 LHS.get()->getValueKind(), FPOptionsOverride());
20706 Context, PtrRedTy, CK_UncheckedDerivedToBase, RHS.get(), &BasePath,
20707 RHS.get()->getValueKind(), FPOptionsOverride());
20708 }
20710 QualType Params[] = {PtrRedTy, PtrRedTy};
20711 QualType FnTy = Context.getFunctionType(Context.VoidTy, Params, EPI);
20712 auto *OVE = new (Context) OpaqueValueExpr(
20713 ELoc, Context.getPointerType(FnTy), VK_PRValue, OK_Ordinary,
20714 S.DefaultLvalueConversion(DeclareReductionRef.get()).get());
20715 Expr *Args[] = {LHS.get(), RHS.get()};
20716 ReductionOp =
20717 CallExpr::Create(Context, OVE, Args, Context.VoidTy, VK_PRValue, ELoc,
20719 } else {
20721 if (Type->isRecordType() && CombBOK != BOK) {
20723 ReductionOp =
20724 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20725 CombBOK, LHSDRE, RHSDRE);
20726 }
20727 if (!ReductionOp.isUsable()) {
20728 ReductionOp =
20729 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(), BOK,
20730 LHSDRE, RHSDRE);
20731 if (ReductionOp.isUsable()) {
20732 if (BOK != BO_LT && BOK != BO_GT) {
20733 ReductionOp =
20734 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20735 BO_Assign, LHSDRE, ReductionOp.get());
20736 } else {
20737 auto *ConditionalOp = new (Context)
20738 ConditionalOperator(ReductionOp.get(), ELoc, LHSDRE, ELoc,
20739 RHSDRE, Type, VK_LValue, OK_Ordinary);
20740 ReductionOp =
20741 S.BuildBinOp(Stack->getCurScope(), ReductionId.getBeginLoc(),
20742 BO_Assign, LHSDRE, ConditionalOp);
20743 }
20744 }
20745 }
20746 if (ReductionOp.isUsable())
20747 ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(),
20748 /*DiscardedValue=*/false);
20749 if (!ReductionOp.isUsable())
20750 continue;
20751 }
20752
20753 // Add copy operations for inscan reductions.
20754 // LHS = RHS;
20755 ExprResult CopyOpRes, TempArrayRes, TempArrayElem;
20756 if (ClauseKind == OMPC_reduction &&
20757 RD.RedModifier == OMPC_REDUCTION_inscan) {
20758 ExprResult RHS = S.DefaultLvalueConversion(RHSDRE);
20759 CopyOpRes = S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, LHSDRE,
20760 RHS.get());
20761 if (!CopyOpRes.isUsable())
20762 continue;
20763 CopyOpRes =
20764 S.ActOnFinishFullExpr(CopyOpRes.get(), /*DiscardedValue=*/true);
20765 if (!CopyOpRes.isUsable())
20766 continue;
20767 // For simd directive and simd-based directives in simd mode no need to
20768 // construct temp array, need just a single temp element.
20769 if (Stack->getCurrentDirective() == OMPD_simd ||
20770 (S.getLangOpts().OpenMPSimd &&
20771 isOpenMPSimdDirective(Stack->getCurrentDirective()))) {
20772 VarDecl *TempArrayVD =
20773 buildVarDecl(S, ELoc, PrivateTy, D->getName(),
20774 D->hasAttrs() ? &D->getAttrs() : nullptr);
20775 // Add a constructor to the temp decl.
20776 S.ActOnUninitializedDecl(TempArrayVD);
20777 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, PrivateTy, ELoc);
20778 } else {
20779 // Build temp array for prefix sum.
20780 auto *Dim = new (S.Context)
20783 PrivateTy, Dim, ArraySizeModifier::Normal,
20784 /*IndexTypeQuals=*/0);
20785 VarDecl *TempArrayVD =
20786 buildVarDecl(S, ELoc, ArrayTy, D->getName(),
20787 D->hasAttrs() ? &D->getAttrs() : nullptr);
20788 // Add a constructor to the temp decl.
20789 S.ActOnUninitializedDecl(TempArrayVD);
20790 TempArrayRes = buildDeclRefExpr(S, TempArrayVD, ArrayTy, ELoc);
20791 TempArrayElem =
20792 S.DefaultFunctionArrayLvalueConversion(TempArrayRes.get());
20793 auto *Idx = new (S.Context)
20795 TempArrayElem = S.CreateBuiltinArraySubscriptExpr(TempArrayElem.get(),
20796 ELoc, Idx, ELoc);
20797 }
20798 }
20799
20800 // OpenMP [2.15.4.6, Restrictions, p.2]
20801 // A list item that appears in an in_reduction clause of a task construct
20802 // must appear in a task_reduction clause of a construct associated with a
20803 // taskgroup region that includes the participating task in its taskgroup
20804 // set. The construct associated with the innermost region that meets this
20805 // condition must specify the same reduction-identifier as the in_reduction
20806 // clause.
20807 if (ClauseKind == OMPC_in_reduction) {
20808 SourceRange ParentSR;
20809 BinaryOperatorKind ParentBOK;
20810 const Expr *ParentReductionOp = nullptr;
20811 Expr *ParentBOKTD = nullptr, *ParentReductionOpTD = nullptr;
20812 DSAStackTy::DSAVarData ParentBOKDSA =
20813 Stack->getTopMostTaskgroupReductionData(D, ParentSR, ParentBOK,
20814 ParentBOKTD);
20815 DSAStackTy::DSAVarData ParentReductionOpDSA =
20816 Stack->getTopMostTaskgroupReductionData(
20817 D, ParentSR, ParentReductionOp, ParentReductionOpTD);
20818 bool IsParentBOK = ParentBOKDSA.DKind != OMPD_unknown;
20819 bool IsParentReductionOp = ParentReductionOpDSA.DKind != OMPD_unknown;
20820 if ((DeclareReductionRef.isUnset() && IsParentReductionOp) ||
20821 (DeclareReductionRef.isUsable() && IsParentBOK) ||
20822 (IsParentBOK && BOK != ParentBOK) || IsParentReductionOp) {
20823 bool EmitError = true;
20824 if (IsParentReductionOp && DeclareReductionRef.isUsable()) {
20825 llvm::FoldingSetNodeID RedId, ParentRedId;
20826 ParentReductionOp->Profile(ParentRedId, Context, /*Canonical=*/true);
20827 DeclareReductionRef.get()->Profile(RedId, Context,
20828 /*Canonical=*/true);
20829 EmitError = RedId != ParentRedId;
20830 }
20831 if (EmitError) {
20832 S.Diag(ReductionId.getBeginLoc(),
20833 diag::err_omp_reduction_identifier_mismatch)
20834 << ReductionIdRange << RefExpr->getSourceRange();
20835 S.Diag(ParentSR.getBegin(),
20836 diag::note_omp_previous_reduction_identifier)
20837 << ParentSR
20838 << (IsParentBOK ? ParentBOKDSA.RefExpr
20839 : ParentReductionOpDSA.RefExpr)
20840 ->getSourceRange();
20841 continue;
20842 }
20843 }
20844 TaskgroupDescriptor = IsParentBOK ? ParentBOKTD : ParentReductionOpTD;
20845 }
20846
20847 DeclRefExpr *Ref = nullptr;
20848 Expr *VarsExpr = RefExpr->IgnoreParens();
20849 if (!VD && !S.CurContext->isDependentContext()) {
20850 if (ASE || OASE) {
20851 TransformExprToCaptures RebuildToCapture(S, D);
20852 VarsExpr =
20853 RebuildToCapture.TransformExpr(RefExpr->IgnoreParens()).get();
20854 Ref = RebuildToCapture.getCapturedExpr();
20855 } else {
20856 VarsExpr = Ref = buildCapture(S, D, SimpleRefExpr, /*WithInit=*/false);
20857 }
20858 if (!S.OpenMP().isOpenMPCapturedDecl(D)) {
20859 RD.ExprCaptures.emplace_back(Ref->getDecl());
20860 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
20861 ExprResult RefRes = S.DefaultLvalueConversion(Ref);
20862 if (!RefRes.isUsable())
20863 continue;
20864 ExprResult PostUpdateRes =
20865 S.BuildBinOp(Stack->getCurScope(), ELoc, BO_Assign, SimpleRefExpr,
20866 RefRes.get());
20867 if (!PostUpdateRes.isUsable())
20868 continue;
20869 if (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
20870 Stack->getCurrentDirective() == OMPD_taskgroup) {
20871 S.Diag(RefExpr->getExprLoc(),
20872 diag::err_omp_reduction_non_addressable_expression)
20873 << RefExpr->getSourceRange();
20874 continue;
20875 }
20876 RD.ExprPostUpdates.emplace_back(
20877 S.IgnoredValueConversions(PostUpdateRes.get()).get());
20878 }
20879 }
20880 }
20881 // All reduction items are still marked as reduction (to do not increase
20882 // code base size).
20883 unsigned Modifier = RD.RedModifier;
20884 // Consider task_reductions as reductions with task modifier. Required for
20885 // correct analysis of in_reduction clauses.
20886 if (CurrDir == OMPD_taskgroup && ClauseKind == OMPC_task_reduction)
20887 Modifier = OMPC_REDUCTION_task;
20888 Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref, Modifier,
20889 ASE || OASE);
20890 if (Modifier == OMPC_REDUCTION_task &&
20891 (CurrDir == OMPD_taskgroup ||
20892 ((isOpenMPParallelDirective(CurrDir) ||
20893 isOpenMPWorksharingDirective(CurrDir)) &&
20894 !isOpenMPSimdDirective(CurrDir)))) {
20895 if (DeclareReductionRef.isUsable())
20896 Stack->addTaskgroupReductionData(D, ReductionIdRange,
20897 DeclareReductionRef.get());
20898 else
20899 Stack->addTaskgroupReductionData(D, ReductionIdRange, BOK);
20900 }
20901 RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
20902 TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
20903 TempArrayElem.get(), IsPrivate);
20904 }
20905 return RD.Vars.empty();
20906}
20907
20909 ArrayRef<Expr *> VarList,
20911 SourceLocation StartLoc, SourceLocation LParenLoc,
20912 SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
20913 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20914 ArrayRef<Expr *> UnresolvedReductions) {
20916 static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
20917 OpenMPOriginalSharingModifier OriginalSharingModifier =
20918 static_cast<OpenMPOriginalSharingModifier>(
20919 Modifiers.OriginalSharingModifier);
20920 if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
20921 Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
20922 << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
20923 /*Last=*/OMPC_REDUCTION_unknown)
20924 << getOpenMPClauseNameForDiag(OMPC_reduction);
20925 return nullptr;
20926 }
20927 // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
20928 // A reduction clause with the inscan reduction-modifier may only appear on a
20929 // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
20930 // construct, a parallel worksharing-loop construct or a parallel
20931 // worksharing-loop SIMD construct.
20932 if (Modifier == OMPC_REDUCTION_inscan &&
20933 (DSAStack->getCurrentDirective() != OMPD_for &&
20934 DSAStack->getCurrentDirective() != OMPD_for_simd &&
20935 DSAStack->getCurrentDirective() != OMPD_simd &&
20936 DSAStack->getCurrentDirective() != OMPD_parallel_for &&
20937 DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
20938 Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
20939 return nullptr;
20940 }
20941 ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
20942 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
20943 StartLoc, LParenLoc, ColonLoc, EndLoc,
20944 ReductionIdScopeSpec, ReductionId,
20945 UnresolvedReductions, RD))
20946 return nullptr;
20947
20948 return OMPReductionClause::Create(
20949 getASTContext(), StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
20950 Modifier, RD.Vars,
20951 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20952 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
20953 RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
20954 buildPreInits(getASTContext(), RD.ExprCaptures),
20955 buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
20956 OriginalSharingModifier);
20957}
20958
20960 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20961 SourceLocation ColonLoc, SourceLocation EndLoc,
20962 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20963 ArrayRef<Expr *> UnresolvedReductions) {
20964 ReductionData RD(VarList.size());
20965 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_task_reduction,
20966 VarList, StartLoc, LParenLoc, ColonLoc,
20967 EndLoc, ReductionIdScopeSpec, ReductionId,
20968 UnresolvedReductions, RD))
20969 return nullptr;
20970
20971 return OMPTaskReductionClause::Create(
20972 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20973 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20974 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps,
20975 buildPreInits(getASTContext(), RD.ExprCaptures),
20976 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20977}
20978
20980 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
20981 SourceLocation ColonLoc, SourceLocation EndLoc,
20982 CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
20983 ArrayRef<Expr *> UnresolvedReductions) {
20984 ReductionData RD(VarList.size());
20985 if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_in_reduction, VarList,
20986 StartLoc, LParenLoc, ColonLoc, EndLoc,
20987 ReductionIdScopeSpec, ReductionId,
20988 UnresolvedReductions, RD))
20989 return nullptr;
20990
20991 return OMPInReductionClause::Create(
20992 getASTContext(), StartLoc, LParenLoc, ColonLoc, EndLoc, RD.Vars,
20993 ReductionIdScopeSpec.getWithLocInContext(getASTContext()), ReductionId,
20994 RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.TaskgroupDescriptors,
20995 buildPreInits(getASTContext(), RD.ExprCaptures),
20996 buildPostUpdate(SemaRef, RD.ExprPostUpdates));
20997}
20998
21000 SourceLocation LinLoc) {
21001 if ((!getLangOpts().CPlusPlus && LinKind != OMPC_LINEAR_val) ||
21002 LinKind == OMPC_LINEAR_unknown || LinKind == OMPC_LINEAR_step) {
21003 Diag(LinLoc, diag::err_omp_wrong_linear_modifier)
21004 << getLangOpts().CPlusPlus;
21005 return true;
21006 }
21007 return false;
21008}
21009
21011 OpenMPLinearClauseKind LinKind,
21012 QualType Type, bool IsDeclareSimd) {
21013 const auto *VD = dyn_cast_or_null<VarDecl>(D);
21014 // A variable must not have an incomplete type or a reference type.
21015 if (SemaRef.RequireCompleteType(ELoc, Type,
21016 diag::err_omp_linear_incomplete_type))
21017 return true;
21018 if ((LinKind == OMPC_LINEAR_uval || LinKind == OMPC_LINEAR_ref) &&
21019 !Type->isReferenceType()) {
21020 Diag(ELoc, diag::err_omp_wrong_linear_modifier_non_reference)
21021 << Type << getOpenMPSimpleClauseTypeName(OMPC_linear, LinKind);
21022 return true;
21023 }
21024 Type = Type.getNonReferenceType();
21025
21026 // OpenMP 5.0 [2.19.3, List Item Privatization, Restrictions]
21027 // A variable that is privatized must not have a const-qualified type
21028 // unless it is of class type with a mutable member. This restriction does
21029 // not apply to the firstprivate clause, nor to the linear clause on
21030 // declarative directives (like declare simd).
21031 if (!IsDeclareSimd &&
21032 rejectConstNotMutableType(SemaRef, D, Type, OMPC_linear, ELoc))
21033 return true;
21034
21035 // A list item must be of integral or pointer type.
21036 Type = Type.getUnqualifiedType().getCanonicalType();
21037 const auto *Ty = Type.getTypePtrOrNull();
21038 if (!Ty || (LinKind != OMPC_LINEAR_ref && !Ty->isDependentType() &&
21039 !Ty->isIntegralType(getASTContext()) && !Ty->isPointerType())) {
21040 Diag(ELoc, diag::err_omp_linear_expected_int_or_ptr) << Type;
21041 if (D) {
21042 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21044 Diag(D->getLocation(),
21045 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21046 << D;
21047 }
21048 return true;
21049 }
21050 return false;
21051}
21052
21054 ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc,
21055 SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind,
21056 SourceLocation LinLoc, SourceLocation ColonLoc,
21057 SourceLocation StepModifierLoc, SourceLocation EndLoc) {
21061 SmallVector<Decl *, 4> ExprCaptures;
21062 SmallVector<Expr *, 4> ExprPostUpdates;
21063 // OpenMP 5.2 [Section 5.4.6, linear clause]
21064 // step-simple-modifier is exclusive, can't be used with 'val', 'uval', or
21065 // 'ref'
21066 if (LinLoc.isValid() && StepModifierLoc.isInvalid() && Step &&
21067 getLangOpts().OpenMP >= 52)
21068 Diag(Step->getBeginLoc(), diag::err_omp_step_simple_modifier_exclusive);
21069 if (CheckOpenMPLinearModifier(LinKind, LinLoc))
21070 LinKind = OMPC_LINEAR_val;
21071 for (Expr *RefExpr : VarList) {
21072 assert(RefExpr && "NULL expr in OpenMP linear clause.");
21073 SourceLocation ELoc;
21074 SourceRange ERange;
21075 Expr *SimpleRefExpr = RefExpr;
21076 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21077 if (Res.second) {
21078 // It will be analyzed later.
21079 Vars.push_back(RefExpr);
21080 Privates.push_back(nullptr);
21081 Inits.push_back(nullptr);
21082 }
21083 ValueDecl *D = Res.first;
21084 if (!D)
21085 continue;
21086
21087 QualType Type = D->getType();
21088 auto *VD = dyn_cast<VarDecl>(D);
21089
21090 // OpenMP [2.14.3.7, linear clause]
21091 // A list-item cannot appear in more than one linear clause.
21092 // A list-item that appears in a linear clause cannot appear in any
21093 // other data-sharing attribute clause.
21094 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
21095 if (DVar.RefExpr) {
21096 Diag(ELoc, diag::err_omp_wrong_dsa)
21097 << getOpenMPClauseNameForDiag(DVar.CKind)
21098 << getOpenMPClauseNameForDiag(OMPC_linear);
21100 continue;
21101 }
21102
21103 if (CheckOpenMPLinearDecl(D, ELoc, LinKind, Type))
21104 continue;
21105 Type = Type.getNonReferenceType().getUnqualifiedType().getCanonicalType();
21106
21107 // Build private copy of original var.
21108 VarDecl *Private =
21109 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
21110 D->hasAttrs() ? &D->getAttrs() : nullptr,
21111 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
21112 DeclRefExpr *PrivateRef = buildDeclRefExpr(SemaRef, Private, Type, ELoc);
21113 // Build var to save initial value.
21114 VarDecl *Init = buildVarDecl(SemaRef, ELoc, Type, ".linear.start");
21115 Expr *InitExpr;
21116 DeclRefExpr *Ref = nullptr;
21117 if (!VD && !SemaRef.CurContext->isDependentContext()) {
21118 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
21119 if (!isOpenMPCapturedDecl(D)) {
21120 ExprCaptures.push_back(Ref->getDecl());
21121 if (Ref->getDecl()->hasAttr<OMPCaptureNoInitAttr>()) {
21122 ExprResult RefRes = SemaRef.DefaultLvalueConversion(Ref);
21123 if (!RefRes.isUsable())
21124 continue;
21125 ExprResult PostUpdateRes =
21126 SemaRef.BuildBinOp(DSAStack->getCurScope(), ELoc, BO_Assign,
21127 SimpleRefExpr, RefRes.get());
21128 if (!PostUpdateRes.isUsable())
21129 continue;
21130 ExprPostUpdates.push_back(
21131 SemaRef.IgnoredValueConversions(PostUpdateRes.get()).get());
21132 }
21133 }
21134 }
21135 if (LinKind == OMPC_LINEAR_uval)
21136 InitExpr = VD ? VD->getInit() : SimpleRefExpr;
21137 else
21138 InitExpr = VD ? SimpleRefExpr : Ref;
21139 SemaRef.AddInitializerToDecl(
21140 Init, SemaRef.DefaultLvalueConversion(InitExpr).get(),
21141 /*DirectInit=*/false);
21142 DeclRefExpr *InitRef = buildDeclRefExpr(SemaRef, Init, Type, ELoc);
21143
21144 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_linear, Ref);
21145 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
21146 ? RefExpr->IgnoreParens()
21147 : Ref);
21148 Privates.push_back(PrivateRef);
21149 Inits.push_back(InitRef);
21150 }
21151
21152 if (Vars.empty())
21153 return nullptr;
21154
21155 Expr *StepExpr = Step;
21156 Expr *CalcStepExpr = nullptr;
21157 if (Step && !Step->isValueDependent() && !Step->isTypeDependent() &&
21158 !Step->isInstantiationDependent() &&
21160 SourceLocation StepLoc = Step->getBeginLoc();
21162 if (Val.isInvalid())
21163 return nullptr;
21164 StepExpr = Val.get();
21165
21166 // Build var to save the step value.
21167 VarDecl *SaveVar =
21168 buildVarDecl(SemaRef, StepLoc, StepExpr->getType(), ".linear.step");
21169 ExprResult SaveRef =
21170 buildDeclRefExpr(SemaRef, SaveVar, StepExpr->getType(), StepLoc);
21171 ExprResult CalcStep = SemaRef.BuildBinOp(
21172 SemaRef.getCurScope(), StepLoc, BO_Assign, SaveRef.get(), StepExpr);
21173 CalcStep =
21174 SemaRef.ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue=*/false);
21175
21176 // Warn about zero linear step (it would be probably better specified as
21177 // making corresponding variables 'const').
21178 if (std::optional<llvm::APSInt> Result =
21180 if (!Result->isNegative() && !Result->isStrictlyPositive())
21181 Diag(StepLoc, diag::warn_omp_linear_step_zero)
21182 << Vars[0] << (Vars.size() > 1);
21183 } else if (CalcStep.isUsable()) {
21184 // Calculate the step beforehand instead of doing this on each iteration.
21185 // (This is not used if the number of iterations may be kfold-ed).
21186 CalcStepExpr = CalcStep.get();
21187 }
21188 }
21189
21190 return OMPLinearClause::Create(getASTContext(), StartLoc, LParenLoc, LinKind,
21191 LinLoc, ColonLoc, StepModifierLoc, EndLoc,
21192 Vars, Privates, Inits, StepExpr, CalcStepExpr,
21193 buildPreInits(getASTContext(), ExprCaptures),
21194 buildPostUpdate(SemaRef, ExprPostUpdates));
21195}
21196
21197static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV,
21198 Expr *NumIterations, Sema &SemaRef,
21199 Scope *S, DSAStackTy *Stack) {
21200 // Walk the vars and build update/final expressions for the CodeGen.
21203 SmallVector<Expr *, 8> UsedExprs;
21204 Expr *Step = Clause.getStep();
21205 Expr *CalcStep = Clause.getCalcStep();
21206 // OpenMP [2.14.3.7, linear clause]
21207 // If linear-step is not specified it is assumed to be 1.
21208 if (!Step)
21209 Step = SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get();
21210 else if (CalcStep)
21211 Step = cast<BinaryOperator>(CalcStep)->getLHS();
21212 bool HasErrors = false;
21213 auto CurInit = Clause.inits().begin();
21214 auto CurPrivate = Clause.privates().begin();
21215 OpenMPLinearClauseKind LinKind = Clause.getModifier();
21216 for (Expr *RefExpr : Clause.varlist()) {
21217 SourceLocation ELoc;
21218 SourceRange ERange;
21219 Expr *SimpleRefExpr = RefExpr;
21220 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21221 ValueDecl *D = Res.first;
21222 if (Res.second || !D) {
21223 Updates.push_back(nullptr);
21224 Finals.push_back(nullptr);
21225 HasErrors = true;
21226 continue;
21227 }
21228 auto &&Info = Stack->isLoopControlVariable(D);
21229 // OpenMP [2.15.11, distribute simd Construct]
21230 // A list item may not appear in a linear clause, unless it is the loop
21231 // iteration variable.
21232 if (isOpenMPDistributeDirective(Stack->getCurrentDirective()) &&
21233 isOpenMPSimdDirective(Stack->getCurrentDirective()) && !Info.first) {
21234 SemaRef.Diag(ELoc,
21235 diag::err_omp_linear_distribute_var_non_loop_iteration);
21236 Updates.push_back(nullptr);
21237 Finals.push_back(nullptr);
21238 HasErrors = true;
21239 continue;
21240 }
21241 Expr *InitExpr = *CurInit;
21242
21243 // Build privatized reference to the current linear var.
21244 auto *DE = cast<DeclRefExpr>(SimpleRefExpr);
21245 Expr *CapturedRef;
21246 if (LinKind == OMPC_LINEAR_uval)
21247 CapturedRef = cast<VarDecl>(DE->getDecl())->getInit();
21248 else
21249 CapturedRef =
21250 buildDeclRefExpr(SemaRef, cast<VarDecl>(DE->getDecl()),
21251 DE->getType().getUnqualifiedType(), DE->getExprLoc(),
21252 /*RefersToCapture=*/true);
21253
21254 // Build update: Var = InitExpr + IV * Step
21256 if (!Info.first)
21258 SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
21259 /*Subtract=*/false, /*IsNonRectangularLB=*/false);
21260 else
21261 Update = *CurPrivate;
21262 Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
21263 /*DiscardedValue=*/false);
21264
21265 // Build final: Var = PrivCopy;
21266 ExprResult Final;
21267 if (!Info.first)
21268 Final = SemaRef.BuildBinOp(
21269 S, RefExpr->getExprLoc(), BO_Assign, CapturedRef,
21270 SemaRef.DefaultLvalueConversion(*CurPrivate).get());
21271 else
21272 Final = *CurPrivate;
21273 Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
21274 /*DiscardedValue=*/false);
21275
21276 if (!Update.isUsable() || !Final.isUsable()) {
21277 Updates.push_back(nullptr);
21278 Finals.push_back(nullptr);
21279 UsedExprs.push_back(nullptr);
21280 HasErrors = true;
21281 } else {
21282 Updates.push_back(Update.get());
21283 Finals.push_back(Final.get());
21284 if (!Info.first)
21285 UsedExprs.push_back(SimpleRefExpr);
21286 }
21287 ++CurInit;
21288 ++CurPrivate;
21289 }
21290 if (Expr *S = Clause.getStep())
21291 UsedExprs.push_back(S);
21292 // Fill the remaining part with the nullptr.
21293 UsedExprs.append(Clause.varlist_size() + 1 - UsedExprs.size(), nullptr);
21294 Clause.setUpdates(Updates);
21295 Clause.setFinals(Finals);
21296 Clause.setUsedExprs(UsedExprs);
21297 return HasErrors;
21298}
21299
21301 ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc,
21302 SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc) {
21304 for (Expr *RefExpr : VarList) {
21305 assert(RefExpr && "NULL expr in OpenMP aligned clause.");
21306 SourceLocation ELoc;
21307 SourceRange ERange;
21308 Expr *SimpleRefExpr = RefExpr;
21309 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21310 if (Res.second) {
21311 // It will be analyzed later.
21312 Vars.push_back(RefExpr);
21313 }
21314 ValueDecl *D = Res.first;
21315 if (!D)
21316 continue;
21317
21318 QualType QType = D->getType();
21319 auto *VD = dyn_cast<VarDecl>(D);
21320
21321 // OpenMP [2.8.1, simd construct, Restrictions]
21322 // The type of list items appearing in the aligned clause must be
21323 // array, pointer, reference to array, or reference to pointer.
21325 const Type *Ty = QType.getTypePtrOrNull();
21326 if (!Ty || (!Ty->isArrayType() && !Ty->isPointerType())) {
21327 Diag(ELoc, diag::err_omp_aligned_expected_array_or_ptr)
21328 << QType << getLangOpts().CPlusPlus << ERange;
21329 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21331 Diag(D->getLocation(),
21332 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21333 << D;
21334 continue;
21335 }
21336
21337 // OpenMP [2.8.1, simd construct, Restrictions]
21338 // A list-item cannot appear in more than one aligned clause.
21339 if (const Expr *PrevRef = DSAStack->addUniqueAligned(D, SimpleRefExpr)) {
21340 Diag(ELoc, diag::err_omp_used_in_clause_twice)
21341 << 0 << getOpenMPClauseNameForDiag(OMPC_aligned) << ERange;
21342 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
21343 << getOpenMPClauseNameForDiag(OMPC_aligned);
21344 continue;
21345 }
21346
21347 DeclRefExpr *Ref = nullptr;
21348 if (!VD && isOpenMPCapturedDecl(D))
21349 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
21350 Vars.push_back(SemaRef
21351 .DefaultFunctionArrayConversion(
21352 (VD || !Ref) ? RefExpr->IgnoreParens() : Ref)
21353 .get());
21354 }
21355
21356 // OpenMP [2.8.1, simd construct, Description]
21357 // The parameter of the aligned clause, alignment, must be a constant
21358 // positive integer expression.
21359 // If no optional parameter is specified, implementation-defined default
21360 // alignments for SIMD instructions on the target platforms are assumed.
21361 if (Alignment != nullptr) {
21362 ExprResult AlignResult =
21363 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_aligned);
21364 if (AlignResult.isInvalid())
21365 return nullptr;
21366 Alignment = AlignResult.get();
21367 }
21368 if (Vars.empty())
21369 return nullptr;
21370
21371 return OMPAlignedClause::Create(getASTContext(), StartLoc, LParenLoc,
21372 ColonLoc, EndLoc, Vars, Alignment);
21373}
21374
21376 SourceLocation StartLoc,
21377 SourceLocation LParenLoc,
21378 SourceLocation EndLoc) {
21380 SmallVector<Expr *, 8> SrcExprs;
21381 SmallVector<Expr *, 8> DstExprs;
21382 SmallVector<Expr *, 8> AssignmentOps;
21383 for (Expr *RefExpr : VarList) {
21384 assert(RefExpr && "NULL expr in OpenMP copyin clause.");
21385 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21386 // It will be analyzed later.
21387 Vars.push_back(RefExpr);
21388 SrcExprs.push_back(nullptr);
21389 DstExprs.push_back(nullptr);
21390 AssignmentOps.push_back(nullptr);
21391 continue;
21392 }
21393
21394 SourceLocation ELoc = RefExpr->getExprLoc();
21395 // OpenMP [2.1, C/C++]
21396 // A list item is a variable name.
21397 // OpenMP [2.14.4.1, Restrictions, p.1]
21398 // A list item that appears in a copyin clause must be threadprivate.
21399 auto *DE = dyn_cast<DeclRefExpr>(RefExpr);
21400 if (!DE || !isa<VarDecl>(DE->getDecl())) {
21401 Diag(ELoc, diag::err_omp_expected_var_name_member_expr)
21402 << 0 << RefExpr->getSourceRange();
21403 continue;
21404 }
21405
21406 Decl *D = DE->getDecl();
21407 auto *VD = cast<VarDecl>(D);
21408
21409 QualType Type = VD->getType();
21411 // It will be analyzed later.
21412 Vars.push_back(DE);
21413 SrcExprs.push_back(nullptr);
21414 DstExprs.push_back(nullptr);
21415 AssignmentOps.push_back(nullptr);
21416 continue;
21417 }
21418
21419 // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
21420 // A list item that appears in a copyin clause must be threadprivate.
21421 if (!DSAStack->isThreadPrivate(VD)) {
21422 unsigned OMPVersion = getLangOpts().OpenMP;
21423 Diag(ELoc, diag::err_omp_required_access)
21424 << getOpenMPClauseNameForDiag(OMPC_copyin)
21425 << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
21426 continue;
21427 }
21428
21429 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21430 // A variable of class type (or array thereof) that appears in a
21431 // copyin clause requires an accessible, unambiguous copy assignment
21432 // operator for the class type.
21433 QualType ElemType =
21435 VarDecl *SrcVD =
21436 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType.getUnqualifiedType(),
21437 ".copyin.src", VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21438 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(
21439 SemaRef, SrcVD, ElemType.getUnqualifiedType(), DE->getExprLoc());
21440 VarDecl *DstVD =
21441 buildVarDecl(SemaRef, DE->getBeginLoc(), ElemType, ".copyin.dst",
21442 VD->hasAttrs() ? &VD->getAttrs() : nullptr);
21443 DeclRefExpr *PseudoDstExpr =
21444 buildDeclRefExpr(SemaRef, DstVD, ElemType, DE->getExprLoc());
21445 // For arrays generate assignment operation for single element and replace
21446 // it by the original array element in CodeGen.
21447 ExprResult AssignmentOp =
21448 SemaRef.BuildBinOp(/*S=*/nullptr, DE->getExprLoc(), BO_Assign,
21449 PseudoDstExpr, PseudoSrcExpr);
21450 if (AssignmentOp.isInvalid())
21451 continue;
21452 AssignmentOp =
21453 SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(),
21454 /*DiscardedValue=*/false);
21455 if (AssignmentOp.isInvalid())
21456 continue;
21457
21458 DSAStack->addDSA(VD, DE, OMPC_copyin);
21459 Vars.push_back(DE);
21460 SrcExprs.push_back(PseudoSrcExpr);
21461 DstExprs.push_back(PseudoDstExpr);
21462 AssignmentOps.push_back(AssignmentOp.get());
21463 }
21464
21465 if (Vars.empty())
21466 return nullptr;
21467
21468 return OMPCopyinClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21469 Vars, SrcExprs, DstExprs, AssignmentOps);
21470}
21471
21473 SourceLocation StartLoc,
21474 SourceLocation LParenLoc,
21475 SourceLocation EndLoc) {
21477 SmallVector<Expr *, 8> SrcExprs;
21478 SmallVector<Expr *, 8> DstExprs;
21479 SmallVector<Expr *, 8> AssignmentOps;
21480 for (Expr *RefExpr : VarList) {
21481 assert(RefExpr && "NULL expr in OpenMP copyprivate clause.");
21482 SourceLocation ELoc;
21483 SourceRange ERange;
21484 Expr *SimpleRefExpr = RefExpr;
21485 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
21486 if (Res.second) {
21487 // It will be analyzed later.
21488 Vars.push_back(RefExpr);
21489 SrcExprs.push_back(nullptr);
21490 DstExprs.push_back(nullptr);
21491 AssignmentOps.push_back(nullptr);
21492 }
21493 ValueDecl *D = Res.first;
21494 if (!D)
21495 continue;
21496
21497 QualType Type = D->getType();
21498 auto *VD = dyn_cast<VarDecl>(D);
21499
21500 // OpenMP [2.14.4.2, Restrictions, p.2]
21501 // A list item that appears in a copyprivate clause may not appear in a
21502 // private or firstprivate clause on the single construct.
21503 if (!VD || !DSAStack->isThreadPrivate(VD)) {
21504 DSAStackTy::DSAVarData DVar =
21505 DSAStack->getTopDSA(D, /*FromParent=*/false);
21506 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_copyprivate &&
21507 DVar.RefExpr) {
21508 Diag(ELoc, diag::err_omp_wrong_dsa)
21509 << getOpenMPClauseNameForDiag(DVar.CKind)
21510 << getOpenMPClauseNameForDiag(OMPC_copyprivate);
21512 continue;
21513 }
21514
21515 // OpenMP [2.11.4.2, Restrictions, p.1]
21516 // All list items that appear in a copyprivate clause must be either
21517 // threadprivate or private in the enclosing context.
21518 if (DVar.CKind == OMPC_unknown) {
21519 DVar = DSAStack->getImplicitDSA(D, false);
21520 if (DVar.CKind == OMPC_shared) {
21521 Diag(ELoc, diag::err_omp_required_access)
21522 << getOpenMPClauseNameForDiag(OMPC_copyprivate)
21523 << "threadprivate or private in the enclosing context";
21525 continue;
21526 }
21527 }
21528 }
21529
21530 // Variably modified types are not supported.
21532 unsigned OMPVersion = getLangOpts().OpenMP;
21533 Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
21534 << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
21535 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
21536 OMPVersion);
21537 bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
21539 Diag(D->getLocation(),
21540 IsDecl ? diag::note_previous_decl : diag::note_defined_here)
21541 << D;
21542 continue;
21543 }
21544
21545 // OpenMP [2.14.4.1, Restrictions, C/C++, p.2]
21546 // A variable of class type (or array thereof) that appears in a
21547 // copyin clause requires an accessible, unambiguous copy assignment
21548 // operator for the class type.
21550 .getBaseElementType(Type.getNonReferenceType())
21552 VarDecl *SrcVD =
21553 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.src",
21554 D->hasAttrs() ? &D->getAttrs() : nullptr);
21555 DeclRefExpr *PseudoSrcExpr = buildDeclRefExpr(SemaRef, SrcVD, Type, ELoc);
21556 VarDecl *DstVD =
21557 buildVarDecl(SemaRef, RefExpr->getBeginLoc(), Type, ".copyprivate.dst",
21558 D->hasAttrs() ? &D->getAttrs() : nullptr);
21559 DeclRefExpr *PseudoDstExpr = buildDeclRefExpr(SemaRef, DstVD, Type, ELoc);
21560 ExprResult AssignmentOp = SemaRef.BuildBinOp(
21561 DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr);
21562 if (AssignmentOp.isInvalid())
21563 continue;
21564 AssignmentOp = SemaRef.ActOnFinishFullExpr(AssignmentOp.get(), ELoc,
21565 /*DiscardedValue=*/false);
21566 if (AssignmentOp.isInvalid())
21567 continue;
21568
21569 // No need to mark vars as copyprivate, they are already threadprivate or
21570 // implicitly private.
21571 assert(VD || isOpenMPCapturedDecl(D));
21572 Vars.push_back(
21573 VD ? RefExpr->IgnoreParens()
21574 : buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false));
21575 SrcExprs.push_back(PseudoSrcExpr);
21576 DstExprs.push_back(PseudoDstExpr);
21577 AssignmentOps.push_back(AssignmentOp.get());
21578 }
21579
21580 if (Vars.empty())
21581 return nullptr;
21582
21583 return OMPCopyprivateClause::Create(getASTContext(), StartLoc, LParenLoc,
21584 EndLoc, Vars, SrcExprs, DstExprs,
21585 AssignmentOps);
21586}
21587
21589 SourceLocation StartLoc,
21590 SourceLocation LParenLoc,
21591 SourceLocation EndLoc) {
21592 if (VarList.empty())
21593 return nullptr;
21594
21595 return OMPFlushClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21596 VarList);
21597}
21598
21599/// Tries to find omp_depend_t. type.
21600static bool findOMPDependT(Sema &S, SourceLocation Loc, DSAStackTy *Stack,
21601 bool Diagnose = true) {
21602 QualType OMPDependT = Stack->getOMPDependT();
21603 if (!OMPDependT.isNull())
21604 return true;
21605 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_depend_t");
21606 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
21607 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
21608 if (Diagnose)
21609 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_depend_t";
21610 return false;
21611 }
21612 Stack->setOMPDependT(PT.get());
21613 return true;
21614}
21615
21617 SourceLocation StartLoc,
21618 SourceLocation LParenLoc,
21619 SourceLocation EndLoc) {
21620 if (!Depobj)
21621 return nullptr;
21622
21623 bool OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack);
21624
21625 // OpenMP 5.0, 2.17.10.1 depobj Construct
21626 // depobj is an lvalue expression of type omp_depend_t.
21627 if (!Depobj->isTypeDependent() && !Depobj->isValueDependent() &&
21628 !Depobj->isInstantiationDependent() &&
21630 (OMPDependTFound && !getASTContext().typesAreCompatible(
21631 DSAStack->getOMPDependT(), Depobj->getType(),
21632 /*CompareUnqualified=*/true))) {
21633 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21634 << 0 << Depobj->getType() << Depobj->getSourceRange();
21635 }
21636
21637 if (!Depobj->isLValue()) {
21638 Diag(Depobj->getExprLoc(), diag::err_omp_expected_omp_depend_t_lvalue)
21639 << 1 << Depobj->getSourceRange();
21640 }
21641
21642 return OMPDepobjClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
21643 Depobj);
21644}
21645
21646namespace {
21647// Utility struct that gathers the related info for doacross clause.
21648struct DoacrossDataInfoTy {
21649 // The list of expressions.
21651 // The OperatorOffset for doacross loop.
21652 DSAStackTy::OperatorOffsetTy OpsOffs;
21653 // The depended loop count.
21654 llvm::APSInt TotalDepCount;
21655};
21656} // namespace
21657static DoacrossDataInfoTy
21659 ArrayRef<Expr *> VarList, DSAStackTy *Stack,
21660 SourceLocation EndLoc) {
21661
21663 DSAStackTy::OperatorOffsetTy OpsOffs;
21664 llvm::APSInt DepCounter(/*BitWidth=*/32);
21665 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21666
21667 if (const Expr *OrderedCountExpr =
21668 Stack->getParentOrderedRegionParam().first) {
21669 TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
21670 TotalDepCount.setIsUnsigned(/*Val=*/true);
21671 }
21672
21673 for (Expr *RefExpr : VarList) {
21674 assert(RefExpr && "NULL expr in OpenMP doacross clause.");
21675 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21676 // It will be analyzed later.
21677 Vars.push_back(RefExpr);
21678 continue;
21679 }
21680
21681 SourceLocation ELoc = RefExpr->getExprLoc();
21682 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21683 if (!IsSource) {
21684 if (Stack->getParentOrderedRegionParam().first &&
21685 DepCounter >= TotalDepCount) {
21686 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
21687 continue;
21688 }
21689 ++DepCounter;
21690 // OpenMP [2.13.9, Summary]
21691 // depend(dependence-type : vec), where dependence-type is:
21692 // 'sink' and where vec is the iteration vector, which has the form:
21693 // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
21694 // where n is the value specified by the ordered clause in the loop
21695 // directive, xi denotes the loop iteration variable of the i-th nested
21696 // loop associated with the loop directive, and di is a constant
21697 // non-negative integer.
21698 if (SemaRef.CurContext->isDependentContext()) {
21699 // It will be analyzed later.
21700 Vars.push_back(RefExpr);
21701 continue;
21702 }
21703 SimpleExpr = SimpleExpr->IgnoreImplicit();
21705 SourceLocation OOLoc;
21706 Expr *LHS = SimpleExpr;
21707 Expr *RHS = nullptr;
21708 if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
21709 OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
21710 OOLoc = BO->getOperatorLoc();
21711 LHS = BO->getLHS()->IgnoreParenImpCasts();
21712 RHS = BO->getRHS()->IgnoreParenImpCasts();
21713 } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
21714 OOK = OCE->getOperator();
21715 OOLoc = OCE->getOperatorLoc();
21716 LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21717 RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
21718 } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
21719 OOK = MCE->getMethodDecl()
21720 ->getNameInfo()
21721 .getName()
21722 .getCXXOverloadedOperator();
21723 OOLoc = MCE->getCallee()->getExprLoc();
21724 LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
21725 RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
21726 }
21727 SourceLocation ELoc;
21728 SourceRange ERange;
21729 auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
21730 if (Res.second) {
21731 // It will be analyzed later.
21732 Vars.push_back(RefExpr);
21733 }
21734 ValueDecl *D = Res.first;
21735 if (!D)
21736 continue;
21737
21738 if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
21739 SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
21740 continue;
21741 }
21742 if (RHS) {
21743 ExprResult RHSRes =
21745 RHS, OMPC_depend, /*StrictlyPositive=*/false);
21746 if (RHSRes.isInvalid())
21747 continue;
21748 }
21749 if (!SemaRef.CurContext->isDependentContext() &&
21750 Stack->getParentOrderedRegionParam().first &&
21751 DepCounter != Stack->isParentLoopControlVariable(D).first) {
21752 const ValueDecl *VD =
21753 Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
21754 if (VD)
21755 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21756 << 1 << VD;
21757 else
21758 SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
21759 << 0;
21760 continue;
21761 }
21762 OpsOffs.emplace_back(RHS, OOK);
21763 }
21764 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21765 }
21766 if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
21767 TotalDepCount > VarList.size() &&
21768 Stack->getParentOrderedRegionParam().first &&
21769 Stack->getParentLoopControlVariable(VarList.size() + 1)) {
21770 SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
21771 << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
21772 }
21773 return {Vars, OpsOffs, TotalDepCount};
21774}
21775
21777 const OMPDependClause::DependDataTy &Data, Expr *DepModifier,
21778 ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc,
21779 SourceLocation EndLoc) {
21780 OpenMPDependClauseKind DepKind = Data.DepKind;
21781 SourceLocation DepLoc = Data.DepLoc;
21782 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
21783 DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
21784 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21785 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
21786 return nullptr;
21787 }
21788 if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
21789 DepKind == OMPC_DEPEND_mutexinoutset) {
21790 Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
21791 return nullptr;
21792 }
21793 if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
21794 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21795 (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
21796 DepKind == OMPC_DEPEND_sink ||
21797 ((getLangOpts().OpenMP < 50 ||
21798 DSAStack->getCurrentDirective() == OMPD_depobj) &&
21799 DepKind == OMPC_DEPEND_depobj))) {
21800 SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
21801 OMPC_DEPEND_outallmemory,
21802 OMPC_DEPEND_inoutallmemory};
21803 if (getLangOpts().OpenMP < 50 ||
21804 DSAStack->getCurrentDirective() == OMPD_depobj)
21805 Except.push_back(OMPC_DEPEND_depobj);
21806 if (getLangOpts().OpenMP < 51)
21807 Except.push_back(OMPC_DEPEND_inoutset);
21808 std::string Expected = (getLangOpts().OpenMP >= 50 && !DepModifier)
21809 ? "depend modifier(iterator) or "
21810 : "";
21811 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
21812 << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
21813 /*Last=*/OMPC_DEPEND_unknown,
21814 Except)
21815 << getOpenMPClauseNameForDiag(OMPC_depend);
21816 return nullptr;
21817 }
21818 if (DepModifier &&
21819 (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
21820 Diag(DepModifier->getExprLoc(),
21821 diag::err_omp_depend_sink_source_with_modifier);
21822 return nullptr;
21823 }
21824 if (DepModifier &&
21825 !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
21826 Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
21827
21829 DSAStackTy::OperatorOffsetTy OpsOffs;
21830 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
21831
21832 if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
21833 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
21834 SemaRef, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
21835 Vars = VarOffset.Vars;
21836 OpsOffs = VarOffset.OpsOffs;
21837 TotalDepCount = VarOffset.TotalDepCount;
21838 } else {
21839 for (Expr *RefExpr : VarList) {
21840 assert(RefExpr && "NULL expr in OpenMP depend clause.");
21841 if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
21842 // It will be analyzed later.
21843 Vars.push_back(RefExpr);
21844 continue;
21845 }
21846
21847 SourceLocation ELoc = RefExpr->getExprLoc();
21848 Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
21849 if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
21850 bool OMPDependTFound = getLangOpts().OpenMP >= 50;
21851 if (OMPDependTFound)
21852 OMPDependTFound = findOMPDependT(SemaRef, StartLoc, DSAStack,
21853 DepKind == OMPC_DEPEND_depobj);
21854 if (DepKind == OMPC_DEPEND_depobj) {
21855 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21856 // List items used in depend clauses with the depobj dependence type
21857 // must be expressions of the omp_depend_t type.
21858 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21859 !RefExpr->isInstantiationDependent() &&
21860 !RefExpr->containsUnexpandedParameterPack() &&
21861 (OMPDependTFound &&
21862 !getASTContext().hasSameUnqualifiedType(
21863 DSAStack->getOMPDependT(), RefExpr->getType()))) {
21864 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21865 << 0 << RefExpr->getType() << RefExpr->getSourceRange();
21866 continue;
21867 }
21868 if (!RefExpr->isLValue()) {
21869 Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
21870 << 1 << RefExpr->getType() << RefExpr->getSourceRange();
21871 continue;
21872 }
21873 } else {
21874 // OpenMP 5.0 [2.17.11, Restrictions]
21875 // List items used in depend clauses cannot be zero-length array
21876 // sections.
21877 QualType ExprTy = RefExpr->getType().getNonReferenceType();
21878 const auto *OASE = dyn_cast<ArraySectionExpr>(SimpleExpr);
21879 if (OASE) {
21880 QualType BaseType =
21882 if (BaseType.isNull())
21883 return nullptr;
21884 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
21885 ExprTy = ATy->getElementType();
21886 else
21887 ExprTy = BaseType->getPointeeType();
21888 if (BaseType.isNull() || ExprTy.isNull())
21889 return nullptr;
21890 ExprTy = ExprTy.getNonReferenceType();
21891 const Expr *Length = OASE->getLength();
21893 if (Length && !Length->isValueDependent() &&
21894 Length->EvaluateAsInt(Result, getASTContext()) &&
21895 Result.Val.getInt().isZero()) {
21896 Diag(ELoc,
21897 diag::err_omp_depend_zero_length_array_section_not_allowed)
21898 << SimpleExpr->getSourceRange();
21899 continue;
21900 }
21901 }
21902
21903 // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
21904 // List items used in depend clauses with the in, out, inout,
21905 // inoutset, or mutexinoutset dependence types cannot be
21906 // expressions of the omp_depend_t type.
21907 if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
21908 !RefExpr->isInstantiationDependent() &&
21909 !RefExpr->containsUnexpandedParameterPack() &&
21910 (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
21911 (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
21912 ExprTy.getTypePtr()))) {
21913 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21914 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21915 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21916 << RefExpr->getSourceRange();
21917 continue;
21918 }
21919
21920 auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
21921 if (ASE && !ASE->getBase()->isTypeDependent() &&
21922 !ASE->getBase()
21923 ->getType()
21924 .getNonReferenceType()
21925 ->isPointerType() &&
21926 !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
21927 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21928 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21929 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21930 << RefExpr->getSourceRange();
21931 continue;
21932 }
21933
21934 ExprResult Res;
21935 {
21937 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
21938 RefExpr->IgnoreParenImpCasts());
21939 }
21940 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
21942 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
21943 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21944 << (getLangOpts().OpenMP >= 50 ? 1 : 0)
21945 << RefExpr->getSourceRange();
21946 continue;
21947 }
21948 }
21949 }
21950 Vars.push_back(RefExpr->IgnoreParenImpCasts());
21951 }
21952 }
21953
21954 if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
21955 DepKind != OMPC_DEPEND_outallmemory &&
21956 DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
21957 return nullptr;
21958
21959 auto *C = OMPDependClause::Create(
21960 getASTContext(), StartLoc, LParenLoc, EndLoc,
21961 {DepKind, DepLoc, Data.ColonLoc, Data.OmpAllMemoryLoc}, DepModifier, Vars,
21962 TotalDepCount.getZExtValue());
21963 if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
21964 DSAStack->isParentOrderedRegion())
21965 DSAStack->addDoacrossDependClause(C, OpsOffs);
21966 return C;
21967}
21968
21971 SourceLocation LParenLoc, SourceLocation ModifierLoc,
21972 SourceLocation EndLoc) {
21973 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 50) &&
21974 "Unexpected device modifier in OpenMP < 50.");
21975
21976 bool ErrorFound = false;
21977 if (ModifierLoc.isValid() && Modifier == OMPC_DEVICE_unknown) {
21978 std::string Values =
21979 getListOfPossibleValues(OMPC_device, /*First=*/0, OMPC_DEVICE_unknown);
21980 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
21981 << Values << getOpenMPClauseNameForDiag(OMPC_device);
21982 ErrorFound = true;
21983 }
21984
21985 Expr *ValExpr = Device;
21986 Stmt *HelperValStmt = nullptr;
21987
21988 // OpenMP [2.9.1, Restrictions]
21989 // The device expression must evaluate to a non-negative integer value.
21990 ErrorFound = !isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_device,
21991 /*StrictlyPositive=*/false) ||
21992 ErrorFound;
21993 if (ErrorFound)
21994 return nullptr;
21995
21996 // OpenMP 5.0 [2.12.5, Restrictions]
21997 // In case of ancestor device-modifier, a requires directive with
21998 // the reverse_offload clause must be specified.
21999 if (Modifier == OMPC_DEVICE_ancestor) {
22000 if (!DSAStack->hasRequiresDeclWithClause<OMPReverseOffloadClause>()) {
22001 SemaRef.targetDiag(
22002 StartLoc,
22003 diag::err_omp_device_ancestor_without_requires_reverse_offload);
22004 ErrorFound = true;
22005 }
22006 }
22007
22008 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
22009 OpenMPDirectiveKind CaptureRegion =
22010 getOpenMPCaptureRegionForClause(DKind, OMPC_device, getLangOpts().OpenMP);
22011 if (CaptureRegion != OMPD_unknown &&
22012 !SemaRef.CurContext->isDependentContext()) {
22013 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
22014 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
22015 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
22016 HelperValStmt = buildPreInits(getASTContext(), Captures);
22017 }
22018
22019 return new (getASTContext())
22020 OMPDeviceClause(Modifier, ValExpr, HelperValStmt, CaptureRegion, StartLoc,
22021 LParenLoc, ModifierLoc, EndLoc);
22022}
22023
22025 DSAStackTy *Stack, QualType QTy,
22026 bool FullCheck = true) {
22027 if (SemaRef.RequireCompleteType(SL, QTy, diag::err_incomplete_type))
22028 return false;
22029 if (FullCheck && !SemaRef.CurContext->isDependentContext() &&
22030 !QTy.isTriviallyCopyableType(SemaRef.Context))
22031 SemaRef.Diag(SL, diag::warn_omp_non_trivial_type_mapped) << QTy << SR;
22032 return true;
22033}
22034
22035/// Return true if it can be proven that the provided array expression
22036/// (array section or array subscript) does NOT specify the whole size of the
22037/// array whose base type is \a BaseQTy.
22039 const Expr *E,
22040 QualType BaseQTy) {
22041 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22042
22043 // If this is an array subscript, it refers to the whole size if the size of
22044 // the dimension is constant and equals 1. Also, an array section assumes the
22045 // format of an array subscript if no colon is used.
22046 if (isa<ArraySubscriptExpr>(E) ||
22047 (OASE && OASE->getColonLocFirst().isInvalid())) {
22048 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
22049 return ATy->getSExtSize() != 1;
22050 // Size can't be evaluated statically.
22051 return false;
22052 }
22053
22054 assert(OASE && "Expecting array section if not an array subscript.");
22055 const Expr *LowerBound = OASE->getLowerBound();
22056 const Expr *Length = OASE->getLength();
22057
22058 // If there is a lower bound that does not evaluates to zero, we are not
22059 // covering the whole dimension.
22060 if (LowerBound) {
22061 Expr::EvalResult Result;
22062 if (!LowerBound->EvaluateAsInt(Result, SemaRef.getASTContext()))
22063 return false; // Can't get the integer value as a constant.
22064
22065 llvm::APSInt ConstLowerBound = Result.Val.getInt();
22066 if (ConstLowerBound.getSExtValue())
22067 return true;
22068 }
22069
22070 // If we don't have a length we covering the whole dimension.
22071 if (!Length)
22072 return false;
22073
22074 // If the base is a pointer, we don't have a way to get the size of the
22075 // pointee.
22076 if (BaseQTy->isPointerType())
22077 return false;
22078
22079 // We can only check if the length is the same as the size of the dimension
22080 // if we have a constant array.
22081 const auto *CATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr());
22082 if (!CATy)
22083 return false;
22084
22085 Expr::EvalResult Result;
22086 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
22087 return false; // Can't get the integer value as a constant.
22088
22089 llvm::APSInt ConstLength = Result.Val.getInt();
22090 return CATy->getSExtSize() != ConstLength.getSExtValue();
22091}
22092
22093// Return true if it can be proven that the provided array expression (array
22094// section or array subscript) does NOT specify a single element of the array
22095// whose base type is \a BaseQTy.
22097 const Expr *E,
22098 QualType BaseQTy) {
22099 const auto *OASE = dyn_cast<ArraySectionExpr>(E);
22100
22101 // An array subscript always refer to a single element. Also, an array section
22102 // assumes the format of an array subscript if no colon is used.
22103 if (isa<ArraySubscriptExpr>(E) ||
22104 (OASE && OASE->getColonLocFirst().isInvalid()))
22105 return false;
22106
22107 assert(OASE && "Expecting array section if not an array subscript.");
22108 const Expr *Length = OASE->getLength();
22109
22110 // If we don't have a length we have to check if the array has unitary size
22111 // for this dimension. Also, we should always expect a length if the base type
22112 // is pointer.
22113 if (!Length) {
22114 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
22115 return ATy->getSExtSize() != 1;
22116 // We cannot assume anything.
22117 return false;
22118 }
22119
22120 // Check if the length evaluates to 1.
22121 Expr::EvalResult Result;
22122 if (!Length->EvaluateAsInt(Result, SemaRef.getASTContext()))
22123 return false; // Can't get the integer value as a constant.
22124
22125 llvm::APSInt ConstLength = Result.Val.getInt();
22126 return ConstLength.getSExtValue() != 1;
22127}
22128
22129// The base of elements of list in a map clause have to be either:
22130// - a reference to variable or field.
22131// - a member expression.
22132// - an array expression.
22133//
22134// E.g. if we have the expression 'r.S.Arr[:12]', we want to retrieve the
22135// reference to 'r'.
22136//
22137// If we have:
22138//
22139// struct SS {
22140// Bla S;
22141// foo() {
22142// #pragma omp target map (S.Arr[:12]);
22143// }
22144// }
22145//
22146// We want to retrieve the member expression 'this->S';
22147
22148// OpenMP 5.0 [2.19.7.1, map Clause, Restrictions, p.2]
22149// If a list item is an array section, it must specify contiguous storage.
22150//
22151// For this restriction it is sufficient that we make sure only references
22152// to variables or fields and array expressions, and that no array sections
22153// exist except in the rightmost expression (unless they cover the whole
22154// dimension of the array). E.g. these would be invalid:
22155//
22156// r.ArrS[3:5].Arr[6:7]
22157//
22158// r.ArrS[3:5].x
22159//
22160// but these would be valid:
22161// r.ArrS[3].Arr[6:7]
22162//
22163// r.ArrS[3].x
22164namespace {
22165class MapBaseChecker final : public StmtVisitor<MapBaseChecker, bool> {
22166 Sema &SemaRef;
22167 OpenMPClauseKind CKind = OMPC_unknown;
22168 OpenMPDirectiveKind DKind = OMPD_unknown;
22170 bool IsNonContiguous = false;
22171 bool NoDiagnose = false;
22172 const Expr *RelevantExpr = nullptr;
22173 bool AllowUnitySizeArraySection = true;
22174 bool AllowWholeSizeArraySection = true;
22175 bool AllowAnotherPtr = true;
22176 SourceLocation ELoc;
22177 SourceRange ERange;
22178
22179 void emitErrorMsg() {
22180 // If nothing else worked, this is not a valid map clause expression.
22181 if (SemaRef.getLangOpts().OpenMP < 50) {
22182 SemaRef.Diag(ELoc,
22183 diag::err_omp_expected_named_var_member_or_array_expression)
22184 << ERange;
22185 } else {
22186 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
22187 << getOpenMPClauseNameForDiag(CKind) << ERange;
22188 }
22189 }
22190
22191public:
22192 bool VisitDeclRefExpr(DeclRefExpr *DRE) {
22193 if (!isa<VarDecl>(DRE->getDecl())) {
22194 emitErrorMsg();
22195 return false;
22196 }
22197 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22198 RelevantExpr = DRE;
22199 // Record the component.
22200 Components.emplace_back(DRE, DRE->getDecl(), IsNonContiguous);
22201 return true;
22202 }
22203
22204 bool VisitMemberExpr(MemberExpr *ME) {
22205 Expr *E = ME;
22206 Expr *BaseE = ME->getBase()->IgnoreParenCasts();
22207
22208 if (isa<CXXThisExpr>(BaseE)) {
22209 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22210 // We found a base expression: this->Val.
22211 RelevantExpr = ME;
22212 } else {
22213 E = BaseE;
22214 }
22215
22216 if (!isa<FieldDecl>(ME->getMemberDecl())) {
22217 if (!NoDiagnose) {
22218 SemaRef.Diag(ELoc, diag::err_omp_expected_access_to_data_field)
22219 << ME->getSourceRange();
22220 return false;
22221 }
22222 if (RelevantExpr)
22223 return false;
22224 return Visit(E);
22225 }
22226
22227 auto *FD = cast<FieldDecl>(ME->getMemberDecl());
22228
22229 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.3]
22230 // A bit-field cannot appear in a map clause.
22231 //
22232 if (FD->isBitField()) {
22233 if (!NoDiagnose) {
22234 SemaRef.Diag(ELoc, diag::err_omp_bit_fields_forbidden_in_clause)
22235 << ME->getSourceRange() << getOpenMPClauseNameForDiag(CKind);
22236 return false;
22237 }
22238 if (RelevantExpr)
22239 return false;
22240 return Visit(E);
22241 }
22242
22243 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22244 // If the type of a list item is a reference to a type T then the type
22245 // will be considered to be T for all purposes of this clause.
22246 QualType CurType = BaseE->getType().getNonReferenceType();
22247
22248 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.2]
22249 // A list item cannot be a variable that is a member of a structure with
22250 // a union type.
22251 //
22252 if (CurType->isUnionType()) {
22253 if (!NoDiagnose) {
22254 SemaRef.Diag(ELoc, diag::err_omp_union_type_not_allowed)
22255 << ME->getSourceRange();
22256 return false;
22257 }
22258 return RelevantExpr || Visit(E);
22259 }
22260
22261 // If we got a member expression, we should not expect any array section
22262 // before that:
22263 //
22264 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.7]
22265 // If a list item is an element of a structure, only the rightmost symbol
22266 // of the variable reference can be an array section.
22267 //
22268 AllowUnitySizeArraySection = false;
22269 AllowWholeSizeArraySection = false;
22270
22271 // Record the component.
22272 Components.emplace_back(ME, FD, IsNonContiguous);
22273 return RelevantExpr || Visit(E);
22274 }
22275
22276 bool VisitArraySubscriptExpr(ArraySubscriptExpr *AE) {
22277 Expr *E = AE->getBase()->IgnoreParenImpCasts();
22278
22279 if (!E->getType()->isAnyPointerType() && !E->getType()->isArrayType()) {
22280 if (!NoDiagnose) {
22281 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22282 << 0 << AE->getSourceRange();
22283 return false;
22284 }
22285 return RelevantExpr || Visit(E);
22286 }
22287
22288 // If we got an array subscript that express the whole dimension we
22289 // can have any array expressions before. If it only expressing part of
22290 // the dimension, we can only have unitary-size array expressions.
22292 AllowWholeSizeArraySection = false;
22293
22294 if (const auto *TE = dyn_cast<CXXThisExpr>(E->IgnoreParenCasts())) {
22295 Expr::EvalResult Result;
22296 if (!AE->getIdx()->isValueDependent() &&
22297 AE->getIdx()->EvaluateAsInt(Result, SemaRef.getASTContext()) &&
22298 !Result.Val.getInt().isZero()) {
22299 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22300 diag::err_omp_invalid_map_this_expr);
22301 SemaRef.Diag(AE->getIdx()->getExprLoc(),
22302 diag::note_omp_invalid_subscript_on_this_ptr_map);
22303 }
22304 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22305 RelevantExpr = TE;
22306 }
22307
22308 // Record the component - we don't have any declaration associated.
22309 Components.emplace_back(AE, nullptr, IsNonContiguous);
22310
22311 return RelevantExpr || Visit(E);
22312 }
22313
22314 bool VisitArraySectionExpr(ArraySectionExpr *OASE) {
22315 // After OMP 5.0 Array section in reduction clause will be implicitly
22316 // mapped
22317 assert(!(SemaRef.getLangOpts().OpenMP < 50 && NoDiagnose) &&
22318 "Array sections cannot be implicitly mapped.");
22319 Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22320 QualType CurType =
22322
22323 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22324 // If the type of a list item is a reference to a type T then the type
22325 // will be considered to be T for all purposes of this clause.
22326 if (CurType->isReferenceType())
22327 CurType = CurType->getPointeeType();
22328
22329 bool IsPointer = CurType->isAnyPointerType();
22330
22331 if (!IsPointer && !CurType->isArrayType()) {
22332 SemaRef.Diag(ELoc, diag::err_omp_expected_base_var_name)
22333 << 0 << OASE->getSourceRange();
22334 return false;
22335 }
22336
22337 bool NotWhole =
22338 checkArrayExpressionDoesNotReferToWholeSize(SemaRef, OASE, CurType);
22339 bool NotUnity =
22340 checkArrayExpressionDoesNotReferToUnitySize(SemaRef, OASE, CurType);
22341
22342 if (AllowWholeSizeArraySection) {
22343 // Any array section is currently allowed. Allowing a whole size array
22344 // section implies allowing a unity array section as well.
22345 //
22346 // If this array section refers to the whole dimension we can still
22347 // accept other array sections before this one, except if the base is a
22348 // pointer. Otherwise, only unitary sections are accepted.
22349 if (NotWhole || IsPointer)
22350 AllowWholeSizeArraySection = false;
22351 } else if (DKind == OMPD_target_update &&
22352 SemaRef.getLangOpts().OpenMP >= 50) {
22353 if (IsPointer && !AllowAnotherPtr)
22354 SemaRef.Diag(ELoc, diag::err_omp_section_length_undefined)
22355 << /*array of unknown bound */ 1;
22356 else
22357 IsNonContiguous = true;
22358 } else if (AllowUnitySizeArraySection && NotUnity) {
22359 // A unity or whole array section is not allowed and that is not
22360 // compatible with the properties of the current array section.
22361 if (NoDiagnose)
22362 return false;
22363 SemaRef.Diag(ELoc,
22364 diag::err_array_section_does_not_specify_contiguous_storage)
22365 << OASE->getSourceRange();
22366 return false;
22367 }
22368
22369 if (IsPointer)
22370 AllowAnotherPtr = false;
22371
22372 if (const auto *TE = dyn_cast<CXXThisExpr>(E)) {
22373 Expr::EvalResult ResultR;
22374 Expr::EvalResult ResultL;
22375 if (!OASE->getLength()->isValueDependent() &&
22376 OASE->getLength()->EvaluateAsInt(ResultR, SemaRef.getASTContext()) &&
22377 !ResultR.Val.getInt().isOne()) {
22378 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22379 diag::err_omp_invalid_map_this_expr);
22380 SemaRef.Diag(OASE->getLength()->getExprLoc(),
22381 diag::note_omp_invalid_length_on_this_ptr_mapping);
22382 }
22383 if (OASE->getLowerBound() && !OASE->getLowerBound()->isValueDependent() &&
22384 OASE->getLowerBound()->EvaluateAsInt(ResultL,
22385 SemaRef.getASTContext()) &&
22386 !ResultL.Val.getInt().isZero()) {
22387 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22388 diag::err_omp_invalid_map_this_expr);
22389 SemaRef.Diag(OASE->getLowerBound()->getExprLoc(),
22390 diag::note_omp_invalid_lower_bound_on_this_ptr_mapping);
22391 }
22392 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22393 RelevantExpr = TE;
22394 }
22395
22396 // Record the component - we don't have any declaration associated.
22397 Components.emplace_back(OASE, nullptr, /*IsNonContiguous=*/false);
22398 return RelevantExpr || Visit(E);
22399 }
22400 bool VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
22401 Expr *Base = E->getBase();
22402
22403 // Record the component - we don't have any declaration associated.
22404 Components.emplace_back(E, nullptr, IsNonContiguous);
22405
22406 return Visit(Base->IgnoreParenImpCasts());
22407 }
22408
22409 bool VisitUnaryOperator(UnaryOperator *UO) {
22410 if (SemaRef.getLangOpts().OpenMP < 50 || !UO->isLValue() ||
22411 UO->getOpcode() != UO_Deref) {
22412 emitErrorMsg();
22413 return false;
22414 }
22415 if (!RelevantExpr) {
22416 // Record the component if haven't found base decl.
22417 Components.emplace_back(UO, nullptr, /*IsNonContiguous=*/false);
22418 }
22419 return RelevantExpr || Visit(UO->getSubExpr()->IgnoreParenImpCasts());
22420 }
22421 bool VisitBinaryOperator(BinaryOperator *BO) {
22422 if (SemaRef.getLangOpts().OpenMP < 50 || !BO->getType()->isPointerType()) {
22423 emitErrorMsg();
22424 return false;
22425 }
22426
22427 // Pointer arithmetic is the only thing we expect to happen here so after we
22428 // make sure the binary operator is a pointer type, the only thing we need
22429 // to do is to visit the subtree that has the same type as root (so that we
22430 // know the other subtree is just an offset)
22431 Expr *LE = BO->getLHS()->IgnoreParenImpCasts();
22432 Expr *RE = BO->getRHS()->IgnoreParenImpCasts();
22433 Components.emplace_back(BO, nullptr, false);
22434 assert((LE->getType().getTypePtr() == BO->getType().getTypePtr() ||
22435 RE->getType().getTypePtr() == BO->getType().getTypePtr()) &&
22436 "Either LHS or RHS have base decl inside");
22437 if (BO->getType().getTypePtr() == LE->getType().getTypePtr())
22438 return RelevantExpr || Visit(LE);
22439 return RelevantExpr || Visit(RE);
22440 }
22441 bool VisitCXXThisExpr(CXXThisExpr *CTE) {
22442 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22443 RelevantExpr = CTE;
22444 Components.emplace_back(CTE, nullptr, IsNonContiguous);
22445 return true;
22446 }
22447 bool VisitCXXOperatorCallExpr(CXXOperatorCallExpr *COCE) {
22448 assert(!RelevantExpr && "RelevantExpr is expected to be nullptr");
22449 Components.emplace_back(COCE, nullptr, IsNonContiguous);
22450 return true;
22451 }
22452 bool VisitOpaqueValueExpr(OpaqueValueExpr *E) {
22453 Expr *Source = E->getSourceExpr();
22454 if (!Source) {
22455 emitErrorMsg();
22456 return false;
22457 }
22458 return Visit(Source);
22459 }
22460 bool VisitStmt(Stmt *) {
22461 emitErrorMsg();
22462 return false;
22463 }
22464 const Expr *getFoundBase() const { return RelevantExpr; }
22465 explicit MapBaseChecker(
22466 Sema &SemaRef, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind,
22468 bool NoDiagnose, SourceLocation &ELoc, SourceRange &ERange)
22469 : SemaRef(SemaRef), CKind(CKind), DKind(DKind), Components(Components),
22470 NoDiagnose(NoDiagnose), ELoc(ELoc), ERange(ERange) {}
22471};
22472} // namespace
22473
22474/// Return the expression of the base of the mappable expression or null if it
22475/// cannot be determined and do all the necessary checks to see if the
22476/// expression is valid as a standalone mappable expression. In the process,
22477/// record all the components of the expression.
22479 Sema &SemaRef, Expr *E,
22481 OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose) {
22482 SourceLocation ELoc = E->getExprLoc();
22483 SourceRange ERange = E->getSourceRange();
22484 MapBaseChecker Checker(SemaRef, CKind, DKind, CurComponents, NoDiagnose, ELoc,
22485 ERange);
22486 if (Checker.Visit(E->IgnoreParens())) {
22487 // Check if the highest dimension array section has length specified
22488 if (SemaRef.getLangOpts().OpenMP >= 50 && !CurComponents.empty() &&
22489 (CKind == OMPC_to || CKind == OMPC_from)) {
22490 auto CI = CurComponents.rbegin();
22491 auto CE = CurComponents.rend();
22492 for (; CI != CE; ++CI) {
22493 const auto *OASE =
22494 dyn_cast<ArraySectionExpr>(CI->getAssociatedExpression());
22495 if (!OASE)
22496 continue;
22497 if (OASE && OASE->getLength())
22498 break;
22499 SemaRef.Diag(ELoc, diag::err_array_section_does_not_specify_length)
22500 << ERange;
22501 }
22502 }
22503 return Checker.getFoundBase();
22504 }
22505 return nullptr;
22506}
22507
22508// Return true if expression E associated with value VD has conflicts with other
22509// map information.
22511 Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E,
22512 bool CurrentRegionOnly,
22514 OpenMPClauseKind CKind) {
22515 assert(VD && E);
22516 SourceLocation ELoc = E->getExprLoc();
22517 SourceRange ERange = E->getSourceRange();
22518
22519 // In order to easily check the conflicts we need to match each component of
22520 // the expression under test with the components of the expressions that are
22521 // already in the stack.
22522
22523 assert(!CurComponents.empty() && "Map clause expression with no components!");
22524 assert(CurComponents.back().getAssociatedDeclaration() == VD &&
22525 "Map clause expression with unexpected base!");
22526
22527 // Variables to help detecting enclosing problems in data environment nests.
22528 bool IsEnclosedByDataEnvironmentExpr = false;
22529 const Expr *EnclosingExpr = nullptr;
22530
22531 bool FoundError = DSAS->checkMappableExprComponentListsForDecl(
22532 VD, CurrentRegionOnly,
22533 [&IsEnclosedByDataEnvironmentExpr, &SemaRef, VD, CurrentRegionOnly, ELoc,
22534 ERange, CKind, &EnclosingExpr,
22536 StackComponents,
22537 OpenMPClauseKind Kind) {
22538 if (CKind == Kind && SemaRef.LangOpts.OpenMP >= 50)
22539 return false;
22540 assert(!StackComponents.empty() &&
22541 "Map clause expression with no components!");
22542 assert(StackComponents.back().getAssociatedDeclaration() == VD &&
22543 "Map clause expression with unexpected base!");
22544 (void)VD;
22545
22546 // The whole expression in the stack.
22547 const Expr *RE = StackComponents.front().getAssociatedExpression();
22548
22549 // Expressions must start from the same base. Here we detect at which
22550 // point both expressions diverge from each other and see if we can
22551 // detect if the memory referred to both expressions is contiguous and
22552 // do not overlap.
22553 auto CI = CurComponents.rbegin();
22554 auto CE = CurComponents.rend();
22555 auto SI = StackComponents.rbegin();
22556 auto SE = StackComponents.rend();
22557 for (; CI != CE && SI != SE; ++CI, ++SI) {
22558
22559 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.3]
22560 // At most one list item can be an array item derived from a given
22561 // variable in map clauses of the same construct.
22562 if (CurrentRegionOnly &&
22563 (isa<ArraySubscriptExpr>(CI->getAssociatedExpression()) ||
22564 isa<ArraySectionExpr>(CI->getAssociatedExpression()) ||
22565 isa<OMPArrayShapingExpr>(CI->getAssociatedExpression())) &&
22566 (isa<ArraySubscriptExpr>(SI->getAssociatedExpression()) ||
22567 isa<ArraySectionExpr>(SI->getAssociatedExpression()) ||
22568 isa<OMPArrayShapingExpr>(SI->getAssociatedExpression()))) {
22569 SemaRef.Diag(CI->getAssociatedExpression()->getExprLoc(),
22570 diag::err_omp_multiple_array_items_in_map_clause)
22571 << CI->getAssociatedExpression()->getSourceRange();
22572 SemaRef.Diag(SI->getAssociatedExpression()->getExprLoc(),
22573 diag::note_used_here)
22574 << SI->getAssociatedExpression()->getSourceRange();
22575 return true;
22576 }
22577
22578 // Do both expressions have the same kind?
22579 if (CI->getAssociatedExpression()->getStmtClass() !=
22580 SI->getAssociatedExpression()->getStmtClass())
22581 break;
22582
22583 // Are we dealing with different variables/fields?
22584 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
22585 break;
22586 }
22587 // Check if the extra components of the expressions in the enclosing
22588 // data environment are redundant for the current base declaration.
22589 // If they are, the maps completely overlap, which is legal.
22590 for (; SI != SE; ++SI) {
22591 QualType Type;
22592 if (const auto *ASE =
22593 dyn_cast<ArraySubscriptExpr>(SI->getAssociatedExpression())) {
22594 Type = ASE->getBase()->IgnoreParenImpCasts()->getType();
22595 } else if (const auto *OASE = dyn_cast<ArraySectionExpr>(
22596 SI->getAssociatedExpression())) {
22597 const Expr *E = OASE->getBase()->IgnoreParenImpCasts();
22599 } else if (const auto *OASE = dyn_cast<OMPArrayShapingExpr>(
22600 SI->getAssociatedExpression())) {
22601 Type = OASE->getBase()->getType()->getPointeeType();
22602 }
22603 if (Type.isNull() || Type->isAnyPointerType() ||
22605 SemaRef, SI->getAssociatedExpression(), Type))
22606 break;
22607 }
22608
22609 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22610 // List items of map clauses in the same construct must not share
22611 // original storage.
22612 //
22613 // If the expressions are exactly the same or one is a subset of the
22614 // other, it means they are sharing storage.
22615 if (CI == CE && SI == SE) {
22616 if (CurrentRegionOnly) {
22617 if (CKind == OMPC_map) {
22618 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22619 } else {
22620 assert(CKind == OMPC_to || CKind == OMPC_from);
22621 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22622 << ERange;
22623 }
22624 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22625 << RE->getSourceRange();
22626 return true;
22627 }
22628 // If we find the same expression in the enclosing data environment,
22629 // that is legal.
22630 IsEnclosedByDataEnvironmentExpr = true;
22631 return false;
22632 }
22633
22634 QualType DerivedType =
22635 std::prev(CI)->getAssociatedDeclaration()->getType();
22636 SourceLocation DerivedLoc =
22637 std::prev(CI)->getAssociatedExpression()->getExprLoc();
22638
22639 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
22640 // If the type of a list item is a reference to a type T then the type
22641 // will be considered to be T for all purposes of this clause.
22642 DerivedType = DerivedType.getNonReferenceType();
22643
22644 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C/C++, p.1]
22645 // A variable for which the type is pointer and an array section
22646 // derived from that variable must not appear as list items of map
22647 // clauses of the same construct.
22648 //
22649 // Also, cover one of the cases in:
22650 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22651 // If any part of the original storage of a list item has corresponding
22652 // storage in the device data environment, all of the original storage
22653 // must have corresponding storage in the device data environment.
22654 //
22655 if (DerivedType->isAnyPointerType()) {
22656 if (CI == CE || SI == SE) {
22657 SemaRef.Diag(
22658 DerivedLoc,
22659 diag::err_omp_pointer_mapped_along_with_derived_section)
22660 << DerivedLoc;
22661 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22662 << RE->getSourceRange();
22663 return true;
22664 }
22665 if (CI->getAssociatedExpression()->getStmtClass() !=
22666 SI->getAssociatedExpression()->getStmtClass() ||
22667 CI->getAssociatedDeclaration()->getCanonicalDecl() ==
22668 SI->getAssociatedDeclaration()->getCanonicalDecl()) {
22669 assert(CI != CE && SI != SE);
22670 SemaRef.Diag(DerivedLoc, diag::err_omp_same_pointer_dereferenced)
22671 << DerivedLoc;
22672 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22673 << RE->getSourceRange();
22674 return true;
22675 }
22676 }
22677
22678 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.4]
22679 // List items of map clauses in the same construct must not share
22680 // original storage.
22681 //
22682 // An expression is a subset of the other.
22683 if (CurrentRegionOnly && (CI == CE || SI == SE)) {
22684 if (CKind == OMPC_map) {
22685 if (CI != CE || SI != SE) {
22686 // Allow constructs like this: map(s, s.ptr[0:1]), where s.ptr is
22687 // a pointer.
22688 auto Begin =
22689 CI != CE ? CurComponents.begin() : StackComponents.begin();
22690 auto End = CI != CE ? CurComponents.end() : StackComponents.end();
22691 auto It = Begin;
22692 while (It != End && !It->getAssociatedDeclaration())
22693 std::advance(It, 1);
22694 assert(It != End &&
22695 "Expected at least one component with the declaration.");
22696 if (It != Begin && It->getAssociatedDeclaration()
22697 ->getType()
22698 .getCanonicalType()
22699 ->isAnyPointerType()) {
22700 IsEnclosedByDataEnvironmentExpr = false;
22701 EnclosingExpr = nullptr;
22702 return false;
22703 }
22704 }
22705 SemaRef.Diag(ELoc, diag::err_omp_map_shared_storage) << ERange;
22706 } else {
22707 assert(CKind == OMPC_to || CKind == OMPC_from);
22708 SemaRef.Diag(ELoc, diag::err_omp_once_referenced_in_target_update)
22709 << ERange;
22710 }
22711 SemaRef.Diag(RE->getExprLoc(), diag::note_used_here)
22712 << RE->getSourceRange();
22713 return true;
22714 }
22715
22716 // The current expression uses the same base as other expression in the
22717 // data environment but does not contain it completely.
22718 if (!CurrentRegionOnly && SI != SE)
22719 EnclosingExpr = RE;
22720
22721 // The current expression is a subset of the expression in the data
22722 // environment.
22723 IsEnclosedByDataEnvironmentExpr |=
22724 (!CurrentRegionOnly && CI != CE && SI == SE);
22725
22726 return false;
22727 });
22728
22729 if (CurrentRegionOnly)
22730 return FoundError;
22731
22732 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.5]
22733 // If any part of the original storage of a list item has corresponding
22734 // storage in the device data environment, all of the original storage must
22735 // have corresponding storage in the device data environment.
22736 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.6]
22737 // If a list item is an element of a structure, and a different element of
22738 // the structure has a corresponding list item in the device data environment
22739 // prior to a task encountering the construct associated with the map clause,
22740 // then the list item must also have a corresponding list item in the device
22741 // data environment prior to the task encountering the construct.
22742 //
22743 if (EnclosingExpr && !IsEnclosedByDataEnvironmentExpr) {
22744 SemaRef.Diag(ELoc,
22745 diag::err_omp_original_storage_is_shared_and_does_not_contain)
22746 << ERange;
22747 SemaRef.Diag(EnclosingExpr->getExprLoc(), diag::note_used_here)
22748 << EnclosingExpr->getSourceRange();
22749 return true;
22750 }
22751
22752 return FoundError;
22753}
22754
22755// Look up the user-defined mapper given the mapper name and mapped type, and
22756// build a reference to it.
22758 CXXScopeSpec &MapperIdScopeSpec,
22759 const DeclarationNameInfo &MapperId,
22760 QualType Type,
22761 Expr *UnresolvedMapper) {
22762 if (MapperIdScopeSpec.isInvalid())
22763 return ExprError();
22764 // Get the actual type for the array type.
22765 if (Type->isArrayType()) {
22766 assert(Type->getAsArrayTypeUnsafe() && "Expect to get a valid array type");
22768 }
22769 // Find all user-defined mappers with the given MapperId.
22770 SmallVector<UnresolvedSet<8>, 4> Lookups;
22771 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22772 Lookup.suppressDiagnostics();
22773 if (S) {
22774 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22775 /*ObjectType=*/QualType())) {
22776 NamedDecl *D = Lookup.getRepresentativeDecl();
22777 while (S && !S->isDeclScope(D))
22778 S = S->getParent();
22779 if (S)
22780 S = S->getParent();
22781 Lookups.emplace_back();
22782 Lookups.back().append(Lookup.begin(), Lookup.end());
22783 Lookup.clear();
22784 }
22785 } else if (auto *ULE = cast_or_null<UnresolvedLookupExpr>(UnresolvedMapper)) {
22786 // Extract the user-defined mappers with the given MapperId.
22787 Lookups.push_back(UnresolvedSet<8>());
22788 for (NamedDecl *D : ULE->decls()) {
22789 auto *DMD = cast<OMPDeclareMapperDecl>(D);
22790 assert(DMD && "Expect valid OMPDeclareMapperDecl during instantiation.");
22791 Lookups.back().addDecl(DMD);
22792 }
22793 }
22794 // Defer the lookup for dependent types. The results will be passed through
22795 // UnresolvedMapper on instantiation.
22796 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22800 return !D->isInvalidDecl() &&
22801 (D->getType()->isDependentType() ||
22802 D->getType()->isInstantiationDependentType() ||
22803 D->getType()->containsUnexpandedParameterPack());
22804 })) {
22805 UnresolvedSet<8> URS;
22806 for (const UnresolvedSet<8> &Set : Lookups) {
22807 if (Set.empty())
22808 continue;
22809 URS.append(Set.begin(), Set.end());
22810 }
22812 SemaRef.Context, /*NamingClass=*/nullptr,
22813 MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId,
22814 /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false,
22815 /*KnownInstantiationDependent=*/false);
22816 }
22817 SourceLocation Loc = MapperId.getLoc();
22818 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
22819 // The type must be of struct, union or class type in C and C++
22821 (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default")) {
22822 SemaRef.Diag(Loc, diag::err_omp_mapper_wrong_type);
22823 return ExprError();
22824 }
22825 // Perform argument dependent lookup.
22826 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
22827 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
22828 // Return the first user-defined mapper with the desired type.
22830 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
22831 if (!D->isInvalidDecl() &&
22832 SemaRef.Context.hasSameType(D->getType(), Type))
22833 return D;
22834 return nullptr;
22835 }))
22836 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22837 // Find the first user-defined mapper with a type derived from the desired
22838 // type.
22840 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
22841 if (!D->isInvalidDecl() &&
22842 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
22843 !Type.isMoreQualifiedThan(D->getType(),
22844 SemaRef.getASTContext()))
22845 return D;
22846 return nullptr;
22847 })) {
22848 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
22849 /*DetectVirtual=*/false);
22850 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
22851 if (!Paths.isAmbiguous(SemaRef.Context.getCanonicalType(
22852 VD->getType().getUnqualifiedType()))) {
22853 if (SemaRef.CheckBaseClassAccess(
22854 Loc, VD->getType(), Type, Paths.front(),
22855 /*DiagID=*/0) != Sema::AR_inaccessible) {
22856 return SemaRef.BuildDeclRefExpr(VD, Type, VK_LValue, Loc);
22857 }
22858 }
22859 }
22860 }
22861 // Report error if a mapper is specified, but cannot be found.
22862 if (MapperIdScopeSpec.isSet() || MapperId.getAsString() != "default") {
22863 SemaRef.Diag(Loc, diag::err_omp_invalid_mapper)
22864 << Type << MapperId.getName();
22865 return ExprError();
22866 }
22867 return ExprEmpty();
22868}
22869
22870namespace {
22871// Utility struct that gathers all the related lists associated with a mappable
22872// expression.
22873struct MappableVarListInfo {
22874 // The list of expressions.
22875 ArrayRef<Expr *> VarList;
22876 // The list of processed expressions.
22877 SmallVector<Expr *, 16> ProcessedVarList;
22878 // The mappble components for each expression.
22880 // The base declaration of the variable.
22881 SmallVector<ValueDecl *, 16> VarBaseDeclarations;
22882 // The reference to the user-defined mapper associated with every expression.
22883 SmallVector<Expr *, 16> UDMapperList;
22884
22885 MappableVarListInfo(ArrayRef<Expr *> VarList) : VarList(VarList) {
22886 // We have a list of components and base declarations for each entry in the
22887 // variable list.
22888 VarComponents.reserve(VarList.size());
22889 VarBaseDeclarations.reserve(VarList.size());
22890 }
22891};
22892} // namespace
22893
22895 DSAStackTy *Stack,
22897
22898 const RecordDecl *RD = BaseType->getAsRecordDecl();
22899 SourceRange Range = RD->getSourceRange();
22900 DeclarationNameInfo ImplicitName;
22901 // Dummy variable _s for Mapper.
22902 VarDecl *VD = buildVarDecl(S, Range.getEnd(), BaseType, "_s");
22903 DeclRefExpr *MapperVarRef =
22904 buildDeclRefExpr(S, VD, BaseType, SourceLocation());
22905
22906 // Create implicit map clause for mapper.
22908 for (auto *FD : RD->fields()) {
22909 Expr *BE = S.BuildMemberExpr(
22910 MapperVarRef, /*IsArrow=*/false, Range.getBegin(),
22911 NestedNameSpecifierLoc(), Range.getBegin(), FD,
22913 /*HadMultipleCandidates=*/false,
22915 FD->getType(), VK_LValue, OK_Ordinary);
22916 SExprs.push_back(BE);
22917 }
22918 CXXScopeSpec MapperIdScopeSpec;
22919 DeclarationNameInfo MapperId;
22920 OpenMPDirectiveKind DKind = Stack->getCurrentDirective();
22921
22922 OMPClause *MapClause = S.OpenMP().ActOnOpenMPMapClause(
22923 nullptr, OMPC_MAP_MODIFIER_unknown, SourceLocation(), MapperIdScopeSpec,
22924 MapperId, DKind == OMPD_target_enter_data ? OMPC_MAP_to : OMPC_MAP_tofrom,
22925 /*IsMapTypeImplicit=*/true, SourceLocation(), SourceLocation(), SExprs,
22926 OMPVarListLocTy());
22927 Maps.push_back(MapClause);
22928 return MapperVarRef;
22929}
22930
22932 DSAStackTy *Stack) {
22933
22934 // Build impilicit map for mapper
22936 DeclRefExpr *MapperVarRef = buildImplicitMap(S, BaseType, Stack, Maps);
22937
22938 const RecordDecl *RD = BaseType->getAsRecordDecl();
22939 // AST context is RD's ParentASTContext().
22940 ASTContext &Ctx = RD->getParentASTContext();
22941 // DeclContext is RD's DeclContext.
22942 DeclContext *DCT = const_cast<DeclContext *>(RD->getDeclContext());
22943
22944 // Create implicit default mapper for "RD".
22945 DeclarationName MapperId;
22946 auto &DeclNames = Ctx.DeclarationNames;
22947 MapperId = DeclNames.getIdentifier(&Ctx.Idents.get("default"));
22948 auto *DMD = OMPDeclareMapperDecl::Create(Ctx, DCT, SourceLocation(), MapperId,
22949 BaseType, MapperId, Maps, nullptr);
22950 Scope *Scope = S.getScopeForContext(DCT);
22951 if (Scope)
22952 S.PushOnScopeChains(DMD, Scope, /*AddToContext=*/false);
22953 DCT->addDecl(DMD);
22954 DMD->setAccess(clang::AS_none);
22955 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
22956 VD->setDeclContext(DMD);
22957 VD->setLexicalDeclContext(DMD);
22958 DMD->addDecl(VD);
22959 DMD->setMapperVarRef(MapperVarRef);
22960 FieldDecl *FD = *RD->field_begin();
22961 // create mapper refence.
22963 DMD, false, SourceLocation(), BaseType, VK_LValue);
22964}
22965
22966// Look up the user-defined mapper given the mapper name and mapper type,
22967// return true if found one.
22968static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S,
22969 CXXScopeSpec &MapperIdScopeSpec,
22970 const DeclarationNameInfo &MapperId,
22971 QualType Type) {
22972 // Find all user-defined mappers with the given MapperId.
22973 SmallVector<UnresolvedSet<8>, 4> Lookups;
22974 LookupResult Lookup(SemaRef, MapperId, Sema::LookupOMPMapperName);
22975 Lookup.suppressDiagnostics();
22976 while (S && SemaRef.LookupParsedName(Lookup, S, &MapperIdScopeSpec,
22977 /*ObjectType=*/QualType())) {
22978 NamedDecl *D = Lookup.getRepresentativeDecl();
22979 while (S && !S->isDeclScope(D))
22980 S = S->getParent();
22981 if (S)
22982 S = S->getParent();
22983 Lookups.emplace_back();
22984 Lookups.back().append(Lookup.begin(), Lookup.end());
22985 Lookup.clear();
22986 }
22987 if (SemaRef.CurContext->isDependentContext() || Type->isDependentType() ||
22991 return !D->isInvalidDecl() &&
22992 (D->getType()->isDependentType() ||
22993 D->getType()->isInstantiationDependentType() ||
22994 D->getType()->containsUnexpandedParameterPack());
22995 }))
22996 return false;
22997 // Perform argument dependent lookup.
22998 SourceLocation Loc = MapperId.getLoc();
22999 if (SemaRef.getLangOpts().CPlusPlus && !MapperIdScopeSpec.isSet())
23000 argumentDependentLookup(SemaRef, MapperId, Loc, Type, Lookups);
23002 Lookups, [&SemaRef, Type](ValueDecl *D) -> ValueDecl * {
23003 if (!D->isInvalidDecl() &&
23004 SemaRef.Context.hasSameType(D->getType(), Type))
23005 return D;
23006 return nullptr;
23007 }))
23008 return true;
23009 // Find the first user-defined mapper with a type derived from the desired
23010 // type.
23012 Lookups, [&SemaRef, Type, Loc](ValueDecl *D) -> ValueDecl * {
23013 if (!D->isInvalidDecl() &&
23014 SemaRef.IsDerivedFrom(Loc, Type, D->getType()) &&
23015 !Type.isMoreQualifiedThan(D->getType(), SemaRef.getASTContext()))
23016 return D;
23017 return nullptr;
23018 });
23019 if (!VD)
23020 return false;
23021 CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
23022 /*DetectVirtual=*/false);
23023 if (SemaRef.IsDerivedFrom(Loc, Type, VD->getType(), Paths)) {
23024 bool IsAmbiguous = !Paths.isAmbiguous(
23026 if (IsAmbiguous)
23027 return false;
23028 if (SemaRef.CheckBaseClassAccess(Loc, VD->getType(), Type, Paths.front(),
23029 /*DiagID=*/0) != Sema::AR_inaccessible)
23030 return true;
23031 }
23032 return false;
23033}
23034
23035static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack,
23036 QualType CanonType, const Expr *E) {
23037
23038 // DFS over data members in structures/classes.
23040 {CanonType, nullptr});
23041 llvm::DenseMap<const Type *, bool> Visited;
23042 SmallVector<std::pair<FieldDecl *, unsigned>, 4> ParentChain(1, {nullptr, 1});
23043 while (!Types.empty()) {
23044 auto [BaseType, CurFD] = Types.pop_back_val();
23045 while (ParentChain.back().second == 0)
23046 ParentChain.pop_back();
23047 --ParentChain.back().second;
23048 if (BaseType.isNull())
23049 continue;
23050 // Only structs/classes are allowed to have mappers.
23051 const RecordDecl *RD = BaseType.getCanonicalType()->getAsRecordDecl();
23052 if (!RD)
23053 continue;
23054 auto It = Visited.find(BaseType.getTypePtr());
23055 if (It == Visited.end()) {
23056 // Try to find the associated user-defined mapper.
23057 CXXScopeSpec MapperIdScopeSpec;
23058 DeclarationNameInfo DefaultMapperId;
23060 &S.Context.Idents.get("default")));
23061 DefaultMapperId.setLoc(E->getExprLoc());
23062 bool HasUDMapper =
23063 hasUserDefinedMapper(S, Stack->getCurScope(), MapperIdScopeSpec,
23064 DefaultMapperId, BaseType);
23065 It = Visited.try_emplace(BaseType.getTypePtr(), HasUDMapper).first;
23066 }
23067 // Found default mapper.
23068 if (It->second)
23069 return true;
23070 // Check for the "default" mapper for data members.
23071 bool FirstIter = true;
23072 for (FieldDecl *FD : RD->fields()) {
23073 if (!FD)
23074 continue;
23075 QualType FieldTy = FD->getType();
23076 if (FieldTy.isNull() ||
23077 !(FieldTy->isStructureOrClassType() || FieldTy->isUnionType()))
23078 continue;
23079 if (FirstIter) {
23080 FirstIter = false;
23081 ParentChain.emplace_back(CurFD, 1);
23082 } else {
23083 ++ParentChain.back().second;
23084 }
23085 Types.emplace_back(FieldTy, FD);
23086 }
23087 }
23088 return false;
23089}
23090
23091// Check the validity of the provided variable list for the provided clause kind
23092// \a CKind. In the check process the valid expressions, mappable expression
23093// components, variables, and user-defined mappers are extracted and used to
23094// fill \a ProcessedVarList, \a VarComponents, \a VarBaseDeclarations, and \a
23095// UDMapperList in MVLI. \a MapType, \a IsMapTypeImplicit, \a MapperIdScopeSpec,
23096// and \a MapperId are expected to be valid if the clause kind is 'map'.
23098 Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind,
23099 MappableVarListInfo &MVLI, SourceLocation StartLoc,
23100 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId,
23101 ArrayRef<Expr *> UnresolvedMappers,
23103 ArrayRef<OpenMPMapModifierKind> Modifiers = {},
23104 bool IsMapTypeImplicit = false, bool NoDiagnose = false) {
23105 // We only expect mappable expressions in 'to', 'from', 'map', and
23106 // 'use_device_addr' clauses.
23107 assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from ||
23108 CKind == OMPC_use_device_addr) &&
23109 "Unexpected clause kind with mappable expressions!");
23110 unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
23111
23112 // If the identifier of user-defined mapper is not specified, it is "default".
23113 // We do not change the actual name in this clause to distinguish whether a
23114 // mapper is specified explicitly, i.e., it is not explicitly specified when
23115 // MapperId.getName() is empty.
23116 if (!MapperId.getName() || MapperId.getName().isEmpty()) {
23117 auto &DeclNames = SemaRef.getASTContext().DeclarationNames;
23118 MapperId.setName(DeclNames.getIdentifier(
23119 &SemaRef.getASTContext().Idents.get("default")));
23120 MapperId.setLoc(StartLoc);
23121 }
23122
23123 // Iterators to find the current unresolved mapper expression.
23124 auto UMIt = UnresolvedMappers.begin(), UMEnd = UnresolvedMappers.end();
23125 bool UpdateUMIt = false;
23126 Expr *UnresolvedMapper = nullptr;
23127
23128 bool HasHoldModifier =
23129 llvm::is_contained(Modifiers, OMPC_MAP_MODIFIER_ompx_hold);
23130
23131 // Keep track of the mappable components and base declarations in this clause.
23132 // Each entry in the list is going to have a list of components associated. We
23133 // record each set of the components so that we can build the clause later on.
23134 // In the end we should have the same amount of declarations and component
23135 // lists.
23136
23137 for (Expr *RE : MVLI.VarList) {
23138 assert(RE && "Null expr in omp to/from/map clause");
23139 SourceLocation ELoc = RE->getExprLoc();
23140
23141 // Find the current unresolved mapper expression.
23142 if (UpdateUMIt && UMIt != UMEnd) {
23143 UMIt++;
23144 assert(
23145 UMIt != UMEnd &&
23146 "Expect the size of UnresolvedMappers to match with that of VarList");
23147 }
23148 UpdateUMIt = true;
23149 if (UMIt != UMEnd)
23150 UnresolvedMapper = *UMIt;
23151
23152 const Expr *VE = RE->IgnoreParenLValueCasts();
23153
23154 if (VE->isValueDependent() || VE->isTypeDependent() ||
23155 VE->isInstantiationDependent() ||
23156 VE->containsUnexpandedParameterPack()) {
23157 // Try to find the associated user-defined mapper.
23159 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23160 VE->getType().getCanonicalType(), UnresolvedMapper);
23161 if (ER.isInvalid())
23162 continue;
23163 MVLI.UDMapperList.push_back(ER.get());
23164 // We can only analyze this information once the missing information is
23165 // resolved.
23166 MVLI.ProcessedVarList.push_back(RE);
23167 continue;
23168 }
23169
23171
23172 if (!RE->isLValue()) {
23173 if (SemaRef.getLangOpts().OpenMP < 50) {
23174 SemaRef.Diag(
23175 ELoc, diag::err_omp_expected_named_var_member_or_array_expression)
23176 << RE->getSourceRange();
23177 } else {
23178 SemaRef.Diag(ELoc, diag::err_omp_non_lvalue_in_map_or_motion_clauses)
23179 << getOpenMPClauseNameForDiag(CKind) << RE->getSourceRange();
23180 }
23181 continue;
23182 }
23183
23185 ValueDecl *CurDeclaration = nullptr;
23186
23187 // Obtain the array or member expression bases if required. Also, fill the
23188 // components array with all the components identified in the process.
23189 const Expr *BE =
23190 checkMapClauseExpressionBase(SemaRef, SimpleExpr, CurComponents, CKind,
23191 DSAS->getCurrentDirective(), NoDiagnose);
23192 if (!BE)
23193 continue;
23194
23195 assert(!CurComponents.empty() &&
23196 "Invalid mappable expression information.");
23197
23198 if (const auto *TE = dyn_cast<CXXThisExpr>(BE)) {
23199 // Add store "this" pointer to class in DSAStackTy for future checking
23200 DSAS->addMappedClassesQualTypes(TE->getType());
23201 // Try to find the associated user-defined mapper.
23203 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23204 VE->getType().getCanonicalType(), UnresolvedMapper);
23205 if (ER.isInvalid())
23206 continue;
23207 MVLI.UDMapperList.push_back(ER.get());
23208 // Skip restriction checking for variable or field declarations
23209 MVLI.ProcessedVarList.push_back(RE);
23210 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23211 MVLI.VarComponents.back().append(CurComponents.begin(),
23212 CurComponents.end());
23213 MVLI.VarBaseDeclarations.push_back(nullptr);
23214 continue;
23215 }
23216
23217 // For the following checks, we rely on the base declaration which is
23218 // expected to be associated with the last component. The declaration is
23219 // expected to be a variable or a field (if 'this' is being mapped).
23220 CurDeclaration = CurComponents.back().getAssociatedDeclaration();
23221 assert(CurDeclaration && "Null decl on map clause.");
23222 assert(
23223 CurDeclaration->isCanonicalDecl() &&
23224 "Expecting components to have associated only canonical declarations.");
23225
23226 auto *VD = dyn_cast<VarDecl>(CurDeclaration);
23227 const auto *FD = dyn_cast<FieldDecl>(CurDeclaration);
23228
23229 assert((VD || FD) && "Only variables or fields are expected here!");
23230 (void)FD;
23231
23232 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.10]
23233 // threadprivate variables cannot appear in a map clause.
23234 // OpenMP 4.5 [2.10.5, target update Construct]
23235 // threadprivate variables cannot appear in a from clause.
23236 if (VD && DSAS->isThreadPrivate(VD)) {
23237 if (NoDiagnose)
23238 continue;
23239 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23240 SemaRef.Diag(ELoc, diag::err_omp_threadprivate_in_clause)
23242 reportOriginalDsa(SemaRef, DSAS, VD, DVar);
23243 continue;
23244 }
23245
23246 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23247 // A list item cannot appear in both a map clause and a data-sharing
23248 // attribute clause on the same construct.
23249
23250 // Check conflicts with other map clause expressions. We check the conflicts
23251 // with the current construct separately from the enclosing data
23252 // environment, because the restrictions are different. We only have to
23253 // check conflicts across regions for the map clauses.
23254 if (checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23255 /*CurrentRegionOnly=*/true, CurComponents, CKind))
23256 break;
23257 if (CKind == OMPC_map &&
23258 (SemaRef.getLangOpts().OpenMP <= 45 || StartLoc.isValid()) &&
23259 checkMapConflicts(SemaRef, DSAS, CurDeclaration, SimpleExpr,
23260 /*CurrentRegionOnly=*/false, CurComponents, CKind))
23261 break;
23262
23263 // OpenMP 4.5 [2.10.5, target update Construct]
23264 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, C++, p.1]
23265 // If the type of a list item is a reference to a type T then the type will
23266 // be considered to be T for all purposes of this clause.
23267 auto I = llvm::find_if(
23268 CurComponents,
23269 [](const OMPClauseMappableExprCommon::MappableComponent &MC) {
23270 return MC.getAssociatedDeclaration();
23271 });
23272 assert(I != CurComponents.end() && "Null decl on map clause.");
23273 (void)I;
23274 QualType Type;
23275 auto *ASE = dyn_cast<ArraySubscriptExpr>(VE->IgnoreParens());
23276 auto *OASE = dyn_cast<ArraySectionExpr>(VE->IgnoreParens());
23277 auto *OAShE = dyn_cast<OMPArrayShapingExpr>(VE->IgnoreParens());
23278 if (ASE) {
23279 Type = ASE->getType().getNonReferenceType();
23280 } else if (OASE) {
23281 QualType BaseType =
23283 if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
23284 Type = ATy->getElementType();
23285 else
23286 Type = BaseType->getPointeeType();
23287 Type = Type.getNonReferenceType();
23288 } else if (OAShE) {
23289 Type = OAShE->getBase()->getType()->getPointeeType();
23290 } else {
23291 Type = VE->getType();
23292 }
23293
23294 // OpenMP 4.5 [2.10.5, target update Construct, Restrictions, p.4]
23295 // A list item in a to or from clause must have a mappable type.
23296 // OpenMP 4.5 [2.15.5.1, map Clause, Restrictions, p.9]
23297 // A list item must have a mappable type.
23298 if (!checkTypeMappable(VE->getExprLoc(), VE->getSourceRange(), SemaRef,
23299 DSAS, Type, /*FullCheck=*/true))
23300 continue;
23301
23302 if (CKind == OMPC_map) {
23303 // target enter data
23304 // OpenMP [2.10.2, Restrictions, p. 99]
23305 // A map-type must be specified in all map clauses and must be either
23306 // to or alloc. Starting with OpenMP 5.2 the default map type is `to` if
23307 // no map type is present.
23308 OpenMPDirectiveKind DKind = DSAS->getCurrentDirective();
23309 if (DKind == OMPD_target_enter_data &&
23310 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_alloc ||
23311 SemaRef.getLangOpts().OpenMP >= 52)) {
23312 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23313 << (IsMapTypeImplicit ? 1 : 0)
23314 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23315 << getOpenMPDirectiveName(DKind, OMPVersion);
23316 continue;
23317 }
23318
23319 // target exit_data
23320 // OpenMP [2.10.3, Restrictions, p. 102]
23321 // A map-type must be specified in all map clauses and must be either
23322 // from, release, or delete. Starting with OpenMP 5.2 the default map
23323 // type is `from` if no map type is present.
23324 if (DKind == OMPD_target_exit_data &&
23325 !(MapType == OMPC_MAP_from || MapType == OMPC_MAP_release ||
23326 MapType == OMPC_MAP_delete || SemaRef.getLangOpts().OpenMP >= 52)) {
23327 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23328 << (IsMapTypeImplicit ? 1 : 0)
23329 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23330 << getOpenMPDirectiveName(DKind, OMPVersion);
23331 continue;
23332 }
23333
23334 // The 'ompx_hold' modifier is specifically intended to be used on a
23335 // 'target' or 'target data' directive to prevent data from being unmapped
23336 // during the associated statement. It is not permitted on a 'target
23337 // enter data' or 'target exit data' directive, which have no associated
23338 // statement.
23339 if ((DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) &&
23340 HasHoldModifier) {
23341 SemaRef.Diag(StartLoc,
23342 diag::err_omp_invalid_map_type_modifier_for_directive)
23344 OMPC_MAP_MODIFIER_ompx_hold)
23345 << getOpenMPDirectiveName(DKind, OMPVersion);
23346 continue;
23347 }
23348
23349 // target, target data
23350 // OpenMP 5.0 [2.12.2, Restrictions, p. 163]
23351 // OpenMP 5.0 [2.12.5, Restrictions, p. 174]
23352 // A map-type in a map clause must be to, from, tofrom or alloc
23353 if ((DKind == OMPD_target_data ||
23355 !(MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
23356 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc)) {
23357 SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
23358 << (IsMapTypeImplicit ? 1 : 0)
23359 << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
23360 << getOpenMPDirectiveName(DKind, OMPVersion);
23361 continue;
23362 }
23363
23364 // OpenMP 4.5 [2.15.5.1, Restrictions, p.3]
23365 // A list item cannot appear in both a map clause and a data-sharing
23366 // attribute clause on the same construct
23367 //
23368 // OpenMP 5.0 [2.19.7.1, Restrictions, p.7]
23369 // A list item cannot appear in both a map clause and a data-sharing
23370 // attribute clause on the same construct unless the construct is a
23371 // combined construct.
23372 if (VD && ((SemaRef.LangOpts.OpenMP <= 45 &&
23374 DKind == OMPD_target)) {
23375 DSAStackTy::DSAVarData DVar = DSAS->getTopDSA(VD, /*FromParent=*/false);
23376 if (isOpenMPPrivate(DVar.CKind)) {
23377 SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
23378 << getOpenMPClauseNameForDiag(DVar.CKind)
23379 << getOpenMPClauseNameForDiag(OMPC_map)
23380 << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
23381 OMPVersion);
23382 reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
23383 continue;
23384 }
23385 }
23386 }
23387
23388 // Try to find the associated user-defined mapper.
23390 SemaRef, DSAS->getCurScope(), MapperIdScopeSpec, MapperId,
23391 Type.getCanonicalType(), UnresolvedMapper);
23392 if (ER.isInvalid())
23393 continue;
23394
23395 // If no user-defined mapper is found, we need to create an implicit one for
23396 // arrays/array-sections on structs that have members that have
23397 // user-defined mappers. This is needed to ensure that the mapper for the
23398 // member is invoked when mapping each element of the array/array-section.
23399 if (!ER.get()) {
23400 QualType BaseType;
23401
23403 BaseType = VE->getType().getCanonicalType();
23404 if (BaseType->isSpecificBuiltinType(BuiltinType::ArraySection)) {
23405 const auto *OASE = cast<ArraySectionExpr>(VE->IgnoreParenImpCasts());
23406 QualType BType =
23408 QualType ElemType;
23409 if (const auto *ATy = BType->getAsArrayTypeUnsafe())
23410 ElemType = ATy->getElementType();
23411 else
23412 ElemType = BType->getPointeeType();
23413 BaseType = ElemType.getCanonicalType();
23414 }
23415 } else if (VE->getType()->isArrayType()) {
23416 const ArrayType *AT = VE->getType()->getAsArrayTypeUnsafe();
23417 const QualType ElemType = AT->getElementType();
23418 BaseType = ElemType.getCanonicalType();
23419 }
23420
23421 if (!BaseType.isNull() && BaseType->getAsRecordDecl() &&
23422 isImplicitMapperNeeded(SemaRef, DSAS, BaseType, VE)) {
23423 ER = buildImplicitMapper(SemaRef, BaseType, DSAS);
23424 }
23425 }
23426 MVLI.UDMapperList.push_back(ER.get());
23427
23428 // Save the current expression.
23429 MVLI.ProcessedVarList.push_back(RE);
23430
23431 // Store the components in the stack so that they can be used to check
23432 // against other clauses later on.
23433 DSAS->addMappableExpressionComponents(CurDeclaration, CurComponents,
23434 /*WhereFoundClauseKind=*/OMPC_map);
23435
23436 // Save the components and declaration to create the clause. For purposes of
23437 // the clause creation, any component list that has base 'this' uses
23438 // null as base declaration.
23439 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
23440 MVLI.VarComponents.back().append(CurComponents.begin(),
23441 CurComponents.end());
23442 MVLI.VarBaseDeclarations.push_back(isa<MemberExpr>(BE) ? nullptr
23443 : CurDeclaration);
23444 }
23445}
23446
23448 Expr *IteratorModifier, ArrayRef<OpenMPMapModifierKind> MapTypeModifiers,
23449 ArrayRef<SourceLocation> MapTypeModifiersLoc,
23450 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
23451 OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc,
23452 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
23453 const OMPVarListLocTy &Locs, bool NoDiagnose,
23454 ArrayRef<Expr *> UnresolvedMappers) {
23455 OpenMPMapModifierKind Modifiers[] = {
23461
23462 if (IteratorModifier && !IteratorModifier->getType()->isSpecificBuiltinType(
23463 BuiltinType::OMPIterator))
23464 Diag(IteratorModifier->getExprLoc(),
23465 diag::err_omp_map_modifier_not_iterator);
23466
23467 // Process map-type-modifiers, flag errors for duplicate modifiers.
23468 unsigned Count = 0;
23469 for (unsigned I = 0, E = MapTypeModifiers.size(); I < E; ++I) {
23470 if (MapTypeModifiers[I] != OMPC_MAP_MODIFIER_unknown &&
23471 llvm::is_contained(Modifiers, MapTypeModifiers[I])) {
23472 Diag(MapTypeModifiersLoc[I], diag::err_omp_duplicate_map_type_modifier);
23473 continue;
23474 }
23475 assert(Count < NumberOfOMPMapClauseModifiers &&
23476 "Modifiers exceed the allowed number of map type modifiers");
23477 Modifiers[Count] = MapTypeModifiers[I];
23478 ModifiersLoc[Count] = MapTypeModifiersLoc[I];
23479 ++Count;
23480 }
23481
23482 MappableVarListInfo MVLI(VarList);
23484 MapperIdScopeSpec, MapperId, UnresolvedMappers,
23485 MapType, Modifiers, IsMapTypeImplicit,
23486 NoDiagnose);
23487
23488 // We need to produce a map clause even if we don't have variables so that
23489 // other diagnostics related with non-existing map clauses are accurate.
23490 return OMPMapClause::Create(
23491 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
23492 MVLI.VarComponents, MVLI.UDMapperList, IteratorModifier, Modifiers,
23493 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
23494 MapperId, MapType, IsMapTypeImplicit, MapLoc);
23495}
23496
23499 assert(ParsedType.isUsable());
23500
23501 QualType ReductionType = SemaRef.GetTypeFromParser(ParsedType.get());
23502 if (ReductionType.isNull())
23503 return QualType();
23504
23505 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions, C\C++
23506 // A type name in a declare reduction directive cannot be a function type, an
23507 // array type, a reference type, or a type qualified with const, volatile or
23508 // restrict.
23509 if (ReductionType.hasQualifiers()) {
23510 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 0;
23511 return QualType();
23512 }
23513
23514 if (ReductionType->isFunctionType()) {
23515 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 1;
23516 return QualType();
23517 }
23518 if (ReductionType->isReferenceType()) {
23519 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 2;
23520 return QualType();
23521 }
23522 if (ReductionType->isArrayType()) {
23523 Diag(TyLoc, diag::err_omp_reduction_wrong_type) << 3;
23524 return QualType();
23525 }
23526 return ReductionType;
23527}
23528
23531 Scope *S, DeclContext *DC, DeclarationName Name,
23532 ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes,
23533 AccessSpecifier AS, Decl *PrevDeclInScope) {
23535 Decls.reserve(ReductionTypes.size());
23536
23537 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23539 SemaRef.forRedeclarationInCurContext());
23540 // [OpenMP 4.0], 2.15 declare reduction Directive, Restrictions
23541 // A reduction-identifier may not be re-declared in the current scope for the
23542 // same type or for a type that is compatible according to the base language
23543 // rules.
23544 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23545 OMPDeclareReductionDecl *PrevDRD = nullptr;
23546 bool InCompoundScope = true;
23547 if (S != nullptr) {
23548 // Find previous declaration with the same name not referenced in other
23549 // declarations.
23550 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23551 InCompoundScope =
23552 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23553 SemaRef.LookupName(Lookup, S);
23554 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23555 /*AllowInlineNamespace=*/false);
23556 llvm::DenseMap<OMPDeclareReductionDecl *, bool> UsedAsPrevious;
23557 LookupResult::Filter Filter = Lookup.makeFilter();
23558 while (Filter.hasNext()) {
23559 auto *PrevDecl = cast<OMPDeclareReductionDecl>(Filter.next());
23560 if (InCompoundScope) {
23561 UsedAsPrevious.try_emplace(PrevDecl, false);
23562 if (OMPDeclareReductionDecl *D = PrevDecl->getPrevDeclInScope())
23563 UsedAsPrevious[D] = true;
23564 }
23565 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23566 PrevDecl->getLocation();
23567 }
23568 Filter.done();
23569 if (InCompoundScope) {
23570 for (const auto &PrevData : UsedAsPrevious) {
23571 if (!PrevData.second) {
23572 PrevDRD = PrevData.first;
23573 break;
23574 }
23575 }
23576 }
23577 } else if (PrevDeclInScope != nullptr) {
23578 auto *PrevDRDInScope = PrevDRD =
23579 cast<OMPDeclareReductionDecl>(PrevDeclInScope);
23580 do {
23581 PreviousRedeclTypes[PrevDRDInScope->getType().getCanonicalType()] =
23582 PrevDRDInScope->getLocation();
23583 PrevDRDInScope = PrevDRDInScope->getPrevDeclInScope();
23584 } while (PrevDRDInScope != nullptr);
23585 }
23586 for (const auto &TyData : ReductionTypes) {
23587 const auto I = PreviousRedeclTypes.find(TyData.first.getCanonicalType());
23588 bool Invalid = false;
23589 if (I != PreviousRedeclTypes.end()) {
23590 Diag(TyData.second, diag::err_omp_declare_reduction_redefinition)
23591 << TyData.first;
23592 Diag(I->second, diag::note_previous_definition);
23593 Invalid = true;
23594 }
23595 PreviousRedeclTypes[TyData.first.getCanonicalType()] = TyData.second;
23597 getASTContext(), DC, TyData.second, Name, TyData.first, PrevDRD);
23598 DC->addDecl(DRD);
23599 DRD->setAccess(AS);
23600 Decls.push_back(DRD);
23601 if (Invalid)
23602 DRD->setInvalidDecl();
23603 else
23604 PrevDRD = DRD;
23605 }
23606
23607 return DeclGroupPtrTy::make(
23608 DeclGroupRef::Create(getASTContext(), Decls.begin(), Decls.size()));
23609}
23610
23612 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23613
23614 // Enter new function scope.
23615 SemaRef.PushFunctionScope();
23616 SemaRef.setFunctionHasBranchProtectedScope();
23617 SemaRef.getCurFunction()->setHasOMPDeclareReductionCombiner();
23618
23619 if (S != nullptr)
23620 SemaRef.PushDeclContext(S, DRD);
23621 else
23622 SemaRef.CurContext = DRD;
23623
23624 SemaRef.PushExpressionEvaluationContext(
23626
23627 QualType ReductionType = DRD->getType();
23628 // Create 'T* omp_parm;T omp_in;'. All references to 'omp_in' will
23629 // be replaced by '*omp_parm' during codegen. This required because 'omp_in'
23630 // uses semantics of argument handles by value, but it should be passed by
23631 // reference. C lang does not support references, so pass all parameters as
23632 // pointers.
23633 // Create 'T omp_in;' variable.
23634 VarDecl *OmpInParm =
23635 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_in");
23636 // Create 'T* omp_parm;T omp_out;'. All references to 'omp_out' will
23637 // be replaced by '*omp_parm' during codegen. This required because 'omp_out'
23638 // uses semantics of argument handles by value, but it should be passed by
23639 // reference. C lang does not support references, so pass all parameters as
23640 // pointers.
23641 // Create 'T omp_out;' variable.
23642 VarDecl *OmpOutParm =
23643 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_out");
23644 if (S != nullptr) {
23645 SemaRef.PushOnScopeChains(OmpInParm, S);
23646 SemaRef.PushOnScopeChains(OmpOutParm, S);
23647 } else {
23648 DRD->addDecl(OmpInParm);
23649 DRD->addDecl(OmpOutParm);
23650 }
23651 Expr *InE =
23652 ::buildDeclRefExpr(SemaRef, OmpInParm, ReductionType, D->getLocation());
23653 Expr *OutE =
23654 ::buildDeclRefExpr(SemaRef, OmpOutParm, ReductionType, D->getLocation());
23655 DRD->setCombinerData(InE, OutE);
23656}
23657
23659 Expr *Combiner) {
23660 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23661 SemaRef.DiscardCleanupsInEvaluationContext();
23662 SemaRef.PopExpressionEvaluationContext();
23663
23664 SemaRef.PopDeclContext();
23665 SemaRef.PopFunctionScopeInfo();
23666
23667 if (Combiner != nullptr)
23668 DRD->setCombiner(Combiner);
23669 else
23670 DRD->setInvalidDecl();
23671}
23672
23674 Decl *D) {
23675 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23676
23677 // Enter new function scope.
23678 SemaRef.PushFunctionScope();
23679 SemaRef.setFunctionHasBranchProtectedScope();
23680
23681 if (S != nullptr)
23682 SemaRef.PushDeclContext(S, DRD);
23683 else
23684 SemaRef.CurContext = DRD;
23685
23686 SemaRef.PushExpressionEvaluationContext(
23688
23689 QualType ReductionType = DRD->getType();
23690 // Create 'T* omp_parm;T omp_priv;'. All references to 'omp_priv' will
23691 // be replaced by '*omp_parm' during codegen. This required because 'omp_priv'
23692 // uses semantics of argument handles by value, but it should be passed by
23693 // reference. C lang does not support references, so pass all parameters as
23694 // pointers.
23695 // Create 'T omp_priv;' variable.
23696 VarDecl *OmpPrivParm =
23697 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_priv");
23698 // Create 'T* omp_parm;T omp_orig;'. All references to 'omp_orig' will
23699 // be replaced by '*omp_parm' during codegen. This required because 'omp_orig'
23700 // uses semantics of argument handles by value, but it should be passed by
23701 // reference. C lang does not support references, so pass all parameters as
23702 // pointers.
23703 // Create 'T omp_orig;' variable.
23704 VarDecl *OmpOrigParm =
23705 buildVarDecl(SemaRef, D->getLocation(), ReductionType, "omp_orig");
23706 if (S != nullptr) {
23707 SemaRef.PushOnScopeChains(OmpPrivParm, S);
23708 SemaRef.PushOnScopeChains(OmpOrigParm, S);
23709 } else {
23710 DRD->addDecl(OmpPrivParm);
23711 DRD->addDecl(OmpOrigParm);
23712 }
23713 Expr *OrigE =
23714 ::buildDeclRefExpr(SemaRef, OmpOrigParm, ReductionType, D->getLocation());
23715 Expr *PrivE =
23716 ::buildDeclRefExpr(SemaRef, OmpPrivParm, ReductionType, D->getLocation());
23717 DRD->setInitializerData(OrigE, PrivE);
23718 return OmpPrivParm;
23719}
23720
23722 Decl *D, Expr *Initializer, VarDecl *OmpPrivParm) {
23723 auto *DRD = cast<OMPDeclareReductionDecl>(D);
23724 SemaRef.DiscardCleanupsInEvaluationContext();
23725 SemaRef.PopExpressionEvaluationContext();
23726
23727 SemaRef.PopDeclContext();
23728 SemaRef.PopFunctionScopeInfo();
23729
23730 if (Initializer != nullptr) {
23731 DRD->setInitializer(Initializer, OMPDeclareReductionInitKind::Call);
23732 } else if (OmpPrivParm->hasInit()) {
23733 DRD->setInitializer(OmpPrivParm->getInit(),
23734 OmpPrivParm->isDirectInit()
23737 } else {
23738 DRD->setInvalidDecl();
23739 }
23740}
23741
23743 Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid) {
23744 for (Decl *D : DeclReductions.get()) {
23745 if (IsValid) {
23746 if (S)
23747 SemaRef.PushOnScopeChains(cast<OMPDeclareReductionDecl>(D), S,
23748 /*AddToContext=*/false);
23749 } else {
23750 D->setInvalidDecl();
23751 }
23752 }
23753 return DeclReductions;
23754}
23755
23757 Declarator &D) {
23758 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
23759 QualType T = TInfo->getType();
23760 if (D.isInvalidType())
23761 return true;
23762
23763 if (getLangOpts().CPlusPlus) {
23764 // Check that there are no default arguments (C++ only).
23765 SemaRef.CheckExtraCXXDefaultArguments(D);
23766 }
23767
23768 return SemaRef.CreateParsedType(T, TInfo);
23769}
23770
23773 assert(ParsedType.isUsable() && "Expect usable parsed mapper type");
23774
23775 QualType MapperType = SemaRef.GetTypeFromParser(ParsedType.get());
23776 assert(!MapperType.isNull() && "Expect valid mapper type");
23777
23778 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23779 // The type must be of struct, union or class type in C and C++
23780 if (!MapperType->isStructureOrClassType() && !MapperType->isUnionType()) {
23781 Diag(TyLoc, diag::err_omp_mapper_wrong_type);
23782 return QualType();
23783 }
23784 return MapperType;
23785}
23786
23788 Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType,
23790 Expr *MapperVarRef, ArrayRef<OMPClause *> Clauses, Decl *PrevDeclInScope) {
23791 LookupResult Lookup(SemaRef, Name, SourceLocation(),
23793 SemaRef.forRedeclarationInCurContext());
23794 // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions
23795 // A mapper-identifier may not be redeclared in the current scope for the
23796 // same type or for a type that is compatible according to the base language
23797 // rules.
23798 llvm::DenseMap<QualType, SourceLocation> PreviousRedeclTypes;
23799 OMPDeclareMapperDecl *PrevDMD = nullptr;
23800 bool InCompoundScope = true;
23801 if (S != nullptr) {
23802 // Find previous declaration with the same name not referenced in other
23803 // declarations.
23804 FunctionScopeInfo *ParentFn = SemaRef.getEnclosingFunction();
23805 InCompoundScope =
23806 (ParentFn != nullptr) && !ParentFn->CompoundScopes.empty();
23807 SemaRef.LookupName(Lookup, S);
23808 SemaRef.FilterLookupForScope(Lookup, DC, S, /*ConsiderLinkage=*/false,
23809 /*AllowInlineNamespace=*/false);
23810 llvm::DenseMap<OMPDeclareMapperDecl *, bool> UsedAsPrevious;
23811 LookupResult::Filter Filter = Lookup.makeFilter();
23812 while (Filter.hasNext()) {
23813 auto *PrevDecl = cast<OMPDeclareMapperDecl>(Filter.next());
23814 if (InCompoundScope) {
23815 UsedAsPrevious.try_emplace(PrevDecl, false);
23816 if (OMPDeclareMapperDecl *D = PrevDecl->getPrevDeclInScope())
23817 UsedAsPrevious[D] = true;
23818 }
23819 PreviousRedeclTypes[PrevDecl->getType().getCanonicalType()] =
23820 PrevDecl->getLocation();
23821 }
23822 Filter.done();
23823 if (InCompoundScope) {
23824 for (const auto &PrevData : UsedAsPrevious) {
23825 if (!PrevData.second) {
23826 PrevDMD = PrevData.first;
23827 break;
23828 }
23829 }
23830 }
23831 } else if (PrevDeclInScope) {
23832 auto *PrevDMDInScope = PrevDMD =
23833 cast<OMPDeclareMapperDecl>(PrevDeclInScope);
23834 do {
23835 PreviousRedeclTypes[PrevDMDInScope->getType().getCanonicalType()] =
23836 PrevDMDInScope->getLocation();
23837 PrevDMDInScope = PrevDMDInScope->getPrevDeclInScope();
23838 } while (PrevDMDInScope != nullptr);
23839 }
23840 const auto I = PreviousRedeclTypes.find(MapperType.getCanonicalType());
23841 bool Invalid = false;
23842 if (I != PreviousRedeclTypes.end()) {
23843 Diag(StartLoc, diag::err_omp_declare_mapper_redefinition)
23844 << MapperType << Name;
23845 Diag(I->second, diag::note_previous_definition);
23846 Invalid = true;
23847 }
23848 // Build expressions for implicit maps of data members with 'default'
23849 // mappers.
23850 SmallVector<OMPClause *, 4> ClausesWithImplicit(Clauses);
23851 if (getLangOpts().OpenMP >= 50)
23853 ClausesWithImplicit);
23854 auto *DMD = OMPDeclareMapperDecl::Create(getASTContext(), DC, StartLoc, Name,
23855 MapperType, VN, ClausesWithImplicit,
23856 PrevDMD);
23857 if (S)
23858 SemaRef.PushOnScopeChains(DMD, S);
23859 else
23860 DC->addDecl(DMD);
23861 DMD->setAccess(AS);
23862 if (Invalid)
23863 DMD->setInvalidDecl();
23864
23865 auto *VD = cast<DeclRefExpr>(MapperVarRef)->getDecl();
23866 VD->setDeclContext(DMD);
23867 VD->setLexicalDeclContext(DMD);
23868 DMD->addDecl(VD);
23869 DMD->setMapperVarRef(MapperVarRef);
23870
23872}
23873
23875 Scope *S, QualType MapperType, SourceLocation StartLoc,
23876 DeclarationName VN) {
23877 TypeSourceInfo *TInfo =
23878 getASTContext().getTrivialTypeSourceInfo(MapperType, StartLoc);
23879 auto *VD = VarDecl::Create(
23880 getASTContext(), getASTContext().getTranslationUnitDecl(), StartLoc,
23881 StartLoc, VN.getAsIdentifierInfo(), MapperType, TInfo, SC_None);
23882 if (S)
23883 SemaRef.PushOnScopeChains(VD, S, /*AddToContext=*/false);
23884 Expr *E = buildDeclRefExpr(SemaRef, VD, MapperType, StartLoc);
23885 DSAStack->addDeclareMapperVarRef(E);
23886 return E;
23887}
23888
23890 bool IsGlobalVar =
23892 if (DSAStack->getDeclareMapperVarRef()) {
23893 if (IsGlobalVar)
23894 SemaRef.Consumer.HandleTopLevelDecl(DeclGroupRef(VD));
23895 DSAStack->addIteratorVarDecl(VD);
23896 } else {
23897 // Currently, only declare mapper handles global-scope iterator vars.
23898 assert(!IsGlobalVar && "Only declare mapper handles TU-scope iterators.");
23899 }
23900}
23901
23903 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23904 const Expr *Ref = DSAStack->getDeclareMapperVarRef();
23905 if (const auto *DRE = cast_or_null<DeclRefExpr>(Ref)) {
23906 if (VD->getCanonicalDecl() == DRE->getDecl()->getCanonicalDecl())
23907 return true;
23909 return true;
23910 if (getLangOpts().OpenMP >= 52 && DSAStack->isIteratorVarDecl(VD))
23911 return true;
23912 return false;
23913 }
23914 return true;
23915}
23916
23918 assert(getLangOpts().OpenMP && "Expected OpenMP mode.");
23919 return cast<DeclRefExpr>(DSAStack->getDeclareMapperVarRef())->getDecl();
23920}
23921
23923 SourceLocation StartLoc,
23924 SourceLocation LParenLoc,
23925 SourceLocation EndLoc) {
23926 if (VarList.empty())
23927 return nullptr;
23928
23929 for (Expr *ValExpr : VarList) {
23930 // OpenMP [teams Constrcut, Restrictions]
23931 // The num_teams expression must evaluate to a positive integer value.
23932 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_num_teams,
23933 /*StrictlyPositive=*/true))
23934 return nullptr;
23935 }
23936
23937 // OpenMP 5.2: Validate lower-bound ≤ upper-bound constraint
23938 if (VarList.size() == 2) {
23939 Expr *LowerBound = VarList[0];
23940 Expr *UpperBound = VarList[1];
23941
23942 // Check if both are compile-time constants for validation
23943 if (!LowerBound->isValueDependent() && !UpperBound->isValueDependent() &&
23944 LowerBound->isIntegerConstantExpr(getASTContext()) &&
23945 UpperBound->isIntegerConstantExpr(getASTContext())) {
23946
23947 // Get the actual constant values
23948 llvm::APSInt LowerVal =
23949 LowerBound->EvaluateKnownConstInt(getASTContext());
23950 llvm::APSInt UpperVal =
23951 UpperBound->EvaluateKnownConstInt(getASTContext());
23952
23953 if (LowerVal > UpperVal) {
23954 Diag(LowerBound->getExprLoc(),
23955 diag::err_omp_num_teams_lower_bound_larger)
23956 << LowerBound->getSourceRange() << UpperBound->getSourceRange();
23957 return nullptr;
23958 }
23959 }
23960 }
23961
23962 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
23964 DKind, OMPC_num_teams, getLangOpts().OpenMP);
23965 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
23966 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23967 LParenLoc, EndLoc, VarList,
23968 /*PreInit=*/nullptr);
23969
23970 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
23972 for (Expr *ValExpr : VarList) {
23973 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
23974 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
23975 Vars.push_back(ValExpr);
23976 }
23977
23978 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
23979 return OMPNumTeamsClause::Create(getASTContext(), CaptureRegion, StartLoc,
23980 LParenLoc, EndLoc, Vars, PreInit);
23981}
23982
23984 SourceLocation StartLoc,
23985 SourceLocation LParenLoc,
23986 SourceLocation EndLoc) {
23987 if (VarList.empty())
23988 return nullptr;
23989
23990 for (Expr *ValExpr : VarList) {
23991 // OpenMP [teams Constrcut, Restrictions]
23992 // The thread_limit expression must evaluate to a positive integer value.
23993 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_thread_limit,
23994 /*StrictlyPositive=*/true))
23995 return nullptr;
23996 }
23997
23998 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
24000 DKind, OMPC_thread_limit, getLangOpts().OpenMP);
24001 if (CaptureRegion == OMPD_unknown || SemaRef.CurContext->isDependentContext())
24002 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion,
24003 StartLoc, LParenLoc, EndLoc, VarList,
24004 /*PreInit=*/nullptr);
24005
24006 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24008 for (Expr *ValExpr : VarList) {
24009 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24010 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24011 Vars.push_back(ValExpr);
24012 }
24013
24014 Stmt *PreInit = buildPreInits(getASTContext(), Captures);
24015 return OMPThreadLimitClause::Create(getASTContext(), CaptureRegion, StartLoc,
24016 LParenLoc, EndLoc, Vars, PreInit);
24017}
24018
24020 SourceLocation StartLoc,
24021 SourceLocation LParenLoc,
24022 SourceLocation EndLoc) {
24023 Expr *ValExpr = Priority;
24024 Stmt *HelperValStmt = nullptr;
24025 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24026
24027 // OpenMP [2.9.1, task Constrcut]
24028 // The priority-value is a non-negative numerical scalar expression.
24030 ValExpr, SemaRef, OMPC_priority,
24031 /*StrictlyPositive=*/false, /*BuildCapture=*/true,
24032 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24033 return nullptr;
24034
24035 return new (getASTContext()) OMPPriorityClause(
24036 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
24037}
24038
24040 OpenMPGrainsizeClauseModifier Modifier, Expr *Grainsize,
24041 SourceLocation StartLoc, SourceLocation LParenLoc,
24042 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24043 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24044 "Unexpected grainsize modifier in OpenMP < 51.");
24045
24046 if (ModifierLoc.isValid() && Modifier == OMPC_GRAINSIZE_unknown) {
24047 std::string Values = getListOfPossibleValues(OMPC_grainsize, /*First=*/0,
24049 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24050 << Values << getOpenMPClauseNameForDiag(OMPC_grainsize);
24051 return nullptr;
24052 }
24053
24054 Expr *ValExpr = Grainsize;
24055 Stmt *HelperValStmt = nullptr;
24056 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24057
24058 // OpenMP [2.9.2, taskloop Constrcut]
24059 // The parameter of the grainsize clause must be a positive integer
24060 // expression.
24061 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_grainsize,
24062 /*StrictlyPositive=*/true,
24063 /*BuildCapture=*/true,
24064 DSAStack->getCurrentDirective(),
24065 &CaptureRegion, &HelperValStmt))
24066 return nullptr;
24067
24068 return new (getASTContext())
24069 OMPGrainsizeClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24070 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24071}
24072
24074 OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks,
24075 SourceLocation StartLoc, SourceLocation LParenLoc,
24076 SourceLocation ModifierLoc, SourceLocation EndLoc) {
24077 assert((ModifierLoc.isInvalid() || getLangOpts().OpenMP >= 51) &&
24078 "Unexpected num_tasks modifier in OpenMP < 51.");
24079
24080 if (ModifierLoc.isValid() && Modifier == OMPC_NUMTASKS_unknown) {
24081 std::string Values = getListOfPossibleValues(OMPC_num_tasks, /*First=*/0,
24083 Diag(ModifierLoc, diag::err_omp_unexpected_clause_value)
24084 << Values << getOpenMPClauseNameForDiag(OMPC_num_tasks);
24085 return nullptr;
24086 }
24087
24088 Expr *ValExpr = NumTasks;
24089 Stmt *HelperValStmt = nullptr;
24090 OpenMPDirectiveKind CaptureRegion = OMPD_unknown;
24091
24092 // OpenMP [2.9.2, taskloop Constrcut]
24093 // The parameter of the num_tasks clause must be a positive integer
24094 // expression.
24096 ValExpr, SemaRef, OMPC_num_tasks,
24097 /*StrictlyPositive=*/true, /*BuildCapture=*/true,
24098 DSAStack->getCurrentDirective(), &CaptureRegion, &HelperValStmt))
24099 return nullptr;
24100
24101 return new (getASTContext())
24102 OMPNumTasksClause(Modifier, ValExpr, HelperValStmt, CaptureRegion,
24103 StartLoc, LParenLoc, ModifierLoc, EndLoc);
24104}
24105
24107 SourceLocation StartLoc,
24108 SourceLocation LParenLoc,
24109 SourceLocation EndLoc) {
24110 // OpenMP [2.13.2, critical construct, Description]
24111 // ... where hint-expression is an integer constant expression that evaluates
24112 // to a valid lock hint.
24113 ExprResult HintExpr =
24114 VerifyPositiveIntegerConstantInClause(Hint, OMPC_hint, false);
24115 if (HintExpr.isInvalid())
24116 return nullptr;
24117 return new (getASTContext())
24118 OMPHintClause(HintExpr.get(), StartLoc, LParenLoc, EndLoc);
24119}
24120
24121/// Tries to find omp_event_handle_t type.
24123 DSAStackTy *Stack) {
24124 QualType OMPEventHandleT = Stack->getOMPEventHandleT();
24125 if (!OMPEventHandleT.isNull())
24126 return true;
24127 IdentifierInfo *II = &S.PP.getIdentifierTable().get("omp_event_handle_t");
24128 ParsedType PT = S.getTypeName(*II, Loc, S.getCurScope());
24129 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
24130 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_event_handle_t";
24131 return false;
24132 }
24133 Stack->setOMPEventHandleT(PT.get());
24134 return true;
24135}
24136
24138 SourceLocation StartLoc,
24139 SourceLocation LParenLoc,
24140 SourceLocation EndLoc) {
24141 if (!Evt->isValueDependent() && !Evt->isTypeDependent() &&
24142 !Evt->isInstantiationDependent() &&
24145 return nullptr;
24146 // OpenMP 5.0, 2.10.1 task Construct.
24147 // event-handle is a variable of the omp_event_handle_t type.
24148 auto *Ref = dyn_cast<DeclRefExpr>(Evt->IgnoreParenImpCasts());
24149 if (!Ref) {
24150 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24151 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24152 return nullptr;
24153 }
24154 auto *VD = dyn_cast_or_null<VarDecl>(Ref->getDecl());
24155 if (!VD) {
24156 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24157 << "omp_event_handle_t" << 0 << Evt->getSourceRange();
24158 return nullptr;
24159 }
24160 if (!getASTContext().hasSameUnqualifiedType(DSAStack->getOMPEventHandleT(),
24161 VD->getType()) ||
24162 VD->getType().isConstant(getASTContext())) {
24163 Diag(Evt->getExprLoc(), diag::err_omp_var_expected)
24164 << "omp_event_handle_t" << 1 << VD->getType()
24165 << Evt->getSourceRange();
24166 return nullptr;
24167 }
24168 // OpenMP 5.0, 2.10.1 task Construct
24169 // [detach clause]... The event-handle will be considered as if it was
24170 // specified on a firstprivate clause.
24171 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, /*FromParent=*/false);
24172 if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_firstprivate &&
24173 DVar.RefExpr) {
24174 Diag(Evt->getExprLoc(), diag::err_omp_wrong_dsa)
24175 << getOpenMPClauseNameForDiag(DVar.CKind)
24176 << getOpenMPClauseNameForDiag(OMPC_firstprivate);
24178 return nullptr;
24179 }
24180 }
24181
24182 return new (getASTContext())
24183 OMPDetachClause(Evt, StartLoc, LParenLoc, EndLoc);
24184}
24185
24187 OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc,
24188 SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc,
24189 SourceLocation EndLoc) {
24190 if (Kind == OMPC_DIST_SCHEDULE_unknown) {
24191 std::string Values;
24192 Values += "'";
24193 Values += getOpenMPSimpleClauseTypeName(OMPC_dist_schedule, 0);
24194 Values += "'";
24195 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24196 << Values << getOpenMPClauseNameForDiag(OMPC_dist_schedule);
24197 return nullptr;
24198 }
24199 Expr *ValExpr = ChunkSize;
24200 Stmt *HelperValStmt = nullptr;
24201 if (ChunkSize) {
24202 if (!ChunkSize->isValueDependent() && !ChunkSize->isTypeDependent() &&
24203 !ChunkSize->isInstantiationDependent() &&
24204 !ChunkSize->containsUnexpandedParameterPack()) {
24205 SourceLocation ChunkSizeLoc = ChunkSize->getBeginLoc();
24206 ExprResult Val =
24207 PerformOpenMPImplicitIntegerConversion(ChunkSizeLoc, ChunkSize);
24208 if (Val.isInvalid())
24209 return nullptr;
24210
24211 ValExpr = Val.get();
24212
24213 // OpenMP [2.7.1, Restrictions]
24214 // chunk_size must be a loop invariant integer expression with a positive
24215 // value.
24216 if (std::optional<llvm::APSInt> Result =
24218 if (Result->isSigned() && !Result->isStrictlyPositive()) {
24219 Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause)
24220 << "dist_schedule" << /*strictly positive*/ 1
24221 << ChunkSize->getSourceRange();
24222 return nullptr;
24223 }
24225 DSAStack->getCurrentDirective(), OMPC_dist_schedule,
24226 getLangOpts().OpenMP) != OMPD_unknown &&
24227 !SemaRef.CurContext->isDependentContext()) {
24228 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
24229 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
24230 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
24231 HelperValStmt = buildPreInits(getASTContext(), Captures);
24232 }
24233 }
24234 }
24235
24236 return new (getASTContext())
24237 OMPDistScheduleClause(StartLoc, LParenLoc, KindLoc, CommaLoc, EndLoc,
24238 Kind, ValExpr, HelperValStmt);
24239}
24240
24243 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc,
24244 SourceLocation KindLoc, SourceLocation EndLoc) {
24245 if (getLangOpts().OpenMP < 50) {
24246 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom ||
24247 Kind != OMPC_DEFAULTMAP_scalar) {
24248 std::string Value;
24249 SourceLocation Loc;
24250 Value += "'";
24251 if (M != OMPC_DEFAULTMAP_MODIFIER_tofrom) {
24252 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24253 OMPC_DEFAULTMAP_MODIFIER_tofrom);
24254 Loc = MLoc;
24255 } else {
24256 Value += getOpenMPSimpleClauseTypeName(OMPC_defaultmap,
24257 OMPC_DEFAULTMAP_scalar);
24258 Loc = KindLoc;
24259 }
24260 Value += "'";
24261 Diag(Loc, diag::err_omp_unexpected_clause_value)
24262 << Value << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24263 return nullptr;
24264 }
24265 } else {
24266 bool isDefaultmapModifier = (M != OMPC_DEFAULTMAP_MODIFIER_unknown);
24267 bool isDefaultmapKind = (Kind != OMPC_DEFAULTMAP_unknown) ||
24268 (getLangOpts().OpenMP >= 50 && KindLoc.isInvalid());
24269 if (!isDefaultmapKind || !isDefaultmapModifier) {
24270 StringRef KindValue = getLangOpts().OpenMP < 52
24271 ? "'scalar', 'aggregate', 'pointer'"
24272 : "'scalar', 'aggregate', 'pointer', 'all'";
24273 if (getLangOpts().OpenMP == 50) {
24274 StringRef ModifierValue = "'alloc', 'from', 'to', 'tofrom', "
24275 "'firstprivate', 'none', 'default'";
24276 if (!isDefaultmapKind && isDefaultmapModifier) {
24277 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24278 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24279 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24280 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24281 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24282 } else {
24283 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24284 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24285 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24286 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24287 }
24288 } else {
24289 StringRef ModifierValue =
24290 getLangOpts().OpenMP < 60
24291 ? "'alloc', 'from', 'to', 'tofrom', "
24292 "'firstprivate', 'none', 'default', 'present'"
24293 : "'storage', 'from', 'to', 'tofrom', "
24294 "'firstprivate', 'private', 'none', 'default', 'present'";
24295 if (!isDefaultmapKind && isDefaultmapModifier) {
24296 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24297 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24298 } else if (isDefaultmapKind && !isDefaultmapModifier) {
24299 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24300 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24301 } else {
24302 Diag(MLoc, diag::err_omp_unexpected_clause_value)
24303 << ModifierValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24304 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
24305 << KindValue << getOpenMPClauseNameForDiag(OMPC_defaultmap);
24306 }
24307 }
24308 return nullptr;
24309 }
24310
24311 // OpenMP [5.0, 2.12.5, Restrictions, p. 174]
24312 // At most one defaultmap clause for each category can appear on the
24313 // directive.
24314 if (DSAStack->checkDefaultmapCategory(Kind)) {
24315 Diag(StartLoc, diag::err_omp_one_defaultmap_each_category);
24316 return nullptr;
24317 }
24318 }
24319 if (Kind == OMPC_DEFAULTMAP_unknown || Kind == OMPC_DEFAULTMAP_all) {
24320 // Variable category is not specified - mark all categories.
24321 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_aggregate, StartLoc);
24322 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_scalar, StartLoc);
24323 DSAStack->setDefaultDMAAttr(M, OMPC_DEFAULTMAP_pointer, StartLoc);
24324 } else {
24325 DSAStack->setDefaultDMAAttr(M, Kind, StartLoc);
24326 }
24327
24328 return new (getASTContext())
24329 OMPDefaultmapClause(StartLoc, LParenLoc, MLoc, KindLoc, EndLoc, Kind, M);
24330}
24331
24334 DeclContext *CurLexicalContext = SemaRef.getCurLexicalContext();
24335 if (!CurLexicalContext->isFileContext() &&
24336 !CurLexicalContext->isExternCContext() &&
24337 !CurLexicalContext->isExternCXXContext() &&
24338 !isa<CXXRecordDecl>(CurLexicalContext) &&
24339 !isa<ClassTemplateDecl>(CurLexicalContext) &&
24340 !isa<ClassTemplatePartialSpecializationDecl>(CurLexicalContext) &&
24341 !isa<ClassTemplateSpecializationDecl>(CurLexicalContext)) {
24342 Diag(DTCI.Loc, diag::err_omp_region_not_file_context);
24343 return false;
24344 }
24345
24346 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24347 if (getLangOpts().HIP)
24348 Diag(DTCI.Loc, diag::warn_hip_omp_target_directives);
24349
24350 DeclareTargetNesting.push_back(DTCI);
24351 return true;
24352}
24353
24356 assert(!DeclareTargetNesting.empty() &&
24357 "check isInOpenMPDeclareTargetContext() first!");
24358 return DeclareTargetNesting.pop_back_val();
24359}
24360
24363 for (auto &It : DTCI.ExplicitlyMapped)
24364 ActOnOpenMPDeclareTargetName(It.first, It.second.Loc, It.second.MT, DTCI);
24365}
24366
24368 if (DeclareTargetNesting.empty())
24369 return;
24370 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24371 unsigned OMPVersion = getLangOpts().OpenMP;
24372 Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
24373 << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
24374}
24375
24377 Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id) {
24379 SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
24380 /*ObjectType=*/QualType(),
24381 /*AllowBuiltinCreation=*/true);
24382
24383 if (Lookup.isAmbiguous())
24384 return nullptr;
24385 Lookup.suppressDiagnostics();
24386
24387 if (!Lookup.isSingleResult()) {
24388 VarOrFuncDeclFilterCCC CCC(SemaRef);
24389 if (TypoCorrection Corrected =
24390 SemaRef.CorrectTypo(Id, Sema::LookupOrdinaryName, CurScope, nullptr,
24392 SemaRef.diagnoseTypo(Corrected,
24393 SemaRef.PDiag(diag::err_undeclared_var_use_suggest)
24394 << Id.getName());
24395 checkDeclIsAllowedInOpenMPTarget(nullptr, Corrected.getCorrectionDecl());
24396 return nullptr;
24397 }
24398
24399 Diag(Id.getLoc(), diag::err_undeclared_var_use) << Id.getName();
24400 return nullptr;
24401 }
24402
24403 NamedDecl *ND = Lookup.getAsSingle<NamedDecl>();
24404 if (!isa<VarDecl>(ND) && !isa<FunctionDecl>(ND) &&
24406 Diag(Id.getLoc(), diag::err_omp_invalid_target_decl) << Id.getName();
24407 return nullptr;
24408 }
24409 return ND;
24410}
24411
24413 NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT,
24415 assert((isa<VarDecl>(ND) || isa<FunctionDecl>(ND) ||
24417 "Expected variable, function or function template.");
24418
24419 if (auto *VD = dyn_cast<VarDecl>(ND)) {
24420 // Only global variables can be marked as declare target.
24421 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24422 !VD->isStaticDataMember()) {
24423 Diag(Loc, diag::err_omp_declare_target_has_local_vars)
24424 << VD->getNameAsString();
24425 return;
24426 }
24427 }
24428 // Diagnose marking after use as it may lead to incorrect diagnosis and
24429 // codegen.
24430 if (getLangOpts().OpenMP >= 50 &&
24431 (ND->isUsed(/*CheckUsedAttr=*/false) || ND->isReferenced()))
24432 Diag(Loc, diag::warn_omp_declare_target_after_first_use);
24433
24434 // Report affected OpenMP target offloading behavior when in HIP lang-mode.
24435 if (getLangOpts().HIP)
24436 Diag(Loc, diag::warn_hip_omp_target_directives);
24437
24438 // Explicit declare target lists have precedence.
24439 const unsigned Level = -1;
24440
24441 auto *VD = cast<ValueDecl>(ND);
24442 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24443 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24444 if (ActiveAttr && (*ActiveAttr)->getDevType() != DTCI.DT &&
24445 (*ActiveAttr)->getLevel() == Level) {
24446 Diag(Loc, diag::err_omp_device_type_mismatch)
24447 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(DTCI.DT)
24448 << OMPDeclareTargetDeclAttr::ConvertDevTypeTyToStr(
24449 (*ActiveAttr)->getDevType());
24450 return;
24451 }
24452 if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
24453 (*ActiveAttr)->getLevel() == Level) {
24454 Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
24455 return;
24456 }
24457
24458 if (ActiveAttr && (*ActiveAttr)->getLevel() == Level)
24459 return;
24460
24461 Expr *IndirectE = nullptr;
24462 bool IsIndirect = false;
24463 if (DTCI.Indirect) {
24464 IndirectE = *DTCI.Indirect;
24465 if (!IndirectE)
24466 IsIndirect = true;
24467 }
24468 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24469 getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
24470 SourceRange(Loc, Loc));
24471 ND->addAttr(A);
24472 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24473 ML->DeclarationMarkedOpenMPDeclareTarget(ND, A);
24474 checkDeclIsAllowedInOpenMPTarget(nullptr, ND, Loc);
24475 if (auto *VD = dyn_cast<VarDecl>(ND);
24476 getLangOpts().OpenMP && VD && VD->hasAttr<OMPDeclareTargetDeclAttr>() &&
24477 VD->hasGlobalStorage())
24479}
24480
24482 Sema &SemaRef, Decl *D) {
24483 if (!D || !isa<VarDecl>(D))
24484 return;
24485 auto *VD = cast<VarDecl>(D);
24486 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> MapTy =
24487 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
24488 if (SemaRef.LangOpts.OpenMP >= 50 &&
24489 (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) ||
24490 SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
24491 VD->hasGlobalStorage()) {
24492 if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
24493 *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
24494 // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions
24495 // If a lambda declaration and definition appears between a
24496 // declare target directive and the matching end declare target
24497 // directive, all variables that are captured by the lambda
24498 // expression must also appear in a to clause.
24499 SemaRef.Diag(VD->getLocation(),
24500 diag::err_omp_lambda_capture_in_declare_target_not_to);
24501 SemaRef.Diag(SL, diag::note_var_explicitly_captured_here)
24502 << VD << 0 << SR;
24503 return;
24504 }
24505 }
24506 if (MapTy)
24507 return;
24508 SemaRef.Diag(VD->getLocation(), diag::warn_omp_not_in_target_context);
24509 SemaRef.Diag(SL, diag::note_used_here) << SR;
24510}
24511
24513 Sema &SemaRef, DSAStackTy *Stack,
24514 ValueDecl *VD) {
24515 return OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) ||
24516 checkTypeMappable(SL, SR, SemaRef, Stack, VD->getType(),
24517 /*FullCheck=*/false);
24518}
24519
24521 SourceLocation IdLoc) {
24522 if (!D || D->isInvalidDecl())
24523 return;
24524 SourceRange SR = E ? E->getSourceRange() : D->getSourceRange();
24525 SourceLocation SL = E ? E->getBeginLoc() : D->getLocation();
24526 if (auto *VD = dyn_cast<VarDecl>(D)) {
24527 // Only global variables can be marked as declare target.
24528 if (!VD->isFileVarDecl() && !VD->isStaticLocal() &&
24529 !VD->isStaticDataMember())
24530 return;
24531 // 2.10.6: threadprivate variable cannot appear in a declare target
24532 // directive.
24533 if (DSAStack->isThreadPrivate(VD)) {
24534 Diag(SL, diag::err_omp_threadprivate_in_target);
24535 reportOriginalDsa(SemaRef, DSAStack, VD, DSAStack->getTopDSA(VD, false));
24536 return;
24537 }
24538 }
24539 if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
24540 D = FTD->getTemplatedDecl();
24541 if (auto *FD = dyn_cast<FunctionDecl>(D)) {
24542 std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
24543 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
24544 if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
24545 Diag(IdLoc, diag::err_omp_function_in_link_clause);
24546 Diag(FD->getLocation(), diag::note_defined_here) << FD;
24547 return;
24548 }
24549 }
24550 if (auto *VD = dyn_cast<ValueDecl>(D)) {
24551 // Problem if any with var declared with incomplete type will be reported
24552 // as normal, so no need to check it here.
24553 if ((E || !VD->getType()->isIncompleteType()) &&
24555 return;
24556 if (!E && isInOpenMPDeclareTargetContext()) {
24557 // Checking declaration inside declare target region.
24558 if (isa<VarDecl>(D) || isa<FunctionDecl>(D) ||
24560 std::optional<OMPDeclareTargetDeclAttr *> ActiveAttr =
24561 OMPDeclareTargetDeclAttr::getActiveAttr(VD);
24562 unsigned Level = DeclareTargetNesting.size();
24563 if (ActiveAttr && (*ActiveAttr)->getLevel() >= Level)
24564 return;
24565 DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
24566 Expr *IndirectE = nullptr;
24567 bool IsIndirect = false;
24568 if (DTCI.Indirect) {
24569 IndirectE = *DTCI.Indirect;
24570 if (!IndirectE)
24571 IsIndirect = true;
24572 }
24573 auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
24574 getASTContext(),
24575 getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter
24576 : OMPDeclareTargetDeclAttr::MT_To,
24577 DTCI.DT, IndirectE, IsIndirect, Level,
24578 SourceRange(DTCI.Loc, DTCI.Loc));
24579 D->addAttr(A);
24580 if (ASTMutationListener *ML = getASTContext().getASTMutationListener())
24581 ML->DeclarationMarkedOpenMPDeclareTarget(D, A);
24582 }
24583 return;
24584 }
24585 }
24586 if (!E)
24587 return;
24589}
24590
24591/// This class visits every VarDecl that the initializer references and adds
24592/// OMPDeclareTargetDeclAttr to each of them.
24593class GlobalDeclRefChecker final : public StmtVisitor<GlobalDeclRefChecker> {
24594 SmallVector<VarDecl *> DeclVector;
24595 Attr *A;
24596
24597public:
24598 /// A StmtVisitor class function that visits all DeclRefExpr and adds
24599 /// OMPDeclareTargetDeclAttr to them.
24601 if (auto *VD = dyn_cast<VarDecl>(Node->getDecl())) {
24602 VD->addAttr(A);
24603 DeclVector.push_back(VD);
24604 }
24605 }
24606 /// A function that iterates across each of the Expr's children.
24607 void VisitExpr(Expr *Ex) {
24608 for (auto *Child : Ex->children()) {
24609 Visit(Child);
24610 }
24611 }
24612 /// A function that keeps a record of all the Decls that are variables, has
24613 /// OMPDeclareTargetDeclAttr, and has global storage in the DeclVector. Pop
24614 /// each Decl one at a time and use the inherited 'visit' functions to look
24615 /// for DeclRefExpr.
24617 A = TD->getAttr<OMPDeclareTargetDeclAttr>();
24618 DeclVector.push_back(cast<VarDecl>(TD));
24619 llvm::SmallDenseSet<Decl *> Visited;
24620 while (!DeclVector.empty()) {
24621 VarDecl *TargetVarDecl = DeclVector.pop_back_val();
24622 if (!Visited.insert(TargetVarDecl).second)
24623 continue;
24624
24625 if (TargetVarDecl->hasAttr<OMPDeclareTargetDeclAttr>() &&
24626 TargetVarDecl->hasInit() && TargetVarDecl->hasGlobalStorage()) {
24627 if (Expr *Ex = TargetVarDecl->getInit())
24628 Visit(Ex);
24629 }
24630 }
24631 }
24632};
24633
24634/// Adding OMPDeclareTargetDeclAttr to variables with static storage
24635/// duration that are referenced in the initializer expression list of
24636/// variables with static storage duration in declare target directive.
24638 GlobalDeclRefChecker Checker;
24639 if (isa<VarDecl>(TargetDecl))
24640 Checker.declareTargetInitializer(TargetDecl);
24641}
24642
24644 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24645 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24646 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24647 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24648 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24653
24654 // Process motion-modifiers, flag errors for duplicate modifiers.
24655 unsigned Count = 0;
24656 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24657 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24658 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24659 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24660 continue;
24661 }
24662 assert(Count < NumberOfOMPMotionModifiers &&
24663 "Modifiers exceed the allowed number of motion modifiers");
24664 Modifiers[Count] = MotionModifiers[I];
24665 ModifiersLoc[Count] = MotionModifiersLoc[I];
24666 ++Count;
24667 }
24668
24669 MappableVarListInfo MVLI(VarList);
24671 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24672 if (MVLI.ProcessedVarList.empty())
24673 return nullptr;
24674 if (IteratorExpr)
24675 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24676 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24677 DSAStack->addIteratorVarDecl(VD);
24678 return OMPToClause::Create(
24679 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24680 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24681 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24682 MapperId);
24683}
24684
24686 ArrayRef<OpenMPMotionModifierKind> MotionModifiers,
24687 ArrayRef<SourceLocation> MotionModifiersLoc, Expr *IteratorExpr,
24688 CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId,
24689 SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
24690 const OMPVarListLocTy &Locs, ArrayRef<Expr *> UnresolvedMappers) {
24695
24696 // Process motion-modifiers, flag errors for duplicate modifiers.
24697 unsigned Count = 0;
24698 for (unsigned I = 0, E = MotionModifiers.size(); I < E; ++I) {
24699 if (MotionModifiers[I] != OMPC_MOTION_MODIFIER_unknown &&
24700 llvm::is_contained(Modifiers, MotionModifiers[I])) {
24701 Diag(MotionModifiersLoc[I], diag::err_omp_duplicate_motion_modifier);
24702 continue;
24703 }
24704 assert(Count < NumberOfOMPMotionModifiers &&
24705 "Modifiers exceed the allowed number of motion modifiers");
24706 Modifiers[Count] = MotionModifiers[I];
24707 ModifiersLoc[Count] = MotionModifiersLoc[I];
24708 ++Count;
24709 }
24710
24711 MappableVarListInfo MVLI(VarList);
24712 checkMappableExpressionList(SemaRef, DSAStack, OMPC_from, MVLI, Locs.StartLoc,
24713 MapperIdScopeSpec, MapperId, UnresolvedMappers);
24714 if (MVLI.ProcessedVarList.empty())
24715 return nullptr;
24716 if (IteratorExpr)
24717 if (auto *DRE = dyn_cast<DeclRefExpr>(IteratorExpr))
24718 if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
24719 DSAStack->addIteratorVarDecl(VD);
24720 return OMPFromClause::Create(
24721 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24722 MVLI.VarComponents, MVLI.UDMapperList, IteratorExpr, Modifiers,
24723 ModifiersLoc, MapperIdScopeSpec.getWithLocInContext(getASTContext()),
24724 MapperId);
24725}
24726
24728 ArrayRef<Expr *> VarList, const OMPVarListLocTy &Locs,
24729 OpenMPUseDevicePtrFallbackModifier FallbackModifier,
24730 SourceLocation FallbackModifierLoc) {
24731 MappableVarListInfo MVLI(VarList);
24732 SmallVector<Expr *, 8> PrivateCopies;
24734
24735 for (Expr *RefExpr : VarList) {
24736 assert(RefExpr && "NULL expr in OpenMP use_device_ptr clause.");
24737 SourceLocation ELoc;
24738 SourceRange ERange;
24739 Expr *SimpleRefExpr = RefExpr;
24740 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24741 if (Res.second) {
24742 // It will be analyzed later.
24743 MVLI.ProcessedVarList.push_back(RefExpr);
24744 PrivateCopies.push_back(nullptr);
24745 Inits.push_back(nullptr);
24746 }
24747 ValueDecl *D = Res.first;
24748 if (!D)
24749 continue;
24750
24751 QualType Type = D->getType();
24752 Type = Type.getNonReferenceType().getUnqualifiedType();
24753
24754 auto *VD = dyn_cast<VarDecl>(D);
24755
24756 // Item should be a pointer or reference to pointer.
24757 if (!Type->isPointerType()) {
24758 Diag(ELoc, diag::err_omp_usedeviceptr_not_a_pointer)
24759 << 0 << RefExpr->getSourceRange();
24760 continue;
24761 }
24762
24763 // Build the private variable and the expression that refers to it.
24764 auto VDPrivate =
24765 buildVarDecl(SemaRef, ELoc, Type, D->getName(),
24766 D->hasAttrs() ? &D->getAttrs() : nullptr,
24767 VD ? cast<DeclRefExpr>(SimpleRefExpr) : nullptr);
24768 if (VDPrivate->isInvalidDecl())
24769 continue;
24770
24771 SemaRef.CurContext->addDecl(VDPrivate);
24772 DeclRefExpr *VDPrivateRefExpr = buildDeclRefExpr(
24773 SemaRef, VDPrivate, RefExpr->getType().getUnqualifiedType(), ELoc);
24774
24775 // Add temporary variable to initialize the private copy of the pointer.
24776 VarDecl *VDInit =
24777 buildVarDecl(SemaRef, RefExpr->getExprLoc(), Type, ".devptr.temp");
24778 DeclRefExpr *VDInitRefExpr = buildDeclRefExpr(
24779 SemaRef, VDInit, RefExpr->getType(), RefExpr->getExprLoc());
24780 SemaRef.AddInitializerToDecl(
24781 VDPrivate, SemaRef.DefaultLvalueConversion(VDInitRefExpr).get(),
24782 /*DirectInit=*/false);
24783
24784 // If required, build a capture to implement the privatization initialized
24785 // with the current list item value.
24786 DeclRefExpr *Ref = nullptr;
24787 if (!VD)
24788 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24789 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24790 PrivateCopies.push_back(VDPrivateRefExpr);
24791 Inits.push_back(VDInitRefExpr);
24792
24793 // We need to add a data sharing attribute for this variable to make sure it
24794 // is correctly captured. A variable that shows up in a use_device_ptr has
24795 // similar properties of a first private variable.
24796 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24797
24798 // Create a mappable component for the list item. List items in this clause
24799 // only need a component.
24800 MVLI.VarBaseDeclarations.push_back(D);
24801 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24802 MVLI.VarComponents.back().emplace_back(SimpleRefExpr, D,
24803 /*IsNonContiguous=*/false);
24804 }
24805
24806 if (MVLI.ProcessedVarList.empty())
24807 return nullptr;
24808
24810 getASTContext(), Locs, MVLI.ProcessedVarList, PrivateCopies, Inits,
24811 MVLI.VarBaseDeclarations, MVLI.VarComponents, FallbackModifier,
24812 FallbackModifierLoc);
24813}
24814
24815OMPClause *
24817 const OMPVarListLocTy &Locs) {
24818 MappableVarListInfo MVLI(VarList);
24819
24820 for (Expr *RefExpr : VarList) {
24821 assert(RefExpr && "NULL expr in OpenMP use_device_addr clause.");
24822 SourceLocation ELoc;
24823 SourceRange ERange;
24824 Expr *SimpleRefExpr = RefExpr;
24825 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
24826 /*AllowArraySection=*/true,
24827 /*AllowAssumedSizeArray=*/true);
24828 if (Res.second) {
24829 // It will be analyzed later.
24830 MVLI.ProcessedVarList.push_back(RefExpr);
24831 }
24832 ValueDecl *D = Res.first;
24833 if (!D)
24834 continue;
24835 auto *VD = dyn_cast<VarDecl>(D);
24836
24837 // If required, build a capture to implement the privatization initialized
24838 // with the current list item value.
24839 DeclRefExpr *Ref = nullptr;
24840 if (!VD)
24841 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
24842 MVLI.ProcessedVarList.push_back(VD ? RefExpr->IgnoreParens() : Ref);
24843
24844 // We need to add a data sharing attribute for this variable to make sure it
24845 // is correctly captured. A variable that shows up in a use_device_addr has
24846 // similar properties of a first private variable.
24847 DSAStack->addDSA(D, RefExpr->IgnoreParens(), OMPC_firstprivate, Ref);
24848
24849 // Use the map-like approach to fully populate VarComponents
24851
24853 SemaRef, RefExpr, CurComponents, OMPC_use_device_addr,
24854 DSAStack->getCurrentDirective(),
24855 /*NoDiagnose=*/false);
24856
24857 if (!BE)
24858 continue;
24859
24860 assert(!CurComponents.empty() &&
24861 "use_device_addr clause expression with no components!");
24862
24863 // OpenMP use_device_addr: If a list item is an array section, the array
24864 // base must be a base language identifier. We caught the cases where
24865 // the array-section has a base-variable in getPrivateItem. e.g.
24866 // struct S {
24867 // int a[10];
24868 // }; S s1;
24869 // ... use_device_addr(s1.a[0]) // not ok, caught already
24870 //
24871 // But we still neeed to verify that the base-pointer is also a
24872 // base-language identifier, and catch cases like:
24873 // int *pa[10]; *p;
24874 // ... use_device_addr(pa[1][2]) // not ok, base-pointer is pa[1]
24875 // ... use_device_addr(p[1]) // ok
24876 // ... use_device_addr(this->p[1]) // ok
24878 CurComponents, DSAStack->getCurrentDirective());
24879 const Expr *AttachPtrExpr = AttachPtrResult.first;
24880
24881 if (AttachPtrExpr) {
24882 const Expr *BaseExpr = AttachPtrExpr->IgnoreParenImpCasts();
24883 bool IsValidBase = false;
24884
24885 if (isa<DeclRefExpr>(BaseExpr))
24886 IsValidBase = true;
24887 else if (const auto *ME = dyn_cast<MemberExpr>(BaseExpr);
24889 IsValidBase = true;
24890
24891 if (!IsValidBase) {
24892 SemaRef.Diag(ELoc,
24893 diag::err_omp_expected_base_pointer_var_name_member_expr)
24894 << (SemaRef.getCurrentThisType().isNull() ? 0 : 1)
24895 << AttachPtrExpr->getSourceRange();
24896 continue;
24897 }
24898 }
24899
24900 // Get the declaration from the components
24901 ValueDecl *CurDeclaration = CurComponents.back().getAssociatedDeclaration();
24902 assert((isa<CXXThisExpr>(BE) || CurDeclaration) &&
24903 "Unexpected null decl for use_device_addr clause.");
24904
24905 MVLI.VarBaseDeclarations.push_back(CurDeclaration);
24906 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24907 MVLI.VarComponents.back().append(CurComponents.begin(),
24908 CurComponents.end());
24909 }
24910
24911 if (MVLI.ProcessedVarList.empty())
24912 return nullptr;
24913
24915 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
24916 MVLI.VarComponents);
24917}
24918
24919OMPClause *
24921 const OMPVarListLocTy &Locs) {
24922 MappableVarListInfo MVLI(VarList);
24923 for (Expr *RefExpr : VarList) {
24924 assert(RefExpr && "NULL expr in OpenMP is_device_ptr clause.");
24925 SourceLocation ELoc;
24926 SourceRange ERange;
24927 Expr *SimpleRefExpr = RefExpr;
24928 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
24929 if (Res.second) {
24930 // It will be analyzed later.
24931 MVLI.ProcessedVarList.push_back(RefExpr);
24932 }
24933 ValueDecl *D = Res.first;
24934 if (!D)
24935 continue;
24936
24937 QualType Type = D->getType();
24938 // item should be a pointer or array or reference to pointer or array
24939 if (!Type.getNonReferenceType()->isPointerType() &&
24940 !Type.getNonReferenceType()->isArrayType()) {
24941 Diag(ELoc, diag::err_omp_argument_type_isdeviceptr)
24942 << 0 << RefExpr->getSourceRange();
24943 continue;
24944 }
24945
24946 // Check if the declaration in the clause does not show up in any data
24947 // sharing attribute.
24948 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
24949 if (isOpenMPPrivate(DVar.CKind)) {
24950 unsigned OMPVersion = getLangOpts().OpenMP;
24951 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
24952 << getOpenMPClauseNameForDiag(DVar.CKind)
24953 << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
24954 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
24955 OMPVersion);
24957 continue;
24958 }
24959
24960 const Expr *ConflictExpr;
24961 if (DSAStack->checkMappableExprComponentListsForDecl(
24962 D, /*CurrentRegionOnly=*/true,
24963 [&ConflictExpr](
24965 OpenMPClauseKind) -> bool {
24966 ConflictExpr = R.front().getAssociatedExpression();
24967 return true;
24968 })) {
24969 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
24970 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
24971 << ConflictExpr->getSourceRange();
24972 continue;
24973 }
24974
24975 // Store the components in the stack so that they can be used to check
24976 // against other clauses later on.
24978 SimpleRefExpr, D, /*IsNonContiguous=*/false);
24979 DSAStack->addMappableExpressionComponents(
24980 D, MC, /*WhereFoundClauseKind=*/OMPC_is_device_ptr);
24981
24982 // Record the expression we've just processed.
24983 MVLI.ProcessedVarList.push_back(SimpleRefExpr);
24984
24985 // Create a mappable component for the list item. List items in this clause
24986 // only need a component. We use a null declaration to signal fields in
24987 // 'this'.
24988 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
24989 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
24990 "Unexpected device pointer expression!");
24991 MVLI.VarBaseDeclarations.push_back(
24992 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
24993 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
24994 MVLI.VarComponents.back().push_back(MC);
24995 }
24996
24997 if (MVLI.ProcessedVarList.empty())
24998 return nullptr;
24999
25001 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25002 MVLI.VarComponents);
25003}
25004
25005OMPClause *
25007 const OMPVarListLocTy &Locs) {
25008 MappableVarListInfo MVLI(VarList);
25009 for (Expr *RefExpr : VarList) {
25010 assert(RefExpr && "NULL expr in OpenMP has_device_addr clause.");
25011 SourceLocation ELoc;
25012 SourceRange ERange;
25013 Expr *SimpleRefExpr = RefExpr;
25014 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25015 /*AllowArraySection=*/true);
25016 if (Res.second) {
25017 // It will be analyzed later.
25018 MVLI.ProcessedVarList.push_back(RefExpr);
25019 }
25020 ValueDecl *D = Res.first;
25021 if (!D)
25022 continue;
25023
25024 // Check if the declaration in the clause does not show up in any data
25025 // sharing attribute.
25026 DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
25027 if (isOpenMPPrivate(DVar.CKind)) {
25028 unsigned OMPVersion = getLangOpts().OpenMP;
25029 Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
25030 << getOpenMPClauseNameForDiag(DVar.CKind)
25031 << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
25032 << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
25033 OMPVersion);
25035 continue;
25036 }
25037
25038 const Expr *ConflictExpr;
25039 if (DSAStack->checkMappableExprComponentListsForDecl(
25040 D, /*CurrentRegionOnly=*/true,
25041 [&ConflictExpr](
25043 OpenMPClauseKind) -> bool {
25044 ConflictExpr = R.front().getAssociatedExpression();
25045 return true;
25046 })) {
25047 Diag(ELoc, diag::err_omp_map_shared_storage) << RefExpr->getSourceRange();
25048 Diag(ConflictExpr->getExprLoc(), diag::note_used_here)
25049 << ConflictExpr->getSourceRange();
25050 continue;
25051 }
25052
25053 // Store the components in the stack so that they can be used to check
25054 // against other clauses later on.
25055 Expr *Component = SimpleRefExpr;
25056 auto *VD = dyn_cast<VarDecl>(D);
25057 if (VD && (isa<ArraySectionExpr>(RefExpr->IgnoreParenImpCasts()) ||
25058 isa<ArraySubscriptExpr>(RefExpr->IgnoreParenImpCasts())))
25059 Component =
25060 SemaRef.DefaultFunctionArrayLvalueConversion(SimpleRefExpr).get();
25062 Component, D, /*IsNonContiguous=*/false);
25063 DSAStack->addMappableExpressionComponents(
25064 D, MC, /*WhereFoundClauseKind=*/OMPC_has_device_addr);
25065
25066 // Record the expression we've just processed.
25067 if (!VD && !SemaRef.CurContext->isDependentContext()) {
25068 DeclRefExpr *Ref =
25069 buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/true);
25070 assert(Ref && "has_device_addr capture failed");
25071 MVLI.ProcessedVarList.push_back(Ref);
25072 } else
25073 MVLI.ProcessedVarList.push_back(RefExpr->IgnoreParens());
25074
25075 // Create a mappable component for the list item. List items in this clause
25076 // only need a component. We use a null declaration to signal fields in
25077 // 'this'.
25078 assert((isa<DeclRefExpr>(SimpleRefExpr) ||
25079 isa<CXXThisExpr>(cast<MemberExpr>(SimpleRefExpr)->getBase())) &&
25080 "Unexpected device pointer expression!");
25081 MVLI.VarBaseDeclarations.push_back(
25082 isa<DeclRefExpr>(SimpleRefExpr) ? D : nullptr);
25083 MVLI.VarComponents.resize(MVLI.VarComponents.size() + 1);
25084 MVLI.VarComponents.back().push_back(MC);
25085 }
25086
25087 if (MVLI.ProcessedVarList.empty())
25088 return nullptr;
25089
25091 getASTContext(), Locs, MVLI.ProcessedVarList, MVLI.VarBaseDeclarations,
25092 MVLI.VarComponents);
25093}
25094
25096 Expr *Allocator, Expr *Alignment,
25097 OpenMPAllocateClauseModifier FirstAllocateModifier,
25098 SourceLocation FirstAllocateModifierLoc,
25099 OpenMPAllocateClauseModifier SecondAllocateModifier,
25100 SourceLocation SecondAllocateModifierLoc, ArrayRef<Expr *> VarList,
25101 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25102 SourceLocation EndLoc) {
25103 if (Allocator) {
25104 // Allocator expression is dependent - skip it for now and build the
25105 // allocator when instantiated.
25106 bool AllocDependent =
25107 (Allocator->isTypeDependent() || Allocator->isValueDependent() ||
25108 Allocator->isInstantiationDependent() ||
25109 Allocator->containsUnexpandedParameterPack());
25110 if (!AllocDependent) {
25111 // OpenMP [2.11.4 allocate Clause, Description]
25112 // allocator is an expression of omp_allocator_handle_t type.
25114 return nullptr;
25115
25116 ExprResult AllocatorRes = SemaRef.DefaultLvalueConversion(Allocator);
25117 if (AllocatorRes.isInvalid())
25118 return nullptr;
25119 AllocatorRes = SemaRef.PerformImplicitConversion(
25120 AllocatorRes.get(), DSAStack->getOMPAllocatorHandleT(),
25122 /*AllowExplicit=*/true);
25123 if (AllocatorRes.isInvalid())
25124 return nullptr;
25125 Allocator = AllocatorRes.isUsable() ? AllocatorRes.get() : nullptr;
25126 }
25127 } else {
25128 // OpenMP 5.0, 2.11.4 allocate Clause, Restrictions.
25129 // allocate clauses that appear on a target construct or on constructs in a
25130 // target region must specify an allocator expression unless a requires
25131 // directive with the dynamic_allocators clause is present in the same
25132 // compilation unit.
25133 if (getLangOpts().OpenMPIsTargetDevice &&
25134 !DSAStack->hasRequiresDeclWithClause<OMPDynamicAllocatorsClause>())
25135 SemaRef.targetDiag(StartLoc, diag::err_expected_allocator_expression);
25136 }
25137 if (Alignment) {
25138 bool AlignmentDependent = Alignment->isTypeDependent() ||
25139 Alignment->isValueDependent() ||
25140 Alignment->isInstantiationDependent() ||
25142 if (!AlignmentDependent) {
25143 ExprResult AlignResult =
25144 VerifyPositiveIntegerConstantInClause(Alignment, OMPC_allocate);
25145 Alignment = AlignResult.isUsable() ? AlignResult.get() : nullptr;
25146 }
25147 }
25148 // Analyze and build list of variables.
25150 for (Expr *RefExpr : VarList) {
25151 assert(RefExpr && "NULL expr in OpenMP allocate clause.");
25152 SourceLocation ELoc;
25153 SourceRange ERange;
25154 Expr *SimpleRefExpr = RefExpr;
25155 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25156 if (Res.second) {
25157 // It will be analyzed later.
25158 Vars.push_back(RefExpr);
25159 }
25160 ValueDecl *D = Res.first;
25161 if (!D)
25162 continue;
25163
25164 auto *VD = dyn_cast<VarDecl>(D);
25165 DeclRefExpr *Ref = nullptr;
25166 if (!VD && !SemaRef.CurContext->isDependentContext())
25167 Ref = buildCapture(SemaRef, D, SimpleRefExpr, /*WithInit=*/false);
25168 Vars.push_back((VD || SemaRef.CurContext->isDependentContext())
25169 ? RefExpr->IgnoreParens()
25170 : Ref);
25171 }
25172
25173 if (Vars.empty())
25174 return nullptr;
25175
25176 if (Allocator)
25177 DSAStack->addInnerAllocatorExpr(Allocator);
25178
25180 getASTContext(), StartLoc, LParenLoc, Allocator, Alignment, ColonLoc,
25181 FirstAllocateModifier, FirstAllocateModifierLoc, SecondAllocateModifier,
25182 SecondAllocateModifierLoc, EndLoc, Vars);
25183}
25184
25186 SourceLocation StartLoc,
25187 SourceLocation LParenLoc,
25188 SourceLocation EndLoc) {
25190 for (Expr *RefExpr : VarList) {
25191 assert(RefExpr && "NULL expr in OpenMP nontemporal clause.");
25192 SourceLocation ELoc;
25193 SourceRange ERange;
25194 Expr *SimpleRefExpr = RefExpr;
25195 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange);
25196 if (Res.second)
25197 // It will be analyzed later.
25198 Vars.push_back(RefExpr);
25199 ValueDecl *D = Res.first;
25200 if (!D)
25201 continue;
25202
25203 // OpenMP 5.0, 2.9.3.1 simd Construct, Restrictions.
25204 // A list-item cannot appear in more than one nontemporal clause.
25205 if (const Expr *PrevRef =
25206 DSAStack->addUniqueNontemporal(D, SimpleRefExpr)) {
25207 Diag(ELoc, diag::err_omp_used_in_clause_twice)
25208 << 0 << getOpenMPClauseNameForDiag(OMPC_nontemporal) << ERange;
25209 Diag(PrevRef->getExprLoc(), diag::note_omp_explicit_dsa)
25210 << getOpenMPClauseNameForDiag(OMPC_nontemporal);
25211 continue;
25212 }
25213
25214 Vars.push_back(RefExpr);
25215 }
25216
25217 if (Vars.empty())
25218 return nullptr;
25219
25220 return OMPNontemporalClause::Create(getASTContext(), StartLoc, LParenLoc,
25221 EndLoc, Vars);
25222}
25223
25225 Stmt *AStmt,
25226 SourceLocation StartLoc,
25227 SourceLocation EndLoc) {
25228 if (!AStmt)
25229 return StmtError();
25230
25231 SemaRef.setFunctionHasBranchProtectedScope();
25232
25233 return OMPScopeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
25234 AStmt);
25235}
25236
25238 SourceLocation StartLoc,
25239 SourceLocation LParenLoc,
25240 SourceLocation EndLoc) {
25242 for (Expr *RefExpr : VarList) {
25243 assert(RefExpr && "NULL expr in OpenMP inclusive clause.");
25244 SourceLocation ELoc;
25245 SourceRange ERange;
25246 Expr *SimpleRefExpr = RefExpr;
25247 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25248 /*AllowArraySection=*/true);
25249 if (Res.second)
25250 // It will be analyzed later.
25251 Vars.push_back(RefExpr);
25252 ValueDecl *D = Res.first;
25253 if (!D)
25254 continue;
25255
25256 const DSAStackTy::DSAVarData DVar =
25257 DSAStack->getTopDSA(D, /*FromParent=*/true);
25258 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25259 // A list item that appears in the inclusive or exclusive clause must appear
25260 // in a reduction clause with the inscan modifier on the enclosing
25261 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25262 if (DVar.CKind != OMPC_reduction || DVar.Modifier != OMPC_REDUCTION_inscan)
25263 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25264 << RefExpr->getSourceRange();
25265
25266 if (DSAStack->getParentDirective() != OMPD_unknown)
25267 DSAStack->markDeclAsUsedInScanDirective(D);
25268 Vars.push_back(RefExpr);
25269 }
25270
25271 if (Vars.empty())
25272 return nullptr;
25273
25274 return OMPInclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25275 EndLoc, Vars);
25276}
25277
25279 SourceLocation StartLoc,
25280 SourceLocation LParenLoc,
25281 SourceLocation EndLoc) {
25283 for (Expr *RefExpr : VarList) {
25284 assert(RefExpr && "NULL expr in OpenMP exclusive clause.");
25285 SourceLocation ELoc;
25286 SourceRange ERange;
25287 Expr *SimpleRefExpr = RefExpr;
25288 auto Res = getPrivateItem(SemaRef, SimpleRefExpr, ELoc, ERange,
25289 /*AllowArraySection=*/true);
25290 if (Res.second)
25291 // It will be analyzed later.
25292 Vars.push_back(RefExpr);
25293 ValueDecl *D = Res.first;
25294 if (!D)
25295 continue;
25296
25297 OpenMPDirectiveKind ParentDirective = DSAStack->getParentDirective();
25298 DSAStackTy::DSAVarData DVar;
25299 if (ParentDirective != OMPD_unknown)
25300 DVar = DSAStack->getTopDSA(D, /*FromParent=*/true);
25301 // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
25302 // A list item that appears in the inclusive or exclusive clause must appear
25303 // in a reduction clause with the inscan modifier on the enclosing
25304 // worksharing-loop, worksharing-loop SIMD, or simd construct.
25305 if (ParentDirective == OMPD_unknown || DVar.CKind != OMPC_reduction ||
25306 DVar.Modifier != OMPC_REDUCTION_inscan) {
25307 Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
25308 << RefExpr->getSourceRange();
25309 } else {
25310 DSAStack->markDeclAsUsedInScanDirective(D);
25311 }
25312 Vars.push_back(RefExpr);
25313 }
25314
25315 if (Vars.empty())
25316 return nullptr;
25317
25318 return OMPExclusiveClause::Create(getASTContext(), StartLoc, LParenLoc,
25319 EndLoc, Vars);
25320}
25321
25322/// Tries to find omp_alloctrait_t type.
25323static bool findOMPAlloctraitT(Sema &S, SourceLocation Loc, DSAStackTy *Stack) {
25324 QualType OMPAlloctraitT = Stack->getOMPAlloctraitT();
25325 if (!OMPAlloctraitT.isNull())
25326 return true;
25327 IdentifierInfo &II = S.PP.getIdentifierTable().get("omp_alloctrait_t");
25328 ParsedType PT = S.getTypeName(II, Loc, S.getCurScope());
25329 if (!PT.getAsOpaquePtr() || PT.get().isNull()) {
25330 S.Diag(Loc, diag::err_omp_implied_type_not_found) << "omp_alloctrait_t";
25331 return false;
25332 }
25333 Stack->setOMPAlloctraitT(PT.get());
25334 return true;
25335}
25336
25338 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc,
25340 ASTContext &Context = getASTContext();
25341 // OpenMP [2.12.5, target Construct]
25342 // allocator is an identifier of omp_allocator_handle_t type.
25343 if (!findOMPAllocatorHandleT(SemaRef, StartLoc, DSAStack))
25344 return nullptr;
25345 // OpenMP [2.12.5, target Construct]
25346 // allocator-traits-array is an identifier of const omp_alloctrait_t * type.
25347 if (llvm::any_of(
25348 Data,
25349 [](const UsesAllocatorsData &D) { return D.AllocatorTraits; }) &&
25350 !findOMPAlloctraitT(SemaRef, StartLoc, DSAStack))
25351 return nullptr;
25352 llvm::SmallPtrSet<CanonicalDeclPtr<Decl>, 4> PredefinedAllocators;
25353 for (int I = 0; I < OMPAllocateDeclAttr::OMPUserDefinedMemAlloc; ++I) {
25354 auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(I);
25355 StringRef Allocator =
25356 OMPAllocateDeclAttr::ConvertAllocatorTypeTyToStr(AllocatorKind);
25357 DeclarationName AllocatorName = &Context.Idents.get(Allocator);
25358 PredefinedAllocators.insert(SemaRef.LookupSingleName(
25359 SemaRef.TUScope, AllocatorName, StartLoc, Sema::LookupAnyName));
25360 }
25361
25363 for (const UsesAllocatorsData &D : Data) {
25364 Expr *AllocatorExpr = nullptr;
25365 // Check allocator expression.
25366 if (D.Allocator->isTypeDependent()) {
25367 AllocatorExpr = D.Allocator;
25368 } else {
25369 // Traits were specified - need to assign new allocator to the specified
25370 // allocator, so it must be an lvalue.
25371 AllocatorExpr = D.Allocator->IgnoreParenImpCasts();
25372 auto *DRE = dyn_cast<DeclRefExpr>(AllocatorExpr);
25373 bool IsPredefinedAllocator = false;
25374 if (DRE) {
25375 OMPAllocateDeclAttr::AllocatorTypeTy AllocatorTy =
25376 getAllocatorKind(SemaRef, DSAStack, AllocatorExpr);
25377 IsPredefinedAllocator =
25378 AllocatorTy !=
25379 OMPAllocateDeclAttr::AllocatorTypeTy::OMPUserDefinedMemAlloc;
25380 }
25381 QualType OMPAllocatorHandleT = DSAStack->getOMPAllocatorHandleT();
25382 QualType AllocatorExprType = AllocatorExpr->getType();
25383 bool IsTypeCompatible = IsPredefinedAllocator;
25384 IsTypeCompatible = IsTypeCompatible ||
25385 Context.hasSameUnqualifiedType(AllocatorExprType,
25386 OMPAllocatorHandleT);
25387 IsTypeCompatible =
25388 IsTypeCompatible ||
25389 Context.typesAreCompatible(AllocatorExprType, OMPAllocatorHandleT);
25390 bool IsNonConstantLValue =
25391 !AllocatorExprType.isConstant(Context) && AllocatorExpr->isLValue();
25392 if (!DRE || !IsTypeCompatible ||
25393 (!IsPredefinedAllocator && !IsNonConstantLValue)) {
25394 Diag(D.Allocator->getExprLoc(), diag::err_omp_var_expected)
25395 << "omp_allocator_handle_t" << (DRE ? 1 : 0)
25396 << AllocatorExpr->getType() << D.Allocator->getSourceRange();
25397 continue;
25398 }
25399 // OpenMP [2.12.5, target Construct]
25400 // Predefined allocators appearing in a uses_allocators clause cannot have
25401 // traits specified.
25402 if (IsPredefinedAllocator && D.AllocatorTraits) {
25404 diag::err_omp_predefined_allocator_with_traits)
25406 Diag(D.Allocator->getExprLoc(), diag::note_omp_predefined_allocator)
25407 << cast<NamedDecl>(DRE->getDecl())->getName()
25408 << D.Allocator->getSourceRange();
25409 continue;
25410 }
25411 // OpenMP [2.12.5, target Construct]
25412 // Non-predefined allocators appearing in a uses_allocators clause must
25413 // have traits specified.
25414 if (getLangOpts().OpenMP < 52) {
25415 if (!IsPredefinedAllocator && !D.AllocatorTraits) {
25417 diag::err_omp_nonpredefined_allocator_without_traits);
25418 continue;
25419 }
25420 }
25421 // No allocator traits - just convert it to rvalue.
25422 if (!D.AllocatorTraits)
25423 AllocatorExpr = SemaRef.DefaultLvalueConversion(AllocatorExpr).get();
25424 DSAStack->addUsesAllocatorsDecl(
25425 DRE->getDecl(),
25426 IsPredefinedAllocator
25427 ? DSAStackTy::UsesAllocatorsDeclKind::PredefinedAllocator
25428 : DSAStackTy::UsesAllocatorsDeclKind::UserDefinedAllocator);
25429 }
25430 Expr *AllocatorTraitsExpr = nullptr;
25431 if (D.AllocatorTraits) {
25433 AllocatorTraitsExpr = D.AllocatorTraits;
25434 } else {
25435 // OpenMP [2.12.5, target Construct]
25436 // Arrays that contain allocator traits that appear in a uses_allocators
25437 // clause must be constant arrays, have constant values and be defined
25438 // in the same scope as the construct in which the clause appears.
25439 AllocatorTraitsExpr = D.AllocatorTraits->IgnoreParenImpCasts();
25440 // Check that traits expr is a constant array.
25441 QualType TraitTy;
25442 if (const ArrayType *Ty =
25443 AllocatorTraitsExpr->getType()->getAsArrayTypeUnsafe())
25444 if (const auto *ConstArrayTy = dyn_cast<ConstantArrayType>(Ty))
25445 TraitTy = ConstArrayTy->getElementType();
25446 if (TraitTy.isNull() ||
25447 !(Context.hasSameUnqualifiedType(TraitTy,
25448 DSAStack->getOMPAlloctraitT()) ||
25449 Context.typesAreCompatible(TraitTy, DSAStack->getOMPAlloctraitT(),
25450 /*CompareUnqualified=*/true))) {
25452 diag::err_omp_expected_array_alloctraits)
25453 << AllocatorTraitsExpr->getType();
25454 continue;
25455 }
25456 // Do not map by default allocator traits if it is a standalone
25457 // variable.
25458 if (auto *DRE = dyn_cast<DeclRefExpr>(AllocatorTraitsExpr))
25459 DSAStack->addUsesAllocatorsDecl(
25460 DRE->getDecl(),
25461 DSAStackTy::UsesAllocatorsDeclKind::AllocatorTrait);
25462 }
25463 }
25464 OMPUsesAllocatorsClause::Data &NewD = NewData.emplace_back();
25465 NewD.Allocator = AllocatorExpr;
25466 NewD.AllocatorTraits = AllocatorTraitsExpr;
25467 NewD.LParenLoc = D.LParenLoc;
25468 NewD.RParenLoc = D.RParenLoc;
25469 }
25470 return OMPUsesAllocatorsClause::Create(getASTContext(), StartLoc, LParenLoc,
25471 EndLoc, NewData);
25472}
25473
25475 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc,
25476 SourceLocation EndLoc, Expr *Modifier, ArrayRef<Expr *> Locators) {
25478 for (Expr *RefExpr : Locators) {
25479 assert(RefExpr && "NULL expr in OpenMP affinity clause.");
25480 if (isa<DependentScopeDeclRefExpr>(RefExpr) || RefExpr->isTypeDependent()) {
25481 // It will be analyzed later.
25482 Vars.push_back(RefExpr);
25483 continue;
25484 }
25485
25486 SourceLocation ELoc = RefExpr->getExprLoc();
25487 Expr *SimpleExpr = RefExpr->IgnoreParenImpCasts();
25488
25489 if (!SimpleExpr->isLValue()) {
25490 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25491 << 1 << 0 << RefExpr->getSourceRange();
25492 continue;
25493 }
25494
25495 ExprResult Res;
25496 {
25498 Res = SemaRef.CreateBuiltinUnaryOp(ELoc, UO_AddrOf, SimpleExpr);
25499 }
25500 if (!Res.isUsable() && !isa<ArraySectionExpr>(SimpleExpr) &&
25502 Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
25503 << 1 << 0 << RefExpr->getSourceRange();
25504 continue;
25505 }
25506 Vars.push_back(SimpleExpr);
25507 }
25508
25509 return OMPAffinityClause::Create(getASTContext(), StartLoc, LParenLoc,
25510 ColonLoc, EndLoc, Modifier, Vars);
25511}
25512
25514 SourceLocation KindLoc,
25515 SourceLocation StartLoc,
25516 SourceLocation LParenLoc,
25517 SourceLocation EndLoc) {
25518 if (Kind == OMPC_BIND_unknown) {
25519 Diag(KindLoc, diag::err_omp_unexpected_clause_value)
25520 << getListOfPossibleValues(OMPC_bind, /*First=*/0,
25521 /*Last=*/unsigned(OMPC_BIND_unknown))
25522 << getOpenMPClauseNameForDiag(OMPC_bind);
25523 return nullptr;
25524 }
25525
25526 return OMPBindClause::Create(getASTContext(), Kind, KindLoc, StartLoc,
25527 LParenLoc, EndLoc);
25528}
25529
25531 SourceLocation StartLoc,
25532 SourceLocation LParenLoc,
25533 SourceLocation EndLoc) {
25534 Expr *ValExpr = Size;
25535 Stmt *HelperValStmt = nullptr;
25536
25537 // OpenMP [2.5, Restrictions]
25538 // The ompx_dyn_cgroup_mem expression must evaluate to a positive integer
25539 // value.
25540 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_ompx_dyn_cgroup_mem,
25541 /*StrictlyPositive=*/false))
25542 return nullptr;
25543
25544 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25546 DKind, OMPC_ompx_dyn_cgroup_mem, getLangOpts().OpenMP);
25547 if (CaptureRegion != OMPD_unknown &&
25548 !SemaRef.CurContext->isDependentContext()) {
25549 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25550 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25551 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25552 HelperValStmt = buildPreInits(getASTContext(), Captures);
25553 }
25554
25556 ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
25557}
25558
25562 SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc,
25563 SourceLocation M2Loc, SourceLocation EndLoc) {
25564
25565 if ((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ||
25567 std::string Values = getListOfPossibleValues(
25568 OMPC_dyn_groupprivate, /*First=*/0, OMPC_DYN_GROUPPRIVATE_unknown);
25569 Diag((M1Loc.isValid() && M1 == OMPC_DYN_GROUPPRIVATE_unknown) ? M1Loc
25570 : M2Loc,
25571 diag::err_omp_unexpected_clause_value)
25572 << Values << getOpenMPClauseName(OMPC_dyn_groupprivate);
25573 return nullptr;
25574 }
25575
25576 Expr *ValExpr = Size;
25577 Stmt *HelperValStmt = nullptr;
25578
25579 // OpenMP [2.5, Restrictions]
25580 // The dyn_groupprivate expression must evaluate to a positive integer
25581 // value.
25582 if (!isNonNegativeIntegerValue(ValExpr, SemaRef, OMPC_dyn_groupprivate,
25583 /*StrictlyPositive=*/false))
25584 return nullptr;
25585
25586 OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
25588 DKind, OMPC_dyn_groupprivate, getLangOpts().OpenMP);
25589 if (CaptureRegion != OMPD_unknown &&
25590 !SemaRef.CurContext->isDependentContext()) {
25591 ValExpr = SemaRef.MakeFullExpr(ValExpr).get();
25592 llvm::MapVector<const Expr *, DeclRefExpr *> Captures;
25593 ValExpr = tryBuildCapture(SemaRef, ValExpr, Captures).get();
25594 HelperValStmt = buildPreInits(getASTContext(), Captures);
25595 }
25596
25598 StartLoc, LParenLoc, EndLoc, ValExpr, HelperValStmt, CaptureRegion, M1,
25599 M1Loc, M2, M2Loc);
25600}
25601
25604 SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
25605 SourceLocation LParenLoc, SourceLocation EndLoc) {
25606
25607 if (DSAStack->getCurrentDirective() == OMPD_ordered &&
25608 DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
25609 DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
25610 DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
25611 Diag(DepLoc, diag::err_omp_unexpected_clause_value)
25612 << "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_doacross);
25613 return nullptr;
25614 }
25615
25617 DSAStackTy::OperatorOffsetTy OpsOffs;
25618 llvm::APSInt TotalDepCount(/*BitWidth=*/32);
25619 DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
25620 SemaRef,
25621 DepType == OMPC_DOACROSS_source ||
25622 DepType == OMPC_DOACROSS_source_omp_cur_iteration ||
25623 DepType == OMPC_DOACROSS_sink_omp_cur_iteration,
25624 VarList, DSAStack, EndLoc);
25625 Vars = VarOffset.Vars;
25626 OpsOffs = VarOffset.OpsOffs;
25627 TotalDepCount = VarOffset.TotalDepCount;
25628 auto *C = OMPDoacrossClause::Create(getASTContext(), StartLoc, LParenLoc,
25629 EndLoc, DepType, DepLoc, ColonLoc, Vars,
25630 TotalDepCount.getZExtValue());
25631 if (DSAStack->isParentOrderedRegion())
25632 DSAStack->addDoacrossDependClause(C, OpsOffs);
25633 return C;
25634}
25635
25637 SourceLocation StartLoc,
25638 SourceLocation LParenLoc,
25639 SourceLocation EndLoc) {
25640 return new (getASTContext())
25641 OMPXAttributeClause(Attrs, StartLoc, LParenLoc, EndLoc);
25642}
25643
25645 SourceLocation EndLoc) {
25646 return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
25647}
25648
25650 SourceLocation LParenLoc,
25651 SourceLocation EndLoc) {
25652 return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
25653}
25654
25658 switch (CK) {
25659 case OMPC_absent:
25660 return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25661 case OMPC_contains:
25662 return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
25663 default:
25664 llvm_unreachable("Unexpected OpenMP clause");
25665 }
25666}
25667
25669 SourceLocation Loc,
25670 SourceLocation RLoc) {
25671 switch (CK) {
25672 case OMPC_no_openmp:
25673 return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
25674 case OMPC_no_openmp_routines:
25675 return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
25676 case OMPC_no_parallelism:
25677 return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
25678 case OMPC_no_openmp_constructs:
25679 return new (getASTContext()) OMPNoOpenMPConstructsClause(Loc, RLoc);
25680 default:
25681 llvm_unreachable("Unexpected OpenMP clause");
25682 }
25683}
25684
25686 Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
25687 SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
25688 Expr *Stride, SourceLocation RBLoc) {
25689 ASTContext &Context = getASTContext();
25690 if (Base->hasPlaceholderType() &&
25691 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25692 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25693 if (Result.isInvalid())
25694 return ExprError();
25695 Base = Result.get();
25696 }
25697 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
25698 ExprResult Result = SemaRef.CheckPlaceholderExpr(LowerBound);
25699 if (Result.isInvalid())
25700 return ExprError();
25701 Result = SemaRef.DefaultLvalueConversion(Result.get());
25702 if (Result.isInvalid())
25703 return ExprError();
25704 LowerBound = Result.get();
25705 }
25706 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
25707 ExprResult Result = SemaRef.CheckPlaceholderExpr(Length);
25708 if (Result.isInvalid())
25709 return ExprError();
25710 Result = SemaRef.DefaultLvalueConversion(Result.get());
25711 if (Result.isInvalid())
25712 return ExprError();
25713 Length = Result.get();
25714 }
25715 if (Stride && Stride->getType()->isNonOverloadPlaceholderType()) {
25716 ExprResult Result = SemaRef.CheckPlaceholderExpr(Stride);
25717 if (Result.isInvalid())
25718 return ExprError();
25719 Result = SemaRef.DefaultLvalueConversion(Result.get());
25720 if (Result.isInvalid())
25721 return ExprError();
25722 Stride = Result.get();
25723 }
25724
25725 // Build an unanalyzed expression if either operand is type-dependent.
25726 if (Base->isTypeDependent() ||
25727 (LowerBound &&
25728 (LowerBound->isTypeDependent() || LowerBound->isValueDependent())) ||
25729 (Length && (Length->isTypeDependent() || Length->isValueDependent())) ||
25730 (Stride && (Stride->isTypeDependent() || Stride->isValueDependent()))) {
25731 return new (Context) ArraySectionExpr(
25732 Base, LowerBound, Length, Stride, Context.DependentTy, VK_LValue,
25733 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25734 }
25735
25736 // Perform default conversions.
25738 QualType ResultTy;
25739 if (OriginalTy->isAnyPointerType()) {
25740 ResultTy = OriginalTy->getPointeeType();
25741 } else if (OriginalTy->isArrayType()) {
25742 ResultTy = OriginalTy->getAsArrayTypeUnsafe()->getElementType();
25743 } else {
25744 return ExprError(
25745 Diag(Base->getExprLoc(), diag::err_omp_typecheck_section_value)
25746 << Base->getSourceRange());
25747 }
25748 // C99 6.5.2.1p1
25749 if (LowerBound) {
25750 auto Res = PerformOpenMPImplicitIntegerConversion(LowerBound->getExprLoc(),
25751 LowerBound);
25752 if (Res.isInvalid())
25753 return ExprError(Diag(LowerBound->getExprLoc(),
25754 diag::err_omp_typecheck_section_not_integer)
25755 << 0 << LowerBound->getSourceRange());
25756 LowerBound = Res.get();
25757
25758 if (LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25759 LowerBound->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25760 Diag(LowerBound->getExprLoc(), diag::warn_omp_section_is_char)
25761 << 0 << LowerBound->getSourceRange();
25762 }
25763 if (Length) {
25764 auto Res =
25765 PerformOpenMPImplicitIntegerConversion(Length->getExprLoc(), Length);
25766 if (Res.isInvalid())
25767 return ExprError(Diag(Length->getExprLoc(),
25768 diag::err_omp_typecheck_section_not_integer)
25769 << 1 << Length->getSourceRange());
25770 Length = Res.get();
25771
25772 if (Length->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25773 Length->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25774 Diag(Length->getExprLoc(), diag::warn_omp_section_is_char)
25775 << 1 << Length->getSourceRange();
25776 }
25777 if (Stride) {
25778 ExprResult Res =
25780 if (Res.isInvalid())
25781 return ExprError(Diag(Stride->getExprLoc(),
25782 diag::err_omp_typecheck_section_not_integer)
25783 << 1 << Stride->getSourceRange());
25784 Stride = Res.get();
25785
25786 if (Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_S) ||
25787 Stride->getType()->isSpecificBuiltinType(BuiltinType::Char_U))
25788 Diag(Stride->getExprLoc(), diag::warn_omp_section_is_char)
25789 << 1 << Stride->getSourceRange();
25790 }
25791
25792 // C99 6.5.2.1p1: "shall have type "pointer to *object* type". Similarly,
25793 // C++ [expr.sub]p1: The type "T" shall be a completely-defined object
25794 // type. Note that functions are not objects, and that (in C99 parlance)
25795 // incomplete types are not object types.
25796 if (ResultTy->isFunctionType()) {
25797 Diag(Base->getExprLoc(), diag::err_omp_section_function_type)
25798 << ResultTy << Base->getSourceRange();
25799 return ExprError();
25800 }
25801
25802 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
25803 diag::err_omp_section_incomplete_type, Base))
25804 return ExprError();
25805
25806 if (LowerBound && !OriginalTy->isAnyPointerType()) {
25808 if (LowerBound->EvaluateAsInt(Result, Context)) {
25809 // OpenMP 5.0, [2.1.5 Array Sections]
25810 // The array section must be a subset of the original array.
25811 llvm::APSInt LowerBoundValue = Result.Val.getInt();
25812 if (LowerBoundValue.isNegative()) {
25813 Diag(LowerBound->getExprLoc(),
25814 diag::err_omp_section_not_subset_of_array)
25815 << LowerBound->getSourceRange();
25816 return ExprError();
25817 }
25818 }
25819 }
25820
25821 if (Length) {
25823 if (Length->EvaluateAsInt(Result, Context)) {
25824 // OpenMP 5.0, [2.1.5 Array Sections]
25825 // The length must evaluate to non-negative integers.
25826 llvm::APSInt LengthValue = Result.Val.getInt();
25827 if (LengthValue.isNegative()) {
25828 Diag(Length->getExprLoc(), diag::err_omp_section_length_negative)
25829 << toString(LengthValue, /*Radix=*/10, /*Signed=*/true)
25830 << Length->getSourceRange();
25831 return ExprError();
25832 }
25833 }
25834 } else if (SemaRef.getLangOpts().OpenMP < 60 && ColonLocFirst.isValid() &&
25835 (OriginalTy.isNull() || (!OriginalTy->isConstantArrayType() &&
25836 !OriginalTy->isVariableArrayType()))) {
25837 // OpenMP 5.0, [2.1.5 Array Sections]
25838 // When the size of the array dimension is not known, the length must be
25839 // specified explicitly.
25840 Diag(ColonLocFirst, diag::err_omp_section_length_undefined)
25841 << (!OriginalTy.isNull() && OriginalTy->isArrayType());
25842 return ExprError();
25843 }
25844
25845 if (Stride) {
25847 if (Stride->EvaluateAsInt(Result, Context)) {
25848 // OpenMP 5.0, [2.1.5 Array Sections]
25849 // The stride must evaluate to a positive integer.
25850 llvm::APSInt StrideValue = Result.Val.getInt();
25851 if (!StrideValue.isStrictlyPositive()) {
25852 Diag(Stride->getExprLoc(), diag::err_omp_section_stride_non_positive)
25853 << toString(StrideValue, /*Radix=*/10, /*Signed=*/true)
25854 << Stride->getSourceRange();
25855 return ExprError();
25856 }
25857 }
25858 }
25859
25860 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
25861 ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(Base);
25862 if (Result.isInvalid())
25863 return ExprError();
25864 Base = Result.get();
25865 }
25866 return new (Context) ArraySectionExpr(
25867 Base, LowerBound, Length, Stride, Context.ArraySectionTy, VK_LValue,
25868 OK_Ordinary, ColonLocFirst, ColonLocSecond, RBLoc);
25869}
25870
25872 Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc,
25873 ArrayRef<Expr *> Dims, ArrayRef<SourceRange> Brackets) {
25874 ASTContext &Context = getASTContext();
25875 if (Base->hasPlaceholderType()) {
25876 ExprResult Result = SemaRef.CheckPlaceholderExpr(Base);
25877 if (Result.isInvalid())
25878 return ExprError();
25879 Result = SemaRef.DefaultLvalueConversion(Result.get());
25880 if (Result.isInvalid())
25881 return ExprError();
25882 Base = Result.get();
25883 }
25884 QualType BaseTy = Base->getType();
25885 // Delay analysis of the types/expressions if instantiation/specialization is
25886 // required.
25887 if (!BaseTy->isPointerType() && Base->isTypeDependent())
25888 return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
25889 LParenLoc, RParenLoc, Dims, Brackets);
25890 if (!BaseTy->isPointerType() ||
25891 (!Base->isTypeDependent() &&
25892 BaseTy->getPointeeType()->isIncompleteType()))
25893 return ExprError(Diag(Base->getExprLoc(),
25894 diag::err_omp_non_pointer_type_array_shaping_base)
25895 << Base->getSourceRange());
25896
25897 SmallVector<Expr *, 4> NewDims;
25898 bool ErrorFound = false;
25899 for (Expr *Dim : Dims) {
25900 if (Dim->hasPlaceholderType()) {
25901 ExprResult Result = SemaRef.CheckPlaceholderExpr(Dim);
25902 if (Result.isInvalid()) {
25903 ErrorFound = true;
25904 continue;
25905 }
25906 Result = SemaRef.DefaultLvalueConversion(Result.get());
25907 if (Result.isInvalid()) {
25908 ErrorFound = true;
25909 continue;
25910 }
25911 Dim = Result.get();
25912 }
25913 if (!Dim->isTypeDependent()) {
25916 if (Result.isInvalid()) {
25917 ErrorFound = true;
25918 Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
25919 << Dim->getSourceRange();
25920 continue;
25921 }
25922 Dim = Result.get();
25923 Expr::EvalResult EvResult;
25924 if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
25925 // OpenMP 5.0, [2.1.4 Array Shaping]
25926 // Each si is an integral type expression that must evaluate to a
25927 // positive integer.
25928 llvm::APSInt Value = EvResult.Val.getInt();
25929 if (!Value.isStrictlyPositive()) {
25930 Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
25931 << toString(Value, /*Radix=*/10, /*Signed=*/true)
25932 << Dim->getSourceRange();
25933 ErrorFound = true;
25934 continue;
25935 }
25936 }
25937 }
25938 NewDims.push_back(Dim);
25939 }
25940 if (ErrorFound)
25941 return ExprError();
25942 return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
25943 LParenLoc, RParenLoc, NewDims, Brackets);
25944}
25945
25947 SourceLocation IteratorKwLoc,
25948 SourceLocation LLoc,
25949 SourceLocation RLoc,
25951 ASTContext &Context = getASTContext();
25953 bool IsCorrect = true;
25954 for (const OMPIteratorData &D : Data) {
25955 TypeSourceInfo *TInfo = nullptr;
25956 SourceLocation StartLoc;
25957 QualType DeclTy;
25958 if (!D.Type.getAsOpaquePtr()) {
25959 // OpenMP 5.0, 2.1.6 Iterators
25960 // In an iterator-specifier, if the iterator-type is not specified then
25961 // the type of that iterator is of int type.
25962 DeclTy = Context.IntTy;
25963 StartLoc = D.DeclIdentLoc;
25964 } else {
25965 DeclTy = Sema::GetTypeFromParser(D.Type, &TInfo);
25966 StartLoc = TInfo->getTypeLoc().getBeginLoc();
25967 }
25968
25969 bool IsDeclTyDependent = DeclTy->isDependentType() ||
25970 DeclTy->containsUnexpandedParameterPack() ||
25971 DeclTy->isInstantiationDependentType();
25972 if (!IsDeclTyDependent) {
25973 if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
25974 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25975 // The iterator-type must be an integral or pointer type.
25976 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25977 << DeclTy;
25978 IsCorrect = false;
25979 continue;
25980 }
25981 if (DeclTy.isConstant(Context)) {
25982 // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
25983 // The iterator-type must not be const qualified.
25984 Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
25985 << DeclTy;
25986 IsCorrect = false;
25987 continue;
25988 }
25989 }
25990
25991 // Iterator declaration.
25992 assert(D.DeclIdent && "Identifier expected.");
25993 // Always try to create iterator declarator to avoid extra error messages
25994 // about unknown declarations use.
25995 auto *VD =
25996 VarDecl::Create(Context, SemaRef.CurContext, StartLoc, D.DeclIdentLoc,
25997 D.DeclIdent, DeclTy, TInfo, SC_None);
25998 VD->setImplicit();
25999 if (S) {
26000 // Check for conflicting previous declaration.
26001 DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
26004 Previous.suppressDiagnostics();
26005 SemaRef.LookupName(Previous, S);
26006
26007 SemaRef.FilterLookupForScope(Previous, SemaRef.CurContext, S,
26008 /*ConsiderLinkage=*/false,
26009 /*AllowInlineNamespace=*/false);
26010 if (!Previous.empty()) {
26011 NamedDecl *Old = Previous.getRepresentativeDecl();
26012 Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
26013 Diag(Old->getLocation(), diag::note_previous_definition);
26014 } else {
26015 SemaRef.PushOnScopeChains(VD, S);
26016 }
26017 } else {
26018 SemaRef.CurContext->addDecl(VD);
26019 }
26020
26021 /// Act on the iterator variable declaration.
26023
26024 Expr *Begin = D.Range.Begin;
26025 if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
26026 ExprResult BeginRes = SemaRef.PerformImplicitConversion(
26027 Begin, DeclTy, AssignmentAction::Converting);
26028 Begin = BeginRes.get();
26029 }
26030 Expr *End = D.Range.End;
26031 if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
26032 ExprResult EndRes = SemaRef.PerformImplicitConversion(
26033 End, DeclTy, AssignmentAction::Converting);
26034 End = EndRes.get();
26035 }
26036 Expr *Step = D.Range.Step;
26037 if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
26038 if (!Step->getType()->isIntegralType(Context)) {
26039 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
26040 << Step << Step->getSourceRange();
26041 IsCorrect = false;
26042 continue;
26043 }
26044 std::optional<llvm::APSInt> Result =
26045 Step->getIntegerConstantExpr(Context);
26046 // OpenMP 5.0, 2.1.6 Iterators, Restrictions
26047 // If the step expression of a range-specification equals zero, the
26048 // behavior is unspecified.
26049 if (Result && Result->isZero()) {
26050 Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
26051 << Step << Step->getSourceRange();
26052 IsCorrect = false;
26053 continue;
26054 }
26055 }
26056 if (!Begin || !End || !IsCorrect) {
26057 IsCorrect = false;
26058 continue;
26059 }
26060 OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
26061 IDElem.IteratorDecl = VD;
26062 IDElem.AssignmentLoc = D.AssignLoc;
26063 IDElem.Range.Begin = Begin;
26064 IDElem.Range.End = End;
26065 IDElem.Range.Step = Step;
26066 IDElem.ColonLoc = D.ColonLoc;
26067 IDElem.SecondColonLoc = D.SecColonLoc;
26068 }
26069 if (!IsCorrect) {
26070 // Invalidate all created iterator declarations if error is found.
26071 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26072 if (Decl *ID = D.IteratorDecl)
26073 ID->setInvalidDecl();
26074 }
26075 return ExprError();
26076 }
26078 if (!SemaRef.CurContext->isDependentContext()) {
26079 // Build number of ityeration for each iteration range.
26080 // Ni = ((Stepi > 0) ? ((Endi + Stepi -1 - Begini)/Stepi) :
26081 // ((Begini-Stepi-1-Endi) / -Stepi);
26083 // (Endi - Begini)
26084 ExprResult Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Sub,
26085 D.Range.End, D.Range.Begin);
26086 if (!Res.isUsable()) {
26087 IsCorrect = false;
26088 continue;
26089 }
26090 ExprResult St, St1;
26091 if (D.Range.Step) {
26092 St = D.Range.Step;
26093 // (Endi - Begini) + Stepi
26094 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res.get(),
26095 St.get());
26096 if (!Res.isUsable()) {
26097 IsCorrect = false;
26098 continue;
26099 }
26100 // (Endi - Begini) + Stepi - 1
26101 Res = SemaRef.CreateBuiltinBinOp(
26102 D.AssignmentLoc, BO_Sub, Res.get(),
26103 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26104 if (!Res.isUsable()) {
26105 IsCorrect = false;
26106 continue;
26107 }
26108 // ((Endi - Begini) + Stepi - 1) / Stepi
26109 Res = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res.get(),
26110 St.get());
26111 if (!Res.isUsable()) {
26112 IsCorrect = false;
26113 continue;
26114 }
26115 St1 = SemaRef.CreateBuiltinUnaryOp(D.AssignmentLoc, UO_Minus,
26116 D.Range.Step);
26117 // (Begini - Endi)
26118 ExprResult Res1 = SemaRef.CreateBuiltinBinOp(
26119 D.AssignmentLoc, BO_Sub, D.Range.Begin, D.Range.End);
26120 if (!Res1.isUsable()) {
26121 IsCorrect = false;
26122 continue;
26123 }
26124 // (Begini - Endi) - Stepi
26125 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add, Res1.get(),
26126 St1.get());
26127 if (!Res1.isUsable()) {
26128 IsCorrect = false;
26129 continue;
26130 }
26131 // (Begini - Endi) - Stepi - 1
26132 Res1 = SemaRef.CreateBuiltinBinOp(
26133 D.AssignmentLoc, BO_Sub, Res1.get(),
26134 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 1).get());
26135 if (!Res1.isUsable()) {
26136 IsCorrect = false;
26137 continue;
26138 }
26139 // ((Begini - Endi) - Stepi - 1) / (-Stepi)
26140 Res1 = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Div, Res1.get(),
26141 St1.get());
26142 if (!Res1.isUsable()) {
26143 IsCorrect = false;
26144 continue;
26145 }
26146 // Stepi > 0.
26147 ExprResult CmpRes = SemaRef.CreateBuiltinBinOp(
26148 D.AssignmentLoc, BO_GT, D.Range.Step,
26149 SemaRef.ActOnIntegerConstant(D.AssignmentLoc, 0).get());
26150 if (!CmpRes.isUsable()) {
26151 IsCorrect = false;
26152 continue;
26153 }
26154 Res = SemaRef.ActOnConditionalOp(D.AssignmentLoc, D.AssignmentLoc,
26155 CmpRes.get(), Res.get(), Res1.get());
26156 if (!Res.isUsable()) {
26157 IsCorrect = false;
26158 continue;
26159 }
26160 }
26161 Res = SemaRef.ActOnFinishFullExpr(Res.get(), /*DiscardedValue=*/false);
26162 if (!Res.isUsable()) {
26163 IsCorrect = false;
26164 continue;
26165 }
26166
26167 // Build counter update.
26168 // Build counter.
26169 auto *CounterVD = VarDecl::Create(Context, SemaRef.CurContext,
26170 D.IteratorDecl->getBeginLoc(),
26171 D.IteratorDecl->getBeginLoc(), nullptr,
26172 Res.get()->getType(), nullptr, SC_None);
26173 CounterVD->setImplicit();
26174 ExprResult RefRes =
26175 SemaRef.BuildDeclRefExpr(CounterVD, CounterVD->getType(), VK_LValue,
26176 D.IteratorDecl->getBeginLoc());
26177 // Build counter update.
26178 // I = Begini + counter * Stepi;
26179 ExprResult UpdateRes;
26180 if (D.Range.Step) {
26181 UpdateRes = SemaRef.CreateBuiltinBinOp(
26182 D.AssignmentLoc, BO_Mul,
26183 SemaRef.DefaultLvalueConversion(RefRes.get()).get(), St.get());
26184 } else {
26185 UpdateRes = SemaRef.DefaultLvalueConversion(RefRes.get());
26186 }
26187 if (!UpdateRes.isUsable()) {
26188 IsCorrect = false;
26189 continue;
26190 }
26191 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Add,
26192 D.Range.Begin, UpdateRes.get());
26193 if (!UpdateRes.isUsable()) {
26194 IsCorrect = false;
26195 continue;
26196 }
26197 ExprResult VDRes =
26198 SemaRef.BuildDeclRefExpr(cast<VarDecl>(D.IteratorDecl),
26199 cast<VarDecl>(D.IteratorDecl)->getType(),
26200 VK_LValue, D.IteratorDecl->getBeginLoc());
26201 UpdateRes = SemaRef.CreateBuiltinBinOp(D.AssignmentLoc, BO_Assign,
26202 VDRes.get(), UpdateRes.get());
26203 if (!UpdateRes.isUsable()) {
26204 IsCorrect = false;
26205 continue;
26206 }
26207 UpdateRes =
26208 SemaRef.ActOnFinishFullExpr(UpdateRes.get(), /*DiscardedValue=*/true);
26209 if (!UpdateRes.isUsable()) {
26210 IsCorrect = false;
26211 continue;
26212 }
26213 ExprResult CounterUpdateRes = SemaRef.CreateBuiltinUnaryOp(
26214 D.AssignmentLoc, UO_PreInc, RefRes.get());
26215 if (!CounterUpdateRes.isUsable()) {
26216 IsCorrect = false;
26217 continue;
26218 }
26219 CounterUpdateRes = SemaRef.ActOnFinishFullExpr(CounterUpdateRes.get(),
26220 /*DiscardedValue=*/true);
26221 if (!CounterUpdateRes.isUsable()) {
26222 IsCorrect = false;
26223 continue;
26224 }
26225 OMPIteratorHelperData &HD = Helpers.emplace_back();
26226 HD.CounterVD = CounterVD;
26227 HD.Upper = Res.get();
26228 HD.Update = UpdateRes.get();
26229 HD.CounterUpdate = CounterUpdateRes.get();
26230 }
26231 } else {
26232 Helpers.assign(ID.size(), {});
26233 }
26234 if (!IsCorrect) {
26235 // Invalidate all created iterator declarations if error is found.
26236 for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
26237 if (Decl *ID = D.IteratorDecl)
26238 ID->setInvalidDecl();
26239 }
26240 return ExprError();
26241 }
26242 return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
26243 LLoc, RLoc, ID, Helpers);
26244}
26245
26246/// Check if \p AssumptionStr is a known assumption and warn if not.
26248 StringRef AssumptionStr) {
26249 if (llvm::getKnownAssumptionStrings().count(AssumptionStr))
26250 return;
26251
26252 unsigned BestEditDistance = 3;
26253 StringRef Suggestion;
26254 for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) {
26255 unsigned EditDistance =
26256 AssumptionStr.edit_distance(KnownAssumptionIt.getKey());
26257 if (EditDistance < BestEditDistance) {
26258 Suggestion = KnownAssumptionIt.getKey();
26259 BestEditDistance = EditDistance;
26260 }
26261 }
26262
26263 if (!Suggestion.empty())
26264 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown_suggested)
26265 << AssumptionStr << Suggestion;
26266 else
26267 S.Diag(Loc, diag::warn_omp_assume_attribute_string_unknown)
26268 << AssumptionStr;
26269}
26270
26272 // Handle the case where the attribute has a text message.
26273 StringRef Str;
26274 SourceLocation AttrStrLoc;
26275 if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Str, &AttrStrLoc))
26276 return;
26277
26278 checkOMPAssumeAttr(SemaRef, AttrStrLoc, Str);
26279
26280 D->addAttr(::new (getASTContext()) OMPAssumeAttr(getASTContext(), AL, Str));
26281}
26282
26284 : 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.
static const Decl * getCanonicalDecl(const Decl *D)
#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.
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:49
static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)
Build a variable declaration for move parameter.
static NamedDecl * findAcceptableDecl(Sema &SemaRef, NamedDecl *D, unsigned IDNS)
Retrieve the visible declaration corresponding to D, if any.
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 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 bool checkSimdlenSafelenSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto, QualType NewType)
static bool checkOMPArraySectionConstantForReduction(ASTContext &Context, const ArraySectionExpr *OASE, bool &SingleElement, SmallVectorImpl< llvm::APSInt > &ArraySizes)
static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPDirectiveKind > AllowedNameModifiers)
static void handleDeclareVariantConstructTrait(DSAStackTy *Stack, OpenMPDirectiveKind DKind, bool ScopeEntry)
static VarDecl * precomputeExpr(Sema &Actions, SmallVectorImpl< Stmt * > &BodyStmts, Expr *E, StringRef Name)
static bool hasUserDefinedMapper(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type)
static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, CXXScopeSpec &MapperIdScopeSpec, const DeclarationNameInfo &MapperId, QualType Type, Expr *UnresolvedMapper)
static bool checkReductionClauseWithNogroup(Sema &S, ArrayRef< OMPClause * > Clauses)
static bool checkSectionsDirective(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt, DSAStackTy *Stack)
static bool checkScheduleModifiers(Sema &S, OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, SourceLocation M1Loc, SourceLocation M2Loc)
static bool teamsLoopCanBeParallelFor(Stmt *AStmt, Sema &SemaRef)
static Expr * makeFloorIVRef(Sema &SemaRef, ArrayRef< VarDecl * > FloorIndVars, int I, QualType IVTy, DeclRefExpr *OrigCntVar)
Build and return a DeclRefExpr for the floor induction variable using the SemaRef and the provided pa...
static OMPAllocateDeclAttr::AllocatorTypeTy getAllocatorKind(Sema &S, DSAStackTy *Stack, Expr *Allocator)
static bool isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, bool StrictlyPositive, bool BuildCapture=false, OpenMPDirectiveKind DKind=OMPD_unknown, OpenMPDirectiveKind *CaptureRegion=nullptr, Stmt **HelperValStmt=nullptr)
static Expr * buildPostUpdate(Sema &S, ArrayRef< Expr * > PostUpdates)
Build postupdate expression for the given list of postupdates expressions.
static CapturedStmt * buildLoopVarFunc(Sema &Actions, QualType LoopVarTy, QualType LogicalTy, DeclRefExpr *StartExpr, Expr *Step, bool Deref)
Create a closure that computes the loop variable from the logical iteration number.
static ExprResult buildCounterUpdate(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > *Captures=nullptr)
Build 'VarRef = Start + Iter * Step'.
static OpenMPDirectiveKind getOpenMPCaptureRegionForClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion, OpenMPDirectiveKind NameModifier=OMPD_unknown)
static bool finishLinearClauses(Sema &SemaRef, ArrayRef< OMPClause * > Clauses, OMPLoopBasedDirective::HelperExprs &B, DSAStackTy *Stack)
static Expr * getCollapseNumberExpr(ArrayRef< OMPClause * > Clauses)
static Expr * getDirectCallExpr(Expr *E)
static bool checkArrayExpressionDoesNotReferToUnitySize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
static OMPCapturedExprDecl * buildCaptureDecl(Sema &S, IdentifierInfo *Id, Expr *CaptureExpr, bool WithInit, DeclContext *CurContext, bool AsExpression)
static bool findOMPAllocatorHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_allocator_handle_t type.
static bool isClauseMappable(ArrayRef< OMPClause * > Clauses)
Check if the variables in the mapping clause are externally visible.
static BinaryOperatorKind getRelatedCompoundReductionOp(BinaryOperatorKind BOK)
static SmallVector< SemaOpenMP::CapturedParamNameType > getParallelRegionParams(Sema &SemaRef, bool LoopBoundSharing)
static void collectLoopStmts(Stmt *AStmt, MutableArrayRef< Stmt * > LoopStmts)
Collect the loop statements (ForStmt or CXXRangeForStmt) of the affected loop of a construct.
static bool checkMutuallyExclusiveClauses(Sema &S, ArrayRef< OMPClause * > Clauses, ArrayRef< OpenMPClauseKind > MutuallyExclusiveClauses)
Find and diagnose mutually exclusive clause kinds.
static 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 checkOrderedOrderSpecified(Sema &S, const ArrayRef< OMPClause * > Clauses)
static OpenMPMapClauseKind getMapClauseKindFromModifier(OpenMPDefaultmapClauseModifier M, bool IsAggregateOrDeclareTarget)
static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind, Scope *CurScope, SourceLocation Loc)
static const Expr * getExprAsWritten(const Expr *E)
static bool checkMapConflicts(Sema &SemaRef, DSAStackTy *DSAS, const ValueDecl *VD, const Expr *E, bool CurrentRegionOnly, OMPClauseMappableExprCommon::MappableExprComponentListRef CurComponents, OpenMPClauseKind CKind)
static bool isOpenMPDeviceDelayedContext(Sema &S)
static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef)
Convert integer expression E to make it have at least Bits bits.
static SmallVector< SemaOpenMP::CapturedParamNameType > getUnknownRegionParams(Sema &SemaRef)
static bool isImplicitMapperNeeded(Sema &S, DSAStackTy *Stack, QualType CanonType, const Expr *E)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTeamsRegionParams(Sema &SemaRef)
static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr)
Check if AssumptionStr is a known assumption and warn if not.
static void applyOMPAllocateAttribute(Sema &S, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator, Expr *Alignment, SourceRange SR)
static ExprResult buildImplicitMapper(Sema &S, QualType BaseType, DSAStackTy *Stack)
static SmallVector< SemaOpenMP::CapturedParamNameType > getTargetRegionParams(Sema &SemaRef)
static CapturedStmt * buildDistanceFunc(Sema &Actions, QualType LogicalTy, BinaryOperator::Opcode Rel, Expr *StartExpr, Expr *StopExpr, Expr *StepExpr)
Create a closure that computes the number of iterations of a loop.
static bool checkPreviousOMPAllocateAttribute(Sema &S, DSAStackTy *Stack, Expr *RefExpr, VarDecl *VD, OMPAllocateDeclAttr::AllocatorTypeTy AllocatorKind, Expr *Allocator)
static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, Expr *NumIterations, Sema &SemaRef, Scope *S, DSAStackTy *Stack)
static bool rejectConstNotMutableType(Sema &SemaRef, const ValueDecl *D, QualType Type, OpenMPClauseKind CKind, SourceLocation ELoc, bool AcceptIfMutable=true, bool ListItemNotVar=false)
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr, SourceLocation VarLoc, OpenMPClauseKind Kind)
static const ValueDecl * getCanonicalDecl(const ValueDecl *D)
static std::string getOpenMPClauseNameForDiag(OpenMPClauseKind C)
static const Expr * checkMapClauseExpressionBase(Sema &SemaRef, Expr *E, OMPClauseMappableExprCommon::MappableExprComponentList &CurComponents, OpenMPClauseKind CKind, OpenMPDirectiveKind DKind, bool NoDiagnose)
Return the expression of the base of the mappable expression or null if it cannot be determined and d...
static void checkMappableExpressionList(Sema &SemaRef, DSAStackTy *DSAS, OpenMPClauseKind CKind, MappableVarListInfo &MVLI, SourceLocation StartLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo MapperId, ArrayRef< Expr * > UnresolvedMappers, OpenMPMapClauseKind MapType=OMPC_MAP_unknown, ArrayRef< OpenMPMapModifierKind > Modifiers={}, bool IsMapTypeImplicit=false, bool NoDiagnose=false)
static bool hasClauses(ArrayRef< OMPClause * > Clauses, const OpenMPClauseKind K)
Check for existence of a map clause in the list of clauses.
static bool checkOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, llvm::MutableArrayRef< LoopIterationSpace > ResultIterSpaces, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures, const llvm::SmallPtrSetImpl< const Decl * > &CollapsedLoopVarDecls)
Called on a for stmt to check and extract its iteration space for further processing (such as collaps...
static CapturedStmt * setBranchProtectedScope(Sema &SemaRef, OpenMPDirectiveKind DKind, Stmt *AStmt)
static void processImplicitMapsWithDefaultMappers(Sema &S, DSAStackTy *Stack, SmallVectorImpl< OMPClause * > &Clauses)
Perform DFS through the structure/class data members trying to find member(s) with user-defined 'defa...
static bool checkCancelRegion(Sema &SemaRef, OpenMPDirectiveKind CurrentRegion, OpenMPDirectiveKind CancelRegion, SourceLocation StartLoc)
static DeclRefExpr * buildDeclRefExpr(Sema &S, VarDecl *D, QualType Ty, SourceLocation Loc, bool RefersToCapture=false)
static ExprResult buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef, ExprResult Start, bool IsNonRectangularLB, llvm::MapVector< const Expr *, DeclRefExpr * > &Captures)
Build 'VarRef = Start.
static DoacrossDataInfoTy ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource, ArrayRef< Expr * > VarList, DSAStackTy *Stack, SourceLocation EndLoc)
static bool checkValueDeclInTarget(SourceLocation SL, SourceRange SR, Sema &SemaRef, DSAStackTy *Stack, ValueDecl *VD)
static bool findOMPEventHandleT(Sema &S, SourceLocation Loc, DSAStackTy *Stack)
Tries to find omp_event_handle_t type.
static ExprResult buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, Scope *S, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, QualType Ty, CXXCastPath &BasePath, Expr *UnresolvedReduction)
static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef)
Check if the given expression E is a constant integer that fits into Bits bits.
#define DSAStack
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack, ArrayRef< OMPClause * > Clauses)
static bool actOnOMPReductionKindClause(Sema &S, DSAStackTy *Stack, OpenMPClauseKind ClauseKind, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef< Expr * > UnresolvedReductions, ReductionData &RD)
static void reportOriginalDsa(Sema &SemaRef, const DSAStackTy *Stack, const ValueDecl *D, const DSAStackTy::DSAVarData &DVar, bool IsLoopIterVar=false)
static 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 SmallVector< SemaOpenMP::CapturedParamNameType > getTaskloopRegionParams(Sema &SemaRef)
static unsigned checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Expr *OrderedLoopCountExpr, Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA, OMPLoopBasedDirective::HelperExprs &Built)
Called on a for stmt to check itself and nested loops (if any).
static OpenMPDefaultmapClauseKind getVariableCategoryFromDecl(const LangOptions &LO, const ValueDecl *VD)
static bool checkNumExprsInClause(SemaBase &SemaRef, ArrayRef< OMPClause * > Clauses, unsigned MaxNum, unsigned Diag)
This checks whether a ClauseType clause C has at most Max expression.
static bool checkArrayExpressionDoesNotReferToWholeSize(Sema &SemaRef, const Expr *E, QualType BaseQTy)
Return true if it can be proven that the provided array expression (array section or array subscript)...
static OMPClause * createTransparentClause(Sema &SemaRef, ASTContext &Ctx, Expr *ImpexTypeArg, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
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.
Expr * getUpdateExpr()
Get helper expression of the form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or 'OpaqueValueExp...
Expr * getV()
Get 'v' part of the associated expression/statement.
Expr * getR()
Get 'r' part of the associated expression/statement.
Expr * getD()
Get 'd' part of the associated expression/statement.
Expr * getX()
Get 'x' part of the associated expression/statement.
bool isFailOnly() const
Return true if 'v' is updated only when the condition is evaluated false (compare capture only).
bool isPostfixUpdate() const
Return true if 'v' expression must be updated to original value of 'x', false if 'v' must be updated ...
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
bool isXLHSInRHSPart() const
Return true if helper update expression has form 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and...
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)
This represents 'bind' clause in the 'pragma omp ...' directives.
static OMPBindClause * Create(const ASTContext &C, OpenMPBindClauseKind K, SourceLocation KLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'bind' clause with kind K ('teams', 'parallel', or 'thread').
static OMPCancelDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, OpenMPDirectiveKind CancelRegion)
Creates directive.
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.
This represents 'defaultmap' clause in the 'pragma omp ...' directive.
This represents implicit clause 'depend' for the 'pragma omp task' directive.
static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, DependDataTy Data, Expr *DepModifier, ArrayRef< Expr * > VL, unsigned NumLoops)
Creates clause with a list of variables VL.
static OMPDepobjClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Depobj)
Creates clause.
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.
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 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)
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)
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.
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 OMPMasterTaskLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel)
Creates directive with a list of Clauses.
static OMPMasterTaskLoopSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
This represents '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, 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 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 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 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.
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)
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 OMPStripeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp stripe'.
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 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 OMPTeamsDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt)
Creates directive with a list of Clauses.
static OMPTeamsDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef, bool HasCancel)
Creates directive with a list of Clauses.
static OMPTeamsDistributeParallelForSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsDistributeSimdDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPTeamsGenericLoopDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef< OMPClause * > Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs)
Creates directive with a list of Clauses.
static OMPThreadLimitClause * Create(const ASTContext &C, OpenMPDirectiveKind CaptureRegion, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, Stmt *PreInit)
Creates clause with a list of variables VL.
This represents 'threads' clause in the 'pragma omp ...' directive.
static OMPTileDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef< OMPClause * > Clauses, unsigned NumLoops, Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits)
Create a new AST node representation for 'pragma omp tile'.
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)
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:508
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
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:801
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:877
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:797
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:916
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:7218
Expr * getBase()
Get base of the array section.
Definition Expr.h:7296
Expr * getLength()
Get length of array section.
Definition Expr.h:7306
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5366
Expr * getLowerBound()
Get lower bound of array section.
Definition Expr.h:7300
SourceLocation getColonLocFirst() const
Definition Expr.h:7327
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3730
QualType getElementType() const
Definition TypeBase.h:3742
Attr - This represents one attribute.
Definition Attr.h:46
Represents an attribute applied to a statement.
Definition Stmt.h:2195
static AttributedStmt * Create(const ASTContext &C, SourceLocation Loc, ArrayRef< const Attr * > Attrs, Stmt *SubStmt)
Definition Stmt.cpp:441
SourceLocation getBeginLoc() const
Definition Stmt.h:2234
A builtin binary operation expression such as "x + y" or "x <= y".
Definition Expr.h:4041
Expr * getLHS() const
Definition Expr.h:4091
static bool isRelationalOp(Opcode Opc)
Definition Expr.h:4135
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition Expr.cpp:2180
static Opcode getOpForCompoundAssignment(Opcode Opc)
Definition Expr.h:4188
SourceLocation getOperatorLoc() const
Definition Expr.h:4083
SourceLocation getExprLoc() const
Definition Expr.h:4082
static Opcode reverseComparisonOp(Opcode Opc)
Definition Expr.h:4160
Expr * getRHS() const
Definition Expr.h:4093
Opcode getOpcode() const
Definition Expr.h:4086
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Definition Expr.cpp:2142
BinaryOperatorKind Opcode
Definition Expr.h:4046
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:2611
Represents a C++ conversion function within a class.
Definition DeclCXX.h:2946
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
Definition StmtCXX.h:135
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool hasMutableFields() const
Determine whether this class, or any of its class subobjects, contains a mutable field.
Definition DeclCXX.h:1233
bool hasDefinition() const
Definition DeclCXX.h:561
Represents a C++ nested-name-specifier or a global scope specifier.
Definition DeclSpec.h:74
bool isValid() const
A scope specifier is present, and it refers to a real scope.
Definition DeclSpec.h:186
SourceLocation getBeginLoc() const
Definition DeclSpec.h:84
bool isSet() const
Deprecated.
Definition DeclSpec.h:199
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:184
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2946
SourceLocation getBeginLoc() const
Definition Expr.h:3280
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:1517
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition Expr.h:3129
Expr * getCallee()
Definition Expr.h:3093
arg_range arguments()
Definition Expr.h:3198
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:4946
unsigned getNumParams() const
Definition Decl.h:4984
void setNothrow(bool Nothrow=true)
Definition Decl.cpp:5703
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:5699
ImplicitParamDecl * getParam(unsigned i) const
Definition Decl.h:4986
This captures a statement into a function.
Definition Stmt.h:3929
CapturedDecl * getCapturedDecl()
Retrieve the outlined function declaration.
Definition Stmt.cpp:1493
SourceRange getSourceRange() const LLVM_READONLY
Definition Stmt.h:4132
Stmt * getCapturedStmt()
Retrieve the statement being captured.
Definition Stmt.h:4033
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:4124
capture_range captures()
Definition Stmt.h:4067
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition Expr.h:3679
Declaration of a class template.
Complex values, per C99 6.2.5p11.
Definition TypeBase.h:3283
CompoundStmt - This represents a group of statements like { stmt stmt }.
Definition Stmt.h:1732
SourceLocation getBeginLoc() const
Definition Stmt.h:1846
static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)
Definition Stmt.cpp:399
ConditionalOperator - The ?
Definition Expr.h:4394
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:1449
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
bool Equals(const DeclContext *DC) const
Determine whether this declaration context is equivalent to the declaration context DC.
Definition DeclBase.h:2238
bool isFileContext() const
Definition DeclBase.h:2180
DeclContextLookupResult lookup_result
Definition DeclBase.h:2577
ASTContext & getParentASTContext() const
Definition DeclBase.h:2138
bool isExternCXXContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
bool isNamespace() const
Definition DeclBase.h:2198
bool isTranslationUnit() const
Definition DeclBase.h:2185
void addDecl(Decl *D)
Add the declaration D into this context.
decl_range decls() const
decls_begin/decls_end - Iterate over the declarations stored in this context.
Definition DeclBase.h:2373
bool isExternCContext() const
Determines whether this context or some of its ancestors is a linkage specification context that spec...
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:1273
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
Definition Expr.cpp:488
ValueDecl * getDecl()
Definition Expr.h:1341
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Definition Expr.h:1471
SourceLocation getEndLoc() const LLVM_READONLY
Definition Expr.cpp:551
SourceLocation getBeginLoc() const
Definition Expr.h:1352
ConstexprSpecKind getConstexprSpecifier() const
Definition DeclSpec.h:837
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition Stmt.h:1623
SourceLocation getEndLoc() const
Definition Stmt.h:1646
const DeclGroupRef getDeclGroup() const
Definition Stmt.h:1641
const Decl * getSingleDecl() const
Definition Stmt.h:1638
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.h:1649
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
T * getAttr() const
Definition DeclBase.h:573
bool hasAttrs() const
Definition DeclBase.h:518
void addAttr(Attr *A)
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:593
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:178
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
Definition DeclBase.cpp:590
bool isReferenced() const
Whether any declaration of this entity was referenced.
Definition DeclBase.cpp:600
bool isCanonicalDecl() const
Whether this particular Decl is a canonical one.
Definition DeclBase.h:984
bool isInvalidDecl() const
Definition DeclBase.h:588
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
Definition DeclBase.h:559
void setAccess(AccessSpecifier AS)
Definition DeclBase.h:502
SourceLocation getLocation() const
Definition DeclBase.h:439
void setImplicit(bool I=true)
Definition DeclBase.h:594
void setReferenced(bool R=true)
Definition DeclBase.h:623
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition DeclBase.h:1049
bool isUsed(bool CheckUsedAttr=true) const
Whether any (re-)declaration of the entity was used, meaning that a definition is required.
Definition DeclBase.cpp:575
DeclContext * getDeclContext()
Definition DeclBase.h:448
AccessSpecifier getAccess() const
Definition DeclBase.h:507
AttrVec & getAttrs()
Definition DeclBase.h:524
void setDeclContext(DeclContext *DC)
setDeclContext - Set both the semantic and lexical DeclContext to DC.
Definition DeclBase.cpp:382
bool hasAttr() const
Definition DeclBase.h:577
void setLexicalDeclContext(DeclContext *DC)
Definition DeclBase.cpp:386
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:978
Kind getKind() const
Definition DeclBase.h:442
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition DeclBase.h:427
DeclarationName getIdentifier(const IdentifierInfo *ID)
Create a declaration name that is a simple identifier.
The name of a declaration.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
bool isEmpty() const
Evaluates true when this declaration name is empty.
Information about one declarator, including the parsed type information and the identifier.
Definition DeclSpec.h:1921
const DeclSpec & getDeclSpec() const
getDeclSpec - Return the declaration-specifier that this declarator was declared with.
Definition DeclSpec.h:2068
SourceLocation getIdentifierLoc() const
Definition DeclSpec.h:2357
void SetIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Set the name of this declarator to be the given identifier.
Definition DeclSpec.h:2360
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclSpec.h:2104
void setFunctionDefinitionKind(FunctionDefinitionKind Val)
Definition DeclSpec.h:2754
const CXXScopeSpec & getCXXScopeSpec() const
getCXXScopeSpec - Return the C++ scope specifier (global scope or nested-name-specifier) that is part...
Definition DeclSpec.h:2083
bool isInvalidType() const
Definition DeclSpec.h:2735
const IdentifierInfo * getIdentifier() const
Definition DeclSpec.h:2351
virtual bool TraverseStmt(MaybeConst< Stmt > *S)
RAII object that enters a new expression evaluation context.
This represents one expression.
Definition Expr.h:112
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
bool isIntegerConstantExpr(const ASTContext &Ctx) const
bool isGLValue() const
Definition Expr.h:287
@ SE_AllowSideEffects
Allow any unmodeled side effect.
Definition Expr.h:677
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3095
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition Expr.h:177
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Definition Expr.h:447
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition Expr.h:194
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:241
Expr * IgnoreParenLValueCasts() LLVM_READONLY
Skip past any parentheses and lvalue casts which might surround this expression until reaching a fixe...
Definition Expr.cpp:3107
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3090
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3078
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
Definition Expr.h:246
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3086
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language.
Definition Expr.h:284
ExprObjectKind getObjectKind() const
getObjectKind - The object kind that this expression produces.
Definition Expr.h:454
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:223
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3070
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:277
QualType getType() const
Definition Expr.h:144
Represents difference between two FPOptions values.
Represents a member of a struct/union/class.
Definition Decl.h:3160
bool isBitField() const
Determines whether this field is a bitfield.
Definition Decl.h:3263
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4827
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition Decl.h:3407
static FloatingLiteral * Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L)
Definition Expr.cpp:1076
ForStmt - This represents a 'for (init;cond;inc)' stmt.
Definition Stmt.h:2880
Stmt * getBody()
Definition Stmt.h:2924
Represents a function declaration or definition.
Definition Decl.h:2000
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:2797
ArrayRef< ParmVarDecl * > parameters() const
Definition Decl.h:2774
bool isConstexpr() const
Whether this is a (C++11) constexpr function or constexpr constructor.
Definition Decl.h:2470
FunctionDecl * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
bool isConsteval() const
Definition Decl.h:2482
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition Decl.cpp:3827
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:5315
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:2251
Stmt * getThen()
Definition Stmt.h:2340
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:2328
Stmt * getElse()
Definition Stmt.h:2349
SourceLocation getBeginLoc() const
Definition Stmt.h:2463
ImaginaryLiteral - We support imaginary integer and floating point literals, like "1....
Definition Expr.h:1734
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2073
ImplicitConversionSequence - Represents an implicit conversion sequence, which may be a standard conv...
Definition Overload.h:622
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 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:975
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...
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:3450
Expr * getBase() const
Definition Expr.h:3444
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:3428
SourceLocation getExprLoc() const LLVM_READONLY
Definition Expr.h:3562
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
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:317
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:1846
void setDeclName(DeclarationName N)
Set the name of this declaration.
Definition Decl.h:343
A C++ nested-name-specifier augmented with source location information.
static OMPAlignClause * Create(const ASTContext &C, Expr *A, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Build 'align' clause with the given alignment.
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:5474
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.
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 'final' clause in the 'pragma omp ...' directive.
Representation of the 'full' clause of the 'pragma omp unroll' directive.
static OMPFullClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc)
Build an AST node for a 'full' clause.
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:5601
static OMPLoopRangeClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation FirstLoc, SourceLocation CountLoc, SourceLocation EndLoc, Expr *First, Expr *Count)
Build a 'looprange' clause AST node.
This represents 'num_threads' clause in the 'pragma omp ...' directive.
Representation of the 'partial' clause of the 'pragma omp unroll' directive.
static OMPPartialClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, Expr *Factor)
Build an AST node for a 'partial' clause.
Expr * getFactor() const
Returns the argument of the clause or nullptr if not set.
This class represents the 'permutation' clause in the 'pragma omp interchange' directive.
unsigned getNumLoops() const
Returns the number of list items.
MutableArrayRef< Expr * > getArgsRefs()
Returns the permutation index expressions.
static OMPPermutationClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< Expr * > Args)
Build a 'permutation' clause AST node.
This represents '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:1181
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition Expr.h:1231
void setIsUnique(bool V)
Definition Expr.h:1233
Represents a parameter to a function.
Definition Decl.h:1790
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:2958
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:5170
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2911
bool hasQualifiers() const
Determine whether this type has any qualifiers.
Definition TypeBase.h:8477
QualType withRestrict() const
Definition TypeBase.h:1181
QualType getNonLValueExprType(const ASTContext &Context) const
Determine the type of a (typically non-lvalue) expression with the specified result type.
Definition Type.cpp:3624
QualType withConst() const
Definition TypeBase.h:1165
void addConst()
Add the const type qualifier to this QualType.
Definition TypeBase.h:1162
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8388
bool isConstant(const ASTContext &Ctx) const
Definition TypeBase.h:1097
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8573
QualType getCanonicalType() const
Definition TypeBase.h:8440
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8482
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:8542
const Type * getTypePtrOrNull() const
Definition TypeBase.h:8392
Represents a struct/union/class.
Definition Decl.h:4327
field_range fields() const
Definition Decl.h:4530
field_iterator field_begin() const
Definition Decl.cpp:5276
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3581
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
bool isDeclScope(const Decl *D) const
isDeclScope - Return true if this is the scope that the specified decl is declared in.
Definition Scope.h:398
Scope * getBreakParent()
getBreakParent - Return the closest scope that a break statement would be affected by.
Definition Scope.h:322
bool isOpenMPOrderClauseScope() const
Determine whether this scope is some OpenMP directive with order clause which specifies concurrent sc...
Definition Scope.h:558
const Scope * getParent() const
getParent - Return the scope that this is nested in.
Definition Scope.h:287
bool isOpenMPLoopScope() const
Determine whether this scope is a loop having OpenMP loop directive attached.
Definition Scope.h:551
@ OpenMPOrderClauseScope
This is a scope of some OpenMP directive with order clause which specifies concurrent.
Definition Scope.h:150
A generic diagnostic builder for errors which may or may not be deferred.
Definition SemaBase.h:111
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 ActOnOpenMPTargetEnterDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target enter data' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams loop' after parsing of the associated statement.
OMPClause * ActOnOpenMPDetachClause(Expr *Evt, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'detach' clause.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
OMPClause * ActOnOpenMPFailClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'fail' clause.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for simd' after parsing of the as...
StmtResult ActOnOpenMPAssumeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP assume directive.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a 'pragma omp end declare target' was 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...
StmtResult ActOnOpenMPParallelMaskedDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel masked' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp target teams distribute parallel for' after parsing of the associa...
OMPClause * ActOnOpenMPPrivateClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'private' clause.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of 'pragma omp declare mapper'.
OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc=SourceLocation(), Expr *NumForLoops=nullptr)
Called on well-formed 'ordered' clause.
OMPClause * ActOnOpenMPSelfMapsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'self_maps' clause.
bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type, bool IsDeclareSimd=false)
Checks that the specified declaration matches requirements for the linear decls.
OMPClause * ActOnOpenMPIsDevicePtrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'is_device_ptr' clause.
OMPClause * ActOnOpenMPHasDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'has_device_addr' clause.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
OMPClause * ActOnOpenMPPartialClause(Expr *FactorExpr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'partial' clauses.
StmtResult ActOnOpenMPSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp simd' after parsing of the associated statement.
OMPClause * ActOnOpenMPLastprivateClause(ArrayRef< Expr * > VarList, OpenMPLastprivateModifier LPKind, SourceLocation LPKindLoc, SourceLocation ColonLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'lastprivate' clause.
void ActOnOpenMPDeclareTargetName(NamedDecl *ND, SourceLocation Loc, OMPDeclareTargetDeclAttr::MapTypeTy MT, DeclareTargetContextInfo &DTCI)
Called on correct id-expression from the 'pragma omp declare target'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed 'pragma omp requires'.
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)
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< Expr * > AdjustArgsNeedDeviceAddr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target parallel' after parsing of the associated statement.
OMPClause * ActOnOpenMPDistScheduleClause(OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'dist_schedule' clause.
OpenMPClauseKind isOpenMPPrivateDecl(ValueDecl *D, unsigned Level, unsigned CapLevel) const
Check if the specified variable is used in 'private' clause.
OMPClause * 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 * ActOnOpenMPThreadLimitClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'thread_limit' clause.
OMPClause * ActOnOpenMPSharedClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'shared' clause.
StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt)
Called on well-formed '#pragma omp target exit data' after parsing of the associated statement.
StmtResult ActOnOpenMPTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPCopyinClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'copyin' clause.
OMPClause * ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'mergeable' clause.
void startOpenMPCXXRangeFor()
If the current region is a range loop-based region, mark the start of the loop construct.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
StmtResult ActOnOpenMPParallelMaskedTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop' after parsing of the associated statemen...
OMPClause * ActOnOpenMPAffinityClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, Expr *Modifier, ArrayRef< Expr * > Locators)
Called on well-formed 'affinity' clause.
OMPClause * ActOnOpenMPCompareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'compare' clause.
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.
OMPClause * ActOnOpenMPNumTeamsClause(ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'num_teams' clause.
StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp parallel sections' after parsing of the associated statement.
OMPClause * ActOnOpenMPUpdateClause(OpenMPDependClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'update' clause.
OMPClause * ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data, Expr *DepModifier, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'depend' clause.
OMPClause * ActOnOpenMPDoacrossClause(OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'doacross' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
StmtResult ActOnOpenMPTeamsDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for' after parsing of the associated sta...
StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp master' after parsing of the associated statement.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp taskgroup'.
VarDecl * isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo=false, unsigned StopAt=0)
Check if the specified variable is used in one of the private clauses (private, firstprivate,...
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:53
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the 'pragma omp threadprivate'.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed 'pragma omp end assumes'.
OMPClause * ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'nogroup' clause.
OMPClause * ActOnOpenMPGrainsizeClause(OpenMPGrainsizeClauseModifier Modifier, Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'grainsize' clause.
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length, Expr *Stride, SourceLocation RBLoc)
bool isOpenMPRebuildMemberExpr(ValueDecl *D)
The member expression(this->fd) needs to be rebuilt in the template instantiation to generate private...
void ActOnOpenMPDeviceNum(Expr *DeviceNumExpr)
Called on device_num selector in context selectors.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
StmtResult ActOnOpenMPMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp masked taskloop simd' after parsing of the associated statement.
bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level, unsigned OpenMPCaptureLevel) const
Return true if the provided declaration VD should be captured by reference.
StmtResult ActOnOpenMPParallelGenericLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel loop' after parsing of the associated statement.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed 'pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPUnifiedAddressClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind)
Return the number of captured regions created for an OpenMP directive.
bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level, unsigned CaptureLevel) const
Check if the specified variable is captured by 'target' directive.
StmtResult ActOnOpenMPParallelMaskedTaskLoopSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel masked taskloop simd' after parsing of the associated sta...
OMPClause * ActOnOpenMPDynamicAllocatorsClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'dynamic_allocators' clause.
StmtResult ActOnOpenMPScopeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scope' after parsing of the associated statement.
void ActOnOpenMPIteratorVarDecl(VarDecl *VD)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
Definition SemaOpenMP.h:111
StmtResult ActOnOpenMPDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for simd' after parsing of the associated stat...
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp barrier'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of 'pragma omp declare reduction'.
OMPClause * ActOnOpenMPAcqRelClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acq_rel' clause.
OMPClause * ActOnOpenMPAllocatorClause(Expr *Allocator, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocator' clause.
ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind, bool StrictlyPositive=true, bool SuppressExprDiags=false)
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:436
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. 'pragma omp declare target'.
StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute parallel for simd' after parsing of the associate...
OMPClause * ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier, Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'device' clause.
StmtResult ActOnOpenMPDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp section' after parsing of the associated statement.
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp interchange' after parsing of its clauses and the associated 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:249
void setOpenMPDeviceNumID(StringRef ID)
StmtResult ActOnOpenMPDistributeParallelForDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp distribute parallel for' after parsing of the associated statement...
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
StmtResult ActOnOpenMPTeamsDistributeDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp teams distribute' after parsing of the associated statement.
StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target teams' after parsing of the associated statement.
OMPClause * ActOnOpenMPMessageClause(Expr *MS, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'message' clause.
int getOpenMPDeviceNum() const
StmtResult ActOnOpenMPScanDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp scan'.
OMPClause * ActOnOpenMPScheduleClause(OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation M1Loc, SourceLocation M2Loc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc)
Called on well-formed 'schedule' clause.
void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init)
Check if the current region is an OpenMP loop region and if it is, mark loop control variable,...
OMPClause * ActOnOpenMPUnifiedSharedMemoryClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'unified_address' clause.
void DiagnoseUnterminatedOpenMPDeclareTarget()
Report unterminated 'omp declare target' or 'omp begin declare target' at the end of a compilation un...
void finalizeOpenMPDelayedAnalysis(const FunctionDecl *Caller, const FunctionDecl *Callee, SourceLocation Loc)
Finishes analysis of the deferred functions calls that may be declared as host/nohost during device/h...
OMPClause * ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'simdlen' clause.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
StmtResult ActOnOpenMPParallelForSimdDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp parallel for simd' after parsing of the associated statement.
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Definition SemaOpenMP.h:55
OMPClause * ActOnOpenMPReleaseClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'release' clause.
OMPClause * ActOnOpenMPAcquireClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'acquire' clause.
OMPClause * ActOnOpenMPProcBindClause(llvm::omp::ProcBindKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'proc_bind' clause.
OMPClause * ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'simd' clause.
OMPClause * ActOnOpenMPXBareClause(SourceLocation StartLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_bare' clause.
StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Process an OpenMP informational directive.
StmtResult ActOnOpenMPCanonicalLoop(Stmt *AStmt)
Called for syntactical loops (ForStmt or CXXForRangeStmt) associated to an OpenMP loop directive.
OMPClause * 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.
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp reverse'.
ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc, SourceLocation RParenLoc, ArrayRef< Expr * > Dims, ArrayRef< SourceRange > Brackets)
OMPClause * ActOnOpenMPNumThreadsClause(OpenMPNumThreadsClauseModifier Modifier, Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_threads' clause.
OMPClause * ActOnOpenMPAtClause(OpenMPAtClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'at' clause.
StmtResult ActOnOpenMPTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp taskloop' after parsing of the associated statement.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
OMPClause * ActOnOpenMPUseDeviceAddrClause(ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs)
Called on well-formed 'use_device_addr' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
OMPClause * ActOnOpenMPAllocateClause(Expr *Allocator, Expr *Alignment, OpenMPAllocateClauseModifier FirstModifier, SourceLocation FirstModifierLoc, OpenMPAllocateClauseModifier SecondModifier, SourceLocation SecondModifierLoc, ArrayRef< Expr * > VarList, SourceLocation StartLoc, SourceLocation ColonLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'allocate' clause.
std::pair< StringRef, QualType > CapturedParamNameType
Definition SemaOpenMP.h:56
OMPClause * ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-formed 'final' clause.
bool isInOpenMPTargetExecutionDirective() const
Return true inside OpenMP target region.
StmtResult ActOnOpenMPTargetDataDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp target data' after parsing of the associated statement.
StmtResult ActOnOpenMPMasterTaskLoopDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA)
Called on well-formed '#pragma omp master taskloop' after parsing of the associated statement.
void ActOnStartOfFunctionDefinitionInOpenMPDeclareVariantScope(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParameterLists, SmallVectorImpl< FunctionDecl * > &Bases)
The declarator D defines a function in the scope S which is nested in an omp begin/end declare varian...
StmtResult ActOnOpenMPFlushDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed '#pragma omp flush'.
StmtResult ActOnOpenMPUnrollDirective(ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)
Called on well-formed 'pragma omp unroll' after parsing of its clauses and the associated statement.
OMPClause * ActOnOpenMPMapClause(Expr *IteratorModifier, ArrayRef< OpenMPMapModifierKind > MapTypeModifiers, ArrayRef< SourceLocation > MapTypeModifiersLoc, CXXScopeSpec &MapperIdScopeSpec, DeclarationNameInfo &MapperId, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef< Expr * > VarList, const OMPVarListLocTy &Locs, bool NoDiagnose=false, ArrayRef< Expr * > UnresolvedMappers={})
Called on well-formed 'map' clause.
OMPClause * ActOnOpenMPNumTasksClause(OpenMPNumTasksClauseModifier Modifier, Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ModifierLoc, SourceLocation EndLoc)
Called on well-formed 'num_tasks' clause.
void ActOnOpenMPDeclareTargetInitializer(Decl *D)
Adds OMPDeclareTargetDeclAttr to referenced variables in declare target directive.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
Definition SemaOpenMP.h:377
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'.
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:1307
Expr * get() const
Definition Sema.h:7817
RAII class used to indicate that we are performing provisional semantic analysis to determine the val...
Definition Sema.h:12561
Abstract base class used for diagnosing integer constant expression violations.
Definition Sema.h:7768
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
QualType getCurrentThisType()
Try to retrieve the type of the 'this' pointer.
Scope * getCurScope() const
Retrieve the parser's current scope.
Definition Sema.h:1133
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:9382
@ LookupOMPReductionName
Look up the name of an OpenMP user-defined reduction operation.
Definition Sema.h:9423
@ LookupOMPMapperName
Look up the name of an OpenMP user-defined mapper.
Definition Sema.h:9425
@ LookupAnyName
Look up any declaration with any name.
Definition Sema.h:9427
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:1525
FunctionEmissionStatus
Status of the function emission on the CUDA/HIP/OpenMP host/device attrs.
Definition Sema.h:4788
@ AR_inaccessible
Definition Sema.h:1679
Scope * getScopeForContext(DeclContext *Ctx)
Determines the active Scope associated with the given declaration context.
Definition Sema.cpp:2332
FPOptionsOverride CurFPFeatureOverrides()
Definition Sema.h:2069
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:1300
void ActOnCapturedRegionError()
DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)
Definition SemaDecl.cpp:79
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:758
ASTContext & getASTContext() const
Definition Sema.h:939
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:9375
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1204
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:932
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:1299
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.
const LangOptions & LangOpts
Definition Sema.h:1298
sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope=false)
Retrieve the current lambda scope info, if any.
Definition Sema.cpp:2578
llvm::SmallSetVector< DeclContext *, 16 > AssociatedNamespaceSet
Definition Sema.h:9374
DeclContext * getCurLexicalContext() const
Definition Sema.h:1137
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:643
bool isVisible(const NamedDecl *D)
Determine whether a declaration is visible to name lookup.
Definition Sema.h:15575
sema::BlockScopeInfo * getCurBlock()
Retrieve the current block, if any.
Definition Sema.cpp:2533
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
Definition Sema.h:1438
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:15530
void setFunctionHasBranchProtectedScope()
Definition Sema.cpp:2518
std::pair< StringRef, QualType > CapturedParamNameType
Definition Sema.h:11289
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:274
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:6790
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
Definition Sema.h:6759
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
Definition SemaStmt.cpp:75
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Scope * TUScope
Translation Unit Scope - useful to Objective-C actions that need to lookup file scope declarations in...
Definition Sema.h:1259
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:2124
sema::CapturedRegionScopeInfo * getCurCapturedRegion()
Retrieve the current captured region, if any.
Definition Sema.cpp:2907
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:436
FullExprArg MakeFullExpr(Expr *Arg)
Definition Sema.h:7831
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Definition Sema.h:8710
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
void setBegin(SourceLocation b)
SourceLocation getBegin() const
void setEnd(SourceLocation e)
StmtVisitor - This class implements a simple visitor for Stmt subclasses.
Stmt - This represents one statement.
Definition Stmt.h:86
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:1485
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:4894
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:3513
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8359
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:8370
The base class of the type hierarchy.
Definition TypeBase.h:1839
const Type * getPointeeOrArrayElementType() const
If this is a pointer type, return the pointee type.
Definition TypeBase.h:9178
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:8728
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:2083
bool isArrayType() const
Definition TypeBase.h:8724
bool isArithmeticType() const
Definition Type.cpp:2374
bool isPointerType() const
Definition TypeBase.h:8625
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9035
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9285
bool isReferenceType() const
Definition TypeBase.h:8649
bool isEnumeralType() const
Definition TypeBase.h:8756
bool isScalarType() const
Definition TypeBase.h:9097
bool isVariableArrayType() const
Definition TypeBase.h:8736
bool isIntegralType(const ASTContext &Ctx) const
Determine whether this type is an integral type.
Definition Type.cpp:2120
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:753
bool hasUnsignedIntegerRepresentation() const
Determine whether this type has an unsigned integer representation of some sort, e....
Definition Type.cpp:2328
bool isAnyCharacterType() const
Determine whether this type is any of the built-in character types.
Definition Type.cpp:2193
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition TypeBase.h:8985
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition TypeBase.h:2798
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition TypeBase.h:8960
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition TypeBase.h:2790
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2455
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8760
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
Definition TypeBase.h:2411
bool hasSignedIntegerRepresentation() const
Determine whether this type has an signed integer representation of some sort, e.g....
Definition Type.cpp:2274
bool isFunctionProtoType() const
Definition TypeBase.h:2607
bool isOverloadableType() const
Determines whether this is a type for which one can define an overloaded operator.
Definition TypeBase.h:9141
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
Definition TypeBase.h:2808
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition TypeBase.h:9271
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2479
const T * getAsAdjusted() const
Member-template getAsAdjusted<specific type>.
Definition TypeBase.h:9235
bool isFunctionType() const
Definition TypeBase.h:8621
bool isStructureOrClassType() const
Definition Type.cpp:707
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2357
bool isFloatingType() const
Definition Type.cpp:2341
bool isAnyPointerType() const
Definition TypeBase.h:8633
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9218
bool isRecordType() const
Definition TypeBase.h:8752
bool isUnionType() const
Definition Type.cpp:719
bool isFunctionNoProtoType() const
Definition TypeBase.h:2606
Represents the declaration of a typedef-name via the 'typedef' type specifier.
Definition Decl.h:3667
Base class for declarations which introduce a typedef-name.
Definition Decl.h:3562
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:2288
Opcode getOpcode() const
Definition Expr.h:2283
static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)
Definition ExprCXX.cpp:432
void append(iterator I, iterator E)
void addDecl(NamedDecl *D)
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:712
void setType(QualType newType)
Definition Decl.h:724
QualType getType() const
Definition Decl.h:723
VarDecl * getPotentiallyDecomposedVarDecl()
Definition DeclCXX.cpp:3653
const Expr * getExprStmt() const
Definition Stmt.cpp:420
Represents a variable declaration or definition.
Definition Decl.h:926
static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)
Definition Decl.cpp:2163
bool isFunctionOrMethodVarDecl() const
Similar to isLocalVarDecl, but excludes variables declared in blocks.
Definition Decl.h:1267
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition Decl.h:1569
TLSKind getTLSKind() const
Definition Decl.cpp:2180
bool hasInit() const
Definition Decl.cpp:2410
void setInitStyle(InitializationStyle Style)
Definition Decl.h:1452
InitializationStyle getInitStyle() const
The style of initialization for this declaration.
Definition Decl.h:1466
DefinitionKind isThisDeclarationADefinition(ASTContext &) const
Check whether this declaration is a definition.
Definition Decl.cpp:2272
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2202
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2269
@ CInit
C-style initialization with assignment.
Definition Decl.h:931
@ CallInit
Call-style initialization (C++98)
Definition Decl.h:934
bool isStaticDataMember() const
Determines whether this is a static data member.
Definition Decl.h:1283
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1226
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1208
bool isFileVarDecl() const
Returns true for file scoped variable declaration.
Definition Decl.h:1342
const Expr * getInit() const
Definition Decl.h:1368
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1184
@ TLS_None
Not a TLS variable.
Definition Decl.h:946
void setInit(Expr *I)
Definition Decl.cpp:2489
@ DeclarationOnly
This declaration is only a declaration.
Definition Decl.h:1295
bool isLocalVarDecl() const
Returns true for local variable declarations other than parameters.
Definition Decl.h:1253
bool isDirectInit() const
Whether the initializer is a direct-initializer (list or call).
Definition Decl.h:1471
StorageDuration getStorageDuration() const
Get the storage duration of this variable, per C++ [basic.stc].
Definition Decl.h:1229
StorageClass getStorageClass() const
Returns the storage class as written in the source.
Definition Decl.h:1168
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:2540
bool isLocalVarDeclOrParm() const
Similar to isLocalVarDecl but also includes parameters.
Definition Decl.h:1262
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1358
Retains information about a captured region.
Definition ScopeInfo.h:820
Retains information about a function, method, or block that is currently being parsed.
Definition ScopeInfo.h:104
SmallVector< CompoundScopeInfo, 4 > CompoundScopes
The stack of currently active compound statement scopes in the function.
Definition ScopeInfo.h:228
specific_attr_iterator - Iterates over a subrange of an AttrVec, only providing attributes that are o...
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:1326
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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a worksharing directive.
OpenMPOriginalSharingModifier
OpenMP 6.0 original sharing modifiers.
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
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
@ Comparison
A comparison.
Definition Sema.h:667
ExprObjectKind
A further classification of the kind of object referenced by an l-value or x-value.
Definition Specifiers.h:149
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
OpenMPAtClauseKind
OpenMP attributes for 'at' clause.
@ 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...
OpenMPScheduleClauseModifier
OpenMP modifiers for 'schedule' clause.
Definition OpenMPKinds.h:39
@ OMPC_SCHEDULE_MODIFIER_last
Definition OpenMPKinds.h:44
@ OMPC_SCHEDULE_MODIFIER_unknown
Definition OpenMPKinds.h:40
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition Specifiers.h:123
@ AS_public
Definition Specifiers.h:124
@ AS_none
Definition Specifiers.h:127
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
bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a parallel-kind directive.
bool isOpenMPPrivate(OpenMPClauseKind Kind)
Checks if the specified clause is one of private clauses like 'private', 'firstprivate',...
@ SC_Auto
Definition Specifiers.h:256
@ SC_Register
Definition Specifiers.h:257
@ SC_None
Definition Specifiers.h:250
OpenMPDistScheduleClauseKind
OpenMP attributes for 'dist_schedule' clause.
@ OMPC_DIST_SCHEDULE_unknown
Expr * Cond
};
static constexpr StringRef getOpenMPVariantManglingSeparatorStr()
OpenMP variants are mangled early based on their OpenMP context selector.
Definition Decl.h:5387
OpenMPDoacrossClauseModifier
OpenMP dependence types for 'doacross' clause.
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:343
@ Parameter
The parameter type of a method or function.
Definition TypeBase.h:908
@ Result
The result type of a method or function.
Definition TypeBase.h:905
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
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 IsXLHSInRHSPart
True if UE has the first form and false if the second.
bool IsPostfixUpdate
True if original value of 'x' must be stored in 'v', not an updated one.
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:132
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:139
SmallVector< CXXBaseSpecifier *, 4 > CXXCastPath
A simple array of base specifiers.
Definition ASTContext.h:150
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
bool IsFailOnly
True if 'v' is updated only when the condition is false (compare capture only).
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:5935
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:440
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:177
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:314
BinaryOperatorKind Opcode
The original opcode, prior to rewriting.
Definition ExprCXX.h:310
const Expr * LHS
The original left-hand side.
Definition ExprCXX.h:312
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:648
APValue Val
Val - This is the value the expression can be folded to.
Definition Expr.h:650
Extra information about a function prototype.
Definition TypeBase.h:5400
llvm::SmallVector< Expr *, 4 > PreferTypes
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:322
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
Definition SemaOpenMP.h:319
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
Definition SemaOpenMP.h:316
SourceLocation Loc
The directive location.
Definition SemaOpenMP.h:325
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Definition SemaOpenMP.h:313
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.